code-foundry 0.40.3 → 1.0.0
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/draft-pr.yml +1 -3
- package/.github/workflows/draft-pr_self-ci.yml +0 -1
- package/.github/workflows/release-pr.yml +4 -6
- package/.github/workflows/release-pr_self-ci.yml +0 -1
- package/.github/workflows/release.yml +9 -11
- package/.github/workflows/release_self-ci.yml +0 -1
- package/CHANGELOG.md +11 -0
- package/docs/RELEASES.md +3 -3
- package/docs/WORKFLOWS.md +1 -1
- package/package.json +1 -1
- package/src/commands/doctor.mjs +3 -4
- package/src/commands/release.mjs +3 -3
- package/src/lib/github-doctor.mjs +3 -4
|
@@ -16,8 +16,6 @@ on:
|
|
|
16
16
|
secrets:
|
|
17
17
|
CODE_FOUNDRY_TOKEN:
|
|
18
18
|
required: false
|
|
19
|
-
RELEASE_PLEASE_TOKEN:
|
|
20
|
-
required: false
|
|
21
19
|
|
|
22
20
|
permissions:
|
|
23
21
|
contents: read
|
|
@@ -46,7 +44,7 @@ jobs:
|
|
|
46
44
|
- name: Create
|
|
47
45
|
if: steps.check-pr.outputs.existing == '0'
|
|
48
46
|
env:
|
|
49
|
-
AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN
|
|
47
|
+
AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN }}
|
|
50
48
|
GITHUB_TOKEN: ${{ github.token }}
|
|
51
49
|
HEAD_REF: ${{ github.ref_name }}
|
|
52
50
|
run: |
|
|
@@ -11,15 +11,13 @@ on:
|
|
|
11
11
|
secrets:
|
|
12
12
|
CODE_FOUNDRY_TOKEN:
|
|
13
13
|
required: false
|
|
14
|
-
RELEASE_PLEASE_TOKEN:
|
|
15
|
-
required: false
|
|
16
14
|
|
|
17
15
|
permissions:
|
|
18
16
|
contents: write
|
|
19
17
|
pull-requests: write
|
|
20
18
|
|
|
21
19
|
env:
|
|
22
|
-
HAS_AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN != ''
|
|
20
|
+
HAS_AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN != '' }}
|
|
23
21
|
PROMOTION_BRANCH: code-foundry/promote/staging-to-main
|
|
24
22
|
|
|
25
23
|
jobs:
|
|
@@ -158,7 +156,7 @@ jobs:
|
|
|
158
156
|
if: steps.check-pr.outputs.commits != '0' && steps.check-pr.outputs.tree_equal != 'true' && steps.check-pr.outputs.release_only != 'true'
|
|
159
157
|
env:
|
|
160
158
|
GH_TOKEN: ${{ github.token }}
|
|
161
|
-
AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN
|
|
159
|
+
AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN }}
|
|
162
160
|
run: |
|
|
163
161
|
set -euo pipefail
|
|
164
162
|
MAIN_SHA=$(git rev-parse origin/main)
|
|
@@ -202,7 +200,7 @@ jobs:
|
|
|
202
200
|
- name: Create
|
|
203
201
|
if: steps.check-pr.outputs.existing == '0' && steps.check-pr.outputs.commits != '0' && steps.check-pr.outputs.tree_equal != 'true' && steps.check-pr.outputs.release_only != 'true'
|
|
204
202
|
env:
|
|
205
|
-
GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN ||
|
|
203
|
+
GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN || github.token }}
|
|
206
204
|
run: |
|
|
207
205
|
DATE=$(date +%Y-%m-%d)
|
|
208
206
|
BODY_FILE="$RUNNER_TEMP/release-pr.md"
|
|
@@ -264,7 +262,7 @@ jobs:
|
|
|
264
262
|
)
|
|
265
263
|
if [ "$HAS_AUTOMATION_TOKEN" != true ]; then
|
|
266
264
|
CREATE_ARGS+=(--field draft=true)
|
|
267
|
-
echo "::notice title=Manual PR readiness required::Created draft promotion PR because no automation token is configured. Configure CODE_FOUNDRY_TOKEN
|
|
265
|
+
echo "::notice title=Manual PR readiness required::Created draft promotion PR because no automation token is configured. Configure CODE_FOUNDRY_TOKEN, or mark this PR ready manually to trigger validation."
|
|
268
266
|
fi
|
|
269
267
|
|
|
270
268
|
# Prefer the configured automation token for the write, but
|
|
@@ -26,8 +26,6 @@ on:
|
|
|
26
26
|
secrets:
|
|
27
27
|
CODE_FOUNDRY_TOKEN:
|
|
28
28
|
required: false
|
|
29
|
-
RELEASE_PLEASE_TOKEN:
|
|
30
|
-
required: false
|
|
31
29
|
STAGING_DEPLOY_KEY:
|
|
32
30
|
required: false
|
|
33
31
|
NPM_TOKEN:
|
|
@@ -123,8 +121,8 @@ jobs:
|
|
|
123
121
|
- name: Detect release credentials
|
|
124
122
|
id: credentials
|
|
125
123
|
env:
|
|
126
|
-
HAS_AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN != ''
|
|
127
|
-
GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN
|
|
124
|
+
HAS_AUTOMATION_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN != '' }}
|
|
125
|
+
GH_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN }}
|
|
128
126
|
run: |
|
|
129
127
|
set -euo pipefail
|
|
130
128
|
# NiftyLeague rejects long-lived fine-grained automation tokens with
|
|
@@ -141,7 +139,7 @@ jobs:
|
|
|
141
139
|
echo "auto_merge=false" >> "$GITHUB_OUTPUT"
|
|
142
140
|
echo "token_source=fallback" >> "$GITHUB_OUTPUT"
|
|
143
141
|
if [ "$HAS_AUTOMATION_TOKEN" = true ]; then
|
|
144
|
-
echo "::warning title=Release token fallback::The configured CODE_FOUNDRY_TOKEN
|
|
142
|
+
echo "::warning title=Release token fallback::The configured CODE_FOUNDRY_TOKEN was rejected by GitHub; failing over to the short-lived workflow token. The version pull request will be left for manual merge."
|
|
145
143
|
fi
|
|
146
144
|
fi
|
|
147
145
|
- name: Release Please (automation token)
|
|
@@ -149,7 +147,7 @@ jobs:
|
|
|
149
147
|
if: steps.profile.outputs.release_type != 'none' && steps.credentials.outputs.token_source == 'configured'
|
|
150
148
|
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5
|
|
151
149
|
with:
|
|
152
|
-
token: ${{ secrets.CODE_FOUNDRY_TOKEN
|
|
150
|
+
token: ${{ secrets.CODE_FOUNDRY_TOKEN }}
|
|
153
151
|
config-file: release-please-config.json
|
|
154
152
|
release-type: ${{ steps.profile.outputs.legacy_release_type }}
|
|
155
153
|
- name: Release Please (workflow token)
|
|
@@ -197,7 +195,7 @@ jobs:
|
|
|
197
195
|
# when it validated, github.token after fallback. The token value
|
|
198
196
|
# lives only in this masked env expression, never in step outputs.
|
|
199
197
|
AUTO_MERGE: ${{ steps.credentials.outputs.auto_merge }}
|
|
200
|
-
GH_TOKEN: ${{ steps.credentials.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN
|
|
198
|
+
GH_TOKEN: ${{ steps.credentials.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN) || github.token }}
|
|
201
199
|
run: |
|
|
202
200
|
set -euo pipefail
|
|
203
201
|
mapfile -t release_prs < <(
|
|
@@ -229,12 +227,12 @@ jobs:
|
|
|
229
227
|
- name: Leave release pull request for manual merge
|
|
230
228
|
if: steps.release.outputs.prs_created == 'true' && steps.credentials.outputs.auto_merge != 'true'
|
|
231
229
|
run: |
|
|
232
|
-
echo "::notice title=Manual release merge required::Release Please created or updated a version pull request. Configure a valid CODE_FOUNDRY_TOKEN
|
|
230
|
+
echo "::notice title=Manual release merge required::Release Please created or updated a version pull request. Configure a valid CODE_FOUNDRY_TOKEN to enable guarded auto-merge when downstream release workflows require it."
|
|
233
231
|
|
|
234
232
|
- name: Merge generated version pull requests
|
|
235
233
|
if: steps.credentials.outputs.auto_merge == 'true'
|
|
236
234
|
env:
|
|
237
|
-
GH_TOKEN: ${{ steps.credentials.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN
|
|
235
|
+
GH_TOKEN: ${{ steps.credentials.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN) || github.token }}
|
|
238
236
|
run: |
|
|
239
237
|
set -euo pipefail
|
|
240
238
|
mapfile -t release_prs < <(
|
|
@@ -420,8 +418,8 @@ jobs:
|
|
|
420
418
|
# The release job validates the configured automation token and exposes
|
|
421
419
|
# the selection; the post hook reuses the same selected credential so a
|
|
422
420
|
# rejected long-lived token is never used after fallback.
|
|
423
|
-
|
|
424
|
-
GH_TOKEN: ${{ needs.release.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN
|
|
421
|
+
CODE_FOUNDRY_TOKEN: ${{ needs.release.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN) || github.token }}
|
|
422
|
+
GH_TOKEN: ${{ needs.release.outputs.token_source == 'configured' && (secrets.CODE_FOUNDRY_TOKEN) || github.token }}
|
|
425
423
|
steps:
|
|
426
424
|
- name: Checkout repository
|
|
427
425
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -30,6 +30,5 @@ jobs:
|
|
|
30
30
|
runtime-ref: ${{ github.sha }}
|
|
31
31
|
secrets:
|
|
32
32
|
CODE_FOUNDRY_TOKEN: ${{ secrets.CODE_FOUNDRY_TOKEN }}
|
|
33
|
-
RELEASE_PLEASE_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }}
|
|
34
33
|
STAGING_DEPLOY_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
|
|
35
34
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.40.3...v1.0.0) (2026-09-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* automation now reads CODE_FOUNDRY_TOKEN only. Repos still carrying just RELEASE_PLEASE_TOKEN fall back to the short-lived workflow token (manual merges) until they set CODE_FOUNDRY_TOKEN.
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* remove RELEASE_PLEASE_TOKEN fallback in favor of CODE_FOUNDRY_TOKEN ([3f6ba1c](https://github.com/0xPlayerOne/code-foundry/commit/3f6ba1c3cb0db698a7c75485b9e4201720e930d7))
|
|
13
|
+
|
|
3
14
|
## [0.40.3](https://github.com/0xPlayerOne/code-foundry/compare/v0.40.2...v0.40.3) (2026-09-05)
|
|
4
15
|
|
|
5
16
|
|
package/docs/RELEASES.md
CHANGED
|
@@ -104,7 +104,7 @@ its manifest.
|
|
|
104
104
|
## Pull request permissions
|
|
105
105
|
|
|
106
106
|
The release job validates the configured automation token
|
|
107
|
-
(`CODE_FOUNDRY_TOKEN
|
|
107
|
+
(`CODE_FOUNDRY_TOKEN`) against the
|
|
108
108
|
current repository with an authenticated REST probe before any write. When no
|
|
109
109
|
automation token is configured, or the configured token is rejected by GitHub
|
|
110
110
|
(observed with long-lived fine-grained tokens that GitHub rejects with HTTP
|
|
@@ -116,8 +116,8 @@ successfully. The token value is never printed or written to step outputs.
|
|
|
116
116
|
Guarded automatic merging and the downstream workflows triggered by the
|
|
117
117
|
resulting release are enabled only when the configured automation token was
|
|
118
118
|
validated successfully; a rejected token never falls through to any write.
|
|
119
|
-
Configure a valid, narrowly scoped `CODE_FOUNDRY_TOKEN`
|
|
120
|
-
|
|
119
|
+
Configure a valid, narrowly scoped `CODE_FOUNDRY_TOKEN`
|
|
120
|
+
repository or organization secret to enable guarded
|
|
121
121
|
automatic merging and downstream workflows triggered by the resulting
|
|
122
122
|
release. The token needs `contents`, `issues`, and `pull-requests` write
|
|
123
123
|
permissions. Code Foundry validates every changed path in the generated
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -158,7 +158,7 @@ when GitHub rejects pull request creation through the Actions integration.
|
|
|
158
158
|
|
|
159
159
|
For this reconciliation path, maintainer PATs and administrator roles are not
|
|
160
160
|
authorized bypasses; the job deliberately authenticates with `github.token`,
|
|
161
|
-
not `CODE_FOUNDRY_TOKEN
|
|
161
|
+
not `CODE_FOUNDRY_TOKEN`.
|
|
162
162
|
|
|
163
163
|
## GitHub Stacks
|
|
164
164
|
|
package/package.json
CHANGED
package/src/commands/doctor.mjs
CHANGED
|
@@ -120,16 +120,15 @@ export function doctor(root, options = {}) {
|
|
|
120
120
|
console.log('Remote CI, Test, Security, CodeQL, and release runtimes are loaded by the tiered validation orchestrator.')
|
|
121
121
|
if (options.github) {
|
|
122
122
|
const github = doctorGithub(target)
|
|
123
|
-
/** @type {{ codeFoundryTokenPresent?: boolean,
|
|
123
|
+
/** @type {{ codeFoundryTokenPresent?: boolean, stagingDeployKeyPresent?: boolean }} */
|
|
124
124
|
const secrets = github.details.secrets ?? {}
|
|
125
125
|
for (const message of github.warnings) warn(`GitHub: ${message}`)
|
|
126
126
|
for (const message of github.errors) error(`GitHub: ${message}`)
|
|
127
127
|
console.log(`GitHub doctor inspected ${github.details.repository}.`)
|
|
128
128
|
const codeFoundryToken = secrets.codeFoundryTokenPresent ? 'present' : 'absent'
|
|
129
|
-
const releasePleaseToken = secrets.releasePleaseTokenPresent ? 'present' : 'absent'
|
|
130
129
|
const stagingDeployKey = secrets.stagingDeployKeyPresent ? 'present' : 'absent'
|
|
131
|
-
console.log(`GitHub secrets: CODE_FOUNDRY_TOKEN=${codeFoundryToken},
|
|
132
|
-
if (!secrets.codeFoundryTokenPresent
|
|
130
|
+
console.log(`GitHub secrets: CODE_FOUNDRY_TOKEN=${codeFoundryToken}, STAGING_DEPLOY_KEY=${stagingDeployKey}`)
|
|
131
|
+
if (!secrets.codeFoundryTokenPresent) {
|
|
133
132
|
warn('GitHub token routing fallback: PR creation will remain draft and requires manual ready-for-review to trigger validation.')
|
|
134
133
|
}
|
|
135
134
|
}
|
package/src/commands/release.mjs
CHANGED
|
@@ -533,7 +533,7 @@ export function dispatchPostReleaseHook(root, options) {
|
|
|
533
533
|
const repository = process.env.GITHUB_REPOSITORY
|
|
534
534
|
if (!repository) throw new Error('GITHUB_REPOSITORY is required for post-release hooks.')
|
|
535
535
|
if (!options.tag) throw new Error('--tag is required for post-release hooks.')
|
|
536
|
-
const decision = selectHookDelivery({ mode: options.mode, tokenPresent: Boolean(process.env.
|
|
536
|
+
const decision = selectHookDelivery({ mode: options.mode, tokenPresent: Boolean(process.env.CODE_FOUNDRY_TOKEN) })
|
|
537
537
|
console.log(JSON.stringify({ repository, tag: options.tag, workflow: options.workflow, ...decision }, null, 2))
|
|
538
538
|
if (decision.delivery === 'disabled' || decision.delivery === 'release-event') return decision
|
|
539
539
|
if (decision.delivery === 'unavailable') throw new Error(decision.reason)
|
|
@@ -551,7 +551,7 @@ export function dispatchPostReleaseHook(root, options) {
|
|
|
551
551
|
'--ref', options.tag,
|
|
552
552
|
'--field', `release-tag=${options.tag}`,
|
|
553
553
|
'--field', `delivery-key=${key}`,
|
|
554
|
-
], { cwd: resolve(root), stdio: 'inherit', env: { ...process.env, GH_TOKEN: process.env.
|
|
554
|
+
], { cwd: resolve(root), stdio: 'inherit', env: { ...process.env, GH_TOKEN: process.env.CODE_FOUNDRY_TOKEN } })
|
|
555
555
|
if (result.status !== 0) throw new Error(`Failed to dispatch post-release workflow ${options.workflow}.`)
|
|
556
556
|
return { ...decision, deliveryKey: key, dispatched: true }
|
|
557
557
|
}
|
|
@@ -648,7 +648,7 @@ function treeChangedPaths(root, from, to) {
|
|
|
648
648
|
|
|
649
649
|
/** @param {string} root @param {string[]} args @returns {{ status: number | null, stdout: string, stderr: string }} */
|
|
650
650
|
function ghSpawn(root, args) {
|
|
651
|
-
const token = process.env.
|
|
651
|
+
const token = process.env.CODE_FOUNDRY_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN
|
|
652
652
|
return spawnSync('gh', args, { cwd: resolve(root), encoding: 'utf8', env: { ...process.env, ...(token ? { GH_TOKEN: token } : {}) } })
|
|
653
653
|
}
|
|
654
654
|
|
|
@@ -43,16 +43,15 @@ export function doctorGithub(root) {
|
|
|
43
43
|
const secretNames = Array.isArray(secrets) ? secrets.map(/** @param {any} secret */ (secret) => secret.name) : []
|
|
44
44
|
details.secrets = {
|
|
45
45
|
codeFoundryTokenPresent: secretNames.includes('CODE_FOUNDRY_TOKEN'),
|
|
46
|
-
releasePleaseTokenPresent: secretNames.includes('RELEASE_PLEASE_TOKEN'),
|
|
47
46
|
stagingDeployKeyPresent: secretNames.includes('STAGING_DEPLOY_KEY'),
|
|
48
47
|
}
|
|
49
|
-
if (!details.secrets.codeFoundryTokenPresent
|
|
50
|
-
warnings.push('CODE_FOUNDRY_TOKEN
|
|
48
|
+
if (!details.secrets.codeFoundryTokenPresent) {
|
|
49
|
+
warnings.push('CODE_FOUNDRY_TOKEN is absent. PR workflow triggers and automation may require manual readiness.')
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
const config = readConfig(root)
|
|
54
53
|
if (['workflow-dispatch', 'dispatch'].includes(config.post_release_mode) && config.post_release !== 'false' && !details.secrets.codeFoundryTokenPresent && !details.secrets.releasePleaseTokenPresent) {
|
|
55
|
-
errors.push('post-release workflow-dispatch mode requires CODE_FOUNDRY_TOKEN
|
|
54
|
+
errors.push('post-release workflow-dispatch mode requires CODE_FOUNDRY_TOKEN to be present.')
|
|
56
55
|
}
|
|
57
56
|
const credentialChecks = {
|
|
58
57
|
npmTokenPresent: secretNames.includes('NPM_TOKEN'),
|