23 KiB
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 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:
- Commit Analysis: Analyzes commits since last release
- Version Calculation: Determines next version based on commit types
- Changelog Generation: Updates CHANGELOG.md with changes
- Git Operations: Creates tags and commits version bump
- GitHub Release: Creates release with notes and assets
Configuration
Located in .releaserc.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
# 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
- Go to Docker Hub → Account Settings → Security
- Click "New Access Token"
- Name:
cv-app-github-actions - Permissions: Read, Write, Delete
- Copy token and add to GitHub secrets
Local Development
Testing Commit Messages
# 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:
git commit -m "docs: update readme [skip ci]"
Manual Release Trigger
- Go to Actions → Release workflow
- Click "Run workflow"
- Select branch (master)
- Click "Run workflow"
Troubleshooting
Commit Rejected by commitlint
Error: subject must be lower-case
Fix: Use lowercase for the subject:
# Wrong
git commit -m "feat(ui): Add new button"
# Correct
git commit -m "feat(ui): add new button"
Release Not Triggering
Causes:
- No release-worthy commits (only docs/style/refactor/test/build/ci/chore)
- Commit message contains
[skip ci] - 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:
- Verify
DOCKERHUB_USERNAMEandDOCKERHUB_TOKENsecrets - Ensure Docker Hub token has Write permission
- 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!:orBREAKING 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 |