Everything you need to know about releasing A.R.C. CLI
📚 Table of Contents
- Quick Reference
- Branch Naming Conventions
- Release Workflows
- GoReleaser Configuration
- Step-by-Step Guides
- Local Testing
- Troubleshooting
# Local Testing
make release-check # Validate GoReleaser config
make release-test # Test build (current platform)
make release-build # Build all platforms locally
make release-snapshot # Full dry-run (no publish)
# Main Release (Stable)
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
# → Creates stable release automatically
# Feature Release (Pre-release) - Specify Convention
git checkout -b 042-awesome-feature
git push origin 042-awesome-feature
# → Creates pre-release automatically
# Feature Release (Pre-release) - Legacy Convention
git checkout -b feature/awesome-feature
git push origin feature/awesome-feature
# → Creates pre-release automatically
# Beta/Alpha Release
git tag -a v1.0.0-beta1 -m "Beta 1"
git push origin v1.0.0-beta1
# → Creates pre-release automaticallyA.R.C. CLI supports two branch naming conventions:
Format: ###-feature-name (3 digits, dash, name)
# Examples:
001-initial-setup
042-add-authentication
099-refactor-database
123-fix-memory-leakBenefits:
- ✅ Matches
.specifyworkflow tooling - ✅ Easy to track feature progression
- ✅ Multiple branches can work on same spec (e.g.,
042-fix-bug,042-add-tests) - ✅ Automatically organized in specs/ directory
When to use:
- Following Spec-Driven Development workflow
- Working with
.specifytools - Need numbered feature tracking
Format: feature/* or feat/*
# Examples:
feature/add-authentication
feature/new-ui-dashboard
feat/optimize-queries
feat/add-loggingWhen to use:
- Migrating from existing projects
- Quick feature branches without spec tracking
- Teams not using
.specifyworkflow
The feature-release workflow triggers on:
branches:
- '[0-9][0-9][0-9]-*' # Specify convention: 001-feature
- 'feature/**' # Legacy: feature/name
- 'feat/**' # Legacy: feat/name| Use Case | Recommended Convention |
|---|---|
| New projects using .specify | ###-feature-name ⭐ |
| Existing projects | feature/* or feat/* |
| Bug fixes in spec | ###-fix-description |
| Experiments/prototypes | feature/experiment-name |
A.R.C. CLI has two automated release workflows:
File: .github/workflows/release.yml
# Push any tag matching v*
git push origin v1.0.0
git push origin v0.5.2
git push origin v2.0.0-final # Still works but not recommended- ✅ Checkout code with full git history
- ✅ Setup Go (version from go.mod)
- ✅ Run
goreleaser release --clean - ✅ Build binaries for 6 platforms:
- Linux (amd64, arm64)
- macOS (amd64/Intel, arm64/Apple Silicon)
- Windows (amd64, arm64)
- ✅ Create official GitHub release
- ✅ Upload binaries with SHA256 checksums
- ✅ Auto-generate changelog from commits
- ✅ Mark as stable release (green checkmark)
📦 Release: github.com/arc-framework/arc-cli/releases/tag/v1.0.0
✓ Status: Stable
📥 Downloads: 6 platform binaries + checksums.txt
File: .github/workflows/feature-release.yml
A. Specify Convention Branches:
git push origin 001-initial-setup
git push origin 042-add-auth
git push origin 123-refactor-codeB. Legacy Convention Branches:
git push origin feature/new-dashboard
git push origin feat/api-endpointsC. Pre-release Tags:
git push origin v1.0.0-beta1
git push origin v0.5.0-alpha3
git push origin v2.0.0-rc2- ✅ Checkout code with full git history
- ✅ Setup Go (version from go.mod)
- ✅ Run
goreleaser release --snapshot --skip=publish - ✅ Build snapshot binaries (no version tag required)
- ✅ Create pre-release with auto-generated tag:
- Branch:
feature-042-add-auth-abc1234567 - Tag:
feature-v1.0.0-beta1-abc1234567
- ✅ Upload binaries with checksums
⚠️ Mark as pre-release (yellow badge)
📦 Release: github.com/arc-framework/arc-cli/releases/tag/feature-042-add-auth-abc1234567
⚠️ Status: Pre-release
📥 Downloads: 6 platform binaries + checksums.txt
💬 Note: Includes installation instructions
| Aspect | Main Release | Feature Release |
|---|---|---|
| Trigger | v* tags (e.g., v1.0.0) |
###-*, feature/**, feat/** branches or v*-beta/alpha/rc tags |
| Command | goreleaser release --clean |
goreleaser release --snapshot --skip=publish |
| Version | From git tag (v1.0.0) | Snapshot (no version injection) |
| Release Tag | v1.0.0 |
feature-{branch}-{sha} |
| Status | Stable ✓ | Pre-release |
| Changelog | Full, auto-generated, grouped | Commit message only |
| Audience | Production users | Testers, developers, early adopters |
| Permanence | Keep forever (version history) | Clean up after merge |
| Platform Binaries | 6 (all OS/arch) | 6 (all OS/arch) |
git checkout main
git add .
git commit -m "Fix typo in documentation"
git push origin main
# Result: No workflow triggered ✓# Create numbered feature branch
git checkout -b 042-add-authentication
# ... make changes ...
git add .
git commit -m "Add OAuth2 authentication"
git push origin 042-add-authentication
# Result:
# ✓ feature-release.yml triggers
# ✓ Creates: feature-042-add-authentication-abc1234567 (pre-release)
# ✓ Share with testers for feedback# Create legacy feature branch
git checkout -b feature/new-dashboard
# ... make changes ...
git push origin feature/new-dashboard
# Result:
# ✓ feature-release.yml triggers
# ✓ Creates: feature-feature/new-dashboard-abc1234567 (pre-release)git tag -a v2.0.0-beta1 -m "First beta for v2.0.0"
git push origin v2.0.0-beta1
# Result:
# ✓ feature-release.yml triggers
# ✓ Creates: feature-v2.0.0-beta1-abc1234567 (pre-release)
# ✓ Early adopters can testgit tag -a v2.0.0 -m "Official v2.0.0 release"
git push origin v2.0.0
# Result:
# ✓ release.yml triggers
# ✓ Creates: v2.0.0 (stable)
# ✓ Production users downloadFile: .goreleaser.yaml
Both workflows use the same GoReleaser configuration:
- Main Release: Full release mode
- Feature Release: Snapshot mode (
--snapshot --skip=publish)
builds:
- main: ./cmd/arc/main.go # Entry point
binary: arc # Output binary name
env:
- CGO_ENABLED=0 # Static binaries (no C deps)
goos: [linux, windows, darwin]
goarch: [amd64, arm64]ldflags:
- -s -w # Strip debug info
- -X github.com/arc-framework/arc-cli/internal/version.Version={{.Version}}
- -X github.com/arc-framework/arc-cli/internal/version.GitCommit={{.Commit}}
- -X github.com/arc-framework/arc-cli/internal/version.BuildDate={{.Date}}Injects into internal/version/version.go:
Version: Git tag (e.g.,v1.0.0)GitCommit: Full commit hashBuildDate: Build timestamp
archives:
- name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
formats: [tar.gz, zip]
files:
- LICENSE
- README.md
- docs/**/*Output Example: arc_v1.0.0_Darwin_x86_64.tar.gz
changelog:
groups:
- title: 'New Features'
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
- title: 'Bug Fixes'
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'Auto-generates grouped changelog from conventional commits.
# macOS
brew install goreleaser
# Linux (snap)
sudo snap install --classic goreleaser
# Go install
go install github.com/goreleaser/goreleaser/v2@latest# Check if .goreleaser.yaml is valid
goreleaser check
# Or using make
make release-check# Step 1: Create feature branch (Specify convention)
git checkout -b 001-my-first-feature
# Step 2: Make your changes
echo "new feature" > feature.txt
git add feature.txt
git commit -m "feat: add my first feature"
# Step 3: Push to trigger release
git push origin 001-my-first-feature
# Step 4: Wait ~2-5 minutes for GitHub Actions
# Step 5: Check the release
# Visit: https://github.com/arc-framework/arc-cli/releases
# You'll see: feature-001-my-first-feature-{sha} (pre-release)
# Step 6: Download and test
curl -sfL https://github.com/arc-framework/arc-cli/releases/download/feature-001-my-first-feature-{sha}/arc_*_Darwin_arm64.tar.gz | tar xz
./arc --version
# Step 7: Clean up after merge
git checkout main
git merge 001-my-first-feature
git push origin main
git push origin --delete 001-my-first-feature
# Manually delete the pre-release on GitHub# Step 1: Ensure you're on main and up-to-date
git checkout main
git pull origin main
# Step 2: Run pre-release checks
make test # All tests pass
make fmt # Code is formatted
make vet # No vet warnings
make release-check # GoReleaser config valid
# Step 3: Test build locally (optional)
make release-snapshot
# Step 4: Create the version tag
git tag -a v0.1.0 -m "Initial release
Features:
- CLI framework with Cobra
- Beautiful UI with lipgloss
- Theming system
- Version command
"
# Step 5: Push the tag
git push origin v0.1.0
# Step 6: Monitor GitHub Actions
# Visit: https://github.com/arc-framework/arc-cli/actions
# Wait for "Release" workflow to complete
# Step 7: Verify the release
# Visit: https://github.com/arc-framework/arc-cli/releases/tag/v0.1.0
# Download and test the binaries
# Step 8: Test installation
curl -sfL https://github.com/arc-framework/arc-cli/releases/download/v0.1.0/arc_0.1.0_Darwin_arm64.tar.gz | tar xz
./arc --version
# Should output: A.R.C. CLI 0.1.0 (built 2025-12-19, commit abc123...)# Step 1: Prepare beta code on main
git checkout main
# ... make changes ...
git commit -m "feat: prepare v1.0.0 beta"
git push origin main
# Step 2: Create beta tag
git tag -a v1.0.0-beta1 -m "Beta 1 for v1.0.0
Testing:
- New authentication system
- Updated UI theme
- Performance improvements
"
# Step 3: Push beta tag
git push origin v1.0.0-beta1
# Step 4: GitHub Actions creates pre-release
# Tag: feature-v1.0.0-beta1-{sha}
# Status: Pre-release
# Step 5: Share with testers
# Send them: https://github.com/arc-framework/arc-cli/releases
# Step 6: After testing, create stable release
git tag -a v1.0.0 -m "Official v1.0.0 release"
git push origin v1.0.0Test builds locally without creating releases:
make release-test
# Or manually:
goreleaser build --snapshot --clean --single-target
# Output: dist/{platform}/arcmake release-build
# Or manually:
goreleaser build --snapshot --clean
# Output: dist/{linux,darwin,windows}_{amd64,arm64}/arcmake release-snapshot
# Or manually:
goreleaser release --snapshot --clean --skip=publish
# Output: Complete dist/ structure with archives and checksums# Build with version
make build-release
# Check version
./arc --version
# Should show: A.R.C. CLI 0.0.1 (built 2025-12-19, commit abc123)All releases: https://github.com/arc-framework/arc-cli/releases
Latest stable: https://github.com/arc-framework/arc-cli/releases/latest
Specific version: https://github.com/arc-framework/arc-cli/releases/tag/v1.0.0
Pre-releases: (look for yellow "Pre-release" badge)
# List all releases
gh release list
# View latest release
gh release view
# View specific release
gh release view v1.0.0
# Download latest stable
gh release download
# Download specific version
gh release download v1.0.0
# Download pre-release
gh release download feature-042-add-auth-abc1234567# Latest stable (auto-redirects)
curl -sfL https://github.com/arc-framework/arc-cli/releases/latest/download/arc_*_Darwin_arm64.tar.gz | tar xz
# Specific version
curl -sfL https://github.com/arc-framework/arc-cli/releases/download/v1.0.0/arc_1.0.0_Darwin_arm64.tar.gz | tar xz
# Pre-release (need full tag)
curl -sfL https://github.com/arc-framework/arc-cli/releases/download/feature-042-auth-abc123/arc_*_Darwin_arm64.tar.gz | tar xz# List all releases
gh release list
# Delete specific pre-release
gh release delete feature-001-old-feature-abc123
# Delete with tag
git push origin --delete feature-001-old-feature-abc123
# Or via GitHub web interface:
# Releases → Click pre-release → Delete releaseNever delete stable releases (v1.0.0, v2.0.0, etc.) - these are your version history.
# After merging feature branch to main
git checkout main
git merge 001-add-feature
git push origin main
# Delete the branch
git branch -d 001-add-feature
git push origin --delete 001-add-feature
# Delete the pre-release manually on GitHub
# The tag will remain until manually deletedSymptom:
goreleaser: command not found
Solution:
# macOS
brew install goreleaser
# Linux
sudo snap install --classic goreleaser
# Go install
go install github.com/goreleaser/goreleaser/v2@latestSymptom: Pushed feature branch but no release created
Check:
-
Branch name matches pattern?
# Should match one of: 001-feature-name # Specify convention ✓ feature/feature-name # Legacy ✓ feat/feature-name # Legacy ✓ my-branch # ✗ Won't trigger
-
Workflow file exists?
ls -la .github/workflows/feature-release.yml
-
Check GitHub Actions tab:
https://github.com/arc-framework/arc-cli/actions -
Workflow enabled?
- Go to Settings → Actions → General
- Ensure "Allow all actions" is selected
Symptom:
git doesn't contain any tags - either add a tag or use --snapshot
Solution:
Tag must start with v:
# ✗ Wrong
git tag 1.0.0
git tag release-1.0.0
# ✓ Correct
git tag v1.0.0
git tag v0.1.0Symptom:
error: dirty working directory
Solution: Commit all changes before tagging:
git status
git add .
git commit -m "prepare release"
git tag v1.0.0
git push origin v1.0.0Symptom:
GITHUB_TOKEN environment variable not set
Solution:
# Create token: https://github.com/settings/tokens
# Scopes needed: repo, write:packages
export GITHUB_TOKEN="ghp_your_token_here"
goreleaser release --cleanNote: GitHub Actions automatically provides GITHUB_TOKEN - no setup needed.
Symptom:
./arc --version
# Output: A.R.C. CLI 0.0.1-dev (built 2025-12-19, commit )Causes:
- Built with
go buildinstead of GoReleaser - ldflags paths are wrong
Solution:
# Use GoReleaser or make
make release-test
# Or use build-release target
make build-release
# Check version
./arc --version
# Should show commit hash nowSymptom:
configuration is invalid
Solution:
# Validate config
goreleaser check
# Common issues:
# 1. YAML indentation
# 2. Deprecated fields
# 3. Invalid template syntax
# Fix and re-validate
vim .goreleaser.yaml
goreleaser checkSymptom:
build for darwin/arm64 failed
Solution:
-
Check ignore patterns:
# In .goreleaser.yaml ignore: - goos: darwin goarch: "386" # Correct
-
Test locally:
GOOS=darwin GOARCH=arm64 go build ./cmd/arc
-
Check dependencies:
go mod tidy go mod verify
- ✅ Test thoroughly before tagging
- ✅ Follow Semantic Versioning:
v1.0.0- Major (breaking changes)v0.1.0- Minor (new features)v0.0.1- Patch (bug fixes)
- ✅ Use descriptive tag messages:
git tag -a v1.0.0 -m "Release v1.0.0 Features: - Add authentication system - Improve performance by 50% Breaking Changes: - Renamed config file from .arc to arc.yaml Bug Fixes: - Fixed memory leak in worker pool "
- ✅ Test binaries after release
- ✅ Update documentation if needed
- ✅ Announce the release (blog, Twitter, etc.)
- ✅ Use for testing and feedback only
- ✅ Use Specify convention (
###-name) for better tracking - ✅ Clean up old pre-releases after merge
- ✅ Include clear descriptions in commit messages
⚠️ Don't use in production- ✅ Share download links with testers
- ✅ Document known issues in release notes
- ✅ Specify convention for spec-driven features:
042-add-auth - ✅ Legacy convention for quick features:
feature/quick-fix - ✅ Be descriptive:
042-add-oauth2-authenticationnot042-stuff - ✅ Use lowercase and hyphens:
feature/add-new-uinotfeature/Add_New_UI - ✅ Keep it short but meaningful
Do you want to release?
│
├─ YES → Is it production-ready?
│ │
│ ├─ YES → Create stable release
│ │ git tag -a v1.0.0 -m "Release"
│ │ git push origin v1.0.0
│ │
│ └─ NO → Need testing?
│ │
│ ├─ Public beta → Create beta tag
│ │ git tag -a v1.0.0-beta1 -m "Beta"
│ │ git push origin v1.0.0-beta1
│ │
│ └─ Internal test → Push feature branch
│ git push origin 042-feature
│
└─ NO → Just developing?
git push origin main
(no release created)
| Want to... | Do this... | Result |
|---|---|---|
| Develop normally | git push origin main |
No release |
| Test a feature (Specify) | git push origin 042-feature |
Pre-release |
| Test a feature (Legacy) | git push origin feature/name |
Pre-release |
| Beta release | git push origin v1.0.0-beta1 |
Pre-release |
| Stable release | git push origin v1.0.0 |
Stable release |
| Build locally | make release-test |
Local binary |
| Validate config | make release-check |
Check only |
- GoReleaser Docs: https://goreleaser.com/
- GitHub Actions: https://docs.github.com/en/actions
- Semantic Versioning: https://semver.org/
- Conventional Commits: https://www.conventionalcommits.org/
Before creating a stable release:
- All tests pass (
make test) - Code is formatted (
make fmt) - No vet warnings (
make vet) - GoReleaser config valid (
make release-check) - Version number follows semantic versioning
- Changelog/release notes prepared
- Documentation updated
- Local build test successful (
make release-snapshot) - Tag message is descriptive
- Ready to announce
Happy Releasing! 🎉
Last Updated: December 27, 2025