Skip to content

Commit dc4e7cc

Browse files
committed
ci: publish to batch-archive with a scoped bee-runner App token
The GHA_PAT_BASIC org secret was never shared with this repo, so `Checkout batch-archive` resolved its token to empty and failed with "Input required and not supplied: token". Rather than widen that PAT (contents:write across 16 repos, tied to a personal account), mint a token from the bee-runner GitHub App, which is already installed org-wide with contents:write. The token is scoped to batch-archive alone, narrowed to contents:write, and expires in ~1h. Because of that expiry it is minted after the export, not at checkout — the export can easily outrun an hour. batch-archive is public, so the initial clone needs no App token at all; it uses GITHUB_TOKEN with persist-credentials: false so nothing long-lived sits in .git/config while the export runs, and the final push carries the App token itself.
1 parent 06bd66d commit dc4e7cc

1 file changed

Lines changed: 26 additions & 5 deletions

File tree

.github/workflows/batch-sync.yml

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ name: Batch Sync
1515
# Security: dispatch inputs reach run: scripts only via env — `${{ }}`
1616
# interpolation inside run: lets a crafted input inject shell.
1717
#
18-
# Secrets: GHA_PAT_BASIC needs contents:write on ethersphere/batch-archive;
19-
# PRIVATE_GNOSIS_RPC_URL is required; GNOSIS_RPC_USER / GNOSIS_RPC_PASSWORD
20-
# are needed only off-allowlist.
18+
# Secrets: BEE_RUNNER_APP_ID / BEE_RUNNER_KEY mint a short-lived App token
19+
# scoped to ethersphere/batch-archive for the publish push (the App is already
20+
# installed org-wide with contents:write); PRIVATE_GNOSIS_RPC_URL is required;
21+
# GNOSIS_RPC_USER / GNOSIS_RPC_PASSWORD are needed only off-allowlist.
2122

2223
on:
2324
workflow_dispatch:
@@ -82,7 +83,11 @@ jobs:
8283
uses: actions/checkout@v5
8384
with:
8485
repository: ethersphere/batch-archive
85-
token: ${{ secrets.GHA_PAT_BASIC }}
86+
# Public repo: the default token can read it. Write happens at the end
87+
# with an App token, so no long-lived credential sits in .git/config
88+
# for the length of the export.
89+
token: ${{ github.token }}
90+
persist-credentials: false
8691
path: batch-archive
8792
fetch-depth: 0
8893

@@ -151,9 +156,23 @@ jobs:
151156
--slim=true \
152157
--verbosity "${VERBOSITY}"
153158
159+
# Minted here, not at checkout: an App token lives ~1h and the export
160+
# above can outrun that. permission-contents keeps it to what the push
161+
# needs, and repositories keeps it off every other repo in the org.
162+
- name: Generate token for batch-archive
163+
id: archive-token
164+
uses: actions/create-github-app-token@v1
165+
with:
166+
app-id: ${{ secrets.BEE_RUNNER_APP_ID }}
167+
private-key: ${{ secrets.BEE_RUNNER_KEY }}
168+
owner: ethersphere
169+
repositories: batch-archive
170+
permission-contents: write
171+
154172
- name: Publish to batch-archive
155173
env:
156174
TRIGGERED_BY: ${{ github.actor }}
175+
ARCHIVE_TOKEN: ${{ steps.archive-token.outputs.token }}
157176
run: |
158177
set -euo pipefail
159178
cp snapshot.ndjson.gzip batch-archive/archive/export.ndjson.gzip
@@ -193,5 +212,7 @@ jobs:
193212
git tag "${new_tag}"
194213
# --atomic: a rejected push to main rejects the tag too, so no
195214
# orphaned tag can become a later run's resume point.
196-
git push --atomic origin HEAD:main "refs/tags/${new_tag}"
215+
git push --atomic \
216+
"https://x-access-token:${ARCHIVE_TOKEN}@github.com/ethersphere/batch-archive.git" \
217+
HEAD:main "refs/tags/${new_tag}"
197218
echo "::notice::published snapshot at block ${last_block} as ${new_tag} (resumed from ${ARCHIVE_TAG})"

0 commit comments

Comments
 (0)