From d62c0dee137433adbde9bb2bcdd6f68192edcd9b Mon Sep 17 00:00:00 2001 From: William Schmitt Date: Thu, 12 Nov 2026 14:58:58 -0800 Subject: [PATCH] ci: drop the staging promote and back-sync workflows Since CB-591, browserbase/core builds straight into this repo's main and nothing is written to browserbase-python-staging first. The three workflows that kept the two trunks identical have no job left to do: - stlc-promote.yml fast-forwarded this repo up to staging. It only ever ran on the staging repo. - stlc-sync.yml pulled this repo's main back onto staging twice an hour and pinged staging on each release. - trunk-sync-lock.yml gated staging PRs on the trunks being in sync. Deleting them here also retires the staging copies: the staging repo's next back-sync fast-forwards it to this commit, which removes its own schedule. The staging repo can be archived after that. trunk-release-guard.yml stays for now. Its trunk-synced-release job is a required check on main, so it can only go once the ruleset drops it. Co-Authored-By: Claude Fable 5.2 --- .github/workflows/stlc-promote.yml | 87 ------------- .github/workflows/stlc-sync.yml | 173 -------------------------- .github/workflows/trunk-sync-lock.yml | 77 ------------ 3 files changed, 337 deletions(-) delete mode 100644 .github/workflows/stlc-promote.yml delete mode 100644 .github/workflows/stlc-sync.yml delete mode 100644 .github/workflows/trunk-sync-lock.yml diff --git a/.github/workflows/stlc-promote.yml b/.github/workflows/stlc-promote.yml deleted file mode 100644 index d11921fe..00000000 --- a/.github/workflows/stlc-promote.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Promote SDKs - -# Promote staging to production by fast-forwarding production main up to staging, -# preserving SHAs so the trunks stay identical and linear (nothing to heal on the -# next stlc build). Manual dispatch by design: a maintainer promotes the accumulated -# batch to cut a release; release-please then opens its version PR on production. -on: - workflow_dispatch: {} - -permissions: - contents: read - -jobs: - promote: - # Runner comes from the STLC_RUNNER repo/org variable when set; defaults to GitHub-hosted. - runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }} - if: github.repository == 'browserbase/browserbase-python-staging' - # Optional gate: add required reviewers to this environment to approve each - # promote. With none it only scopes secrets and adds no gate. Remove if unused. - environment: production - env: - PRODUCTION_REPO: browserbase/sdk-python - steps: - - name: Check out staging - uses: actions/checkout@v6 - with: - fetch-depth: 0 - persist-credentials: false - - # Short-lived installation token for browserbase-stlc-bot (CB-19) — - # replaces the PRODUCTION_REPO_TOKEN PAT the upstream template expects. - - name: Mint bot token - id: bot-token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2.2.2 - with: - app-id: ${{ secrets.STLC_BOT_APP_ID }} - private-key: ${{ secrets.STLC_BOT_PRIVATE_KEY }} - owner: browserbase - repositories: sdk-python - - - name: Fetch production main - env: - GH_TOKEN: ${{ steps.bot-token.outputs.token }} - run: | - git remote add production \ - "https://x-access-token:${GH_TOKEN}@github.com/${PRODUCTION_REPO}.git" - git fetch production main - - - name: Check whether production already has staging's content - id: diff - run: | - # After a release, production has release-please commits staging lacks, so compare trees. - MERGED=$(git merge-tree --write-tree production/main origin/main) || MERGED=conflict - PRODUCTION_TREE=$(git rev-parse 'production/main^{tree}') - if [ "$MERGED" = "$PRODUCTION_TREE" ]; then - echo "Production already contains staging's content. Nothing to promote." - echo "synced=true" >> "$GITHUB_OUTPUT" - else - echo "synced=false" >> "$GITHUB_OUTPUT" - fi - - - name: Promote staging to production (fast-forward) - if: steps.diff.outputs.synced == 'false' - run: | - # Refuse unless production is an ancestor of staging: otherwise the trunks - # have forked (production advanced without a back-sync) and FF is unsafe. - if ! git merge-base --is-ancestor production/main origin/main; then - echo "::error title=Promote blocked::production/main is not an ancestor of staging main. Back-sync production into staging first." - exit 1 - fi - git push production origin/main:refs/heads/main - echo "Fast-forwarded production/main to staging/main." - - - name: Alert on failure - if: failure() - env: - ALERT_WEBHOOK_URL: ${{ secrets.STLC_ALERT_WEBHOOK_URL }} - run: | - run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - msg="stlc promote failed in ${{ github.repository }}. A stalled promote or back-sync lets custom-code tracking drift, which later builds refuse on — investigate before the next build. Run: $run_url" - echo "::error title=stlc workflow failed::$msg" - { echo "### ⚠️ stlc workflow failed"; echo ""; echo "$msg"; } >> "$GITHUB_STEP_SUMMARY" - if [ -n "${ALERT_WEBHOOK_URL:-}" ]; then - curl -sS -X POST -H 'Content-Type: application/json' \ - -d "$(jq -n --arg text "$msg" '{text:$text}')" "$ALERT_WEBHOOK_URL" \ - || echo "::warning::Alert webhook POST failed" - fi diff --git a/.github/workflows/stlc-sync.yml b/.github/workflows/stlc-sync.yml deleted file mode 100644 index daebda6c..00000000 --- a/.github/workflows/stlc-sync.yml +++ /dev/null @@ -1,173 +0,0 @@ -name: Sync SDK repos - -# Keeps the staging and production trunks in sync. -# Each job self-routes by repo + event, so this one file -# can live in both repos and only the right job runs. The dispatch jobs are -# eager-only (the polls cover them) and no-op when their token isn't set. -on: - schedule: - # back-sync poll: a cheap pure-git check, twice hourly so an unsynced production - # change (e.g. a community PR between releases) can't hold codegen for long. - - cron: "7,37 * * * *" - workflow_dispatch: {} - repository_dispatch: - types: [prod-released] - release: - types: [published] - -jobs: - back-sync: - # Fast-forward production main back onto staging so the trunks stay identical. - # Runner comes from the STLC_RUNNER repo/org variable when set; defaults to GitHub-hosted. - runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }} - if: >- - github.repository == 'browserbase/browserbase-python-staging' && - (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch') - permissions: - contents: read - concurrency: - group: stlc-back-sync - cancel-in-progress: true - env: - PRODUCTION_REPO: browserbase/sdk-python - steps: - - name: Check out staging - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - # Push as the browserbase-stlc-bot app rather than GITHUB_TOKEN so the - # branch ruleset needs exactly one bypass actor (the app) to cover every - # legitimate main writer: codegen, promote, and this back-sync (CB-19). - - name: Mint bot token - id: bot-token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2.2.2 - with: - app-id: ${{ secrets.STLC_BOT_APP_ID }} - private-key: ${{ secrets.STLC_BOT_PRIVATE_KEY }} - owner: browserbase - repositories: browserbase-python-staging - - - name: Fetch production main - env: - PRODUCTION_REPO_TOKEN: ${{ secrets.PRODUCTION_REPO_TOKEN }} - run: | - # Public production reads with no credential; a private production - # repo needs PRODUCTION_REPO_TOKEN (the same token the promote uses). - if [ -n "${PRODUCTION_REPO_TOKEN:-}" ]; then - git remote add production "https://x-access-token:${PRODUCTION_REPO_TOKEN}@github.com/${PRODUCTION_REPO}.git" - else - git remote add production "https://github.com/${PRODUCTION_REPO}.git" - fi - # actions/checkout persists this repo's token as an auth header, which - # outranks the remote URL credential; blank it for this fetch only. - git -c "http.https://github.com/.extraheader=" fetch production main - - - name: Check whether production has content staging lacks - id: diff - run: | - # Content compare: would merging production into staging change its tree? - # If not, staging already has production's content (release-please commits). - MERGED=$(git merge-tree --write-tree origin/main production/main) || MERGED=conflict - STAGING_TREE=$(git rev-parse 'origin/main^{tree}') - if [ "$MERGED" = "$STAGING_TREE" ]; then - echo "Staging already has production's content. Nothing to pull back." - echo "behind=false" >> "$GITHUB_OUTPUT" - else - echo "behind=true" >> "$GITHUB_OUTPUT" - fi - - - name: Sync production to staging (fast-forward) - if: steps.diff.outputs.behind == 'true' - run: | - # Refuse unless staging is an ancestor of production: otherwise the - # trunks have forked and a fast-forward would be unsafe. - if ! git merge-base --is-ancestor origin/main production/main; then - echo "::error title=Back-sync blocked::staging main is not an ancestor of production/main." - exit 1 - fi - # actions/checkout's persisted GITHUB_TOKEN header outranks the URL - # credential; blank it so this push authenticates as the app. - git -c "http.https://github.com/.extraheader=" push \ - "https://x-access-token:${BOT_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \ - production/main:refs/heads/main - echo "Fast-forwarded staging/main to production/main." - env: - BOT_TOKEN: ${{ steps.bot-token.outputs.token }} - - - name: Alert on failure - if: failure() - env: - ALERT_WEBHOOK_URL: ${{ secrets.STLC_ALERT_WEBHOOK_URL }} - run: | - run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - msg="stlc back-sync (sync from production) failed in ${{ github.repository }}. A stalled back-sync lets custom-code tracking drift, which later builds refuse on — investigate before the next build. Run: $run_url" - echo "::error title=stlc workflow failed::$msg" - { echo "### ⚠️ stlc workflow failed"; echo ""; echo "$msg"; } >> "$GITHUB_STEP_SUMMARY" - if [ -n "${ALERT_WEBHOOK_URL:-}" ]; then - curl -sS -X POST -H 'Content-Type: application/json' \ - -d "$(jq -n --arg text "$msg" '{text:$text}')" "$ALERT_WEBHOOK_URL" \ - || echo "::warning::Alert webhook POST failed" - fi - - notify-back-sync: - # On a published release, tell staging to back-sync now instead of waiting for - # the poll. Dispatch-only: it cannot write production or staging contents. - runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }} - if: >- - github.repository == 'browserbase/sdk-python' && - (github.event_name == 'release' || github.event_name == 'workflow_dispatch') - permissions: - contents: read - env: - STAGING_REPO: browserbase/browserbase-python-staging - steps: - # App token in place of the STAGING_DISPATCH_TOKEN PAT (CB-19). - - name: Mint bot token - id: bot-token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2.2.2 - with: - app-id: ${{ secrets.STLC_BOT_APP_ID }} - private-key: ${{ secrets.STLC_BOT_PRIVATE_KEY }} - owner: browserbase - repositories: browserbase-python-staging - - - name: Dispatch back-sync to staging - env: - DISPATCH_TOKEN: ${{ steps.bot-token.outputs.token }} - REF_NAME: ${{ github.ref_name }} - run: | - set -euo pipefail - - if [ -z "${DISPATCH_TOKEN:-}" ]; then - echo "::notice::STAGING_DISPATCH_TOKEN not configured — skipping the eager back-sync notify. The staging repo's twice-hourly poll covers this." - exit 0 - fi - - payload=$(jq -n --arg ref "$REF_NAME" '{event_type:"prod-released",client_payload:{ref:$ref}}') - code=$(curl -sS -o /tmp/dispatch.txt -w '%{http_code}' -X POST \ - -H "Authorization: Bearer ${DISPATCH_TOKEN}" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/${STAGING_REPO}/dispatches" \ - -d "$payload") - if [ "$code" = "204" ]; then - echo "Back-sync dispatched to ${STAGING_REPO}." - else - echo "Dispatch failed (HTTP $code)" >&2; cat /tmp/dispatch.txt >&2; exit 1 - fi - - - name: Alert on failure - if: failure() - env: - ALERT_WEBHOOK_URL: ${{ secrets.STLC_ALERT_WEBHOOK_URL }} - run: | - run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - msg="stlc release back-sync trigger failed in ${{ github.repository }} — the staging repo was NOT notified to back-sync this release (likely an expired STAGING_DISPATCH_TOKEN). Staging catches up on its next poll, but verify the token. Run: $run_url" - echo "::error title=stlc workflow failed::$msg" - { echo "### ⚠️ stlc workflow failed"; echo ""; echo "$msg"; } >> "$GITHUB_STEP_SUMMARY" - if [ -n "${ALERT_WEBHOOK_URL:-}" ]; then - curl -sS -X POST -H 'Content-Type: application/json' \ - -d "$(jq -n --arg text "$msg" '{text:$text}')" "$ALERT_WEBHOOK_URL" \ - || echo "::warning::Alert webhook POST failed" - fi diff --git a/.github/workflows/trunk-sync-lock.yml b/.github/workflows/trunk-sync-lock.yml deleted file mode 100644 index 739387d4..00000000 --- a/.github/workflows/trunk-sync-lock.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Trunk sync lock - -# OPTIONAL: copy into .github/workflows/ if your production repo takes community PRs -# or if custom-code PRs merge on staging during release windows. This workflow posts -# a `trunk-synced` status to open PRs against staging main. -# -# Make it a required check on staging. It gates PRs only; the back-sync pushes staging main directly. -# -# Never route the back-sync through a PR gated by this check or it deadlocks. -# First-run: a check counts as "required" only after it reports once, so trigger this workflow once before marking trunk-synced required. -on: - pull_request: - branches: [main] - types: [opened, synchronize, reopened] - workflow_run: - workflows: ["Sync SDK repos"] - types: [completed] - repository_dispatch: - types: [prod-released] - workflow_dispatch: {} - schedule: - - cron: "*/30 * * * *" - -permissions: - contents: read - statuses: write - pull-requests: read - -jobs: - lock: - # Runner comes from the STLC_RUNNER repo/org variable when set; defaults to GitHub-hosted. - runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }} - if: github.repository == 'browserbase/browserbase-python-staging' - env: - PRODUCTION_REPO: browserbase/sdk-python - PRODUCTION_REPO_TOKEN: ${{ secrets.PRODUCTION_REPO_TOKEN }} - GH_TOKEN: ${{ github.token }} - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - persist-credentials: false - - name: Evaluate sync state and post status to open main PRs - run: | - set -euo pipefail - # Public production reads with no credential; a private production - # repo needs PRODUCTION_REPO_TOKEN (the same token the promote uses). - if [ -n "${PRODUCTION_REPO_TOKEN:-}" ]; then - git remote add production "https://x-access-token:${PRODUCTION_REPO_TOKEN}@github.com/${PRODUCTION_REPO}.git" - else - git remote add production "https://github.com/${PRODUCTION_REPO}.git" - fi - git fetch --no-tags production main - if git merge-base --is-ancestor production/main HEAD; then - state=success; desc="staging main is in sync with production" - else - state=failure; desc="production is ahead — wait for the back-sync before merging" - fi - echo "trunk-synced => $state ($desc)" - # Retry: a transient API failure here would otherwise fail the job even though - # the trunk check above already succeeded. A missing status still blocks a gated - # PR, so giving up after retries and exiting 0 is safe. - shas="" - for attempt in 1 2 3 4 5; do - if shas=$(gh pr list --repo "$GITHUB_REPOSITORY" --base main --state open --json headRefOid --jq '.[].headRefOid'); then - break - fi - echo "::notice::could not list open PRs (attempt $attempt/5); retrying" - shas="" - sleep $((attempt * 5)) - done - if [ -z "$shas" ]; then echo "no open PRs targeting main (or PR list unavailable)"; exit 0; fi - for sha in $shas; do - gh api -X POST "repos/$GITHUB_REPOSITORY/statuses/$sha" \ - -f state="$state" -f context="trunk-synced" -f description="$desc" >/dev/null - echo "posted trunk-synced=$state to $sha" - done