Skip to content

Latest commit

 

History

History
278 lines (206 loc) · 9.08 KB

File metadata and controls

278 lines (206 loc) · 9.08 KB

Versioning Guide

Semantic Versioning

Charon follows Semantic Versioning 2.0.0:

  • MAJOR.MINOR.PATCH (e.g., 1.2.3)
    • MAJOR: Incompatible API changes
    • MINOR: New functionality (backward compatible)
    • PATCH: Bug fixes (backward compatible)

Pre-release Identifiers

  • alpha: Early development, unstable
  • beta: Feature complete, testing phase
  • rc (release candidate): Final testing before release

Example: 0.1.0-alpha, 1.0.0-beta.1, 2.0.0-rc.2

Creating a Release

Canonical Release Process (release-please)

Charon uses googleapis/release-please-action to compute versions, maintain a standing release PR, and cut tags + GitHub Releases from Conventional Commit history. There is no manual tagging step and no in-repo version manifest to hand-edit — .release-please-manifest.json is the single source of truth for "what version are we at," kept in sync by release-please itself.

  1. Commits land on main: every push to main runs .github/workflows/release-please.yml, which walks Conventional Commits since the last release and opens or updates a standing chore(main): release X.Y.Z pull request. If nothing releasable (feat:/fix:) has landed since the last release, no PR is opened or updated.

  2. A human merges the release PR: merging it is what actually ships a release — nothing goes out automatically before that.

  3. On merge, release-please:

    • Tags the merge commit vX.Y.Z (bare, no charon- prefix — pinned via include-component-in-tag: false in release-please-config.json)
    • Creates the GitHub Release for that tag
  4. Downstream, independently of release-please:

    • .github/workflows/orthrus-build.yml triggers on the new v* tag and publishes semver-tagged Orthrus agent images
    • The next nightly-build.yml run picks up the new tag via scripts/generate-changelog.sh's git tag -l 'v*' scan and regenerates the in-app "What's New" changelog data
  5. Container tags are published (via .github/workflows/docker-build.yml, triggered on the branch push, not the tag):

  • v1.0.0 (exact version)
  • 1.0 (minor version)
  • 1 (major version)
  • latest (for non-prerelease on main branch)

Do not manually push v* tags. A manually-created tag desyncs .release-please-manifest.json (which release-please treats as its source of truth, not live tag state) from the repo's real tag history — let release-please create every release tag going forward.

release-please-config.json sets skip-changelog: true, so this hand-curated CHANGELOG.md is never touched by release-please's PRs or Release generation.

Deterministic Rollout Verification Gates (Mandatory)

Release sign-off is blocked until all items below pass in the same validation run.

Enforcement points:

  • Release sign-off checklist/process (mandatory): All gates below remain required for release sign-off.

  • CI-supported checks (current): .github/workflows/docker-build.yml and .github/workflows/supply-chain-verify.yml enforce the subset currently implemented in workflows.

  • Manual validation required until CI parity: Validate any not-yet-implemented workflow gates via VS Code tasks Security: Full Supply Chain Audit, Security: Verify SBOM, Security: Generate SLSA Provenance, and Security: Sign with Cosign.

  • Digest freshness/parity: Capture pre-push and post-push index digests for the target tag in GHCR and Docker Hub, confirm expected freshness, and confirm cross-registry index digest parity.

  • Per-arch parity: Confirm per-platform (linux/amd64, linux/arm64, and any published platform) digest parity between GHCR and Docker Hub.

  • Immutable digest scanning: Run SBOM and vulnerability scans against immutable refs only, using image@sha256:<index-digest>.

  • Artifact freshness: Confirm scan artifacts are generated after the push timestamp and in the same validation run.

  • Evidence block present: Include the mandatory evidence block fields listed below.

Mandatory Evidence Block Fields

  • Tag name
  • Index digest (sha256:...)
  • Per-arch digests (platform -> digest)
  • Scan tool versions
  • Push timestamp and scan timestamp(s)
  • Artifact file names generated in this run

Container Image Tags

Available Tags

  • latest: Latest stable release (main branch)
  • nightly: Latest nightly build (nightly branch, rebuilt daily at 02:00 UTC)
  • nightly-YYYY-MM-DD: Date-specific nightly build
  • nightly-<sha>: Commit-specific nightly build
  • development: Latest development build (development branch)
  • v1.2.3: Specific version tag
  • 1.2: Latest patch for minor version
  • 1: Latest minor for major version
  • main-<sha>: Commit-specific build from main
  • development-<sha>: Commit-specific build from development

Usage Examples

# Use latest stable release
docker pull ghcr.io/wikid82/charon:latest

# Use specific version
docker pull ghcr.io/wikid82/charon:v1.0.0

# Use latest nightly build (automated daily at 02:00 UTC)
docker pull ghcr.io/wikid82/charon:nightly

# Use date-specific nightly build
docker pull ghcr.io/wikid82/charon:nightly-2026-01-13

# Use commit-specific nightly build
docker pull ghcr.io/wikid82/charon:nightly-abc123

# Use development builds (unstable, every commit)
docker pull ghcr.io/wikid82/charon:development

# Use specific commit from main
docker pull ghcr.io/wikid82/charon:main-abc123

Nightly Builds

Nightly builds provide a testing ground for features before they reach main:

  • Automated: Built daily at 02:00 UTC from the nightly branch
  • Source: Auto-merged from development branch
  • Purpose: Pre-release testing and validation
  • Stability: More stable than development, less stable than latest

When to use nightly:

  • Testing new features before stable release
  • Validating bug fixes
  • Contributing to pre-release testing
  • Running in staging environments

When to avoid nightly:

  • Production environments (use latest instead)
  • Critical infrastructure
  • When maximum stability is required

Nightly Versioning Format

Version Precedence

Charon uses the following version hierarchy:

  1. Stable releases: v1.2.3 (highest precedence)
  2. Nightly builds: nightly-YYYY-MM-DD or nightly-{sha}
  3. Development builds: development or development-{sha} (lowest precedence)

Nightly Version Tags

Nightly builds use multiple tag formats:

  • nightly: Always points to the latest nightly build (floating tag)
  • nightly-YYYY-MM-DD: Date-specific build (e.g., nightly-2026-01-13)
  • nightly-{sha}: Commit-specific build (e.g., nightly-abc1234)

Tag characteristics:

Tag Format Immutable Use Case
nightly No Latest nightly features
nightly-2026-01-13 Yes Reproducible date-based testing
nightly-abc1234 Yes Exact commit testing

Version in API responses:

Nightly builds report their version in the health endpoint:

{
  "version": "nightly-2026-01-13",
  "git_commit": "abc1234567890def",
  "build_date": "2026-01-13T02:00:00Z",
  "branch": "nightly"
}

Version Information

Runtime Version Endpoint

curl http://localhost:8080/api/v1/health

Response includes:

{
  "status": "ok",
  "service": "charon",
  "version": "1.0.0",
  "git_commit": "abc1234567890def",
  "build_date": "2025-11-17T12:34:56Z"
}

Container Image Labels

View version metadata:

docker inspect ghcr.io/wikid82/charon:latest \
  --format='{{json .Config.Labels}}' | jq

Returns OCI-compliant labels:

  • org.opencontainers.image.version
  • org.opencontainers.image.created
  • org.opencontainers.image.revision
  • org.opencontainers.image.source

Development Builds

Local builds default to version=dev:

docker build -t charon:dev .

Build with custom version:

docker build \
  --build-arg VERSION=1.2.3 \
  --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
  --build-arg VCS_REF=$(git rev-parse HEAD) \
  -t charon:1.2.3 .

Changelog Generation

release-please's standing release PR body is generated from commit messages. Use conventional commit format:

  • feat: New features
  • fix: Bug fixes
  • docs: Documentation changes
  • chore: Maintenance tasks
  • refactor: Code refactoring
  • test: Test updates
  • ci: CI/CD changes

Example:

git commit -m "feat: add TLS certificate management"
git commit -m "fix: correct proxy timeout handling"

CI Tag-based Releases (recommended)

  • CI derives the release Version from the Git tag (e.g., v1.2.3) and embeds this value into the backend binary via Go ldflags; frontend reads the version from the backend's API. This avoids automatic commits to main.
  • release-please creates the tag and the GitHub Release together when its standing release PR is merged — see "Canonical Release Process (release-please)" above.