This document describes the release process for Headjack, covering the CLI and container images.
Headjack uses release-please to automate releases. The system manages two independent components:
| Component | Tag Format | Changelog |
|---|---|---|
| CLI | v1.0.0 |
CHANGELOG.md |
| base image | images/base/v1.0.0 |
images/base/CHANGELOG.md |
┌─────────────────────────────────────────────────────────────────────────┐
│ Developer Workflow │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Commit with Conventional Commits format │
│ └── feat: add new command │
│ └── fix(images/base): update Node.js │
│ │
│ 2. Push to master │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ release-please.yml workflow │ │
│ │ │ │
│ │ • Analyzes commits since last release │ │
│ │ • Creates/updates release PR │ │
│ │ • Updates CHANGELOG.md │ │
│ │ • Bumps version in manifest │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 3. Review and merge release PR │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ release-please creates: │ │
│ │ • Git tag (v1.0.0 or images/*/v*) │ │
│ │ • GitHub Release │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────┴─────────────┐ │
│ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ CLI Release │ │ Image Release │ │
│ │ (v* tag) │ │ (images/*/v*) │ │
│ └───────────────┘ └───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ release.yml │ │ images.yml │ │
│ │ • GoReleaser │ │ • Docker Bake │ │
│ │ • Homebrew │ │ • Cosign │ │
│ └───────────────┘ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
All commits must follow the Conventional Commits specification. The commit type determines version bumps:
| Commit Type | Version Bump | Example |
|---|---|---|
fix: |
Patch (0.0.x) | fix: resolve container cleanup issue |
feat: |
Minor (0.x.0) | feat: add new run command |
feat!: or BREAKING CHANGE: |
Major (x.0.0) | feat!: redesign CLI interface |
Commits are grouped into changelog sections based on type:
| Type | Section | Visible |
|---|---|---|
feat |
Features | Yes |
fix |
Bug Fixes | Yes |
perf |
Performance | Yes |
refactor |
Code Refactoring | Yes |
revert |
Reverts | Yes |
build |
Build System | Yes |
chore |
Miscellaneous | Yes |
docs |
Documentation | Hidden |
style |
Styles | Hidden |
test |
Tests | Hidden |
ci |
Continuous Integration | Hidden |
Release-please attributes commits to components based on file paths. For clarity, you can use scopes:
# CLI changes (touches Go files in root)
git commit -m "feat: add instance list command"
# Image changes (touches files in images/)
git commit -m "feat(images/base): add ripgrep to base image"CLI releases are handled by GoReleaser when a v* tag is pushed.
| Platform | Architecture | CGO |
|---|---|---|
| darwin (macOS) | amd64, arm64 | Enabled |
| linux | amd64, arm64 | Disabled |
- Binaries:
hjkexecutable for each platform - Archives:
headjack_{version}_{os}_{arch}.tar.gz - Checksums:
checksums.txtwith SHA256 hashes - GitHub Release: Created with changelog from commits
- Homebrew Cask: Updated in GilmanLab/tap
Version information is injected at build time via ldflags:
// internal/version/version.go
var (
Version = "dev" // Set to tag version (e.g., "1.0.0")
Commit = "none" // Set to git commit SHA
Date = "unknown" // Set to build date
)Triggers on v* tags and runs GoReleaser with:
GITHUB_TOKENfor GitHub release creationHOMEBREW_TAP_TOKENfor Homebrew cask updates
Container images are built and published when images/*/v* tags are pushed.
| Variant | Base | Features |
|---|---|---|
base |
Ubuntu 24.04 | Dev tools, agent CLIs, version managers |
Each release creates two tags:
ghcr.io/gilmanlab/headjack:base # Latest
ghcr.io/gilmanlab/headjack:base-v1.0.0 # Versioned
- Multi-architecture: linux/amd64 and linux/arm64
- Signing: Keyless signing with Cosign
- SBOM: SPDX JSON format, attested to the image
- Registry: GitHub Container Registry (ghcr.io)
Triggers on:
images/base/v*tags
Jobs:
- lint: Validates Dockerfiles with hadolint
- prepare: Extracts variant and version from tag
- build: Builds multi-arch images with Docker Bake
- sign: Signs images and attests SBOMs with Cosign
Defines components, release types, and changelog configuration:
{
"separate-pull-requests": true,
"packages": {
".": { "component": "cli", "include-component-in-tag": false },
"images/base": { "component": "images/base", "include-component-in-tag": true }
}
}Tracks current versions for each component:
{
".": "1.0.0",
"images/base": "1.0.0"
}Configures CLI builds, archives, and Homebrew cask publishing.
Defines Docker build targets and multi-platform configuration.
To force a specific version, add Release-As: to a commit message:
git commit -m "feat: major redesign
Release-As: 2.0.0"# Download and verify checksum
curl -LO https://github.com/GilmanLab/headjack/releases/download/v1.0.0/checksums.txt
curl -LO https://github.com/GilmanLab/headjack/releases/download/v1.0.0/headjack_1.0.0_darwin_arm64.tar.gz
sha256sum -c checksums.txt --ignore-missing
# Check version
hjk version# Verify image signature
cosign verify ghcr.io/gilmanlab/headjack:base \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp "github.com/GilmanLab/headjack"
# Verify SBOM attestation
cosign verify-attestation ghcr.io/gilmanlab/headjack:base \
--type spdxjson \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp "github.com/GilmanLab/headjack"- Ensure commits follow Conventional Commits format
- Check that commits touch files in the component's path
- Verify the
release-please.ymlworkflow ran successfully
Release-please uses file paths to attribute commits. Ensure your changes are in the correct directory:
- CLI: Root Go files (
*.go,internal/,cmd/) - Images:
images/base/
Use Release-As: X.Y.Z in a commit message to override automatic versioning.
- Check the workflow logs in GitHub Actions
- For CLI: Verify
HOMEBREW_TAP_TOKENsecret is set - For images: Check Docker build logs and registry permissions
| Secret | Used By | Purpose |
|---|---|---|
GITHUB_TOKEN |
All workflows | GitHub API access (automatic) |
HOMEBREW_TAP_TOKEN |
release.yml | Push to GilmanLab/tap repository |