code-foundry 0.20.3 → 0.21.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.
@@ -12,6 +12,7 @@ languages="${REPO_FOUNDRY_LANGUAGES:-auto}"
12
12
  features="${REPO_FOUNDRY_FEATURES:-all}"
13
13
  package_manager="${REPO_FOUNDRY_PACKAGE_MANAGER:-auto}"
14
14
  runtime_repository="${REPO_FOUNDRY_RUNTIME_REPOSITORY:-}"
15
+ runtime_ref="${REPO_FOUNDRY_RUNTIME_REF:-}"
15
16
  bootstrap=true
16
17
  release_type="${REPO_FOUNDRY_RELEASE_TYPE:-auto}"
17
18
  npm_publish="${REPO_FOUNDRY_NPM_PUBLISH:-false}"
@@ -39,6 +40,7 @@ Options:
39
40
  ci,codeql,security,test,draft-pr,release-pr,release,dependabot
40
41
  --package-manager NAME auto, bun, pnpm, yarn, or npm
41
42
  --runtime-repository OWNER/REPO Reusable workflow runtime repository (auto from source)
43
+ --runtime-ref REF Reusable workflow runtime tag or branch
42
44
  --release-type NAME auto, node, python, rust, or simple
43
45
  --license NAME agpl-3.0-or-later, mit, preserve, or none
44
46
  --license-file PATH Use an exact custom license file
@@ -66,6 +68,7 @@ while [ "$#" -gt 0 ]; do
66
68
  --features) features="${2:?missing feature list}"; shift 2 ;;
67
69
  --package-manager) package_manager="${2:?missing package manager}"; shift 2 ;;
68
70
  --runtime-repository) runtime_repository="${2:?missing runtime repository}"; shift 2 ;;
71
+ --runtime-ref) runtime_ref="${2:?missing runtime ref}"; shift 2 ;;
69
72
  --release-type) release_type="${2:?missing release type}"; shift 2 ;;
70
73
  --license) license="${2:?missing license}"; shift 2 ;;
71
74
  --license-file) license_file="${2:?missing license file}"; shift 2 ;;
@@ -114,6 +117,7 @@ sync_args=(
114
117
  --license "$license"
115
118
  )
116
119
  if [ -n "$runtime_repository" ]; then sync_args+=(--runtime-repository "$runtime_repository"); fi
120
+ if [ -n "$runtime_ref" ]; then sync_args+=(--runtime-ref "$runtime_ref"); fi
117
121
  if [ -n "$license_file" ]; then sync_args+=(--license-file "$license_file"); fi
118
122
  if [ "$dry_run" = true ]; then sync_args+=(--check); else sync_args+=(--apply); fi
119
123
  if [ "$prune" = true ]; then sync_args+=(--prune); fi
@@ -132,6 +136,7 @@ languages="$(awk -F': ' '/^languages:/ {print $2; exit}' .github/template.yml 2>
132
136
  features="$(awk -F': ' '/^features:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
133
137
  package_manager="$(awk -F': ' '/^package_manager:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
134
138
  runtime_repository="$(awk -F': ' '/^runtime_repository:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
139
+ runtime_ref="$(awk -F': ' '/^runtime_ref:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
135
140
  release_type="$(awk -F': ' '/^release_type:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
136
141
  npm_publish="$(awk -F': ' '/^npm_publish:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
137
142
  license="$(awk -F': ' '/^license:/ {print $2; exit}' .github/template.yml 2>/dev/null || true)"
@@ -145,6 +150,7 @@ license="$(awk -F': ' '/^license:/ {print $2; exit}' .github/template.yml 2>/dev
145
150
  printf 'features: %s\n' "$features"
146
151
  printf 'package_manager: %s\n' "$package_manager"
147
152
  printf 'runtime_repository: %s\n' "$runtime_repository"
153
+ printf 'runtime_ref: %s\n' "$runtime_ref"
148
154
  printf 'release_type: %s\n' "$release_type"
149
155
  printf 'npm_publish: %s\n' "$npm_publish"
150
156
  printf 'license: %s\n' "$license"
@@ -14,6 +14,7 @@ Options:
14
14
  --features LIST all or comma-separated standard features
15
15
  --package-manager NAME auto, bun, pnpm, yarn, or npm
16
16
  --runtime-repository OWNER/REPO Reusable workflow runtime repository
17
+ --runtime-ref REF Reusable workflow runtime tag or branch
17
18
  --license NAME preserve, agpl-3.0-or-later, mit, or none
18
19
  --license-file PATH Use an exact custom license file
19
20
  --check Preview changes (default)
@@ -42,8 +43,11 @@ package_manager="${REPO_FOUNDRY_PACKAGE_MANAGER:-}"
42
43
  package_manager_set=false
43
44
  [ -n "${REPO_FOUNDRY_PACKAGE_MANAGER:-}" ] && package_manager_set=true
44
45
  runtime_repository="${REPO_FOUNDRY_RUNTIME_REPOSITORY:-}"
46
+ runtime_ref="${REPO_FOUNDRY_RUNTIME_REF:-}"
45
47
  runtime_repository_set=false
46
48
  [ -n "${REPO_FOUNDRY_RUNTIME_REPOSITORY:-}" ] && runtime_repository_set=true
49
+ runtime_ref_set=false
50
+ [ -n "${REPO_FOUNDRY_RUNTIME_REF:-}" ] && runtime_ref_set=true
47
51
  template_ref=""
48
52
  release_type="${REPO_FOUNDRY_RELEASE_TYPE:-auto}"
49
53
  npm_publish="${REPO_FOUNDRY_NPM_PUBLISH:-false}"
@@ -109,6 +113,7 @@ while [ "$#" -gt 0 ]; do
109
113
  --features) features="${2:?missing feature list}"; features_set=true; shift 2 ;;
110
114
  --package-manager) package_manager="${2:?missing package manager}"; package_manager_set=true; shift 2 ;;
111
115
  --runtime-repository) runtime_repository="${2:?missing runtime repository}"; runtime_repository_set=true; shift 2 ;;
116
+ --runtime-ref) runtime_ref="${2:?missing runtime ref}"; runtime_ref_set=true; shift 2 ;;
112
117
  --license) license="${2:?missing license}"; license_set=true; shift 2 ;;
113
118
  --license-file) license_file="${2:?missing license file}"; shift 2 ;;
114
119
  --check) mode="check"; shift ;;
@@ -140,6 +145,9 @@ if [ -f .github/template.yml ]; then
140
145
  if [ "$runtime_repository_set" = false ]; then
141
146
  runtime_repository="$(awk -F': ' '/^runtime_repository:/ {print $2; exit}' .github/template.yml)"
142
147
  fi
148
+ if [ "$runtime_ref_set" = false ]; then
149
+ runtime_ref="$(awk -F': ' '/^runtime_ref:/ {print $2; exit}' .github/template.yml)"
150
+ fi
143
151
  template_ref="$(awk -F': ' '/^template:/ {print $2; exit}' .github/template.yml)"
144
152
  if [ "$release_type_set" != true ]; then
145
153
  configured_release_type="$(awk -F': ' '/^release_type:/ {print $2; exit}' .github/template.yml)"
@@ -196,6 +204,16 @@ else
196
204
  template_root="$temp_dir/template-repo"
197
205
  fi
198
206
 
207
+ # Prefer an explicit CLI/environment value, then the target's saved contract,
208
+ # then the source template's contract, and finally the stable public runtime.
209
+ if [ -z "$runtime_ref" ] && [ -f "$template_root/.github/template.yml" ]; then
210
+ runtime_ref="$(awk -F': ' '/^runtime_ref:/ {print $2; exit}' "$template_root/.github/template.yml")"
211
+ fi
212
+ [ -n "$runtime_ref" ] || runtime_ref="v0.20.2"
213
+ case "$runtime_ref" in
214
+ ''|*[!A-Za-z0-9._/-]*) printf 'Runtime ref contains unsupported characters: %s\n' "$runtime_ref" >&2; exit 2 ;;
215
+ esac
216
+
199
217
  # Resolve the effective profile after the template is available. This gives
200
218
  # CLI flags and GitHub repository variables priority over template defaults,
201
219
  # while making automatic detection concrete in the generated profile.
@@ -206,6 +224,7 @@ if [ -f "$template_root/.github/scripts/profile.sh" ]; then
206
224
  REPO_FOUNDRY_FEATURES="$features" \
207
225
  REPO_FOUNDRY_PACKAGE_MANAGER="$package_manager" \
208
226
  REPO_FOUNDRY_RUNTIME_REPOSITORY="$runtime_repository" \
227
+ REPO_FOUNDRY_RUNTIME_REF="$runtime_ref" \
209
228
  REPO_FOUNDRY_RELEASE_TYPE="$release_type" \
210
229
  REPO_FOUNDRY_NPM_PUBLISH="$npm_publish" \
211
230
  bash "$template_root/.github/scripts/profile.sh" detect --root "$PWD"
@@ -374,19 +393,25 @@ done
374
393
  # selected runtime repository while leaving custom workflows untouched. Read
375
394
  # the source's configured runtime first so forks remain self-contained.
376
395
  source_runtime_repository=""
396
+ source_runtime_ref=""
377
397
  if [ -f "$template_root/.github/template.yml" ]; then
378
398
  source_runtime_repository="$(awk -F': ' '/^runtime_repository:/ {print $2; exit}' "$template_root/.github/template.yml")"
399
+ source_runtime_ref="$(awk -F': ' '/^runtime_ref:/ {print $2; exit}' "$template_root/.github/template.yml")"
379
400
  fi
380
401
  [ -n "$source_runtime_repository" ] || source_runtime_repository="0xPlayerOne/code-foundry"
402
+ [ -n "$source_runtime_ref" ] || source_runtime_ref="$runtime_ref"
381
403
  for file in .github/workflows/ci.yml .github/workflows/test.yml .github/workflows/security.yml .github/workflows/codeql.yml .github/workflows/draft-pr.yml .github/workflows/release-pr.yml .github/workflows/release.yml; do
382
404
  [ -f "$file" ] || continue
383
- if grep -qF "$source_runtime_repository" "$file" && [ "$source_runtime_repository" != "$runtime_repository" ]; then
405
+ if grep -qF "$source_runtime_repository@" "$file" || grep -q 'runtime-ref:' "$file"; then
384
406
  changed=$((changed + 1))
385
407
  if [ "$mode" = "check" ]; then
386
408
  printf 'Would render runtime repository in %s\n' "$file"
387
409
  else
388
410
  rendered_workflow="$(mktemp)"
389
- sed "s#${source_runtime_repository}#${runtime_repository}#g" "$file" > "$rendered_workflow"
411
+ sed -E \
412
+ -e "s#${source_runtime_repository}@[^[:space:]]+#${runtime_repository}@${runtime_ref}#g" \
413
+ -e "s#runtime-ref: [^[:space:]]+#runtime-ref: ${runtime_ref}#g" \
414
+ "$file" > "$rendered_workflow"
390
415
  mv "$rendered_workflow" "$file"
391
416
  printf 'Rendered runtime repository in %s\n' "$file"
392
417
  fi
@@ -566,6 +591,7 @@ if [ "$mode" = "apply" ]; then
566
591
  printf 'package_manager: %s\n' "$package_manager"
567
592
  fi
568
593
  printf 'runtime_repository: %s\n' "$runtime_repository"
594
+ printf 'runtime_ref: %s\n' "$runtime_ref"
569
595
  printf 'release_type: %s\n' "$release_type"
570
596
  printf 'npm_publish: %s\n' "$npm_publish"
571
597
  printf 'license: %s\n' "$license"
@@ -5,6 +5,7 @@ languages: typescript
5
5
  features: all
6
6
  package_manager: bun
7
7
  runtime_repository: 0xPlayerOne/code-foundry
8
+ runtime_ref: v0.20.2
8
9
  release_type: node
9
10
  npm_publish: true
10
11
  license: agpl-3.0-or-later
@@ -6,6 +6,7 @@ languages: auto
6
6
  features: all
7
7
  package_manager: auto
8
8
  runtime_repository: 0xPlayerOne/code-foundry
9
+ runtime_ref: v0.20.2
9
10
  release_type: auto
10
11
  npm_publish: false
11
12
  license: preserve
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.21.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.20.3...v0.21.0) (2026-07-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * **runtime:** configure reusable workflow refs ([55f20d2](https://github.com/0xPlayerOne/code-foundry/commit/55f20d278f23ece1fed1166f1cad1b15c985ee90))
9
+
3
10
  ## [0.20.3](https://github.com/0xPlayerOne/code-foundry/compare/v0.20.2...v0.20.3) (2026-07-28)
4
11
 
5
12
 
package/README.md CHANGED
@@ -42,7 +42,9 @@ runtime without extra flags. Use `--runtime-repository OWNER/REPO` (or
42
42
  `REPO_FOUNDRY_RUNTIME_REPOSITORY`) only when you want to override it. The
43
43
  selected repository is saved in `.github/template.yml` and rendered into the
44
44
  small CI, Test, Security, CodeQL, Draft PR, and Release PR wrappers
45
- automatically.
45
+ automatically. Use `--runtime-ref REF` (or `REPO_FOUNDRY_RUNTIME_REF`) to pin
46
+ those callers to a fork's release tag or branch; the selected ref is persisted
47
+ alongside the runtime repository.
46
48
 
47
49
  Normal synchronization imports only the local hook, agent-facing command,
48
50
  profile/release, initializer, doctor, ownership, and protection entrypoints.
@@ -114,7 +116,7 @@ bash .github/scripts/init-repo.sh \
114
116
 
115
117
  Supported profiles are `application`, `monorepo`, and `minimal`; use `auto` to detect one. Supported languages are `typescript`, `rust`, `python`, and `solidity`. Supported feature flags are `ci`, `codeql`, `security`, `test`, `draft-pr`, `release-pr`, `release`, and `dependabot`. Use `--prune` only when you explicitly want disabled standard workflows removed; custom workflows are always preserved. The selected profile is stored in `.github/template.yml`, which makes later syncs repeatable and lets workflows consume repository-specific settings without duplicating the template scripts.
116
118
 
117
- Profile precedence is consistent everywhere: explicit CLI flags, then `REPO_FOUNDRY_*` GitHub repository variables/environment values, then `.github/template.yml`, then automatic detection and standard defaults. Useful repository variables include `REPO_FOUNDRY_PROFILE`, `REPO_FOUNDRY_LANGUAGES`, `REPO_FOUNDRY_FEATURES`, `REPO_FOUNDRY_PACKAGE_MANAGER`, `REPO_FOUNDRY_RUNTIME_REPOSITORY`, `REPO_FOUNDRY_RUNNER`, `REPO_FOUNDRY_UNIT_RUNNER`, `REPO_FOUNDRY_CACHE_PACKAGES`, `REPO_FOUNDRY_CACHE_BUILD`, `REPO_FOUNDRY_COVERAGE_MINIMUM`, and `REPO_FOUNDRY_TURBO_REMOTE`. Use CLI flags for one-off initialization; use repository variables for local overrides that should not be committed.
119
+ Profile precedence is consistent everywhere: explicit CLI flags, then `REPO_FOUNDRY_*` GitHub repository variables/environment values, then `.github/template.yml`, then automatic detection and standard defaults. Useful repository variables include `REPO_FOUNDRY_PROFILE`, `REPO_FOUNDRY_LANGUAGES`, `REPO_FOUNDRY_FEATURES`, `REPO_FOUNDRY_PACKAGE_MANAGER`, `REPO_FOUNDRY_RUNTIME_REPOSITORY`, `REPO_FOUNDRY_RUNTIME_REF`, `REPO_FOUNDRY_RUNNER`, `REPO_FOUNDRY_UNIT_RUNNER`, `REPO_FOUNDRY_CACHE_PACKAGES`, `REPO_FOUNDRY_CACHE_BUILD`, `REPO_FOUNDRY_COVERAGE_MINIMUM`, and `REPO_FOUNDRY_TURBO_REMOTE`. Use CLI flags for one-off initialization; use repository variables for local overrides that should not be committed.
118
120
 
119
121
  Inspect the resolved profile at any time with `bash .github/scripts/profile.sh detect`; use `profile.sh get KEY` when another script needs one setting.
120
122
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "0.20.3",
3
+ "version": "0.21.0",
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",
package/src/cli.mjs CHANGED
@@ -23,6 +23,7 @@ Init/sync options:
23
23
  --features LIST all or ci,codeql,security,test,draft-pr,release-pr,release,dependabot
24
24
  --package-manager NAME auto, bun, pnpm, yarn, or npm
25
25
  --runtime-repository OWNER/REPO Reusable workflow runtime repository
26
+ --runtime-ref REF Reusable workflow runtime tag or branch
26
27
  --release-type NAME auto, node, python, rust, simple, or none
27
28
  --license NAME agpl-3.0-or-later, mit, preserve, or none
28
29
  --license-file PATH Use an exact custom license file
@@ -54,6 +55,7 @@ function parseArgs(argv) {
54
55
  // initializer can then derive the runtime from --source, which keeps
55
56
  // organization forks plug-and-play.
56
57
  runtimeRepository: process.env.REPO_FOUNDRY_RUNTIME_REPOSITORY || '',
58
+ runtimeRef: process.env.REPO_FOUNDRY_RUNTIME_REF || '',
57
59
  releaseType: process.env.REPO_FOUNDRY_RELEASE_TYPE || 'auto',
58
60
  license: process.env.REPO_FOUNDRY_LICENSE || (command === 'init' ? 'agpl-3.0-or-later' : 'preserve'),
59
61
  licenseFile: process.env.REPO_FOUNDRY_LICENSE_FILE || '',
@@ -75,6 +77,7 @@ function parseArgs(argv) {
75
77
  ['--features', 'features'],
76
78
  ['--package-manager', 'packageManager'],
77
79
  ['--runtime-repository', 'runtimeRepository'],
80
+ ['--runtime-ref', 'runtimeRef'],
78
81
  ['--release-type', 'releaseType'],
79
82
  ['--license', 'license'],
80
83
  ['--license-file', 'licenseFile'],
@@ -127,6 +130,7 @@ function main() {
127
130
  if (options.languagesSet) common.push('--languages', options.languages)
128
131
  if (options.featuresSet) common.push('--features', options.features)
129
132
  if (options.runtimeRepository) common.push('--runtime-repository', options.runtimeRepository)
133
+ if (options.runtimeRef) common.push('--runtime-ref', options.runtimeRef)
130
134
  if (options.prune) common.push('--prune')
131
135
  if (options.force) common.push('--force')
132
136
  if (options.dryRun) common.push('--check')
@@ -144,6 +148,7 @@ function main() {
144
148
  '--license', options.license,
145
149
  ]
146
150
  if (options.runtimeRepository) initArgs.push('--runtime-repository', options.runtimeRepository)
151
+ if (options.runtimeRef) initArgs.push('--runtime-ref', options.runtimeRef)
147
152
  if (options.licenseFile) initArgs.push('--license-file', options.licenseFile)
148
153
  if (options.protection) initArgs.push('--protection')
149
154
  if (options.dryRun) initArgs.push('--dry-run')