This guide explains how to release a new version of proj.
- Git repository access
- Go 1.24+ installed locally
- A GitHub account with push access to the repository
- Commitizen installed (
pipx install commitizen)
The project includes an automated release script that handles version bumping, changelog generation, and tag creation using commitizen.
# Test the release (dry-run mode)
make release-dry-run
# OR
./scripts/release.sh --dry-run
# Create the actual release
make release
# OR
./scripts/release.shThe release.sh script automates the entire release process:
-
Validates Git State
- Checks for uncommitted changes (fails if any exist)
- Confirms you're on the
mainbranch - Shows warning if on a different branch
-
Analyzes Commits
- Uses commitizen to analyze conventional commits since last release
- Groups commits by type: feat, fix, refactor, ci, docs, chore
- Shows commit breakdown with counts
-
Determines Version Bump
- MAJOR (1.0.0): Breaking changes with
BREAKING CHANGE:footer - MINOR (0.x.0): New features with
feat:prefix - PATCH (0.0.x): Bug fixes with
fix:prefix - Other commit types (ci, refactor, docs) don't trigger bumps
- MAJOR (1.0.0): Breaking changes with
-
Generates Changelog
- Creates/updates
CHANGELOG.mdautomatically - Groups changes by type (Feat, Fix, Refactor, etc.)
- Includes commit messages and dates
- Creates/updates
-
Creates and Pushes Tag
- Creates an annotated git tag with the new version
- Pushes tag to GitHub
- Triggers GitHub Actions release workflow
$ ./scripts/release.sh --dry-run
🚀 Starting release process...
📋 Current version: v0.9.2
📝 Recent commits since last release:
5be0803 feat: add automated release script with commitizen
8bb64ed refactor: remove unused dimStyle variable
2ada360 refactor: remove unused actionDescStyle variable
7fa6bd8 fix: handle file.Close errors in script detection
📊 Analyzing commits...
Found 15 commits since last release
Commit breakdown:
5 ci
3 refactor
3 fix
2 feat
1 docs
1 chore
🔍 DRY RUN MODE - No changes will be made
Would run: cz bump --changelog
bump: version 0.9.2 → 0.10.0
tag to create: v0.10.0
increment detected: MINOR# Show help
./scripts/release.sh --help
# Test without making changes
./scripts/release.sh --dry-run
# Execute the release
./scripts/release.shRelease settings are configured in .cz.toml:
[tool.commitizen]
name = "cz_conventional_commits"
version = "0.9.2"
tag_format = "v$version"
version_files = [".cz.toml:version"]
update_changelog_on_bump = true
changelog_file = "CHANGELOG.md"
changelog_incremental = true
changelog_start_rev = "v0.9.2"Ensure all changes are:
- Committed to the
mainbranch - Tested locally with
make test - Documented in
CHANGELOG.md
Example:
git log --oneline origin/main..main # Review commits to be released
make test # Run testsUpdate the version in CHANGELOG.md at the top with:
- New version number (following Semantic Versioning)
- Release date
- Summary of changes
Example CHANGELOG.md entry:
## [v0.9.0] - 2026-01-19
### Added
- New cmd/proj entry point with full CLI support
- Release automation with GitHub Actions
- Binary distribution for Linux and macOS
### Fixed
- Installation script now validates downloaded binaries
- Fixed .gitignore to allow cmd/proj source files
### Changed
- Release workflow now uploads raw binaries instead of tarballsUse semantic versioning (e.g., v1.0.0, v0.9.0, v0.8.1-beta).
# Create an annotated tag with release notes
git tag -a v0.9.0 -m "Release v0.9.0
- Added CLI entry point
- Automated release pipeline
- See CHANGELOG.md for details"
# Push the tag to GitHub
git push origin v0.9.0Important: The tag must start with v and be a valid semantic version.
Once you push the tag, the release workflow automatically:
- Detects the new release tag
- Builds binaries for all supported platforms:
proj-linux-amd64proj-linux-arm64proj-darwin-amd64(macOS Intel)proj-darwin-arm64(macOS Apple Silicon)
- Creates SHA256 checksums for each binary
- Uploads assets to the GitHub release page
Monitor the workflow:
- Go to: https://github.com/s33g/proj/actions
- Look for the release workflow run for your tag
- Check that all build jobs completed successfully
Once the workflow completes:
# View the release on GitHub
open https://github.com/s33g/proj/releases/tag/v0.9.0
# Download and test a binary
curl -L https://github.com/s33g/proj/releases/download/v0.9.0/proj-linux-amd64 \
-o /tmp/proj-test && chmod +x /tmp/proj-test && /tmp/proj-test --versionVerify that the new installation script works with the released binary:
# Run install script (it will download the latest release)
bash <(curl -sSL https://raw.githubusercontent.com/s33g/proj/main/scripts/install.sh)
# Test the installed binary
proj --version
# Verify it can detect projects
proj --init
proj --set-path ~/code
proj --listFollow Semantic Versioning:
- MAJOR (v1.0.0): Breaking changes to API or CLI
- MINOR (v0.9.0): New features, backwards compatible
- PATCH (v0.8.1): Bug fixes only
Examples:
v1.0.0- First stable releasev0.9.0- New features during developmentv0.8.1- Bug fix for v0.8.0v0.9.0-beta- Pre-release version (optional)
Keep CHANGELOG.md organized with:
- Version and date in heading
- Subsections: Added, Changed, Fixed, Removed, Deprecated
- Bullet points with brief descriptions
- Reference issue/PR numbers if applicable
Example:
## [v0.9.0] - 2026-01-19
### Added
- CLI entry point with --version, --help, --init commands (#42)
- Automated release pipeline with multi-platform builds
### Fixed
- Installation script now validates downloaded binaries (#41)
- Fixed binary upload format in release workflow
### Changed
- Release assets now include raw binaries (was tarballs)Check the GitHub Actions logs:
- Visit https://github.com/s33g/proj/actions
- Click the failed workflow run
- Review build logs for errors (usually Go compilation or missing dependencies)
Common causes:
- Go version mismatch (requires 1.24+)
- Missing
cmd/proj/main.goentry point - Syntax errors in code
Verify:
- Workflow completed successfully (check Actions tab)
- Tag name starts with
v(e.g.,v0.9.0) softprops/action-gh-release@v2has correctfiles:configuration
Check that:
- Binary was uploaded to the release (visit GitHub release page)
- Binary name matches what script expects:
proj-linux-amd64,proj-darwin-arm64, etc. - HTTP status code check in install.sh is working (should see "HTTP 200")
If GitHub Actions is unavailable:
# Build all platforms locally
make build-all VERSION=v0.9.0
# Create a release draft on GitHub
open https://github.com/s33g/proj/releases/new
# Upload binaries and checksums manually
# Then publish the releaseAfter a successful release:
- Update main branch with any version bumps or release notes
- Announce on relevant channels (social media, forums, etc.)
- Monitor issues for bug reports from the new release
- Plan next iteration based on feedback
The release pipeline is defined in .github/workflows/release.yml.
Triggered by: Creating a GitHub Release with a v* tag
Steps:
- Checkout code
- Setup Go 1.24
- Build binary for each platform
- Generate SHA256 checksums
- Upload assets to GitHub release
Matrix builds for:
- linux-amd64, linux-arm64
- darwin-amd64, darwin-arm64
Build time: ~2-3 minutes total
- Tags are signed commits recommended (not required)
- SHA256 checksums provided for verification
- GitHub Actions are pinned to specific versions
To verify a downloaded binary:
# Download checksum
curl -L https://github.com/s33g/proj/releases/download/v0.9.0/proj-linux-amd64.sha256 \
-o proj-linux-amd64.sha256
# Verify download
sha256sum -c proj-linux-amd64.sha256
# Expected output: proj-linux-amd64: OKSee CONTRIBUTING.md for development setup and contribution guidelines.