code-foundry 1.39.2 → 1.40.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.
@@ -6,8 +6,15 @@ if [ -z "$(git diff --cached --name-only)" ]; then
6
6
  exit 0
7
7
  fi
8
8
 
9
- if command -v npx >/dev/null 2>&1 && npx --yes code-foundry@__VERSION__ pre-commit; then
10
- exit 0
9
+ # Prefer a runtime the repository already depends on. A repository opts into
10
+ # the gate by depending on code-foundry; one that does not keeps the
11
+ # whitespace guard and stays offline. Nothing is fetched at commit time.
12
+ if [ -x node_modules/.bin/code-foundry ]; then
13
+ exec node_modules/.bin/code-foundry pre-commit
14
+ fi
15
+
16
+ if [ -f src/runtime.mjs ]; then
17
+ exec node src/runtime.mjs pre-commit
11
18
  fi
12
19
 
13
20
  git diff --cached --check
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.40.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.39.3...v1.40.0) (2026-10-02)
4
+
5
+
6
+ ### Features
7
+
8
+ * **sync:** add dependency_updater setting to gate Dependabot and scaffold Renovate ([#692](https://github.com/0xPlayerOne/code-foundry/issues/692)) ([15805de](https://github.com/0xPlayerOne/code-foundry/commit/15805dee09a93ca168bbc00dbc3c3af36a40e7bf))
9
+
10
+ ## [1.39.3](https://github.com/0xPlayerOne/code-foundry/compare/v1.39.2...v1.39.3) (2026-10-01)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **hooks:** run the gate from a local dependency, not npx ([#688](https://github.com/0xPlayerOne/code-foundry/issues/688)) ([d256b69](https://github.com/0xPlayerOne/code-foundry/commit/d256b69b8f89f0041a01c53cc51af32fe582b5dc))
16
+
3
17
  ## [1.39.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.39.1...v1.39.2) (2026-10-01)
4
18
 
5
19
 
@@ -34,21 +34,22 @@ to require an existing mise configuration.
34
34
 
35
35
  ## Repository and runtime
36
36
 
37
- | Key | Values | Notes |
38
- | ----------------------- | -------------------------------------------- | -------------------------------------------------------------------- |
39
- | `version` | `1` | Configuration schema version. |
40
- | `profile` | `auto`, `application`, `monorepo`, `minimal` | Repository shape; `auto` detects it. |
41
- | `languages` | comma-separated language names | Supported values are `typescript`, `rust`, `python`, and `solidity`. |
42
- | `package_manager` | `bun`, `pnpm`, `yarn`, `npm`, `none` | JavaScript package-manager policy. |
43
- | `toolchain` | `auto`, `native`, `mise` | Environment setup policy. |
44
- | `runtime_repository` | `OWNER/REPO` | Source of reusable workflows and runtime code. |
45
- | `runtime_ref` | tag or commit | Runtime version used by generated callers. |
46
- | `features` | `all` or a list | See [Feature selection](#feature-selection). |
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. |
49
- | `codeql` | `auto`, `true`, `false` | Enable CodeQL when the repository and GitHub plan support it. |
50
- | `dependency_review` | `auto`, `true`, `false` | Enable Dependency Review when supported. |
51
- | `runner` and `*_runner` | GitHub runner labels | Override the default runner per workflow. |
37
+ | Key | Values | Notes |
38
+ | ----------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------- |
39
+ | `version` | `1` | Configuration schema version. |
40
+ | `profile` | `auto`, `application`, `monorepo`, `minimal` | Repository shape; `auto` detects it. |
41
+ | `languages` | comma-separated language names | Supported values are `typescript`, `rust`, `python`, and `solidity`. |
42
+ | `package_manager` | `bun`, `pnpm`, `yarn`, `npm`, `none` | JavaScript package-manager policy. |
43
+ | `toolchain` | `auto`, `native`, `mise` | Environment setup policy. |
44
+ | `runtime_repository` | `OWNER/REPO` | Source of reusable workflows and runtime code. |
45
+ | `runtime_ref` | tag or commit | Runtime version used by generated callers. |
46
+ | `features` | `all` or a list | See [Feature selection](#feature-selection). |
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. |
49
+ | `dependency_updater` | `dependabot`, `renovate`, `none` | Which dependency-update bot sync manages; see [Feature selection](#feature-selection). |
50
+ | `codeql` | `auto`, `true`, `false` | Enable CodeQL when the repository and GitHub plan support it. |
51
+ | `dependency_review` | `auto`, `true`, `false` | Enable Dependency Review when supported. |
52
+ | `runner` and `*_runner` | GitHub runner labels | Override the default runner per workflow. |
52
53
 
53
54
  For `codeql: auto` and `dependency_review: auto`, public repositories use the
54
55
  available GitHub security checks and private repositories require the relevant
@@ -82,6 +83,22 @@ remain aliases for compatibility. Other selectable features are:
82
83
  - `release` — run Release Please and optional package publication.
83
84
  - `dependabot` — install the language-aware Dependabot configuration.
84
85
 
86
+ The `dependency_updater` key selects which dependency-update bot `sync`
87
+ manages, and an explicit value wins over the `dependabot` feature (including
88
+ `features: all`):
89
+
90
+ - `dependabot` (default) — render `.github/dependabot.yml` whenever the
91
+ `dependabot` feature is selected; existing repositories are unaffected.
92
+ - `renovate` — never render `.github/dependabot.yml` and remove an existing
93
+ one; install `renovate.json` from the runtime template only when the
94
+ repository has none. A repository-owned `renovate.json` is never modified.
95
+ - `none` — never render `.github/dependabot.yml`, remove an existing one, and
96
+ install nothing.
97
+
98
+ Installing `renovate.json` does not schedule update runs: a repository still
99
+ needs the Renovate GitHub App or a self-hosted runner. The `billing_paused`
100
+ Dependabot pause applies only while `dependency_updater` is `dependabot`.
101
+
85
102
  The release-integrity and OpenCode Security callers are installed independently
86
103
  of feature selection. OpenCode Security is disabled unless the repository or
87
104
  organization variable `OPENCODE_SECURITY` is `true` and the
package/docs/WORKFLOWS.md CHANGED
@@ -141,7 +141,9 @@ While paused, set `billing_paused: true` in `.github/code-foundry.yml` and run a
141
141
  sync so the rendered `dependabot.yml` disables version updates
142
142
  (`open-pull-requests-limit: 0`, monthly cadence). Remove the flag and sync to
143
143
  restore updates when billing resumes. `npx code-foundry ci status` reports the
144
- Dependabot state, and `pause` warns when updates are still active.
144
+ Dependabot state, and `pause` warns when updates are still active. A repository
145
+ whose `dependency_updater` is `renovate` or `none` has no Dependabot
146
+ configuration to pause.
145
147
 
146
148
  ## Standard workflow responsibilities
147
149
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "1.39.2",
3
+ "version": "1.40.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": {
@@ -145,6 +145,14 @@ function synchronize(options) {
145
145
  if (!['true', 'false'].includes(draftProtection)) {
146
146
  throw new Error(`Unsupported draft_protection: ${draftProtection}; use true or false.`)
147
147
  }
148
+ // Validate the dependency-update bot policy before any sync writes so a
149
+ // typo fails fast instead of leaving a half-switched updater behind.
150
+ const dependencyUpdater = configured(config.dependency_updater, 'dependabot')
151
+ if (!['renovate', 'dependabot', 'none'].includes(dependencyUpdater)) {
152
+ throw new Error(
153
+ `Unsupported dependency_updater: ${dependencyUpdater}; use renovate, dependabot, or none.`
154
+ )
155
+ }
148
156
  const obsoleteConfigKeys = [
149
157
  'opencode_security',
150
158
  ...(workflow === 'direct' ? ['staging_validation_mode'] : []),
@@ -260,9 +268,6 @@ function synchronize(options) {
260
268
  if (file === 'LICENSE' && license !== 'preserve' && license !== 'none') continue
261
269
  if (file === '.github/CODEOWNERS' && existsSync(destination)) continue
262
270
  let content = readFileSync(sourceFile)
263
- if (file === '.githooks/pre-commit') {
264
- content = Buffer.from(renderHook(sourceFile, source))
265
- }
266
271
  if (file === 'release-please-config.json') {
267
272
  content = Buffer.from(renderReleaseConfig(target, sourceFile))
268
273
  }
@@ -338,6 +343,33 @@ function synchronize(options) {
338
343
  }
339
344
  }
340
345
 
346
+ // `dependency_updater` owns the dependency-update bot contract, and an
347
+ // explicit value wins over the features gate above: a repository that
348
+ // leaves Dependabot must not keep a previously rendered dependabot.yml,
349
+ // and a Renovate repository gets a config only when it does not already
350
+ // own one (repository-owned renovate.json is never modified).
351
+ if (dependencyUpdater !== 'dependabot') {
352
+ const destination = join(target, '.github/dependabot.yml')
353
+ if (existsSync(destination)) {
354
+ changed.push('.github/dependabot.yml')
355
+ if (dryRun)
356
+ console.log(
357
+ `Would remove .github/dependabot.yml; dependency_updater selects ${dependencyUpdater}.`
358
+ )
359
+ else rmSync(destination, { force: true })
360
+ }
361
+ }
362
+ if (dependencyUpdater === 'renovate') {
363
+ const destination = join(target, 'renovate.json')
364
+ if (!existsSync(destination)) {
365
+ const template = join(source, 'src/templates/renovate.json')
366
+ if (!existsSync(template))
367
+ throw new Error('Template file missing: src/templates/renovate.json')
368
+ changed.push('renovate.json')
369
+ writeOrReport(destination, readFileSync(template), dryRun)
370
+ }
371
+ }
372
+
341
373
  // Preserved (repository-owned) workflows may reference the runtime directly,
342
374
  // for example a hand-maintained Cloudflare preview caller. Advance their
343
375
  // plain semver pins to the synced runtime ref so a stale hand-added pin
@@ -589,26 +621,16 @@ function renderReleaseConfig(target, sourceFile) {
589
621
  return `${JSON.stringify(mergeReleaseConfig(target, sourceFile), null, 2)}\n`
590
622
  }
591
623
 
592
- /**
593
- * The hook runs `npx code-foundry@<version>` on every commit, so the version
594
- * is substituted at generation time rather than resolved at run time. A
595
- * mutable dist-tag there would let any publish under that tag run code on
596
- * every developer's machine at commit time; pinning means the gate a
597
- * repository received is the gate that generated it.
598
- *
599
- * @param {string} sourceFile the template path
600
- * @param {string} sourceRoot the package root that carries package.json
601
- */
602
- function renderHook(sourceFile, sourceRoot) {
603
- return readFileSync(sourceFile, 'utf8').replaceAll('__VERSION__', readPackageVersion(sourceRoot))
604
- }
605
-
606
624
  /** @param {string} file @param {string} languages @param {string} features @param {Record<string, string>} config */
607
625
  function shouldInclude(file, languages, features, config) {
608
626
  if (file === 'ruff.toml') return includesValue(languages, 'python')
609
627
  if (file === '.oxfmtrc.json' || file === '.oxlintrc.json')
610
628
  return includesValue(languages, 'typescript')
611
- if (file === '.github/dependabot.yml') return includesValue(features, 'dependabot')
629
+ if (file === '.github/dependabot.yml')
630
+ return (
631
+ configured(config.dependency_updater, 'dependabot') === 'dependabot' &&
632
+ includesValue(features, 'dependabot')
633
+ )
612
634
  // The OpenCode Security caller is installed in every repository so the
613
635
  // OPENCODE_SECURITY repository variable can opt a repository in (or out)
614
636
  // without a configuration change. The detect job keeps the scan off unless
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": ["config:recommended"],
4
+ "draftPR": true,
5
+ "labels": ["dependencies"],
6
+ "packageRules": [
7
+ {
8
+ "description": "Non-major dependency updates ride one grouped draft PR per cycle.",
9
+ "matchUpdateTypes": ["minor", "patch", "pin", "digest"],
10
+ "groupName": "non-major dependency updates"
11
+ },
12
+ {
13
+ "description": "Major dependency bumps share one grouped draft PR per cycle so a batch reads as one upgrade decision.",
14
+ "matchUpdateTypes": ["major"],
15
+ "groupName": "major dependency updates"
16
+ }
17
+ ]
18
+ }