code-foundry 0.30.1 → 0.30.3
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/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/cli.mjs +5 -3
- package/src/commands/fleet.mjs +10 -2
- package/src/commands/sync.mjs +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.30.3](https://github.com/0xPlayerOne/code-foundry/compare/v0.30.2...v0.30.3) (2026-07-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **fleet:** branch upgrades from remote staging ([58d4389](https://github.com/0xPlayerOne/code-foundry/commit/58d43890436789ec5289e0aaeea71dea0375a140))
|
|
9
|
+
|
|
10
|
+
## [0.30.2](https://github.com/0xPlayerOne/code-foundry/compare/v0.30.1...v0.30.2) (2026-07-29)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **fleet:** support explicit repository exclusions ([2c3a641](https://github.com/0xPlayerOne/code-foundry/commit/2c3a641814de392457f94f3581f01e5b625056ee))
|
|
16
|
+
|
|
3
17
|
## [0.30.1](https://github.com/0xPlayerOne/code-foundry/compare/v0.30.0...v0.30.1) (2026-07-29)
|
|
4
18
|
|
|
5
19
|
|
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { syncRepository } from './commands/sync.mjs'
|
|
|
11
11
|
|
|
12
12
|
const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)))
|
|
13
13
|
|
|
14
|
-
/** @typedef {{ target: string, root: string, dryRun: boolean, force: boolean, github: boolean, createPr: boolean, base: string, head: string, tag: string, workflow: string, mode: string, version: string, releaseSubcommand?: string, fleetSubcommand?: string }} Options */
|
|
14
|
+
/** @typedef {{ target: string, root: string, dryRun: boolean, force: boolean, github: boolean, createPr: boolean, exclude: string[], base: string, head: string, tag: string, workflow: string, mode: string, version: string, releaseSubcommand?: string, fleetSubcommand?: string }} Options */
|
|
15
15
|
/** @typedef {{ command: string, options: Options }} ParsedArgs */
|
|
16
16
|
|
|
17
17
|
const usage = `code-foundry — initialize and maintain agent-ready repositories
|
|
@@ -42,6 +42,7 @@ Options:
|
|
|
42
42
|
--root PATH Fleet root containing repositories (default: current directory)
|
|
43
43
|
--create-pr Create isolated upgrade branches and pull requests
|
|
44
44
|
--version TAG Runtime tag to report in fleet upgrade branches
|
|
45
|
+
--exclude NAME Skip a repository path or owner/name in fleet operations
|
|
45
46
|
-h, --help Show this help
|
|
46
47
|
`
|
|
47
48
|
|
|
@@ -57,7 +58,7 @@ function parseArgs(argv) {
|
|
|
57
58
|
const hasCommand = Boolean(first && !first.startsWith('-'))
|
|
58
59
|
const command = hasCommand ? /** @type {string} */ (argv.shift()) : 'init'
|
|
59
60
|
/** @type {Options} */
|
|
60
|
-
const options = { target: process.cwd(), root: process.cwd(), dryRun: false, force: false, github: false, createPr: false, base: 'main', head: 'staging', tag: '', workflow: '', mode: 'auto', version: `v${readPackageVersion(packageRoot)}` }
|
|
61
|
+
const options = { target: process.cwd(), root: process.cwd(), dryRun: false, force: false, github: false, createPr: false, exclude: [], base: 'main', head: 'staging', tag: '', workflow: '', mode: 'auto', version: `v${readPackageVersion(packageRoot)}` }
|
|
61
62
|
|
|
62
63
|
if (command === 'release') {
|
|
63
64
|
const subcommand = argv.shift() ?? ''
|
|
@@ -90,6 +91,7 @@ function parseArgs(argv) {
|
|
|
90
91
|
else if (arg === '--root') options.root = argv.shift() ?? fail('--root requires a path')
|
|
91
92
|
else if (arg === '--create-pr') options.createPr = true
|
|
92
93
|
else if (arg === '--version') options.version = argv.shift() ?? fail('--version requires a tag')
|
|
94
|
+
else if (arg === '--exclude') options.exclude.push(argv.shift() ?? fail('--exclude requires a name'))
|
|
93
95
|
else fail(`unknown option: ${arg}; run --help for the supported options`)
|
|
94
96
|
}
|
|
95
97
|
|
|
@@ -132,7 +134,7 @@ function main() {
|
|
|
132
134
|
try {
|
|
133
135
|
const root = resolve(options.root)
|
|
134
136
|
if (options.fleetSubcommand === 'status') console.log(JSON.stringify(discoverRepositories(root), null, 2))
|
|
135
|
-
else upgradeFleet(root, packageRoot, { createPr: options.createPr, dryRun: options.dryRun, force: options.force, version: options.version })
|
|
137
|
+
else upgradeFleet(root, packageRoot, { createPr: options.createPr, dryRun: options.dryRun, force: options.force, version: options.version, exclude: options.exclude })
|
|
136
138
|
} catch (error) {
|
|
137
139
|
fail(error instanceof Error ? error.message : String(error))
|
|
138
140
|
}
|
package/src/commands/fleet.mjs
CHANGED
|
@@ -29,11 +29,15 @@ export function discoverRepositories(root) {
|
|
|
29
29
|
return result.sort((a, b) => a.path.localeCompare(b.path))
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/** @param {string} root @param {string} source @param {{ createPr?: boolean, dryRun?: boolean, force?: boolean, version: string }} options */
|
|
32
|
+
/** @param {string} root @param {string} source @param {{ createPr?: boolean, dryRun?: boolean, force?: boolean, version: string, exclude?: string[] }} options */
|
|
33
33
|
export function upgradeFleet(root, source, options) {
|
|
34
34
|
const repositories = discoverRepositories(root)
|
|
35
35
|
const report = []
|
|
36
36
|
for (const repository of repositories) {
|
|
37
|
+
if ((options.exclude ?? []).some((value) => repository.path === value || repository.repository === value || repository.path.endsWith(`/${value}`))) {
|
|
38
|
+
report.push({ path: repository.path, status: 'skipped', reason: 'excluded by fleet policy' })
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
37
41
|
if (!repository.configured) {
|
|
38
42
|
report.push({ path: repository.path, status: 'skipped', reason: 'missing .github/code-foundry.yml' })
|
|
39
43
|
continue
|
|
@@ -62,7 +66,11 @@ function upgradeRepository(repository, source, version) {
|
|
|
62
66
|
const branch = `codex/code-foundry-upgrade-${version.replace(/^v/, '')}`
|
|
63
67
|
const temporary = mkdtempSync(join(tmpdir(), 'code-foundry-fleet-'))
|
|
64
68
|
try {
|
|
65
|
-
const
|
|
69
|
+
const fetch = spawnSync('git', ['-C', repository.path, 'fetch', 'origin', 'staging', '--quiet'], { encoding: 'utf8' })
|
|
70
|
+
if (fetch.status !== 0) return { path: repository.path, status: 'skipped', reason: fetch.stderr.trim() || 'unable to refresh staging baseline' }
|
|
71
|
+
const baseline = spawnSync('git', ['-C', repository.path, 'rev-parse', 'origin/staging'], { encoding: 'utf8' })
|
|
72
|
+
if (baseline.status !== 0) return { path: repository.path, status: 'skipped', reason: 'remote staging branch is unavailable' }
|
|
73
|
+
const add = spawnSync('git', ['-C', repository.path, 'worktree', 'add', '-b', branch, temporary, baseline.stdout.trim()], { encoding: 'utf8' })
|
|
66
74
|
if (add.status !== 0) return { path: repository.path, status: 'skipped', reason: add.stderr.trim() || 'unable to create isolated worktree' }
|
|
67
75
|
const result = syncRepository({ target: temporary, source, force: false })
|
|
68
76
|
if (!result.changed.length) return { path: repository.path, status: 'unchanged', branch }
|
package/src/commands/sync.mjs
CHANGED
|
@@ -56,7 +56,7 @@ export function syncRepository(options) {
|
|
|
56
56
|
const missing = Object.keys(defaults).filter((key) => !(key in existingConfig))
|
|
57
57
|
if (missing.length) {
|
|
58
58
|
const current = readFileSync(configPath, 'utf8').trimEnd()
|
|
59
|
-
const additions = missing.map((key) =>
|
|
59
|
+
const additions = missing.map((key) => renderConfigLine(key, defaults[key])).join('\n')
|
|
60
60
|
writeOrReport(configPath, `${current}\n${additions}\n`, dryRun)
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -64,7 +64,8 @@ export function syncRepository(options) {
|
|
|
64
64
|
const languages = configured(config.languages, detectLanguages(target).join(','))
|
|
65
65
|
const features = configured(config.features, 'all')
|
|
66
66
|
const runtimeRepository = configured(config.runtime_repository, '0xPlayerOne/code-foundry')
|
|
67
|
-
const
|
|
67
|
+
const sourceRuntimeRef = `v${readPackageVersion(source)}`
|
|
68
|
+
let runtimeRef = configured(config.runtime_ref, sourceRuntimeRef)
|
|
68
69
|
const toolchain = configured(config.toolchain, 'auto')
|
|
69
70
|
const overlays = overlayPolicy(target, config)
|
|
70
71
|
if (!['auto', 'native', 'mise'].includes(toolchain)) {
|
|
@@ -73,6 +74,18 @@ export function syncRepository(options) {
|
|
|
73
74
|
const license = configured(config.license, existsSync(join(target, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later')
|
|
74
75
|
const changed = []
|
|
75
76
|
|
|
77
|
+
// Keep normal semver pins current during sync while preserving intentional
|
|
78
|
+
// refs such as `main`, `staging`, or a custom immutable SHA.
|
|
79
|
+
if (existingConfig.runtime_ref && /^v\d+\.\d+\.\d+$/.test(existingConfig.runtime_ref) && existingConfig.runtime_ref !== sourceRuntimeRef) {
|
|
80
|
+
runtimeRef = sourceRuntimeRef
|
|
81
|
+
const current = readFileSync(configPath, 'utf8')
|
|
82
|
+
const updated = current.replace(/^runtime_ref:\s*.*$/m, `runtime_ref: ${sourceRuntimeRef}`)
|
|
83
|
+
if (updated !== current) {
|
|
84
|
+
changed.push('.github/code-foundry.yml')
|
|
85
|
+
writeOrReport(configPath, updated, dryRun)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
76
89
|
for (const file of standardFiles) {
|
|
77
90
|
if (!shouldInclude(file, languages, features, config)) continue
|
|
78
91
|
const sourceFile = sourcePath(source, file)
|
|
@@ -259,7 +272,9 @@ function createDefaultConfig(root, source) {
|
|
|
259
272
|
}
|
|
260
273
|
|
|
261
274
|
/** @param {Record<string,string>} config */
|
|
262
|
-
function renderConfig(config) { return `${Object.entries(config).map(([key, value]) =>
|
|
275
|
+
function renderConfig(config) { return `${Object.entries(config).map(([key, value]) => renderConfigLine(key, value)).join('\n')}\n` }
|
|
276
|
+
/** @param {string} key @param {string} value */
|
|
277
|
+
function renderConfigLine(key, value) { return value === '' ? `${key}:` : `${key}: ${value}` }
|
|
263
278
|
/** @param {string} root */
|
|
264
279
|
function readPackageVersion(root) {
|
|
265
280
|
try { return JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).version ?? '0.0.0' } catch { return '0.0.0' }
|