Skip to content

ADR-002: GitVersion Mode - ContinuousDeployment with Conventional Commits

Status

Approved - Implemented

Context

The SyRF monorepo requires a consistent versioning strategy that:

  • Supports per-service versioning in a monorepo
  • Works with path-based change detection
  • Provides semantic versioning based on commit messages
  • Integrates with CI/CD workflows
  • Maintains performance as the repository grows

Two main GitVersion modes were evaluated:

  1. Mainline Development: Every commit on main is deployable, uses +semver: directives
  2. ContinuousDeployment: Version stays stable until tagged, uses conventional commits

Decision

Use GitVersion in ContinuousDeployment mode with conventional commit messages.

Configuration

mode: ContinuousDeployment
tag-prefix: '{service}-v'

# Conventional commit patterns
major-version-bump-message: '^(feat|fix|chore)(\([a-z]+\))?!:|^BREAKING CHANGE:'
minor-version-bump-message: '^feat(\([a-z]+\))?:'
patch-version-bump-message: '^fix(\([a-z]+\))?:'
no-bump-message: '^(chore|docs|style|refactor|test|ci)(\([a-z]+\))?:'

branches:
  master:
    increment: Patch
    regex: ^master$|^main$
    label: ''

Commit Message Convention

  • feat: → Minor version bump (0.X.0)
  • fix: → Patch version bump (0.0.X)
  • feat!: or BREAKING CHANGE: → Major version bump (X.0.0)
  • chore:, docs:, style: → No version bump

Consequences

Positive

  • Industry Standard: Conventional commits are widely adopted
  • Team Familiarity: Developers likely know feat: and fix: patterns
  • Tooling Support: Better integration with commitlint, changelog generators
  • Performance: No cumulative history calculation, doesn't slow over time
  • Monorepo Fit: Path filtering with conventional commits is well-tested
  • Clear Workflow: commit → calculate version → tag → build → deploy

Negative

  • Tag Requirement: Must create tags to mark releases
  • Multiple Commits Same Version: Several commits share version until tagged
  • Not True CD: Every commit doesn't immediately deploy to production

Alternatives Considered

Mainline Development Mode

Pros:

  • Every commit on main triggers deployment
  • Forward-focused development
  • Works well with trunk-based development

Cons:

  • Performance degrades over time
  • Less intuitive syntax (+semver: vs fix:)
  • Requires 100% test coverage confidence

Rejected because: Our workflow uses controlled releases via tags and GitOps, not immediate deployment of every commit.

Implementation

Service GitVersion Configuration

Each service has its own GitVersion.yml:

tag-prefix: 'api-v'  # Service-specific prefix
ignore:
  paths:
    - ^(?!services\/api\/|libs\/).*  # Ignore other services

CI/CD Integration

  1. Commit to main with conventional message
  2. GitVersion calculates next version
  3. Workflow creates service tag (e.g., api-v1.2.3)
  4. Docker build triggered by tag
  5. Image pushed to registry
  6. GitOps deployment via promotion PR

Example Workflow

# Developer commits
git commit -m "feat(api): add export endpoint"

# CI/CD workflow
# - Detects change in api service
# - GitVersion calculates: 1.2.0 → 1.3.0 (minor bump)
# - Creates tag: api-v1.3.0
# - Builds Docker image: ghcr.io/camaradesuk/syrf-api:1.3.0
# - Creates promotion PR to cluster-gitops