486 lines
25 KiB
Markdown
486 lines
25 KiB
Markdown
<!-- markdownlint-disable MD013 -->
|
|
|
|
# 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:
|
|
|
|
```
|
|
<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"
|
|
]
|
|
}
|
|
```
|
|
|
|
### 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 |
|