code-foundry 0.34.9 → 0.34.10
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.
- package/.github/workflows/release.yml +72 -17
- package/CHANGELOG.md +7 -0
- package/docs/RELEASES.md +20 -11
- package/package.json +1 -1
|
@@ -54,6 +54,7 @@ jobs:
|
|
|
54
54
|
release_created: ${{ steps.release.outputs.release_created || 'false' }}
|
|
55
55
|
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
56
56
|
npm_publish: ${{ steps.profile.outputs.npm_publish }}
|
|
57
|
+
token_source: ${{ steps.credentials.outputs.token_source }}
|
|
57
58
|
steps:
|
|
58
59
|
- name: Checkout
|
|
59
60
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -116,25 +117,80 @@ jobs:
|
|
|
116
117
|
id: credentials
|
|
117
118
|
env:
|
|
118
119
|
HAS_AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN != '' || secrets.RELEASE_PLEASE_TOKEN != '' }}
|
|
120
|
+
GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN }}
|
|
119
121
|
run: |
|
|
120
|
-
|
|
122
|
+
set -euo pipefail
|
|
123
|
+
# NiftyLeague rejects long-lived fine-grained automation tokens with
|
|
124
|
+
# HTTP 403 even on REST (observed in the release-pr promotion flow),
|
|
125
|
+
# so the configured automation token is validated against the current
|
|
126
|
+
# repository before any write. gh api authenticates through the
|
|
127
|
+
# GH_TOKEN environment variable and never prints the token; the
|
|
128
|
+
# response body is discarded and only the exit status selects the
|
|
129
|
+
# credential for the rest of the job.
|
|
130
|
+
if [ "$HAS_AUTOMATION_TOKEN" = true ] && gh api "repos/${GITHUB_REPOSITORY}" --jq '.full_name' >/dev/null 2>&1; then
|
|
121
131
|
echo "auto_merge=true" >> "$GITHUB_OUTPUT"
|
|
132
|
+
echo "token_source=configured" >> "$GITHUB_OUTPUT"
|
|
122
133
|
else
|
|
123
134
|
echo "auto_merge=false" >> "$GITHUB_OUTPUT"
|
|
135
|
+
echo "token_source=fallback" >> "$GITHUB_OUTPUT"
|
|
136
|
+
if [ "$HAS_AUTOMATION_TOKEN" = true ]; then
|
|
137
|
+
echo "::warning title=Release token fallback::The configured CODE_FOUNDRY_TOKEN or RELEASE_PLEASE_TOKEN was rejected by GitHub; failing over to the short-lived workflow token. The version pull request will be left for manual merge."
|
|
138
|
+
fi
|
|
124
139
|
fi
|
|
125
|
-
- name: Release Please
|
|
126
|
-
id:
|
|
127
|
-
if: steps.profile.outputs.release_type != 'none'
|
|
140
|
+
- name: Release Please (automation token)
|
|
141
|
+
id: release_automation
|
|
142
|
+
if: steps.profile.outputs.release_type != 'none' && steps.credentials.outputs.token_source == 'configured'
|
|
128
143
|
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5
|
|
129
144
|
with:
|
|
130
|
-
token: ${{ secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN
|
|
145
|
+
token: ${{ secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN }}
|
|
131
146
|
config-file: release-please-config.json
|
|
132
147
|
release-type: ${{ steps.profile.outputs.legacy_release_type }}
|
|
148
|
+
- name: Release Please (workflow token)
|
|
149
|
+
id: release_workflow
|
|
150
|
+
if: steps.profile.outputs.release_type != 'none' && steps.credentials.outputs.token_source != 'configured'
|
|
151
|
+
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5
|
|
152
|
+
with:
|
|
153
|
+
token: ${{ github.token }}
|
|
154
|
+
config-file: release-please-config.json
|
|
155
|
+
release-type: ${{ steps.profile.outputs.legacy_release_type }}
|
|
156
|
+
- name: Normalize Release Please outputs
|
|
157
|
+
id: release
|
|
158
|
+
if: steps.profile.outputs.release_type != 'none'
|
|
159
|
+
env:
|
|
160
|
+
AUTOMATION_RELEASE_CREATED: ${{ steps.release_automation.outputs.release_created }}
|
|
161
|
+
AUTOMATION_TAG_NAME: ${{ steps.release_automation.outputs.tag_name }}
|
|
162
|
+
AUTOMATION_PRS_CREATED: ${{ steps.release_automation.outputs.prs_created }}
|
|
163
|
+
WORKFLOW_RELEASE_CREATED: ${{ steps.release_workflow.outputs.release_created }}
|
|
164
|
+
WORKFLOW_TAG_NAME: ${{ steps.release_workflow.outputs.tag_name }}
|
|
165
|
+
WORKFLOW_PRS_CREATED: ${{ steps.release_workflow.outputs.prs_created }}
|
|
166
|
+
run: |
|
|
167
|
+
set -euo pipefail
|
|
168
|
+
# Exactly one of the two Release Please steps runs, so selecting the
|
|
169
|
+
# source by a non-empty release_created is deterministic. The stable
|
|
170
|
+
# release step id keeps the job outputs and downstream jobs reading
|
|
171
|
+
# steps.release.outputs.* unchanged.
|
|
172
|
+
if [ -n "$AUTOMATION_RELEASE_CREATED" ]; then
|
|
173
|
+
{
|
|
174
|
+
echo "release_created=$AUTOMATION_RELEASE_CREATED"
|
|
175
|
+
echo "tag_name=$AUTOMATION_TAG_NAME"
|
|
176
|
+
echo "prs_created=$AUTOMATION_PRS_CREATED"
|
|
177
|
+
} >> "$GITHUB_OUTPUT"
|
|
178
|
+
else
|
|
179
|
+
{
|
|
180
|
+
echo "release_created=$WORKFLOW_RELEASE_CREATED"
|
|
181
|
+
echo "tag_name=$WORKFLOW_TAG_NAME"
|
|
182
|
+
echo "prs_created=$WORKFLOW_PRS_CREATED"
|
|
183
|
+
} >> "$GITHUB_OUTPUT"
|
|
184
|
+
fi
|
|
133
185
|
- name: Normalize generated release PR draft state
|
|
134
186
|
if: steps.release.outcome == 'success'
|
|
135
187
|
env:
|
|
136
|
-
|
|
137
|
-
|
|
188
|
+
# The credential selected by the validation step is reused verbatim
|
|
189
|
+
# for every release-PR shell operation: the configured token only
|
|
190
|
+
# when it validated, github.token after fallback. The token value
|
|
191
|
+
# lives only in this masked env expression, never in step outputs.
|
|
192
|
+
AUTO_MERGE: ${{ steps.credentials.outputs.auto_merge }}
|
|
193
|
+
GH_TOKEN: ${{ steps.credentials.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN) || github.token }}
|
|
138
194
|
run: |
|
|
139
195
|
set -euo pipefail
|
|
140
196
|
mapfile -t release_prs < <(
|
|
@@ -152,7 +208,7 @@ jobs:
|
|
|
152
208
|
|
|
153
209
|
for pr in "${release_prs[@]}"; do
|
|
154
210
|
PR_DRAFT=$(gh pr view "$pr" --repo "$GITHUB_REPOSITORY" --json isDraft --jq '.isDraft')
|
|
155
|
-
if [ "$
|
|
211
|
+
if [ "$AUTO_MERGE" = true ]; then
|
|
156
212
|
if [ "$PR_DRAFT" = true ]; then
|
|
157
213
|
gh pr ready "$pr" --repo "$GITHUB_REPOSITORY"
|
|
158
214
|
fi
|
|
@@ -160,22 +216,18 @@ jobs:
|
|
|
160
216
|
if [ "$PR_DRAFT" = false ]; then
|
|
161
217
|
gh pr ready --undo "$pr" --repo "$GITHUB_REPOSITORY"
|
|
162
218
|
fi
|
|
163
|
-
echo "::notice title=Manual release merge required::Release Please created or updated a version pull request. No
|
|
219
|
+
echo "::notice title=Manual release merge required::Release Please created or updated a version pull request. No valid automation token is available (absent or rejected by GitHub), so release PRs are left in draft and need manual readiness before validation and merge workflows trigger."
|
|
164
220
|
fi
|
|
165
221
|
done
|
|
166
222
|
- name: Leave release pull request for manual merge
|
|
167
223
|
if: steps.release.outputs.prs_created == 'true' && steps.credentials.outputs.auto_merge != 'true'
|
|
168
|
-
env:
|
|
169
|
-
HAS_AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN != '' || secrets.RELEASE_PLEASE_TOKEN != '' }}
|
|
170
224
|
run: |
|
|
171
|
-
|
|
172
|
-
echo "::notice title=Manual release merge required::Release Please created or updated a version pull request. Configure CODE_FOUNDRY_TOKEN or RELEASE_PLEASE_TOKEN to enable guarded auto-merge when downstream release workflows require it."
|
|
173
|
-
fi
|
|
225
|
+
echo "::notice title=Manual release merge required::Release Please created or updated a version pull request. Configure a valid CODE_FOUNDRY_TOKEN or RELEASE_PLEASE_TOKEN to enable guarded auto-merge when downstream release workflows require it."
|
|
174
226
|
|
|
175
227
|
- name: Merge generated version pull requests
|
|
176
228
|
if: steps.credentials.outputs.auto_merge == 'true'
|
|
177
229
|
env:
|
|
178
|
-
GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN || github.token }}
|
|
230
|
+
GH_TOKEN: ${{ steps.credentials.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN) || github.token }}
|
|
179
231
|
run: |
|
|
180
232
|
set -euo pipefail
|
|
181
233
|
mapfile -t release_prs < <(
|
|
@@ -388,8 +440,11 @@ jobs:
|
|
|
388
440
|
actions: write
|
|
389
441
|
contents: read
|
|
390
442
|
env:
|
|
391
|
-
|
|
392
|
-
|
|
443
|
+
# The release job validates the configured automation token and exposes
|
|
444
|
+
# the selection; the post hook reuses the same selected credential so a
|
|
445
|
+
# rejected long-lived token is never used after fallback.
|
|
446
|
+
RELEASE_PLEASE_TOKEN: ${{ needs.release.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN) || github.token }}
|
|
447
|
+
GH_TOKEN: ${{ needs.release.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN || secrets.RELEASE_PLEASE_TOKEN) || github.token }}
|
|
393
448
|
steps:
|
|
394
449
|
- name: Checkout repository
|
|
395
450
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.34.10](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.9...v0.34.10) (2026-08-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **release:** validate automation token before Release Please ([654094f](https://github.com/0xPlayerOne/code-foundry/commit/654094f452a4a6351de247aa82bf2448d7ea79c6))
|
|
9
|
+
|
|
3
10
|
## [0.34.9](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.8...v0.34.9) (2026-08-02)
|
|
4
11
|
|
|
5
12
|
|
package/docs/RELEASES.md
CHANGED
|
@@ -71,17 +71,26 @@ its manifest.
|
|
|
71
71
|
|
|
72
72
|
## Pull request permissions
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
`
|
|
76
|
-
|
|
77
|
-
the
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
The release job validates the configured automation token
|
|
75
|
+
(`CODE_FOUNDRY_TOKEN`, falling back to `RELEASE_PLEASE_TOKEN`) against the
|
|
76
|
+
current repository with an authenticated REST probe before any write. When no
|
|
77
|
+
automation token is configured, or the configured token is rejected by GitHub
|
|
78
|
+
(observed with long-lived fine-grained tokens that GitHub rejects with HTTP
|
|
79
|
+
403 even on REST), the release job fails over to the repository's short-lived
|
|
80
|
+
`GITHUB_TOKEN`. In that mode, Code Foundry opens or updates the version pull
|
|
81
|
+
request, leaves it for manual merge, and completes the release job
|
|
82
|
+
successfully. The token value is never printed or written to step outputs.
|
|
83
|
+
|
|
84
|
+
Guarded automatic merging and the downstream workflows triggered by the
|
|
85
|
+
resulting release are enabled only when the configured automation token was
|
|
86
|
+
validated successfully; a rejected token never falls through to any write.
|
|
87
|
+
Configure a valid, narrowly scoped `CODE_FOUNDRY_TOKEN` or
|
|
88
|
+
`RELEASE_PLEASE_TOKEN` repository or organization secret to enable guarded
|
|
89
|
+
automatic merging and downstream workflows triggered by the resulting
|
|
90
|
+
release. The token needs `contents`, `issues`, and `pull-requests` write
|
|
91
|
+
permissions. Code Foundry validates every changed path in the generated
|
|
92
|
+
version pull request before using the token to merge it, waits for the
|
|
93
|
+
required checks to finish, and then polls the pull request's
|
|
85
94
|
`mergeStateStatus` until it is `CLEAN`, or `UNSTABLE` with `mergeable`
|
|
86
95
|
`MERGEABLE`, before merging. Non-required checks that branch policy does not
|
|
87
96
|
require (for example external code review still running after every required
|
package/package.json
CHANGED