code-foundry 0.34.7 → 0.34.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,25 +41,31 @@ jobs:
41
41
  # The partial clone (filter: blob:none) defers blob downloads, so the
42
42
  # merge-base/diff comparison below can trigger a promisor fetch. With
43
43
  # persist-credentials disabled, git has no auth for that fetch; configure
44
- # the credential helper with the same token the Check step uses. The token
45
- # is scoped to contents: read, so this never enables write credentials.
44
+ # the credential helper with the short-lived workflow token. NiftyLeague
45
+ # rejects long-lived fine-grained automation tokens with HTTP 403 even
46
+ # on REST, so all read-only operations use github.token; it is scoped
47
+ # to contents: read, so this never enables write credentials.
46
48
  env:
47
- GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN || github.token }}
49
+ GH_TOKEN: ${{ github.token }}
48
50
  run: gh auth setup-git
49
51
 
50
52
  - name: Check
51
53
  id: check-pr
52
54
  env:
53
- GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN || github.token }}
55
+ GH_TOKEN: ${{ github.token }}
54
56
  run: |
55
57
  set -euo pipefail
56
- EXISTING=$(gh pr list \
57
- --repo "$GITHUB_REPOSITORY" \
58
- --limit 1 \
59
- --base main \
60
- --head staging \
61
- --state open \
62
- --json number | node -e 'let d=""; process.stdin.on("data", c => d += c).on("end", () => console.log(JSON.parse(d || "[]").length))')
58
+ # Every lookup in this step is read-only and uses the short-lived
59
+ # workflow token: NiftyLeague rejects long-lived fine-grained
60
+ # automation tokens with HTTP 403 even on REST. The
61
+ # existing-promotion-PR lookup uses authenticated REST (gh api)
62
+ # rather than gh pr list, which issues a GraphQL query that
63
+ # NiftyLeague's long-lived fine-grained token policy rejects. The
64
+ # REST query keeps the exact base/head/state filter and the per_page=1
65
+ # cap (existing is 0 or 1) and fails closed on any API error.
66
+ EXISTING=$(gh api \
67
+ "repos/${GITHUB_REPOSITORY}/pulls?base=main&head=staging&state=open&per_page=1" \
68
+ --jq 'length')
63
69
  MAIN_TREE=$(gh api "repos/${GITHUB_REPOSITORY}/commits/main" --jq '.commit.tree.sha')
64
70
  STAGING_TREE=$(gh api "repos/${GITHUB_REPOSITORY}/commits/staging" --jq '.commit.tree.sha')
65
71
  TREE_EQUAL=false
@@ -186,26 +192,51 @@ jobs:
186
192
  - After merge, Release Please opens a separate versioned release PR with the changelog.
187
193
  EOF
188
194
 
189
- DRAFT_ARGS=()
195
+ # Creation uses authenticated REST (gh api POST) rather than
196
+ # `gh pr create`, which issues a GraphQL mutation that
197
+ # NiftyLeague's long-lived fine-grained token policy rejects. The
198
+ # REST payload keeps the exact base/head/title/body fields, adds
199
+ # draft=true only when no automation token is configured, and stays
200
+ # fail-closed through the create-race fallback below.
201
+ CREATE_ARGS=(
202
+ "repos/${GITHUB_REPOSITORY}/pulls"
203
+ --method POST
204
+ --field base=main
205
+ --field head=staging
206
+ --field title="Promote staging -> main ($DATE)"
207
+ --field body=@"$BODY_FILE"
208
+ )
190
209
  if [ "$HAS_AUTOMATION_TOKEN" != true ]; then
191
- DRAFT_ARGS+=(--draft)
210
+ CREATE_ARGS+=(--field draft=true)
192
211
  echo "::notice title=Manual PR readiness required::Created draft promotion PR because no automation token is configured. Configure CODE_FOUNDRY_TOKEN or RELEASE_PLEASE_TOKEN, or mark this PR ready manually to trigger validation."
193
212
  fi
194
213
 
195
- if ! gh pr create \
196
- --repo "$GITHUB_REPOSITORY" \
197
- --base main \
198
- --head staging \
199
- "${DRAFT_ARGS[@]}" \
200
- --title "Promote staging -> main ($DATE)" \
201
- --body-file "$BODY_FILE"; then
202
- EXISTING_NUMBER=$(gh pr list \
203
- --repo "$GITHUB_REPOSITORY" \
204
- --limit 1 \
205
- --base main \
206
- --head staging \
207
- --state open \
208
- --json number \
214
+ # Prefer the configured automation token for the write, but
215
+ # NiftyLeague rejects long-lived fine-grained tokens with HTTP 403
216
+ # even on REST, so retry the POST once with the short-lived workflow
217
+ # token before the create-race fallback. With no automation token
218
+ # configured, the first attempt already runs as github.token, so the
219
+ # retry only applies when an automation token was configured.
220
+ CREATED=false
221
+ if gh api "${CREATE_ARGS[@]}"; then
222
+ CREATED=true
223
+ elif [ "$HAS_AUTOMATION_TOKEN" = true ]; then
224
+ echo "::warning title=Token fallback::Automation token PR creation failed; retrying with the short-lived workflow token."
225
+ if GH_TOKEN="${{ github.token }}" gh api "${CREATE_ARGS[@]}"; then
226
+ CREATED=true
227
+ fi
228
+ fi
229
+
230
+ if [ "$CREATED" != true ]; then
231
+ # The create-race lookup runs only after creation failed: with a
232
+ # configured automation token that was rejected (its github.token
233
+ # retry also failed), or with no automation token configured, when
234
+ # the first attempt already ran as github.token. The lookup uses
235
+ # the same authenticated REST query as the Check step, always with
236
+ # the short-lived workflow token; gh pr list issues a GraphQL query
237
+ # that NiftyLeague's long-lived fine-grained token policy rejects.
238
+ EXISTING_NUMBER=$(GH_TOKEN="${{ github.token }}" gh api \
239
+ "repos/${GITHUB_REPOSITORY}/pulls?base=main&head=staging&state=open&per_page=1" \
209
240
  --jq '.[0].number // empty')
210
241
  if [ -z "$EXISTING_NUMBER" ]; then
211
242
  echo 'Pull request creation failed and no existing promotion PR was found.' >&2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.34.9](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.8...v0.34.9) (2026-08-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **ci:** fall back to github token for promotion ([37ff019](https://github.com/0xPlayerOne/code-foundry/commit/37ff019e95a9024338c05fec7579476bd5cf0b3f))
9
+
10
+ ## [0.34.8](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.7...v0.34.8) (2026-08-02)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **ci:** create promotion PRs through REST ([c123e21](https://github.com/0xPlayerOne/code-foundry/commit/c123e21e868de685a91de228ca57cf6614767bb7))
16
+
3
17
  ## [0.34.7](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.6...v0.34.7) (2026-08-02)
4
18
 
5
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "0.34.7",
3
+ "version": "0.34.9",
4
4
  "description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-or-later",