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

19 KiB

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 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:

{
  "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)

# 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

# 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

  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:

# 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