# Release Engineering Documentation ## Overview This project uses a fully automated release engineering pipeline powered by **semantic-release**, **commitlint**, and **GitHub Actions**. The pipeline handles versioning, changelog generation, Docker image publishing, and multi-environment deployments. ## 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 │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ GitHub Actions Pipeline │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────────┐ ┌──────────────────────────┐ │ │ │ CI Job │───►│ Release Job │───►│ Docker Build Job │ │ │ │ │ │ │ │ │ │ │ │ • Lint │ │ • Analyze │ │ • Multi-platform build │ │ │ │ • Test │ │ commits │ │ (amd64, arm64) │ │ │ │ • Build │ │ • Bump version │ │ • Push to Docker Hub │ │ │ │ • Commitlint│ │ • Update │ │ • Push to GHCR │ │ │ │ │ │ CHANGELOG │ │ │ │ │ │ │ │ • Create tag │ │ │ │ │ │ │ │ • GitHub release│ │ │ │ │ └─────────────┘ └─────────────────┘ └──────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ Registries │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────┐ ┌─────────────────────────────────┐ │ │ │ Docker Hub │ │ GitHub Container Registry │ │ │ │ │ │ │ │ │ │ username/cv-app:latest │ │ ghcr.io/owner/cv-app:latest │ │ │ │ username/cv-app:v1.0.0 │ │ ghcr.io/owner/cv-app:v1.0.0 │ │ │ │ username/cv-app:staging │ │ ghcr.io/owner/cv-app:staging │ │ │ │ username/cv-app:nightly │ │ ghcr.io/owner/cv-app:nightly │ │ │ └─────────────────────────────┘ └─────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ## Components ### 1. Conventional Commits All commits must follow the [Conventional Commits](https://www.conventionalcommits.org/) specification: ``` (): [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" ] } ``` ### 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 before commit | `npm run lint` | | `commit-msg` | Validate commit message | `commitlint --edit` | ### 5. GitHub 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 20 │ │ 3. Install dependencies (root + backend) │ │ 4. Lint │ │ 5. Run tests (root + backend) │ │ 6. Build │ │ 7. semantic-release │ │ - Analyze commits │ │ - Bump version │ │ - Update CHANGELOG.md │ │ - Create git tag │ │ - Create GitHub release │ └───────────────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────────────┐ │ Docker Build Job │ ├───────────────────────────────────────────────────────────┤ │ 1. Checkout │ │ 2. Get version from git tag │ │ 3. Setup QEMU (for multi-platform) │ │ 4. Setup Docker Buildx │ │ 5. Login to Docker Hub │ │ 6. Login to GHCR │ │ 7. Build and push (amd64 + arm64) │ └───────────────────────────────────────────────────────────┘ ``` #### Staging Workflow (`.github/workflows/staging.yml`) Runs on: Push to staging branch ``` ┌───────────────────────────────────────────────────────────┐ │ Staging Deploy Job │ ├───────────────────────────────────────────────────────────┤ │ 1. Checkout │ │ 2. Install + Lint + Test + Build │ │ 3. Build Docker image (multi-platform) │ │ 4. Push with tag: staging │ └───────────────────────────────────────────────────────────┘ ``` #### Nightly Workflow (`.github/workflows/nightly.yml`) Runs on: Schedule (daily at 02:00 UTC) ``` ┌───────────────────────────────────────────────────────────┐ │ Nightly Build Job │ ├───────────────────────────────────────────────────────────┤ │ 1. Checkout master │ │ 2. Get current date │ │ 3. Install + Build │ │ 4. Build Docker image (multi-platform) │ │ 5. Push with tags: nightly, edge, YYYY-MM-DD │ └───────────────────────────────────────────────────────────┘ ``` ## Docker Image Tags | Tag | Registry | Description | Update Frequency | |-----|----------|-------------|------------------| | `latest` | Both | Latest stable release | Every release | | `v1.0.0` | Both | Specific version | Immutable | | `1.0` | Both | Major.minor | Points to latest patch | | `1` | Both | Major version | Points to latest minor | | `staging` | Both | Staging environment | Every staging push | | `nightly` | Both | Latest nightly build | Daily | | `edge` | Both | Alias for nightly | Daily | | `2026-02-20` | Both | Date-specific nightly | Immutable | ### Pulling Images ```bash # Docker Hub docker pull username/cv-app:latest docker pull username/cv-app:v1.0.0 docker pull username/cv-app:staging docker pull username/cv-app:nightly # 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 | Docker Tag | |-------------|--------|---------|------------| | Production | `master` | semantic-release (feat/fix commits) | `latest`, `vX.Y.Z` | | Staging | `staging` | Push to branch | `staging` | | Nightly | `master` | Daily at 02:00 UTC | `nightly`, `edge`, `YYYY-MM-DD` | ## Release Flow Example ``` Developer commits: feat(admin): add export functionality │ ▼ ┌─────────────────┐ │ Git Hook Runs │ │ (pre-commit) │ │ • npm run lint │ └─────────────────┘ │ ▼ ┌─────────────────┐ │ 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 │ └─────────────────┘ │ ▼ ┌─────────────────┐ │ GitHub Release │ │ created │ │ with notes │ └─────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ Docker images built and │ │ pushed to: │ │ │ │ • username/cv-app:latest │ │ • username/cv-app:v1.1.0 │ │ • ghcr.io/owner/cv-app:latest │ │ • ghcr.io/owner/cv-app:v1.1.0 │ └─────────────────────────────────┘ ``` ## Required Secrets Configure these in GitHub repository settings → Secrets and variables → Actions: | Secret | Description | Required For | |--------|-------------|--------------| | `DOCKERHUB_USERNAME` | Docker Hub username | Docker Hub push | | `DOCKERHUB_TOKEN` | Docker Hub access token | Docker Hub push | | `GITHUB_TOKEN` | GitHub token (automatic) | GHCR push, releases | ### Creating Docker Hub Token 1. Go to Docker Hub → Account Settings → Security 2. Click "New Access Token" 3. Name: `cv-app-github-actions` 4. Permissions: Read, Write, Delete 5. Copy token and add to GitHub secrets ## 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. ### Docker Push Fails **Error**: `denied: requested access to the resource is denied` **Fix**: 1. Verify `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets 2. Ensure Docker Hub token has Write permission 3. Check Docker Hub repository exists (or enable auto-create) ### 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 |