Skip to content
This repository was archived by the owner on Apr 17, 2026. It is now read-only.

Commit ce7efa1

Browse files
fix: release flow + docs (pinchtab#371)
Co-authored-by: Luigi Agosti <luigi@tengio.com>
1 parent 25b3374 commit ce7efa1

9 files changed

Lines changed: 98 additions & 59 deletions

File tree

.github/workflows/release-manual-publish.yml

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,68 @@ name: Release / Manual Publish
33
on:
44
workflow_dispatch:
55
inputs:
6-
version:
7-
description: 'Release version (e.g. 0.8.0, without v prefix)'
6+
tag:
7+
description: 'Existing release tag to publish (e.g. v0.8.0)'
88
required: true
9-
ref:
10-
description: 'Git ref to tag. Defaults to main.'
11-
required: false
12-
default: 'main'
139

1410
permissions:
15-
contents: write
11+
contents: read
1612

1713
concurrency:
18-
group: release-manual-${{ inputs.version }}
14+
group: release-manual-${{ inputs.tag }}
1915
cancel-in-progress: false
2016

2117
jobs:
2218
validate:
23-
uses: ./.github/workflows/reusable-validate-release.yml
24-
with:
25-
version: ${{ inputs.version }}
26-
ref: ${{ inputs.ref }}
27-
28-
create-tag:
29-
name: Create Release Tag
30-
needs: validate
19+
name: Validate Existing Tag
3120
runs-on: ubuntu-latest
32-
environment:
33-
name: release-approval
34-
permissions:
35-
contents: write
21+
outputs:
22+
tag: ${{ steps.meta.outputs.tag }}
23+
ref: ${{ steps.meta.outputs.ref }}
3624
steps:
3725
- uses: actions/checkout@v6
3826
with:
3927
fetch-depth: 0
40-
ref: ${{ needs.validate.outputs.sha }}
4128

42-
- name: Create and push tag
29+
- name: Normalize and validate tag
30+
id: meta
4331
run: |
44-
TAG="${{ needs.validate.outputs.tag }}"
32+
TAG="${{ inputs.tag }}"
33+
if [ "${TAG#v}" = "$TAG" ]; then
34+
TAG="v$TAG"
35+
fi
4536
46-
if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null 2>&1; then
47-
echo "tag $TAG already exists on origin" >&2
37+
git fetch --tags origin
38+
if ! git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
39+
echo "tag $TAG not found on origin" >&2
4840
exit 1
4941
fi
5042
51-
git config user.name "github-actions[bot]"
52-
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
53-
git tag -a "$TAG" -m "Release $TAG (manual)"
54-
git push origin "refs/tags/$TAG"
43+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
44+
echo "ref=refs/tags/$TAG" >> "$GITHUB_OUTPUT"
5545
46+
approval:
47+
name: Manual Approval
48+
needs: validate
49+
runs-on: ubuntu-latest
50+
environment:
51+
name: release-approval
52+
steps:
5653
- name: Summarize
5754
run: |
58-
echo "## Release Tag Created (Manual)" >> "$GITHUB_STEP_SUMMARY"
55+
echo "## Manual Publish Approval" >> "$GITHUB_STEP_SUMMARY"
5956
echo "- Tag: ${{ needs.validate.outputs.tag }}" >> "$GITHUB_STEP_SUMMARY"
60-
echo "- Commit: \`${{ needs.validate.outputs.sha }}\`" >> "$GITHUB_STEP_SUMMARY"
61-
echo "" >> "$GITHUB_STEP_SUMMARY"
62-
echo "The **Release / Publish** workflow will trigger automatically." >> "$GITHUB_STEP_SUMMARY"
57+
58+
publish:
59+
name: Publish Existing Tag
60+
needs:
61+
- validate
62+
- approval
63+
permissions:
64+
contents: write
65+
packages: write
66+
uses: ./.github/workflows/reusable-release-publish.yml
67+
with:
68+
ref: ${{ needs.validate.outputs.ref }}
69+
tag: ${{ needs.validate.outputs.tag }}
70+
secrets: inherit
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Release / Prepare
1+
name: Release
22

33
on:
44
workflow_dispatch:
@@ -222,3 +222,19 @@ jobs:
222222
echo "## Release Tag Created" >> "$GITHUB_STEP_SUMMARY"
223223
echo "- Tag: ${{ needs.validate.outputs.tag }}" >> "$GITHUB_STEP_SUMMARY"
224224
echo "- Commit: \`${{ needs.validate.outputs.sha }}\`" >> "$GITHUB_STEP_SUMMARY"
225+
echo "" >> "$GITHUB_STEP_SUMMARY"
226+
echo "Publishing continues in this workflow from the approved tag." >> "$GITHUB_STEP_SUMMARY"
227+
228+
publish:
229+
name: Publish Release
230+
needs:
231+
- validate
232+
- create-tag
233+
permissions:
234+
contents: write
235+
packages: write
236+
uses: ./.github/workflows/reusable-release-publish.yml
237+
with:
238+
ref: refs/tags/${{ needs.validate.outputs.tag }}
239+
tag: ${{ needs.validate.outputs.tag }}
240+
secrets: inherit

.github/workflows/release-publish.yml renamed to .github/workflows/reusable-release-publish.yml

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
name: Release / Publish
1+
name: Reusable / Release Publish
22

33
on:
4-
push:
5-
tags: ['v*']
4+
workflow_call:
5+
inputs:
6+
ref:
7+
description: 'Git ref to publish from (for example refs/tags/v0.8.0)'
8+
required: true
9+
type: string
10+
tag:
11+
description: 'Release tag with v prefix'
12+
required: true
13+
type: string
614

715
env:
816
GORELEASER_VERSION: v2.14.3
@@ -11,7 +19,7 @@ permissions:
1119
contents: write
1220

1321
concurrency:
14-
group: release-${{ github.ref_name }}
22+
group: release-${{ inputs.tag }}
1523
cancel-in-progress: false
1624

1725
jobs:
@@ -24,7 +32,7 @@ jobs:
2432
- uses: actions/checkout@v6
2533
with:
2634
fetch-depth: 0
27-
ref: ${{ github.ref }}
35+
ref: ${{ inputs.ref }}
2836

2937
- uses: actions/setup-go@v6
3038
with:
@@ -54,7 +62,7 @@ jobs:
5462
steps:
5563
- uses: actions/checkout@v6
5664
with:
57-
ref: ${{ github.ref }}
65+
ref: ${{ inputs.ref }}
5866

5967
- uses: actions/setup-node@v6
6068
with:
@@ -64,7 +72,7 @@ jobs:
6472
- name: Extract version
6573
id: version
6674
run: |
67-
TAG="${{ github.ref_name }}"
75+
TAG="${{ inputs.tag }}"
6876
VERSION="${TAG#v}"
6977
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
7078
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
@@ -106,12 +114,12 @@ jobs:
106114
steps:
107115
- uses: actions/checkout@v6
108116
with:
109-
ref: ${{ github.ref }}
117+
ref: ${{ inputs.ref }}
110118

111119
- name: Extract Docker metadata
112120
id: meta
113121
run: |
114-
TAG="${{ github.ref_name }}"
122+
TAG="${{ inputs.tag }}"
115123
VERSION="${TAG#v}"
116124
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
117125
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
@@ -155,6 +163,6 @@ jobs:
155163
- npm
156164
uses: ./.github/workflows/reusable-publish-skill.yml
157165
with:
158-
version: ${{ github.ref_name }}
166+
version: ${{ inputs.tag }}
159167
secrets:
160168
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<p align="center">
66
<strong>PinchTab</strong><br/>
77
<strong>Browser control for AI agents</strong><br/>
8-
12MB Go binary • HTTP API • Token-efficient
8+
Small Go binary • HTTP API • Token-efficient
99
</p>
1010

1111

@@ -16,7 +16,7 @@
1616
</td>
1717
<td align="left" valign="middle">
1818
<a href="https://github.com/pinchtab/pinchtab/releases/latest"><img src="https://img.shields.io/github/v/release/pinchtab/pinchtab?style=flat-square&color=FFD700" alt="Release"/></a><br/>
19-
<a href="https://github.com/pinchtab/pinchtab/actions/workflows/go-verify.yml"><img src="https://img.shields.io/github/actions/workflow/status/pinchtab/pinchtab/go-verify.yml?branch=main&style=flat-square&label=Build" alt="Build"/></a><br/>
19+
<a href="https://github.com/pinchtab/pinchtab/actions/workflows/ci-go.yml"><img src="https://img.shields.io/github/actions/workflow/status/pinchtab/pinchtab/ci-go.yml?branch=main&style=flat-square&label=Go%20CI" alt="Go CI"/></a><br/>
2020
<img src="https://img.shields.io/badge/Go-1.25+-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go 1.25+"/><br/>
2121
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square" alt="License"/></a>
2222
</td>

RELEASE.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ grep -A 2 "^release:" .goreleaser.yml
6666
-`checksum:` generates `checksums.txt` (used by npm postinstall verification)
6767
-`release:` points to GitHub (uploads everything automatically)
6868

69-
**Ready to release.** The recommended path is now the manual `Prepare Release` workflow, which runs the full verification suite, pauses for approval, and only then creates the tag.
69+
**Ready to release.** The recommended path is now the manual `Release` workflow, which runs the full verification suite, pauses for approval, creates the tag, and then finishes publishing in the same run.
7070

7171
## Releasing
7272

7373
## Manual Release Flow
7474

7575
1. Choose the branch, tag, or SHA you want to release.
76-
`Prepare Release` now validates the requested version format and tag availability, then rewrites the npm package version inside the CI workspace for the dry-run steps.
77-
2. Open **Actions → Prepare Release**.
76+
`Release` now validates the requested version format and tag availability, then rewrites the npm package version inside the CI workspace for the dry-run steps.
77+
2. Open **Actions → Release**.
7878
3. Run it with:
7979
- `version`: the release version, for example `0.8.0`
8080
- `ref`: the branch, tag, or SHA you want to release
@@ -88,13 +88,21 @@ grep -A 2 "^release:" .goreleaser.yml
8888
- GoReleaser snapshot
8989
- `npm publish --dry-run`
9090
5. After those pass, GitHub pauses at the `release-approval` environment gate.
91-
6. Approve the run. The workflow creates and pushes `v0.8.0` from the exact tested commit SHA.
92-
7. That tag triggers the `Release` workflow automatically.
91+
6. Approve the run. The workflow creates and pushes `v0.8.0` from the exact tested commit SHA, then continues publishing from that tag in the same run.
92+
7. Monitor the remaining publish jobs in the same workflow run:
93+
- GitHub release binaries
94+
- npm publish
95+
- Docker image publish
96+
- ClawHub skill publish
9397

9498
### Required GitHub setup
9599

96100
Configure a protected environment named `release-approval` with the required reviewers for the manual gate to be effective.
97101

102+
### Recovery publish
103+
104+
If a tag already exists and you need to retry publishing, use **Actions → Release / Manual Publish** with the existing tag, for example `v0.8.0`.
105+
98106
## Pipeline details
99107

100108
### 1. Goreleaser (Go binary) — CRITICAL for npm

docs/guides/contributing.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ Workflows follow a naming convention:
356356
|--------|---------|---------|
357357
| `ci-*` | Automatic checks on PR/push | `ci-go.yml`**CI / Go** |
358358
| `reusable-*` | Building blocks (`workflow_call` only) | `reusable-e2e.yml`**Reusable / E2E** |
359-
| `release-*` | Release pipeline | `release-prepare.yml`**Release / Prepare** |
359+
| `release-*` | Release pipeline | `release.yml`**Release** |
360360
361361
### CI Checks
362362
@@ -375,11 +375,10 @@ Run automatically on pull requests and/or push to `main`:
375375
376376
| Workflow | Trigger | What it does |
377377
|----------|---------|--------------|
378-
| **Release / Prepare** | Manual | Runs all checks + E2E → manual approval gate → creates tag |
379-
| **Release / Publish** | Tag push (`v*`) | GoReleaser + npm + Docker + ClawHub skill |
380-
| **Release / Manual Publish** | Manual | Validates + creates tag (bypasses Prepare) → triggers Publish |
378+
| **Release** | Manual | Runs all checks + E2E → manual approval gate → creates tag → publishes binaries, npm, Docker, and skill |
379+
| **Release / Manual Publish** | Manual | Publishes an existing tag as a recovery path |
381380
382-
In **Release / Prepare**, E2E and Docker smoke failures are non-blocking — they surface
381+
In **Release**, E2E and Docker smoke failures are non-blocking — they surface
383382
in the approval summary so you can decide whether to proceed. Core checks (Go, Dashboard,
384383
Docs, npm, publish dry-run) must pass for the approval gate to appear.
385384

install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ ERROR='\033[38;2;230;57;70m' # red #e63946
1212
MUTED='\033[38;2;90;100;128m' # text-muted #5a6480
1313
NC='\033[0m' # No Color
1414

15-
TAGLINE="12MB binary. Zero config. Accessibility-first browser control."
15+
TAGLINE="Small binary. Zero config. Accessibility-first browser control."
1616

1717
cleanup_tmpfiles() {
1818
local f

skills/pinchtab-dev/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Develop and contribute to the PinchTab project. Use when working on
55

66
# PinchTab Development
77

8-
PinchTab is a browser control server for AI agents — 12MB Go binary with HTTP API.
8+
PinchTab is a browser control server for AI agents — Small Go binary with HTTP API.
99

1010
## Project Location
1111

skills/pinchtab/TRUST.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Binaries are built automatically from tagged commits via GitHub Actions (publicl
3838
- **Releases**: https://github.com/pinchtab/pinchtab/releases
3939
- **Latest**: v0.8.4 (Mar 2026)
4040

41-
If you're concerned, audit the source—it's 12MB, zero external dependencies, mostly Go stdlib.
41+
If you're concerned, audit the source—it's ~15MB, zero external dependencies, mostly Go stdlib.
4242

4343
## VirusTotal Flag
4444

0 commit comments

Comments
 (0)