| # Release Process |
|
|
| **β οΈ CRITICAL:** The npm package depends on Go binaries being in the GitHub release. The release pipeline will fail hard if goreleaser doesn't upload binaries β npm users won't get a working binary. |
|
|
| Pinchtab uses an automated CI/CD pipeline triggered by Git tags. When you push a tag like `v0.7.0`, GitHub Actions: |
|
|
| 1. **Builds Go binaries** β darwin-arm64, darwin-x64, linux-x64, linux-arm64, windows-x64 |
| 2. **Creates GitHub release** β with checksums.txt for integrity verification |
| 3. **Publishes to npm** β TypeScript SDK with auto-download postinstall script |
| 4. **Builds Docker images** β linux/amd64, linux/arm64 |
|
|
| ## Prerequisites |
|
|
| ### Secrets (configure once in GitHub) |
|
|
| Go to **Settings β Secrets and variables β Actions** and add: |
|
|
| - **NPM_TOKEN** β npm authentication token |
| - Create at https://npmjs.com/settings/~/tokens |
| - Scope: `automation` (publish + read) |
| |
| - **DOCKERHUB_USER** β Docker Hub username (if using Docker Hub) |
| - **DOCKERHUB_TOKEN** β Docker Hub personal access token |
| |
| ### Local setup |
| |
| ```bash |
| # 1. Ensure main branch is up to date |
| git checkout main && git pull origin main |
| |
| # 2. Merge feature branches |
| # (all features should be on main before tagging) |
| |
| # 3. Verify version consistency |
| cat package.json | jq .version # npm package |
| cat go.mod | grep "module" # Go module |
| git describe --tags # latest tag |
| ``` |
| |
| ## Pre-Release Checklist |
| |
| Goreleaser is already configured correctly. Verify before tagging: |
| |
| ```bash |
| # 1. Check builds section (compiles for all platforms) |
| grep -A 8 "^builds:" .goreleaser.yml |
| # Should output: linux/darwin/windows + amd64/arm64 |
| |
| # 2. Check archives use binary format (required for npm) |
| grep -A 5 "^archives:" .goreleaser.yml |
| # Should show: format: binary (not tar/zip) |
| |
| # 3. Verify checksums enabled |
| grep "checksum:" .goreleaser.yml |
| # Should output: name_template: checksums.txt |
| |
| # 4. Check release config |
| grep -A 2 "^release:" .goreleaser.yml |
| # Should output: GitHub owner/repo |
| ``` |
| |
| **Configuration status:** |
| - β
`builds:` section compiles all platforms (darwin-arm64, darwin-amd64, linux-arm64, linux-amd64, windows-amd64, windows-arm64) |
| - β
`archives:` outputs binaries directly: `pinchtab-darwin-arm64`, `pinchtab-linux-x64`, etc. |
| - β
`checksum:` generates `checksums.txt` (used by npm postinstall verification) |
| - β
`release:` points to GitHub (uploads everything automatically) |
|
|
| **Ready to release.** Just tag and push. |
|
|
| ## Releasing |
|
|
| ### For patch/minor versions (recommended) |
|
|
| ```bash |
| # 1. Bump version in all places |
| npm version patch # or minor, major |
| git push origin main |
| |
| # 2. Create tag |
| git tag v0.7.1 |
| git push origin v0.7.1 |
| ``` |
|
|
| ### For manual releases |
|
|
| ```bash |
| # 1. Tag directly |
| git tag -a v0.7.1 -m "Release v0.7.1" |
| git push origin v0.7.1 |
| |
| # 2. Or via GitHub UI: Releases β Create from tag |
| # (workflow will auto-create if not present) |
| ``` |
|
|
| ### Using workflow_dispatch (manual trigger) |
| |
| If you need to re-release an existing tag: |
| |
| 1. Go to **Actions β Release** |
| 2. **Run workflow** |
| 3. Enter tag (e.g. `v0.7.1`) |
| |
| For a no-side-effects dry run from `main` or any other ref: |
| |
| 1. Go to **Actions β Release** |
| 2. **Run workflow** |
| 3. Leave `tag` empty |
| 4. Set `ref` to the branch, tag, or commit you want to test |
| 5. Set `dry_run` to `true` |
|
|
| Dry-run behavior: |
| - GoReleaser runs in snapshot mode, so artifacts are built but not published |
| - npm runs `npm publish --dry-run` |
| - Docker runs a multi-arch `buildx` build with `push=false` |
| - ClawHub skill publishing is not part of this workflow and is therefore skipped |
|
|
| ## Pipeline details |
|
|
| ### 1. Goreleaser (Go binary) β CRITICAL for npm |
|
|
| Triggered on `v*` tag push. Builds binaries and creates GitHub release. |
|
|
| **What it does:** |
| - β
Compiles for all platforms (darwin-arm64, darwin-x64, linux-x64, linux-arm64, windows-x64) |
| - β
Generates `checksums.txt` (SHA256) |
| - β
**Uploads binaries to GitHub Releases** β Required by npm postinstall! |
| - Also: Docker images, changelog, etc. |
|
|
| **β οΈ CRITICAL:** npm postinstall script downloads binaries from GitHub Releases. If the release doesn't have the binaries (e.g., only Docker images), `npm install pinchtab` will fail silently and the binary won't be available. |
|
|
| **Configured in:** `.goreleaser.yml` |
|
|
| **Verify release has binaries:** |
| ```bash |
| curl -s https://api.github.com/repos/pinchtab/pinchtab/releases/v0.7.0 | jq '.assets[].name' |
| # Should output: pinchtab-darwin-arm64, pinchtab-darwin-x64, etc. |
| ``` |
|
|
| ### 2. npm publish |
|
|
| Depends on: `release` job (waits for goreleaser to finish) |
|
|
| **What it does:** |
| - Syncs version from tag (v0.7.0 β 0.7.0) |
| - Builds TypeScript (`npm run build`) |
| - Publishes to npm registry |
| - Users get postinstall script that downloads binaries from GitHub Releases |
|
|
| **User flow on `npm install pinchtab`:** |
| ``` |
| 1. npm downloads @pinchtab/cli package |
| 2. Runs postinstall script |
| 3. Script detects OS/arch (darwin-arm64, linux-x64, etc.) |
| 4. Downloads binary from GitHub release |
| 5. Verifies SHA256 checksum |
| 6. Stores in ~/.pinchtab/bin/0.7.0/pinchtab-<os>-<arch> |
| 7. Makes executable |
| 8. If ANY STEP fails β npm install fails (exit 1) |
| ``` |
|
|
| **β οΈ REQUIRES:** Goreleaser must have successfully uploaded binaries to GitHub release. The npm postinstall will verify this and fail hard if binaries are missing. |
|
|
| ### 3. Docker |
|
|
| GitHub Actions builds the release image directly from the tagged source with `docker buildx`. |
| The workflow pushes the same multi-arch build to both GHCR and Docker Hub, so Docker no longer depends on GoReleaser's temporary build context. |
|
|
| ### 4. ClawHub skill |
|
|
| The main `Release` workflow publishes the Pinchtab skill to ClawHub only after both npm and Docker complete successfully. |
| The standalone `Publish Skill` workflow is manual-only and is intended for retries or one-off recovery publishes. |
|
|
| ## Troubleshooting |
|
|
| ### npm publish fails (403) |
|
|
| - Check **NPM_TOKEN** is set in secrets |
| - Verify token has `automation` scope |
| - Check you're not already published (can't overwrite existing version) |
| |
| ### Binary checksum mismatch |
| |
| - goreleaser must generate `checksums.txt` |
| - Verify `.goreleaser.yml` has `checksum:` section |
| - Check GitHub release includes `checksums.txt` |
| |
| ### Docker push fails |
| |
| - Verify DOCKERHUB_USER and DOCKERHUB_TOKEN |
| - Check token has permission to push |
| |
| ## Rolling back |
| |
| If something goes wrong: |
| |
| ```bash |
| # Delete the tag locally and on GitHub |
| git tag -d v0.7.1 |
| git push origin :refs/tags/v0.7.1 |
| |
| # Delete npm version (requires owner permission) |
| npm unpublish pinchtab@0.7.1 |
| |
| # Revert any commits |
| git revert <commit> |
| git push origin main |
| |
| # Retag when ready |
| git tag v0.7.1 |
| git push origin v0.7.1 |
| ``` |
| |
| ## Version strategy |
| |
| - Use **semantic versioning**: v0.7.0 (major.minor.patch) |
| - Tag on main branch only |
| - One tag = one release (all artifacts) |
| - npm version must match Go binary tag |
| |
| ## See also |
| |
| - `.github/workflows/release.yml` β GitHub Actions workflow |
| - `.goreleaser.yml` β Go binary release config |
| - `npm/package.json` β npm package metadata |
| |