draforge

Release Process

This document describes the release workflow for DRAForge.


Version Injection

All three binaries embed version and commit information at build time via GoReleaser ldflags:

Binary LDFLAGS
draforge -X main.versionVal= -X main.commitSHA=
draforge-controller -X main.versionVal= -X main.commitSHA=
draforge-sim-driver -X main.versionVal= -X main.commitSHA=

These values are set by GoReleaser during goreleaser release and are visible via go version -m on the compiled binary. The CLI also exposes them via draforge version.

Snapshot builds (local dry-runs) use a synthetic version like v0.0.0-SNAPSHOT-<commit> and do not publish anything. The CI pipeline validates the release configuration with goreleaser release --snapshot --skip=docker,sbom,sign in the goreleaser job (see .github/workflows/ci.yml).

Prerequisites

Environment variables

export GITHUB_TOKEN=ghp_...          # GitHub PAT with repo + write:packages
export COSIGN_PASSWORD=...           # If signing with a cosign key

Snapshot release (local dry-run)

A snapshot build validates the pipeline without publishing anything:

goreleaser release --snapshot --clean --skip=publish

To verify the output:

task release:verify

Tagged release flow

1. Prepare the release

Ensure CHANGELOG.md is up to date:

# Review unreleased changes
grep -A 999 "## \\[Unreleased\\]" CHANGELOG.md | head -50

# Move Unreleased entries to a new version section
# and update the [Unreleased] compare link at the bottom of CHANGELOG.md

Commit the changelog update:

git add CHANGELOG.md
git commit -m "docs: prepare v0.1.0 changelog"

2. Tag and push

git tag v0.1.0
git push origin v0.1.0

3. Run GoReleaser

goreleaser release --clean

This will:

  1. Build all three binaries (draforge, draforge-controller, draforge-sim-driver) for linux/amd64, linux/arm64, darwin/amd64, darwin/arm64.
  2. Create compressed archives (tar.gz / zip).
  3. Generate checksums.txt.
  4. Generate CycloneDX SBOMs for each archive.
  5. Build and push Docker images to ghcr.io/oaslananka/:
    • Per-architecture images tagged with v0.1.0-amd64, v0.1.0-arm64.
    • Multi-arch manifest images (v0.1.0, v0.1, latest).
  6. Create a GitHub release with the archives and checksums attached.
  7. (If configured) Sign checksums and Docker images with Cosign.

4. Verify the release

# Check GitHub release
gh release view v0.1.0

# Check container images
docker pull ghcr.io/oaslananka/draforge-server:v0.1.0

# Verify binary version
docker run --rm ghcr.io/oaslananka/draforge-server:v0.1.0 version

# Check SBOM
gh release download v0.1.0 -p "*.sbom"

SBOM generation

SBOMs are generated by GoReleaser via Syft during the release pipeline. Each archive gets a CycloneDX JSON SBOM (.sbom).

To generate an SBOM manually outside the release pipeline:

# Full project SBOM
task sbom
# Equivalent to: syft dir:. -o cyclonedx-json > draforge.sbom.json

# Per-binary SBOM
syft dist/draforge_linux_amd64_v1/draforge -o cyclonedx-json > draforge.sbom.json

Artifacts

Artifact Location Description
Binaries dist/ GoReleaser staging directory (not committed)
Archives dist/*.tar.gz, dist/*.zip Compressed release archives
Checksums dist/checksums.txt SHA-256 checksums of all archives
SBOMs dist/*.sbom CycloneDX JSON software bills of materials
Docker images ghcr.io/oaslananka/ Multi-arch container images
GitHub release https://github.com/oaslananka/draforge/releases/tag/v0.1.0 Release with assets

Rollback

Before pushing a tag

Simple — delete the tag locally and revert the changelog commit:

git tag -d v0.1.0
git reset --hard HEAD~1

After pushing a tag (no release run)

git push --delete origin v0.1.0
git tag -d v0.1.0

After a release is published

  1. Draft a new release on GitHub that supersedes the faulty one.
  2. Do not delete the existing tag — it may be referenced by users.
  3. If Docker images were pushed, consider whether they need to be deprecated (the old images remain pullable under the same tag unless overwritten).
  4. Fix the issue, bump the patch version, and cut a new release (e.g. v0.1.1).

What not to commit

The following are generated by GoReleaser and must not be committed (already covered by .gitignore):

Additionally, never commit:


Troubleshooting

Problem Likely cause Fix
goreleaser not found Not installed or not on $PATH Install via go install github.com/goreleaser/goreleaser/v2@latest
Docker build fails Docker daemon not running Start Docker Desktop / dockerd
syft command not found Syft not installed Install from https://github.com/anchore/syft
gh auth failure No GitHub token or expired token Run gh auth login or set GITHUB_TOKEN
Cosign signing fails Cosign key not set up See Cosign documentation
Release created but no assets Missing GITHUB_TOKEN Ensure token has repo scope