This guide explains how to set up and maintain Homebrew distribution for the hostodo-cli.
- Go 1.24+
- Git
- GitHub account with repository access
- GoReleaser (
brew install goreleaser) - Homebrew (for testing)
Ensure your repository is set up correctly:
# Verify repository URL in go.mod
cat go.mod | grep module
# Should show: module github.com/hostodo/odo-cli/v2
# Ensure you're on GitHub
git remote -vbrew install goreleaser# Check if configuration is valid
goreleaser check
# Create a test/snapshot release (doesn't push to GitHub)
goreleaser release --snapshot --clean
# Check the generated files
ls -la dist/Update cmd/root.go to include version information:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var (
Version = "dev"
Commit = "none"
Date = "unknown"
)
var rootCmd = &cobra.Command{
Use: "hostodo",
Short: "Official CLI for managing Hostodo VPS instances",
Long: `Hostodo CLI allows you to manage your VPS instances from the command line.`,
Version: fmt.Sprintf("%s (commit: %s, built: %s)", Version, Commit, Date),
}
func Execute() error {
return rootCmd.Execute()
}
func init() {
// Add version template
rootCmd.SetVersionTemplate(`{{.Version}}`)
}GoReleaser can create a formula in the same repository:
- Update
.goreleaser.yml:
brews:
- name: hostodo
repository:
owner: hostodo
name: hostodo-cli
directory: Formula
# ... rest of config- Users install with:
brew install hostodo/hostodo-cli/hostodoThis is the standard Homebrew practice:
-
Create a new repository on GitHub named
homebrew-tap:- Go to https://github.com/hostodo
- Click "New repository"
- Name:
homebrew-tap(must start withhomebrew-) - Public visibility
- Initialize with README
-
Set up repository access:
- Create a Personal Access Token (PAT) with
reposcope - Go to: GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token with
repopermissions - Save the token securely
- Create a Personal Access Token (PAT) with
-
Add token to repository secrets:
- Go to hostodo-cli repository → Settings → Secrets and variables → Actions
- Click "New repository secret"
- Name:
TAP_GITHUB_TOKEN - Value: Your PAT
- Click "Add secret"
-
Update
.goreleaser.yml:
brews:
- name: hostodo
repository:
owner: hostodo
name: homebrew-tap
token: "{{ .Env.TAP_GITHUB_TOKEN }}"
# ... rest stays the same- Update GitHub Actions workflow (
.github/workflows/release.yml):
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}- Users install with:
brew tap hostodo/tap
brew install hostodoFollow Semantic Versioning:
vX.Y.Z(e.g., v1.2.3)- MAJOR version for incompatible API changes
- MINOR version for new features (backwards compatible)
- PATCH version for bug fixes
# Ensure you're on main branch and up to date
git checkout main
git pull origin main
# Create and push a tag
git tag -a v0.1.0 -m "Release v0.1.0"
git push origin v0.1.0
# GitHub Actions will automatically:
# 1. Build binaries for all platforms
# 2. Create a GitHub release
# 3. Upload binaries
# 4. Update Homebrew formula# Set GitHub token
export GITHUB_TOKEN="your_github_token"
export TAP_GITHUB_TOKEN="your_tap_token" # If using separate tap
# Create a tag
git tag -a v0.1.0 -m "Release v0.1.0"
git push origin v0.1.0
# Run GoReleaser
goreleaser release --cleanBefore creating a release:
- Update version in README badges
- Update CHANGELOG.md
- Test all commands locally
- Run tests:
go test ./... - Build locally:
make build - Commit all changes
- Push to main branch
After creating a release:
- Verify GitHub release was created
- Download and test binaries
- Test Homebrew installation
- Announce release (if applicable)
# Create a snapshot release (local only)
goreleaser release --snapshot --clean
# Test the binary
./dist/hostodo_darwin_arm64/hostodo --version
./dist/hostodo_darwin_arm64/hostodo --help# Test formula syntax
brew audit --formula Formula/hostodo.rb
# Test installation from local formula
brew install --build-from-source Formula/hostodo.rb
# Verify installation
which hostodo
hostodo --version
# Clean up
brew uninstall hostodo# If using separate tap
brew tap hostodo/tap
brew install hostodo
# Or directly
brew install hostodo/tap/hostodo
# Test
hostodo --version
hostodo --help
# Uninstall
brew uninstall hostodo
brew untap hostodo/tapError: "Git is in dirty state"
# Commit all changes
git status
git add .
git commit -m "your message"Error: "Token not found"
# Set GitHub token
export GITHUB_TOKEN="your_token"
export TAP_GITHUB_TOKEN="your_tap_token"Error: "Formula not found"
# Update Homebrew
brew update
# If using tap, ensure it's added
brew tap hostodo/tap
# Force refresh
brew untap hostodo/tap
brew tap hostodo/tapError: "Checksum mismatch"
- GoReleaser should handle this automatically
- If manual formula, calculate checksum:
shasum -a 256 your-binary.tar.gzEnsure ldflags are set correctly in .goreleaser.yml:
ldflags:
- -X github.com/hostodo/odo-cli/v2/cmd.Version={{.Version}}
- -X github.com/hostodo/odo-cli/v2/cmd.Commit={{.Commit}}
- -X github.com/hostodo/odo-cli/v2/cmd.Date={{.Date}}GoReleaser handles everything automatically. Just create a new tag.
If you change binary name, dependencies, or installation process:
- Update
.goreleaser.yml - Test with
goreleaser release --snapshot --clean - Review generated formula in
dist/ - Create release
If you need to manually update the formula in your tap:
# Clone the tap repository
git clone https://github.com/hostodo/homebrew-tap.git
cd homebrew-tap
# Edit Formula/hostodo.rb
# Update version, URL, sha256
# Test locally
brew install --build-from-source Formula/hostodo.rb
# Commit and push
git add Formula/hostodo.rb
git commit -m "Update hostodo formula to v0.2.0"
git push origin main-
Always test locally first
- Use
--snapshotflag to test without publishing - Test installation from generated binaries
- Use
-
Use semantic versioning
- Clear version numbers help users understand changes
- Follow semver.org guidelines
-
Write good release notes
- GoReleaser auto-generates from git commits
- Use conventional commits (feat:, fix:, etc.)
-
Keep formula simple
- Let GoReleaser handle formula generation
- Only customize if necessary
-
Monitor installations
- Check GitHub release downloads
- Monitor issues related to installation
If you encounter issues:
- Check the Troubleshooting section
- Review GoReleaser logs in GitHub Actions
- Open an issue on GitHub
- Contact the development team