release-sidecar

star 1.0k

Release new versions of sidecar. Covers version tagging with semver, td dependency updates, go.mod validation, CHANGELOG updates, GoReleaser automation, Homebrew tap updates, and verification steps. Use when preparing or executing a release.

marcus By marcus schedule Updated 2/10/2026

name: release-sidecar description: Release new versions of sidecar. Covers version tagging with semver, td dependency updates, go.mod validation, CHANGELOG updates, GoReleaser automation, Homebrew tap updates, and verification steps. Use when preparing or executing a release. disable-model-invocation: true

Releasing a New Version

Prerequisites

  • Go installed matching go.mod version
  • Clean working tree (git status shows no changes)
  • All tests passing (go test ./...)
  • GitHub CLI authenticated (gh auth status)
  • No replace directives in go.mod
  • GoReleaser configured (.goreleaser.yml in repo root)
  • HOMEBREW_TAP_TOKEN secret exists in GitHub repo settings

Beware of go.work: A parent go.work file can silently use local dependencies instead of published versions. Always use GOWORK=off when updating dependencies and testing builds.

Release Process

1. Determine Version

Follow semantic versioning:

  • Major (v2.0.0): Breaking changes
  • Minor (v0.2.0): New features, backward compatible
  • Patch (v0.1.1): Bug fixes only
git tag -l | sort -V | tail -1

2. Update td Dependency

Sidecar embeds td as a Go module. Always update to latest before releasing:

GOWORK=off go get github.com/marcus/td@latest
GOWORK=off go mod tidy

3. Verify go.mod

Ensure no replace directives (they break go install):

grep replace go.mod && echo "ERROR: Remove replace directives before releasing!" && exit 1

4. Verify Build Without go.work

GOWORK=off go build ./...

If this fails with "undefined" errors, the required dependency version hasn't been published yet.

5. Update CHANGELOG.md

## [vX.Y.Z] - YYYY-MM-DD

### Features
- New feature description

### Bug Fixes
- Fix description

### Dependencies
- Dependency update description
git add CHANGELOG.md
git commit -m "docs: Update changelog for vX.Y.Z"

6. Create and Push Tag

git tag vX.Y.Z -m "Brief description of release"
git push origin main && git push origin vX.Y.Z

7. GitHub Release (Automated)

Pushing the tag triggers GitHub Actions GoReleaser, which:

  • Creates the GitHub Release with changelog
  • Builds and attaches binaries for darwin/linux (amd64/arm64)
  • Generates checksums

⚠️ GoReleaser does NOT update the Homebrew tap automatically. The tap uses source-build formulas (to avoid macOS Gatekeeper warnings on pre-built binaries), which GoReleaser doesn't support. You MUST manually update the tap.

7b. Update Homebrew Tap (REQUIRED — Manual Step)

The Homebrew tap at marcus/homebrew-tap must be updated for every release. If you skip this, users will see "update available" but brew upgrade won't find it (see #122).

# Get the source tarball SHA256
curl -sL "https://github.com/marcus/sidecar/archive/refs/tags/vX.Y.Z.tar.gz" | shasum -a 256

# Edit the formula (local tap is at /opt/homebrew/Library/Taps/marcus/homebrew-tap/)
# Update: url (tag version) and sha256
cd /opt/homebrew/Library/Taps/marcus/homebrew-tap
# Edit Formula/sidecar.rb — update version in URL and sha256

# Commit and push
git add Formula/sidecar.rb
git commit -m "sidecar: bump to vX.Y.Z"
git push

Also bump td and nightshift formulas if releasing those.

8. Verify

# Check workflow succeeded
gh run list --workflow=release.yml --limit=1

# Check release exists with binaries
gh release view vX.Y.Z

# Test Homebrew install
brew install marcus/tap/sidecar
sidecar --version

# Test go install (critical!)
GOWORK=off go install github.com/marcus/sidecar/cmd/sidecar@vX.Y.Z
sidecar --version
# Should output: sidecar version vX.Y.Z

# Test update notification
go build -ldflags "-X main.Version=v0.0.1" -o /tmp/sidecar-test ./cmd/sidecar
/tmp/sidecar-test
# Should show toast: "Update vX.Y.Z available!"

Version in Binaries

Version is embedded at build time via ldflags:

go build -ldflags "-X main.Version=v0.2.0" ./cmd/sidecar
go install -ldflags "-X main.Version=v0.2.0" ./cmd/sidecar

Without ldflags, version falls back to:

  1. Go module version (if installed via go install)
  2. Git revision (devel+abc123)
  3. devel

Update Mechanism

On startup, sidecar checks https://api.github.com/repos/marcus/sidecar/releases/latest, compares tag_name against current version, and shows a toast if newer. Results cached for 3 hours. Pre-release suffixes (-rc1, -beta) are stripped for comparison. Dev versions skip the check.

Recovery: Fixing a Bad Release

  1. Publish a new patch release with fixes
  2. For critical bugs, release immediately
  3. Delete unpublished GitHub release: gh release delete vX.Y.Z
  4. Keep git tags to preserve history
  5. If GoReleaser workflow fails, re-run locally: goreleaser release --clean

Install Methods

  1. Setup script: curl -fsSL https://raw.githubusercontent.com/marcus/sidecar/main/setup.sh | bash
  2. Homebrew: brew install marcus/tap/sidecar
  3. Download binary: from GitHub Releases page
  4. From source: go install github.com/marcus/sidecar/cmd/sidecar@latest

Checklist

  • Tests pass
  • Working tree clean
  • td dependency updated (GOWORK=off go get github.com/marcus/td@latest)
  • No replace directives in go.mod
  • Build works without go.work (GOWORK=off go build ./...)
  • CHANGELOG.md updated
  • Version follows semver
  • Tag created and pushed
  • GitHub Actions workflow completed
  • Binaries attached to release
  • Homebrew tap updated (MANUAL — see step 7b, GoReleaser does NOT do this)
  • Installation verified (GOWORK=off go install ...@vX.Y.Z)
  • Update notification verified
Install via CLI
npx skills add https://github.com/marcus/sidecar --skill release-sidecar
Repository Details
star Stars 1,027
call_split Forks 77
navigation Branch main
article Path SKILL.md
More from Creator