Files
kilo-cv/docs/release-engineering.md
Tuan-Dat Tran dd3b83f7e1
Some checks failed
Release / Build & Push Docker Image (push) Has been cancelled
Release / Release (push) Has been cancelled
docs: update release-engineering documentation
- Reflect Gitea Actions instead of GitHub Actions
- Document npm install optimization flags
- Add gitleaks to pre-commit hook documentation
- Update semantic-release config for Gitea compatibility
- Mark Docker workflows as temporarily disabled
- Update pipeline diagrams and environment table
2026-02-23 22:29:47 +01:00

422 lines
19 KiB
Markdown

<!-- markdownlint-disable MD013 -->
# Release Engineering Documentation
## Overview
This project uses a fully automated release engineering pipeline powered by **semantic-release**, **commitlint**, and **Gitea Actions**. The pipeline handles versioning, changelog generation, and releases. Docker publishing is currently disabled pending runner configuration.
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Developer Workflow │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Write code with conventional commits │
│ 2. Push to feature branch │
│ 3. Create PR → CI validates commits + code │
│ 4. Merge to master → Release pipeline triggers │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ Gitea Actions Pipeline │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────────────────────────────────────────┐ │
│ │ CI Job │───►│ Release Job │ │
│ │ │ │ │ │
│ │ • Lint │ │ • Analyze commits │ │
│ │ • Test │ │ • Bump version │ │
│ │ • Build │ │ • Update CHANGELOG │ │
│ │ • Commitlint│ │ • Create tag │ │
│ │ │ │ • Create Gitea release │ │
│ └─────────────┘ └─────────────────────────────────────────────────┘ │
│ │
│ Note: Docker publishing temporarily disabled (runner lacks Docker) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## Components
### 1. Conventional Commits
All commits must follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
```
<type>(<scope>): <description>
[optional body]
[optional footer]
```
#### Commit Types
| Type | Description | Version Bump | Example |
| ---------- | ----------------------- | --------------------- | ------------------------------------------- |
| `feat` | New feature | Minor (1.0.0 → 1.1.0) | `feat(admin): add password protection` |
| `fix` | Bug fix | Patch (1.0.0 → 1.0.1) | `fix(skills): prevent focus loss` |
| `perf` | Performance improvement | Patch | `perf(ui): lazy load images` |
| `feat!` | Breaking change | Major (1.0.0 → 2.0.0) | `feat(api)!: remove deprecated endpoints` |
| `docs` | Documentation only | None | `docs(readme): update installation` |
| `style` | Code style (formatting) | None | `style(ui): fix indentation` |
| `refactor` | Code refactoring | None | `refactor(auth): simplify token validation` |
| `test` | Adding/updating tests | None | `test(api): add auth middleware tests` |
| `build` | Build system changes | None | `build(docker): update node version` |
| `ci` | CI/CD changes | None | `ci(github): add staging workflow` |
| `chore` | Maintenance tasks | None | `chore(deps): update dependencies` |
| `revert` | Revert previous commit | Patch | `revert: remove broken feature` |
#### Allowed Scopes
| Scope | Description |
| ------------ | ---------------------- |
| `admin` | Admin panel components |
| `api` | Backend API |
| `ui` | Frontend UI components |
| `docker` | Docker configuration |
| `ci` | CI/CD workflows |
| `deps` | Dependencies |
| `release` | Release configuration |
| `auth` | Authentication |
| `skills` | Skills section |
| `experience` | Experience section |
| `education` | Education section |
| `projects` | Projects section |
| `personal` | Personal info section |
### 2. semantic-release
semantic-release automates the entire release process:
1. **Commit Analysis**: Analyzes commits since last release
2. **Version Calculation**: Determines next version based on commit types
3. **Changelog Generation**: Updates CHANGELOG.md with changes
4. **Git Operations**: Creates tags and commits version bump
5. **GitHub Release**: Creates release with notes and assets
#### Configuration
Located in `.releaserc.json`:
```json
{
"branches": ["master", { "name": "staging", "prerelease": true }],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git",
[
"@semantic-release/github",
{
"successCommentCondition": false,
"failCommentCondition": false,
"releasedLabels": false
}
]
]
}
```
Note: The `successCommentCondition` and `failCommentCondition` are set to `false` for Gitea compatibility (Gitea lacks GitHub's GraphQL API).
### 3. commitlint
Enforces conventional commits via:
- **Git hook**: Validates every commit message locally
- **CI job**: Validates commits in pull requests
Configuration in `commitlint.config.js`:
- Validates commit types
- Validates scopes
- Enforces lowercase subjects
- Limits subject length to 72 characters
### 4. Husky Git Hooks
| Hook | Purpose | Command |
| ------------ | ------------------------- | ------------------------------------ |
| `pre-commit` | Run linting + secret scan | `npm run lint` + `gitleaks protect` |
| `commit-msg` | Validate commit message | `commitlint --edit` |
Note: Gitleaks scans for secrets before commit. If not installed locally, it's skipped gracefully.
### 5. Gitea Actions Workflows
#### CI Workflow (`.github/workflows/ci.yml`)
Runs on: Push to master, Pull requests to master
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Frontend │ │ Backend │ │ Commitlint │
│ Job │ │ Job │ │ Job │
├─────────────┤ ├─────────────┤ ├─────────────┤
│ • Lint │ │ • Install │ │ • Validate │
│ • Test │ │ • Test │ │ commits │
│ • Build │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└────────────────┼────────────────┘
┌─────────────────┐
│ Integration │
│ Job │
└─────────────────┘
┌─────────────────┐
│ E2E │
│ Job │
└─────────────────┘
```
#### Release Workflow (`.github/workflows/release.yml`)
Runs on: Push to master (excluding [skip ci] commits)
```
┌───────────────────────────────────────────────────────────┐
│ Release Job │
├───────────────────────────────────────────────────────────┤
│ 1. Checkout (fetch-depth: 0 for full history) │
│ 2. Setup Node.js 24 │
│ 3. Install dependencies (root + backend) │
│ - Uses --prefer-offline --no-audit --no-fund │
│ 4. Lint │
│ 5. Run tests (root + backend) │
│ 6. Build │
│ 7. semantic-release │
│ - Analyze commits │
│ - Bump version │
│ - Update CHANGELOG.md │
│ - Create git tag │
│ - Create Gitea release │
└───────────────────────────────────────────────────────────┘
```
Note: Docker build job temporarily disabled (runner lacks Docker support).
#### Staging Workflow (`.github/workflows/staging.yml`)
Runs on: Push to staging branch
**Status: Temporarily disabled** - Requires Docker support on runner.
#### Nightly Workflow (`.github/workflows/nightly.yml`)
Runs on: Schedule (daily at 02:00 UTC)
**Status: Temporarily disabled** - Requires Docker support on runner.
## Docker Image Tags
**Status: Temporarily disabled** - Docker publishing requires runner with Docker-in-Docker support.
| Tag | Registry | Description | Update Frequency |
| ------------ | -------- | --------------------- | ---------------------- |
| `latest` | Both | Latest stable release | Every release |
| `v1.0.0` | Both | Specific version | Immutable |
| `staging` | Both | Staging environment | Every staging push |
| `nightly` | Both | Latest nightly build | Daily |
### Pulling Images (when Docker publishing is enabled)
```bash
# Docker Hub
docker pull username/cv-app:latest
docker pull username/cv-app:v1.0.0
# GitHub Container Registry
docker pull ghcr.io/owner/cv-app:latest
docker pull ghcr.io/owner/cv-app:v1.0.0
```
## Environments
| Environment | Branch | Trigger | Status |
| ----------- | --------- | ----------------------------------- | ---------------------------- |
| Production | `master` | semantic-release (feat/fix commits) | Active (release only) |
| Staging | `staging` | Push to branch | Disabled (Docker required) |
| Nightly | `master` | Daily at 02:00 UTC | Disabled (Docker required) |
## Release Flow Example
```
Developer commits: feat(admin): add export functionality
┌─────────────────┐
│ Git Hook Runs │
│ (pre-commit) │
│ • npm run lint │
│ • gitleaks │
└─────────────────┘
┌─────────────────┐
│ Git Hook Runs │
│ (commit-msg) │
│ • commitlint │
└─────────────────┘
┌─────────────────┐
│ Push to PR │
│ │
│ CI validates: │
│ • commitlint │
│ • lint │
│ • test │
│ • build │
└─────────────────┘
┌─────────────────┐
│ Merge to │
│ master │
└─────────────────┘
┌─────────────────┐
│ Release Workflow│
│ Triggers │
└─────────────────┘
┌─────────────────────────────────────┐
│ semantic-release analyzes │
│ │
│ Previous version: 1.0.0 │
│ Commits since last release: │
│ • feat(admin): add export │
│ │
│ Decision: MINOR release │
│ New version: 1.1.0 │
└─────────────────────────────────────┘
┌─────────────────┐
│ Version bumped │
│ in package.json │
│ 1.0.0 → 1.1.0│
└─────────────────┘
┌─────────────────┐
│ CHANGELOG.md │
│ updated │
└─────────────────┘
┌─────────────────┐
│ Git tag created │
│ v1.1.0 │
└─────────────────┘
┌─────────────────┐
│ Gitea Release │
│ created │
│ with notes │
└─────────────────┘
```
## Required Secrets
Configure these in Gitea repository settings → Settings → Secrets:
| Secret | Description | Required For |
| -------------------- | ------------------------ | ------------------- |
| `DOCKERHUB_USERNAME` | Docker Hub username | Docker Hub push |
| `DOCKERHUB_TOKEN` | Docker Hub access token | Docker Hub push |
| `GITHUB_TOKEN` | Gitea token (automatic) | Releases |
Note: Docker publishing is currently disabled until runner supports Docker-in-Docker.
## Local Development
### Testing Commit Messages
```bash
# Test a valid commit message
echo "feat(ui): add new button component" | npx commitlint
# Test an invalid commit message
echo "added a button" | npx commitlint
```
### Skipping CI
Add `[skip ci]` to commit message to skip CI:
```bash
git commit -m "docs: update readme [skip ci]"
```
### Manual Release Trigger
1. Go to Actions → Release workflow
2. Click "Run workflow"
3. Select branch (master)
4. Click "Run workflow"
## Troubleshooting
### Commit Rejected by commitlint
**Error**: `subject must be lower-case`
**Fix**: Use lowercase for the subject:
```bash
# Wrong
git commit -m "feat(ui): Add new button"
# Correct
git commit -m "feat(ui): add new button"
```
### Release Not Triggering
**Causes**:
1. No release-worthy commits (only docs/style/refactor/test/build/ci/chore)
2. Commit message contains `[skip ci]`
3. Workflow already running
**Solution**: Ensure you have `feat`, `fix`, or `perf` commits since last release.
### Version Not Bumping
**Cause**: semantic-release requires conventional commits with proper types.
**Fix**: Ensure commits follow:
- `feat:` for features (minor bump)
- `fix:` for bug fixes (patch bump)
- `feat!:` or `BREAKING CHANGE:` for breaking changes (major bump)
## File Reference
| File | Purpose |
| ------------------------------- | ---------------------------------- |
| `.releaserc.json` | semantic-release configuration |
| `commitlint.config.js` | Commitlint rules |
| `.husky/pre-commit` | Pre-commit hook (lint) |
| `.husky/commit-msg` | Commit message hook (commitlint) |
| `.github/workflows/ci.yml` | CI pipeline |
| `.github/workflows/release.yml` | Release pipeline |
| `.github/workflows/staging.yml` | Staging deployment |
| `.github/workflows/nightly.yml` | Nightly builds |
| `docker-bake.hcl` | Multi-platform Docker build config |
| `CHANGELOG.md` | Auto-generated changelog |