code-foundry 1.33.2 → 1.34.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/cloudflare-deploy.yml +2 -2
- package/CHANGELOG.md +14 -0
- package/docs/CONFIGURATION.md +9 -0
- package/docs/WORKFLOWS.md +8 -0
- package/package.json +1 -1
- package/src/commands/ci.mjs +42 -0
- package/src/commands/sync.mjs +33 -1
|
@@ -285,12 +285,12 @@ jobs:
|
|
|
285
285
|
set -euo pipefail
|
|
286
286
|
if [ "$WRANGLER_VERSION" = local ]; then
|
|
287
287
|
if [ -n "$BUILD_SCRIPT" ]; then
|
|
288
|
-
wrangler=(
|
|
288
|
+
wrangler=(npx --no-install wrangler)
|
|
289
289
|
else
|
|
290
290
|
wrangler=(npx --no-install wrangler)
|
|
291
291
|
fi
|
|
292
292
|
elif [ -n "$BUILD_SCRIPT" ]; then
|
|
293
|
-
wrangler=(
|
|
293
|
+
wrangler=(npx -y "wrangler@$WRANGLER_VERSION")
|
|
294
294
|
else
|
|
295
295
|
wrangler=(npx -y "wrangler@$WRANGLER_VERSION")
|
|
296
296
|
fi
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.34.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.33.3...v1.34.0) (2026-09-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* billing-paused-dependabot ([#651](https://github.com/0xPlayerOne/code-foundry/issues/651)) ([eda05b5](https://github.com/0xPlayerOne/code-foundry/commit/eda05b5cfa28fc7314ec33a94e539a1660549511))
|
|
9
|
+
|
|
10
|
+
## [1.33.3](https://github.com/0xPlayerOne/code-foundry/compare/v1.33.2...v1.33.3) (2026-09-29)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **ci:** launch wrangler under Node in the cloudflare deploy step ([#649](https://github.com/0xPlayerOne/code-foundry/issues/649)) ([e797934](https://github.com/0xPlayerOne/code-foundry/commit/e7979343d3ff4d1fe5dc1520568a501cce0c47f3))
|
|
16
|
+
|
|
3
17
|
## [1.33.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.33.1...v1.33.2) (2026-09-26)
|
|
4
18
|
|
|
5
19
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -45,6 +45,7 @@ to require an existing mise configuration.
|
|
|
45
45
|
| `runtime_ref` | tag or commit | Runtime version used by generated callers. |
|
|
46
46
|
| `features` | `all` or a list | See [Feature selection](#feature-selection). |
|
|
47
47
|
| `draft_protection` | `true`, `false` | Skip generated runner-heavy gates for draft PRs when false. |
|
|
48
|
+
| `billing_paused` | `true`, `false` | Disable Dependabot version updates while CI billing is paused. |
|
|
48
49
|
| `codeql` | `auto`, `true`, `false` | Enable CodeQL when the repository and GitHub plan support it. |
|
|
49
50
|
| `dependency_review` | `auto`, `true`, `false` | Enable Dependency Review when supported. |
|
|
50
51
|
| `runner` and `*_runner` | GitHub runner labels | Override the default runner per workflow. |
|
|
@@ -62,6 +63,14 @@ intentionally runs generated gates for draft PRs. Cloudflare reusable-workflow
|
|
|
62
63
|
callers use their equivalent `draft-protection` input. These opt-outs affect
|
|
63
64
|
CI/deployment gates only and do not disable Draft Guard or draft-PR automation.
|
|
64
65
|
|
|
66
|
+
The `CI_BILLING_PAUSED` repository variable gates every generated workflow job,
|
|
67
|
+
but Dependabot's update runs execute under the `dynamic` event and never see
|
|
68
|
+
that variable. Set `billing_paused: true` alongside the variable and re-run
|
|
69
|
+
`sync` so the rendered `dependabot.yml` sets `open-pull-requests-limit: 0` and
|
|
70
|
+
drops the update cadence to monthly for every ecosystem. Removing the flag and
|
|
71
|
+
syncing again restores the active template. `npx code-foundry ci status` reports
|
|
72
|
+
when a paused repository still has Dependabot updates active.
|
|
73
|
+
|
|
65
74
|
## Feature selection
|
|
66
75
|
|
|
67
76
|
Use `features: all` or a comma/space-separated list. The canonical validation
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -128,6 +128,14 @@ second toggle: the `OPENCODE_SECURITY` repository or organization variable
|
|
|
128
128
|
(`true`/`false`) is its only enablement control, so individual repositories can
|
|
129
129
|
opt in or out without a code change.
|
|
130
130
|
|
|
131
|
+
Dependabot is the one billable runner source the variable cannot gate: its
|
|
132
|
+
update runs execute under the `dynamic` event, outside every job-level guard.
|
|
133
|
+
While paused, set `billing_paused: true` in `.github/code-foundry.yml` and run a
|
|
134
|
+
sync so the rendered `dependabot.yml` disables version updates
|
|
135
|
+
(`open-pull-requests-limit: 0`, monthly cadence). Remove the flag and sync to
|
|
136
|
+
restore updates when billing resumes. `npx code-foundry ci status` reports the
|
|
137
|
+
Dependabot state, and `pause` warns when updates are still active.
|
|
138
|
+
|
|
131
139
|
## Standard workflow responsibilities
|
|
132
140
|
|
|
133
141
|
| Workflow | Responsibility |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.34.0",
|
|
4
4
|
"description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
|
|
5
5
|
"homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
|
|
6
6
|
"bugs": {
|
package/src/commands/ci.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from 'node:child_process'
|
|
4
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
5
|
+
import { readConfig } from '../lib/config.mjs'
|
|
4
6
|
|
|
5
7
|
export const CI_BILLING_PAUSED_VARIABLE = 'CI_BILLING_PAUSED'
|
|
6
8
|
export const CI_BILLING_BACKUP_VARIABLE = 'CI_BILLING_GATE_BACKUP'
|
|
@@ -26,11 +28,13 @@ export function manageCiBilling(root, action) {
|
|
|
26
28
|
const backup = backupText ? parseBackup(backupText) : null
|
|
27
29
|
|
|
28
30
|
if (action === 'status') {
|
|
31
|
+
const dependabot = dependabotPauseState(root)
|
|
29
32
|
const result = {
|
|
30
33
|
repository,
|
|
31
34
|
paused,
|
|
32
35
|
requiredCheck: CI_BILLING_REQUIRED_CHECK,
|
|
33
36
|
backupPresent: Boolean(backup),
|
|
37
|
+
dependabot,
|
|
34
38
|
}
|
|
35
39
|
console.log(JSON.stringify(result, null, 2))
|
|
36
40
|
return result
|
|
@@ -87,12 +91,25 @@ export function manageCiBilling(root, action) {
|
|
|
87
91
|
setVariable(repository, CI_BILLING_PAUSED_VARIABLE, 'true')
|
|
88
92
|
const cancelledRuns = cancelActiveRuns(repository)
|
|
89
93
|
for (const change of changes) updateRuleset(repository, change.ruleset)
|
|
94
|
+
const dependabot = dependabotPauseState(root)
|
|
90
95
|
const result = {
|
|
91
96
|
repository,
|
|
92
97
|
paused: true,
|
|
93
98
|
changed: true,
|
|
94
99
|
cancelledRuns,
|
|
95
100
|
rulesets: changes.map((change) => change.ruleset.name),
|
|
101
|
+
// Dependabot update runs execute under the `dynamic` event, so the
|
|
102
|
+
// repository variable alone never stops them. Surface the gap every
|
|
103
|
+
// time so a paused repository cannot keep burning minutes silently.
|
|
104
|
+
dependabot,
|
|
105
|
+
...(dependabot.active
|
|
106
|
+
? {
|
|
107
|
+
dependabotWarning:
|
|
108
|
+
'Dependabot version updates are still active and are not gated by ' +
|
|
109
|
+
`${CI_BILLING_PAUSED_VARIABLE}. Set billing_paused: true in .github/code-foundry.yml ` +
|
|
110
|
+
'and run a sync so dependabot.yml renders open-pull-requests-limit: 0.',
|
|
111
|
+
}
|
|
112
|
+
: {}),
|
|
96
113
|
}
|
|
97
114
|
console.log(JSON.stringify(result, null, 2))
|
|
98
115
|
return result
|
|
@@ -133,6 +150,31 @@ export function manageCiBilling(root, action) {
|
|
|
133
150
|
return result
|
|
134
151
|
}
|
|
135
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Inspect whether Dependabot version updates are still active in the working
|
|
155
|
+
* tree. The repository variable gates workflow jobs but not Dependabot's own
|
|
156
|
+
* `dynamic` update runs, so a paused repository also needs dependabot.yml to
|
|
157
|
+
* render `open-pull-requests-limit: 0` (the `billing_paused` config does this
|
|
158
|
+
* during sync). An ecosystem without an explicit limit of 0 counts as active
|
|
159
|
+
* because Dependabot defaults the limit to 5.
|
|
160
|
+
*
|
|
161
|
+
* @param {string} root
|
|
162
|
+
* @returns {{ configured: boolean, active: boolean, file: string }}
|
|
163
|
+
*/
|
|
164
|
+
export function dependabotPauseState(root) {
|
|
165
|
+
const file = '.github/dependabot.yml'
|
|
166
|
+
const path = `${root.replace(/\/$/, '')}/${file}`
|
|
167
|
+
if (!existsSync(path)) return { configured: false, active: false, file }
|
|
168
|
+
const source = readFileSync(path, 'utf8')
|
|
169
|
+
const configured =
|
|
170
|
+
readConfig(`${root.replace(/\/$/, '')}/.github/code-foundry.yml`).billing_paused === 'true'
|
|
171
|
+
const blocks = source
|
|
172
|
+
.split(/(?=^ - package-ecosystem: )/m)
|
|
173
|
+
.filter((block) => block.startsWith(' - package-ecosystem: '))
|
|
174
|
+
const active = blocks.some((block) => !/^ open-pull-requests-limit: 0(\s|#|$)/m.test(block))
|
|
175
|
+
return { configured, active, file }
|
|
176
|
+
}
|
|
177
|
+
|
|
136
178
|
/** @param {any} ruleset */
|
|
137
179
|
export function buildPausedRuleset(ruleset) {
|
|
138
180
|
const requiredRuleIndexes = (ruleset.rules ?? []).flatMap(
|
package/src/commands/sync.mjs
CHANGED
|
@@ -823,12 +823,21 @@ function removeWorkflowBlock(content, blockId) {
|
|
|
823
823
|
* part of the configured language set, respectively; weekly updater runs
|
|
824
824
|
* fail when an ecosystem has no manifests to read, so unconfigured
|
|
825
825
|
* ecosystems are dropped instead of left to error.
|
|
826
|
+
*
|
|
827
|
+
* The billing pause must also cover Dependabot: its update runs execute as
|
|
828
|
+
* Actions workflows under the `dynamic` event, so the `CI_BILLING_PAUSED`
|
|
829
|
+
* repository variable that gates every workflow job cannot stop them. When
|
|
830
|
+
* `billing_paused: true` is configured, version updates are disabled by
|
|
831
|
+
* rendering `open-pull-requests-limit: 0` and dropping the cadence to
|
|
832
|
+
* monthly; `schedule` is a required key, so the ecosystem blocks stay
|
|
833
|
+
* structurally valid and a later sync with the flag removed restores the
|
|
834
|
+
* template verbatim.
|
|
826
835
|
* @param {string} content
|
|
827
836
|
* @param {Record<string,string>} config
|
|
828
837
|
* @param {string} languages
|
|
829
838
|
* @returns {string}
|
|
830
839
|
*/
|
|
831
|
-
function renderDependabot(content, config, languages) {
|
|
840
|
+
export function renderDependabot(content, config, languages) {
|
|
832
841
|
let rendered = content
|
|
833
842
|
if (!includesValue(languages, 'rust')) {
|
|
834
843
|
rendered = stripDependabotEcosystem(rendered, 'cargo')
|
|
@@ -839,10 +848,33 @@ function renderDependabot(content, config, languages) {
|
|
|
839
848
|
if (!includesValue(languages, 'python')) {
|
|
840
849
|
rendered = stripDependabotEcosystem(rendered, 'pip')
|
|
841
850
|
}
|
|
851
|
+
if (configured(config.billing_paused, 'false') === 'true') {
|
|
852
|
+
rendered = pauseDependabot(rendered)
|
|
853
|
+
}
|
|
842
854
|
if (isStagingRelease(config.git_workflow)) return rendered
|
|
843
855
|
return rendered.replaceAll('target-branch: staging', 'target-branch: main')
|
|
844
856
|
}
|
|
845
857
|
|
|
858
|
+
/**
|
|
859
|
+
* Disable Dependabot version updates for every remaining ecosystem. The
|
|
860
|
+
* transformations are regex-based so they hold for any ecosystem count and
|
|
861
|
+
* any future template default; an unchanged file after both replacements
|
|
862
|
+
* means the template stopped defining schedules or limits, which is a loud
|
|
863
|
+
* template drift the next sync test will catch.
|
|
864
|
+
* @param {string} content
|
|
865
|
+
* @returns {string}
|
|
866
|
+
*/
|
|
867
|
+
function pauseDependabot(content) {
|
|
868
|
+
const limited = content.replace(
|
|
869
|
+
/^(\s*)open-pull-requests-limit:\s*\d+\s*$/gm,
|
|
870
|
+
`$1open-pull-requests-limit: 0 # billing_paused: version updates disabled`
|
|
871
|
+
)
|
|
872
|
+
return limited.replace(
|
|
873
|
+
/^(\s*)interval:\s*weekly\s*$/gm,
|
|
874
|
+
`$1interval: monthly # billing_paused: reduced cadence`
|
|
875
|
+
)
|
|
876
|
+
}
|
|
877
|
+
|
|
846
878
|
/**
|
|
847
879
|
* Remove one package-ecosystem update block from a dependabot template.
|
|
848
880
|
* Blocks are split on their leading list marker so removal never disturbs
|