Skip to content

Commit 3bd7660

Browse files
authored
CI cleanup + docs (#298)
* fix: CI was pulling the entire stagehand repo and re-creating the node sea binary. Now it just pulls the binary. docs: Added docs * lint fix * Use release id instead of release tag
1 parent 74cb7fb commit 3bd7660

File tree

3 files changed

+76
-41
lines changed

3 files changed

+76
-41
lines changed

.github/workflows/publish-pypi.yml

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ name: Publish PyPI
44

55
on:
66
workflow_dispatch:
7-
inputs:
8-
stagehand_tag:
9-
description: "Stagehand repo git ref to build SEA binaries from (e.g. @browserbasehq/stagehand@3.0.6)"
10-
required: true
11-
type: string
7+
inputs: {}
128

139
release:
1410
types: [published]
@@ -49,39 +45,38 @@ jobs:
4945
with:
5046
version: "0.9.13"
5147

52-
- name: Checkout stagehand (server source)
53-
uses: actions/checkout@v4
48+
- name: Resolve latest stagehand/server release
49+
id: stagehand-server-release
50+
uses: actions/github-script@v6
5451
with:
55-
repository: browserbase/stagehand
56-
ref: ${{ inputs.stagehand_tag || vars.STAGEHAND_TAG }}
57-
path: _stagehand
58-
fetch-depth: 1
59-
# If browserbase/stagehand is private, set STAGEHAND_SOURCE_TOKEN (PAT) in this repo.
60-
token: ${{ secrets.STAGEHAND_SOURCE_TOKEN || github.token }}
61-
62-
- name: Setup pnpm
63-
uses: pnpm/action-setup@v4
64-
with:
65-
version: 9
66-
67-
- name: Setup Node.js
68-
uses: actions/setup-node@v4
69-
with:
70-
node-version: "23"
71-
cache: "pnpm"
72-
cache-dependency-path: _stagehand/pnpm-lock.yaml
73-
74-
- name: Build SEA server binary (from source)
52+
github-token: ${{ secrets.STAGEHAND_SOURCE_TOKEN || github.token }}
53+
script: |
54+
const { data } = await github.rest.repos.listReleases({
55+
owner: 'browserbase',
56+
repo: 'stagehand',
57+
per_page: 100,
58+
});
59+
const release = data.find(r => typeof r.tag_name === 'string' && r.tag_name.startsWith('stagehand-server/v'));
60+
if (!release) {
61+
core.setFailed('No stagehand-server/v* release found in browserbase/stagehand');
62+
return;
63+
}
64+
core.info(`Using stagehand/server release tag: ${release.tag_name}`);
65+
core.setOutput('tag', release.tag_name);
66+
core.setOutput('id', String(release.id));
67+
68+
- name: Download stagehand/server SEA binary (from GitHub Release assets)
69+
env:
70+
GH_TOKEN: ${{ secrets.STAGEHAND_SOURCE_TOKEN || github.token }}
71+
RELEASE_TAG: ${{ steps.stagehand-server-release.outputs.tag }}
72+
RELEASE_ID: ${{ steps.stagehand-server-release.outputs.id }}
73+
ASSET_NAME: ${{ matrix.binary_name }}
74+
OUTPUT_PATH: ${{ matrix.output_path }}
7575
shell: bash
7676
run: |
7777
set -euo pipefail
7878
79-
if [[ -z "${{ inputs.stagehand_tag }}" && -z "${{ vars.STAGEHAND_TAG }}" ]]; then
80-
echo "Missing stagehand ref: set repo variable STAGEHAND_TAG or provide workflow input stagehand_tag." >&2
81-
exit 1
82-
fi
83-
84-
# Ensure we only ship the binary built for this runner's OS/arch.
79+
# Ensure we only ship the binary for this runner's OS/arch.
8580
python - <<'PY'
8681
from pathlib import Path
8782
sea_dir = Path("src/stagehand/_sea")
@@ -92,15 +87,31 @@ jobs:
9287
p.unlink(missing_ok=True)
9388
PY
9489
95-
pushd _stagehand >/dev/null
96-
pnpm install --frozen-lockfile
97-
CI=true pnpm --filter @browserbasehq/stagehand-server build:binary
98-
popd >/dev/null
90+
echo "Downloading ${ASSET_NAME} from browserbase/stagehand@${RELEASE_TAG}"
91+
92+
url="$(
93+
curl -fsSL \
94+
-H "Authorization: Bearer ${GH_TOKEN}" \
95+
-H "Accept: application/vnd.github+json" \
96+
"https://api.github.com/repos/browserbase/stagehand/releases/${RELEASE_ID}" \
97+
| python -c 'import json,sys; d=json.load(sys.stdin); a=next((x for x in d.get("assets",[]) if x.get("name")==sys.argv[1]), None); print(a.get("url","") if a else "")' \
98+
"${ASSET_NAME}"
99+
)"
100+
101+
if [ -z "${url}" ]; then
102+
echo "Release asset not found: ${ASSET_NAME} (tag=${RELEASE_TAG})" >&2
103+
exit 1
104+
fi
105+
106+
mkdir -p "$(dirname "${OUTPUT_PATH}")"
107+
curl -fsSL \
108+
-H "Authorization: Bearer ${GH_TOKEN}" \
109+
-H "Accept: application/octet-stream" \
110+
"${url}" \
111+
-o "${OUTPUT_PATH}"
99112
100-
cp "_stagehand/packages/server/dist/sea/${{ matrix.binary_name }}" "${{ matrix.output_path }}"
101-
chmod +x "${{ matrix.output_path }}" 2>/dev/null || true
113+
chmod +x "${OUTPUT_PATH}" 2>/dev/null || true
102114
rm -f src/stagehand/_sea/.keep || true
103-
git add -f src/stagehand/_sea/*
104115
105116
- name: Build wheel
106117
env:

RELEASE_WORKFLOWS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Release + publish workflow
2+
3+
This repo publishes the `stagehand` Python package to PyPI when a **GitHub Release** is published. The release is currently initiated manually via the `release-please` CLI.
4+
5+
## Chronological flow (step-by-step)
6+
7+
1. Run `pnpx release-please release-pr` (local machine).
8+
- Opens/updates a Release PR to `main` with version + `CHANGELOG.md` updates.
9+
2. Merge the Release PR into `main`.
10+
3. Run `pnpx release-please github-release` (local machine).
11+
- Publishes the GitHub Release + git tag.
12+
4. Wait for GitHub Actions to publish to PyPI (automatic).
13+
- Trigger: GitHub Release `published` event runs `.github/workflows/publish-pypi.yml`.
14+
- Builds platform wheels that embed the Stagehand server binary (downloaded from the latest `stagehand-server/v*` GitHub Release in `browserbase/stagehand`), then publishes to PyPI.
15+
16+
## Important implementation notes
17+
18+
- **Server binary bundling into wheels**
19+
- `.github/workflows/publish-pypi.yml` downloads the prebuilt Stagehand server SEA binary from the latest `stagehand-server/v*` GitHub Release in `browserbase/stagehand`, then places it into `src/stagehand/_sea/*` before running `uv build --wheel`.
20+
- **Stagehand server version selection (current behavior)**
21+
- `publish-pypi.yml` resolves the latest GitHub Release tag matching `stagehand-server/v*` from `browserbase/stagehand` and downloads the matching `stagehand-server-<platform>` release asset for each wheel build.
22+
- **Secrets**
23+
- PyPI publish uses `secrets.STAGEHAND_PYPI_TOKEN || secrets.PYPI_TOKEN`.
24+
- `.github/workflows/release-doctor.yml` runs `bin/check-release-environment` on qualifying PRs and fails if `PYPI_TOKEN` is missing.

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)