Skip to content

Commit b7cc44a

Browse files
committed
ci: cover the permissions the nightly's build and OTA callees declare
The nightly still failed validation after the claw-server fix. Bisecting with push-triggered copies of the workflow on a scratch branch localised two more call sites; each was proven in isolation: - build-browseros/build-browserclaw had no permissions block, so they inherited the workflow-level permissions: {} and granted nothing to nightly-macos-product.yml, which declares contents: read. - server-ota/claw-server-ota granted contents: read to publish-server-ota.yml, which declares contents and pull-requests write. A called workflow can only narrow the caller's GITHUB_TOKEN, and that is checked statically for the whole nested tree before any job is created, so a short ceiling rejects the entire run. With both covered, a full copy of the workflow created all 17 jobs and stopped at the intended 'must run from refs/heads/main' guard. ci_workflow_test asserted the contents: read ceiling that caused this, so it encoded the bug; updated to the ceiling that actually validates.
1 parent 54021c3 commit b7cc44a

2 files changed

Lines changed: 16 additions & 3 deletions

File tree

.github/workflows/nightly.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ jobs:
182182
name: Build signed BrowserOS nightly
183183
needs: [transaction, verify-components]
184184
uses: ./.github/workflows/nightly-macos-product.yml
185+
permissions:
186+
contents: read
185187
with:
186188
product: browseros
187189
state_ref: ${{ needs.transaction.outputs.state_ref }}
@@ -197,6 +199,8 @@ jobs:
197199
name: Build signed BrowserOS neo nightly
198200
needs: [transaction, verify-components]
199201
uses: ./.github/workflows/nightly-macos-product.yml
202+
permissions:
203+
contents: read
200204
with:
201205
product: browserclaw
202206
state_ref: ${{ needs.transaction.outputs.state_ref }}
@@ -275,7 +279,8 @@ jobs:
275279
needs: [transaction, finalize-server]
276280
uses: ./.github/workflows/publish-server-ota.yml
277281
permissions:
278-
contents: read
282+
contents: write
283+
pull-requests: write
279284
with:
280285
product: browseros
281286
version: ${{ needs.transaction.outputs.server_version }}
@@ -289,7 +294,8 @@ jobs:
289294
needs: [transaction, finalize-claw-server]
290295
uses: ./.github/workflows/publish-server-ota.yml
291296
permissions:
292-
contents: read
297+
contents: write
298+
pull-requests: write
293299
with:
294300
product: browserclaw
295301
version: ${{ needs.transaction.outputs.claw_server_version }}

packages/browseros/bos_build/ci_workflow_test.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,14 @@ def test_public_finalization_and_state_merge_follow_both_builds(self):
16871687
self.assertEqual(job["uses"], "./.github/workflows/publish-server-ota.yml")
16881688
self.assertEqual(job["with"]["product"], product)
16891689
self.assertEqual(job["with"]["state_owner"], "suite")
1690-
self.assertEqual(job["permissions"], {"contents": "read"})
1690+
# A called workflow can only narrow the caller's GITHUB_TOKEN, so the
1691+
# ceiling must cover what publish-server-ota.yml declares. Granting
1692+
# less rejects the whole run at validation time, before any job is
1693+
# created — see run 33689075661.
1694+
self.assertEqual(
1695+
job["permissions"],
1696+
{"contents": "write", "pull-requests": "write"},
1697+
)
16911698

16921699
reconcile = jobs["reconcile-state"]
16931700
self.assertTrue(set(finalizers).issubset(set(reconcile["needs"])))

0 commit comments

Comments
 (0)