code-foundry 1.53.3 → 1.53.4
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 +8 -8
- package/docs/PERFORMANCE.md +1 -1
- package/package.json +1 -1
- package/src/lib/run-concurrent.mjs +45 -0
- package/src/runtime-core.mjs +24 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.53.4](https://github.com/0xPlayerOne/code-foundry/compare/v1.53.3...v1.53.4) (2026-10-30)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Performance
|
|
7
|
+
|
|
8
|
+
* **ci:** run mixed unit runners concurrently ([#821](https://github.com/0xPlayerOne/code-foundry/issues/821)) ([dac0d93](https://github.com/0xPlayerOne/code-foundry/commit/dac0d9313cc2fc6309e0f55aa45274e3dbbff767))
|
|
9
|
+
|
|
3
10
|
## [1.53.3](https://github.com/0xPlayerOne/code-foundry/compare/v1.53.2...v1.53.3) (2026-10-30)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -143,16 +150,9 @@
|
|
|
143
150
|
|
|
144
151
|
* **release:** hydrate audit blobs and refresh changing PR state ([#779](https://github.com/0xPlayerOne/code-foundry/issues/779)) ([8734ed7](https://github.com/0xPlayerOne/code-foundry/commit/8734ed77d159818cd5ff613f40a5dab796789d8a))
|
|
145
152
|
|
|
146
|
-
## [1.48.7](https://github.com/0xPlayerOne/code-foundry/compare/v1.48.6...v1.48.7) (2026-10-23)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
### Bug Fixes
|
|
150
|
-
|
|
151
|
-
* **release:** sync bun.lock workspace versions on generated release PRs ([#777](https://github.com/0xPlayerOne/code-foundry/issues/777)) ([b24bfae](https://github.com/0xPlayerOne/code-foundry/commit/b24bfae309ac7003fcc4cd57f79ddc418c27b039))
|
|
152
|
-
|
|
153
153
|
<!-- code-foundry: packaged changelog -->
|
|
154
154
|
|
|
155
155
|
---
|
|
156
156
|
|
|
157
|
-
This packaged changelog lists the 20 most recent releases;
|
|
157
|
+
This packaged changelog lists the 20 most recent releases; 275 older releases are omitted to keep the package small.
|
|
158
158
|
See the [full changelog](https://github.com/0xPlayerOne/code-foundry/blob/main/CHANGELOG.md) for the complete history.
|
package/docs/PERFORMANCE.md
CHANGED
|
@@ -31,7 +31,7 @@ changelog size and its packaged (trimmed) size as informational metrics. At
|
|
|
31
31
|
v1.44.0 the measured artifact was 280,902 packed bytes, 1,070,333 unpacked bytes,
|
|
32
32
|
and 118 files.
|
|
33
33
|
|
|
34
|
-
v1.
|
|
34
|
+
v1.53.3 main no-changelog, plus the concurrent unit runner (`src/lib/run-concurrent.mjs`): 317,788 packed, 1,226,187 unpacked, 120 files. Limits: 318,000 packed, 1,227,000 unpacked, 120 files.
|
|
35
35
|
|
|
36
36
|
The published package ships a changelog trimmed to the 20 most recent releases
|
|
37
37
|
with a link to the full history on GitHub. `scripts/package-changelog.mjs`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.53.
|
|
3
|
+
"version": "1.53.4",
|
|
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": {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Runs independent test commands at the same time so a mixed repository's
|
|
3
|
+
// unit wall time is its slowest runner, not the sum of all of them. Each line
|
|
4
|
+
// of output is prefixed with its runner's label, and the exit status is the
|
|
5
|
+
// first failing command's in the order given, so the result stays stable.
|
|
6
|
+
import { spawn } from 'node:child_process'
|
|
7
|
+
import { createInterface } from 'node:readline'
|
|
8
|
+
import { resolve } from 'node:path'
|
|
9
|
+
import { pathToFileURL } from 'node:url'
|
|
10
|
+
|
|
11
|
+
/** @typedef {{ label: string, command: string, args: string[] }} Job */
|
|
12
|
+
|
|
13
|
+
/** @param {Job} job @returns {Promise<number>} */
|
|
14
|
+
function runJob(job) {
|
|
15
|
+
return new Promise((resolvePromise) => {
|
|
16
|
+
const child = spawn(job.command, job.args, {
|
|
17
|
+
cwd: process.cwd(),
|
|
18
|
+
env: process.env,
|
|
19
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
20
|
+
})
|
|
21
|
+
const prefix = `[${job.label}] `
|
|
22
|
+
/** @param {import('node:stream').Readable} stream @param {NodeJS.WriteStream} sink */
|
|
23
|
+
const relay = (stream, sink) =>
|
|
24
|
+
createInterface({ input: stream, crlfDelay: Infinity }).on('line', (line) =>
|
|
25
|
+
sink.write(`${prefix}${line}\n`)
|
|
26
|
+
)
|
|
27
|
+
relay(child.stdout, process.stdout)
|
|
28
|
+
relay(child.stderr, process.stderr)
|
|
29
|
+
child.on('error', (error) => {
|
|
30
|
+
process.stderr.write(`${prefix}${error.message}\n`)
|
|
31
|
+
resolvePromise(1)
|
|
32
|
+
})
|
|
33
|
+
child.on('close', (code, signal) => resolvePromise(signal ? 1 : (code ?? 1)))
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** @param {Job[]} jobs */
|
|
38
|
+
export async function runConcurrent(jobs) {
|
|
39
|
+
const statuses = await Promise.all(jobs.map(runJob))
|
|
40
|
+
return statuses.find((status) => status !== 0) ?? 0
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
|
|
44
|
+
process.exitCode = await runConcurrent(JSON.parse(process.argv[2] ?? '[]'))
|
|
45
|
+
}
|
package/src/runtime-core.mjs
CHANGED
|
@@ -835,8 +835,18 @@ function ci(task) {
|
|
|
835
835
|
e2e: ['test:e2e', 'e2e'],
|
|
836
836
|
smoke: ['test:smoke', 'smoke'],
|
|
837
837
|
}
|
|
838
|
-
|
|
839
|
-
|
|
838
|
+
// Unit runners share no state, so they run together and the task takes as
|
|
839
|
+
// long as its slowest runner. Other categories may share services or ports
|
|
840
|
+
// and keep running one after another.
|
|
841
|
+
/** @type {{ label: string, command: string, args: string[] }[]} */
|
|
842
|
+
const jobs = []
|
|
843
|
+
/** @param {string} label @param {string} command @param {string[]} args */
|
|
844
|
+
const queue = (label, command, args) =>
|
|
845
|
+
task === 'unit' ? jobs.push({ label, command, args }) : run(command, args)
|
|
846
|
+
const scriptName = scriptsByTask[task]?.find((candidate) => hasScript(candidate))
|
|
847
|
+
const [scriptManager, scriptArgs] = scriptName ? packageCommand(['run', scriptName]) : [null, []]
|
|
848
|
+
const scripted = Boolean(scriptManager)
|
|
849
|
+
if (scriptName && scriptManager) queue(scriptName, scriptManager, scriptArgs)
|
|
840
850
|
const testFiles = taskTestFiles(/** @type {'unit'|'integration'|'e2e'|'smoke'} */ (task))
|
|
841
851
|
const javascriptTests = testFiles.filter((file) => /\.(?:[cm]?[jt]sx?)$/i.test(file))
|
|
842
852
|
const pythonTests = testFiles.filter((file) => /\.py$/i.test(file))
|
|
@@ -851,14 +861,16 @@ function ci(task) {
|
|
|
851
861
|
(hasLanguage('typescript') || hasLanguage('javascript') || hasLanguage('solidity')) &&
|
|
852
862
|
hasRootJavascriptProject()
|
|
853
863
|
) {
|
|
854
|
-
if (javascriptTests.length > 0 || task === 'unit')
|
|
864
|
+
if (javascriptTests.length > 0 || task === 'unit')
|
|
865
|
+
queue('bun', 'bun', ['test', ...javascriptTests])
|
|
855
866
|
}
|
|
856
867
|
|
|
857
868
|
if (hasLanguage('python') && hasRootPythonProject()) {
|
|
858
869
|
const python = existsSync(resolve(root, '.venv/bin/python'))
|
|
859
870
|
? resolve(root, '.venv/bin/python')
|
|
860
871
|
: 'python'
|
|
861
|
-
if (pythonTests.length > 0 || task === 'unit')
|
|
872
|
+
if (pythonTests.length > 0 || task === 'unit')
|
|
873
|
+
queue('pytest', python, ['-m', 'pytest', ...pythonTests])
|
|
862
874
|
}
|
|
863
875
|
|
|
864
876
|
if (hasLanguage('rust') && hasRootRustProject()) {
|
|
@@ -872,7 +884,7 @@ function ci(task) {
|
|
|
872
884
|
const args = [...testArgs]
|
|
873
885
|
if (existsSync(resolve(root, 'src/lib.rs'))) args.push('--lib')
|
|
874
886
|
if (existsSync(resolve(root, 'src/main.rs'))) args.push('--bin', packageName())
|
|
875
|
-
|
|
887
|
+
queue('cargo', 'cargo', args)
|
|
876
888
|
} else {
|
|
877
889
|
// Keep --test selection narrow; --tests includes unit targets.
|
|
878
890
|
const targets = rustTests.flatMap((file) => {
|
|
@@ -882,6 +894,13 @@ function ci(task) {
|
|
|
882
894
|
if (targets.length > 0) run('cargo', [...testArgs, ...targets])
|
|
883
895
|
}
|
|
884
896
|
}
|
|
897
|
+
|
|
898
|
+
if (jobs.length === 1) run(jobs[0].command, jobs[0].args)
|
|
899
|
+
else if (jobs.length > 1)
|
|
900
|
+
run(process.execPath, [
|
|
901
|
+
fileURLToPath(new URL('./lib/run-concurrent.mjs', import.meta.url)),
|
|
902
|
+
JSON.stringify(jobs),
|
|
903
|
+
])
|
|
885
904
|
}
|
|
886
905
|
|
|
887
906
|
function packageName() {
|