@invarn/cibuild 2.3.7 → 2.4.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/dist/cli.cjs +54 -37
- package/dist/src/cli.js +8 -0
- package/dist/src/commands/fidelity-trim.d.ts +13 -0
- package/dist/src/commands/fidelity-trim.d.ts.map +1 -0
- package/dist/src/commands/fidelity-trim.js +21 -0
- package/dist/src/commands/fidelity-trim.test.d.ts +8 -0
- package/dist/src/commands/fidelity-trim.test.d.ts.map +1 -0
- package/dist/src/commands/fidelity-trim.test.js +79 -0
- package/dist/src/yaml/steps/render-post-processor.d.ts +52 -32
- package/dist/src/yaml/steps/render-post-processor.d.ts.map +1 -1
- package/dist/src/yaml/steps/render-post-processor.js +104 -205
- package/dist/src/yaml/steps/render-post-processor.test.d.ts +7 -10
- package/dist/src/yaml/steps/render-post-processor.test.d.ts.map +1 -1
- package/dist/src/yaml/steps/render-post-processor.test.js +80 -183
- package/dist/src/yaml/steps/trim-align-corpus.test.d.ts +28 -0
- package/dist/src/yaml/steps/trim-align-corpus.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/trim-align-corpus.test.js +383 -0
- package/dist/src/yaml/steps/trim-align.d.ts +85 -0
- package/dist/src/yaml/steps/trim-align.d.ts.map +1 -0
- package/dist/src/yaml/steps/trim-align.js +348 -0
- package/dist/src/yaml/steps/trim-align.test.d.ts +11 -0
- package/dist/src/yaml/steps/trim-align.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/trim-align.test.js +258 -0
- package/dist/src/yaml/steps/ui-fidelity-preview-android.d.ts +1 -1
- package/dist/src/yaml/steps/ui-fidelity-preview-android.d.ts.map +1 -1
- package/dist/src/yaml/steps/ui-fidelity-preview-android.js +9 -0
- package/dist/src/yaml/steps/ui-fidelity-preview-android.test.js +4 -3
- package/dist/src/yaml/steps/ui-fidelity-preview.d.ts.map +1 -1
- package/dist/src/yaml/steps/ui-fidelity-preview.js +9 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.test.js +13 -3
- package/dist/src/yaml/steps/ui-fidelity-render-android.d.ts.map +1 -1
- package/dist/src/yaml/steps/ui-fidelity-render-android.js +7 -16
- package/dist/src/yaml/steps/ui-fidelity-render-android.test.js +9 -9
- package/dist/src/yaml/steps/ui-fidelity-render.js +1 -1
- package/dist/src/yaml/steps/ui-fidelity-render.test.js +25 -20
- package/package.json +3 -1
|
@@ -36,10 +36,11 @@ const FAKE_GRADLEW = [
|
|
|
36
36
|
// Fake `swift`: only the script-interpreter branch the shared trim stage uses
|
|
37
37
|
// (`swift <Trim.swift> <in> <out> <aligned> <ref>`). Writes trimmed + aligned
|
|
38
38
|
// PNGs and emits a fixed TRIMDIMS line.
|
|
39
|
-
|
|
39
|
+
// Fake `ci` covering the shared trim stage's `ci fidelity-trim` invocation.
|
|
40
|
+
const FAKE_CI = [
|
|
40
41
|
'#!/bin/bash',
|
|
41
42
|
'case "$1" in',
|
|
42
|
-
'
|
|
43
|
+
' fidelity-trim)',
|
|
43
44
|
' in_png="$2"; out_png="$3"; aligned_png="$4"',
|
|
44
45
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out_png\"",
|
|
45
46
|
' printf \'trimmed:%s\' "$(basename "$in_png")" >> "$out_png"',
|
|
@@ -56,7 +57,7 @@ function fakeToolchain() {
|
|
|
56
57
|
const bin = tempDir('ui-fidelity-android-fakebin-');
|
|
57
58
|
for (const [name, body] of [
|
|
58
59
|
['java', FAKE_JAVA],
|
|
59
|
-
['
|
|
60
|
+
['ci', FAKE_CI],
|
|
60
61
|
]) {
|
|
61
62
|
const p = join(bin, name);
|
|
62
63
|
writeFileSync(p, body + '\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-fidelity-preview.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"ui-fidelity-preview.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA6BH,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAChD,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAC/C;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,aAAa,EAAE,QAAQ,CAAC;IACxB,oEAAoE;IACpE,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrD,wDAAwD;IACxD,OAAO,EAAE,6BAA6B,EAAE,CAAC;IACzC,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,EAAE,EAAE,OAAO,CAAC;CACb;AAED,kEAAkE;AAClE,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAChD,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;CACjD;AAuBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,gBAAgB,EACrB,YAAY,EAAE,MAAM,GACnB,6BAA6B,CAgB/B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAqIzB"}
|
|
@@ -21,6 +21,7 @@ import { tmpdir } from 'node:os';
|
|
|
21
21
|
import { basename, join, resolve } from 'node:path';
|
|
22
22
|
import { DEFAULT_RENDER_SIZE, DEFAULT_SCALE, generateRenderScript, parseRenderSize, parseScale, } from './ui-fidelity-render.js';
|
|
23
23
|
import { evaluateAspectRatio, formatAspectRatioWarning, } from './fidelity-aspect-guard.js';
|
|
24
|
+
import { resolveCliJsPath } from './render-post-processor.js';
|
|
24
25
|
function runTar(args, pathPrepend) {
|
|
25
26
|
const env = pathPrepend
|
|
26
27
|
? { ...process.env, PATH: pathPrepend + ':' + (process.env.PATH ?? '') }
|
|
@@ -143,6 +144,14 @@ export function renderUiFidelityPreview(options) {
|
|
|
143
144
|
if (options.toolchainPath) {
|
|
144
145
|
env.PATH = options.toolchainPath + ':' + (process.env.PATH ?? '');
|
|
145
146
|
}
|
|
147
|
+
// Hand the script this installation's CLI entrypoint so its trim stage can
|
|
148
|
+
// spawn `fidelity-trim` without a ci on PATH (library callers like the
|
|
149
|
+
// Invarn CLI). Never override an explicitly-set entrypoint.
|
|
150
|
+
if (!env.CIBUILD_CLI_JS) {
|
|
151
|
+
const cliJs = resolveCliJsPath();
|
|
152
|
+
if (cliJs !== null)
|
|
153
|
+
env.CIBUILD_CLI_JS = cliJs;
|
|
154
|
+
}
|
|
146
155
|
const run = spawnSync('node', ['-e', script], {
|
|
147
156
|
cwd: workDir,
|
|
148
157
|
env,
|
|
@@ -52,8 +52,16 @@ const FAKE_SWIFT = [
|
|
|
52
52
|
' out="${pos[1]}"',
|
|
53
53
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out\"; printf 'fake-render' >> \"$out\"",
|
|
54
54
|
' exit 0 ;;',
|
|
55
|
-
'
|
|
56
|
-
'
|
|
55
|
+
' *) exit 0 ;;',
|
|
56
|
+
'esac',
|
|
57
|
+
].join('\n');
|
|
58
|
+
const FAKE_XCRUN = ['#!/bin/bash', 'exit 0'].join('\n');
|
|
59
|
+
// Fake `ci` covering the shared trim stage's `ci fidelity-trim` invocation.
|
|
60
|
+
const FAKE_CI = [
|
|
61
|
+
'#!/bin/bash',
|
|
62
|
+
'case "$1" in',
|
|
63
|
+
' fidelity-trim)',
|
|
64
|
+
' out_png="$3"; aligned_png="$4"',
|
|
57
65
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out_png\"; printf 'trimmed' >> \"$out_png\"",
|
|
58
66
|
' if [ -n "$aligned_png" ]; then printf \'\\x89PNG\\r\\n\\x1a\\n\' > "$aligned_png"; printf \'aligned\' >> "$aligned_png"; fi',
|
|
59
67
|
' echo "TRIMDIMS 320 640 160 320 400 800"',
|
|
@@ -61,7 +69,6 @@ const FAKE_SWIFT = [
|
|
|
61
69
|
' *) exit 0 ;;',
|
|
62
70
|
'esac',
|
|
63
71
|
].join('\n');
|
|
64
|
-
const FAKE_XCRUN = ['#!/bin/bash', 'exit 0'].join('\n');
|
|
65
72
|
function fakeToolchain() {
|
|
66
73
|
const bin = tempDir('ui-fidelity-fakebin-');
|
|
67
74
|
const swiftPath = join(bin, 'swift');
|
|
@@ -70,6 +77,9 @@ function fakeToolchain() {
|
|
|
70
77
|
const xcrunPath = join(bin, 'xcrun');
|
|
71
78
|
writeFileSync(xcrunPath, FAKE_XCRUN + '\n');
|
|
72
79
|
chmodSync(xcrunPath, 0o755);
|
|
80
|
+
const ciPath = join(bin, 'ci');
|
|
81
|
+
writeFileSync(ciPath, FAKE_CI + '\n');
|
|
82
|
+
chmodSync(ciPath, 0o755);
|
|
73
83
|
return bin;
|
|
74
84
|
}
|
|
75
85
|
function writeReference() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-fidelity-render-android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render-android.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAMpE,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,iDAAiD;AACjD,eAAO,MAAM,eAAe,6BAA8B,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC;AAE9D,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAA0B,CAAC;AAElE,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"ui-fidelity-render-android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render-android.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAMpE,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,iDAAiD;AACjD,eAAO,MAAM,eAAe,6BAA8B,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC;AAE9D,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAA0B,CAAC;AAElE,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAuhCD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAqBrF;AAED;;;GAGG;AACH,qBAAa,mCAAoC,SAAQ,gBAAgB;IACvE,yBAAyB,CACvB,OAAO,EAAE,6BAA6B,EACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAapB,OAAO,CACX,MAAM,EAAE,6BAA6B,EACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CA0EpB"}
|
|
@@ -500,20 +500,9 @@ function cleanupShippedProject() {
|
|
|
500
500
|
|
|
501
501
|
// ---- render stage ----
|
|
502
502
|
//
|
|
503
|
-
//
|
|
504
|
-
//
|
|
505
|
-
//
|
|
506
|
-
|
|
507
|
-
function runSwift(args) {
|
|
508
|
-
var result = cp.spawnSync('swift', args, { encoding: 'utf-8', maxBuffer: 16 * 1024 * 1024 });
|
|
509
|
-
if (result.stdout) process.stdout.write(result.stdout);
|
|
510
|
-
if (result.stderr) process.stderr.write(result.stderr);
|
|
511
|
-
if (result.error) {
|
|
512
|
-
result.status = result.status == null ? 127 : result.status;
|
|
513
|
-
result.stderr = (result.stderr || '') + String(result.error.message || result.error);
|
|
514
|
-
}
|
|
515
|
-
return result;
|
|
516
|
-
}
|
|
503
|
+
// Trim/align runs through the shared trim stage's runTrimHelper (the pure-JS
|
|
504
|
+
// helper inside the ci binary — the same bytes iOS uses), so this step has no
|
|
505
|
+
// platform-toolchain dependency and runs on macOS and Linux workers alike.
|
|
517
506
|
|
|
518
507
|
// Runs the project's Roborazzi record task once, from the project root, so
|
|
519
508
|
// Gradle resolves the task in whichever module declares it. Prefers the shipped
|
|
@@ -692,7 +681,7 @@ function renderScreens(renderable, projectRoot) {
|
|
|
692
681
|
entry.source_digest = __fidSourceDigest(packageFiles, referenceBytes);
|
|
693
682
|
}
|
|
694
683
|
log('rendered ' + entry.screen + ' -> ' + relative);
|
|
695
|
-
trimRenderedImage(entry, outputPath
|
|
684
|
+
trimRenderedImage(entry, outputPath);
|
|
696
685
|
// Signal A: the render emits a per-node layout dump into a roborazzi
|
|
697
686
|
// output dir (named "<Screen>.layout.json" or "...render<Screen>.layout.json").
|
|
698
687
|
// Locate it the same way as the PNG and derive structural facts; absent or
|
|
@@ -1160,8 +1149,10 @@ export function generateAndroidRenderScript(config) {
|
|
|
1160
1149
|
*/
|
|
1161
1150
|
export class UiFidelityRenderAndroidStepExecutor extends BaseStepExecutor {
|
|
1162
1151
|
getValidationRequirements(_inputs, _env, _config) {
|
|
1152
|
+
// No platform-toolchain requirement: trim/align is pure JS inside the ci
|
|
1153
|
+
// binary (fidelity-linux 06), so the step validates on macOS and Linux
|
|
1154
|
+
// runners alike.
|
|
1163
1155
|
return [
|
|
1164
|
-
this.requireCommand('swift', 'Swift toolchain used to run the CoreGraphics trim/align helper', 'Install Xcode (or the Swift toolchain) on the runner'),
|
|
1165
1156
|
this.requireCommand('tar', 'Archive tool used to extract the shipped Gradle project', 'Install tar on the runner'),
|
|
1166
1157
|
];
|
|
1167
1158
|
}
|
|
@@ -57,14 +57,14 @@ const FAKE_GRADLEW_LINES = [
|
|
|
57
57
|
'done',
|
|
58
58
|
'exit 0',
|
|
59
59
|
];
|
|
60
|
-
// Fake `
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
const
|
|
60
|
+
// Fake `ci`, providing only the branch the shared trim stage uses:
|
|
61
|
+
// `ci fidelity-trim <in> <out> <aligned> <ref>`. Overwrites <out> with a
|
|
62
|
+
// "trimmed:<in basename>" PNG, writes an "aligned:<in basename>" PNG, and
|
|
63
|
+
// emits a fixed TRIMDIMS line. FAKE_TRIM_FAIL exercises warn-and-continue.
|
|
64
|
+
const FAKE_CI_LINES = [
|
|
65
65
|
'#!/bin/bash',
|
|
66
66
|
'case "$1" in',
|
|
67
|
-
'
|
|
67
|
+
' fidelity-trim)',
|
|
68
68
|
' if [ -n "$FAKE_TRIM_FAIL" ]; then echo "trim: simulated failure" >&2; exit 1; fi',
|
|
69
69
|
' in_png="$2"; out_png="$3"; aligned_png="$4"',
|
|
70
70
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out_png\"",
|
|
@@ -84,9 +84,9 @@ function makeProject(params) {
|
|
|
84
84
|
mkdirSync(join(dir, '.ci', 'inputs'), { recursive: true });
|
|
85
85
|
const binDir = join(dir, 'bin');
|
|
86
86
|
mkdirSync(binDir, { recursive: true });
|
|
87
|
-
const
|
|
88
|
-
writeFileSync(
|
|
89
|
-
chmodSync(
|
|
87
|
+
const ciPath = join(binDir, 'ci');
|
|
88
|
+
writeFileSync(ciPath, FAKE_CI_LINES.join('\n') + '\n');
|
|
89
|
+
chmodSync(ciPath, 0o755);
|
|
90
90
|
if (params !== undefined) {
|
|
91
91
|
writeFileSync(join(dir, '.ci', 'inputs', 'params.json'), typeof params === 'string' ? params : JSON.stringify(params));
|
|
92
92
|
}
|
|
@@ -1250,7 +1250,7 @@ function buildPackageSourceMain() {
|
|
|
1250
1250
|
// crop each rendered PNG to its content bounding box right after it renders.
|
|
1251
1251
|
main = replaceOnce(main, 'function renderWithHarness(renderable, packagePath) {', RENDER_SCRIPT_TRIM_STAGE + '\nfunction renderWithHarness(renderable, packagePath) {');
|
|
1252
1252
|
main = replaceOnce(main, " log('rendered ' + entry.screen + ' -> ' + relative);", " log('rendered ' + entry.screen + ' -> ' + relative);\n" +
|
|
1253
|
-
' trimRenderedImage(entry, outputPath
|
|
1253
|
+
' trimRenderedImage(entry, outputPath);');
|
|
1254
1254
|
// Per-screen result entries gain the trimmed-render fields: the aligned
|
|
1255
1255
|
// (reference-sized) image and the rendered/logical/reference dimensions.
|
|
1256
1256
|
// They stay null until a screen renders and is trimmed.
|
|
@@ -111,15 +111,24 @@ const FAKE_SWIFT_LINES = [
|
|
|
111
111
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out\"",
|
|
112
112
|
' printf \'fake-render:%s\' "$screen" >> "$out"',
|
|
113
113
|
' exit 0 ;;',
|
|
114
|
-
'
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
' *)',
|
|
115
|
+
' exit 0 ;;',
|
|
116
|
+
'esac',
|
|
117
|
+
];
|
|
118
|
+
/**
|
|
119
|
+
* PATH-shimmed fake `ci`, providing only the branch the shared trim stage
|
|
120
|
+
* uses: `ci fidelity-trim <in> <out> <aligned> <ref>`. Overwrites <out> with a
|
|
121
|
+
* PNG marked "trimmed:<in basename>" and writes an "aligned:<in basename>" PNG
|
|
122
|
+
* so tests can prove both outputs. Emits a fixed TRIMDIMS line (rendered
|
|
123
|
+
* 320x640, reference 160x320, source 400x800). FAKE_TRIM_FAIL exercises
|
|
124
|
+
* warn-and-continue.
|
|
125
|
+
*/
|
|
126
|
+
const FAKE_CI_LINES = [
|
|
127
|
+
'#!/bin/bash',
|
|
128
|
+
'case "$1" in',
|
|
129
|
+
' fidelity-trim)',
|
|
121
130
|
' if [ -n "$FAKE_TRIM_FAIL" ]; then echo "trim: simulated failure" >&2; exit 1; fi',
|
|
122
|
-
' in_png="$
|
|
131
|
+
' in_png="$2"; out_png="$3"; aligned_png="$4"',
|
|
123
132
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out_png\"",
|
|
124
133
|
' printf \'trimmed:%s\' "$(basename "$in_png")" >> "$out_png"',
|
|
125
134
|
' if [ -n "$aligned_png" ]; then',
|
|
@@ -128,8 +137,7 @@ const FAKE_SWIFT_LINES = [
|
|
|
128
137
|
' fi',
|
|
129
138
|
' echo "TRIMDIMS 320 640 160 320 400 800"',
|
|
130
139
|
' exit 0 ;;',
|
|
131
|
-
' *)',
|
|
132
|
-
' exit 0 ;;',
|
|
140
|
+
' *) exit 0 ;;',
|
|
133
141
|
'esac',
|
|
134
142
|
];
|
|
135
143
|
/**
|
|
@@ -186,6 +194,9 @@ function makeProject(params) {
|
|
|
186
194
|
const xcrunPath = join(binDir, 'xcrun');
|
|
187
195
|
writeFileSync(xcrunPath, FAKE_XCRUN_LINES.join('\n') + '\n');
|
|
188
196
|
chmodSync(xcrunPath, 0o755);
|
|
197
|
+
const ciPath = join(binDir, 'ci');
|
|
198
|
+
writeFileSync(ciPath, FAKE_CI_LINES.join('\n') + '\n');
|
|
199
|
+
chmodSync(ciPath, 0o755);
|
|
189
200
|
if (params !== undefined) {
|
|
190
201
|
writeFileSync(join(dir, '.ci', 'inputs', 'params.json'), typeof params === 'string' ? params : JSON.stringify(params));
|
|
191
202
|
}
|
|
@@ -1016,20 +1027,14 @@ describe('render output trimming (package_source variants)', () => {
|
|
|
1016
1027
|
function readArtifact(project, relative) {
|
|
1017
1028
|
return readFileSync(artifact(project, relative), 'utf-8');
|
|
1018
1029
|
}
|
|
1019
|
-
test('trims the rendered PNG in place via the
|
|
1030
|
+
test('trims the rendered PNG in place via the ci fidelity-trim helper', async () => {
|
|
1020
1031
|
const project = makeProject({ screens: { HomeView: 'home.png' } });
|
|
1021
1032
|
writeReference(project, 'home.png');
|
|
1022
1033
|
const script = await buildScript(project, { package_source: 'repo' });
|
|
1023
|
-
const
|
|
1024
|
-
const run = runScript(project, script, { FAKE_SWIFT_LOG: logPath });
|
|
1034
|
+
const run = runScript(project, script);
|
|
1025
1035
|
expect(run.status).toBe(0);
|
|
1026
|
-
// The
|
|
1027
|
-
// (in
|
|
1028
|
-
const invocations = readFileSync(logPath, 'utf-8').trim().split('\n');
|
|
1029
|
-
const trimCall = invocations.find((c) => c.includes('Trim.swift'));
|
|
1030
|
-
expect(trimCall).toBeTruthy();
|
|
1031
|
-
expect(trimCall).toContain('ui-fidelity/rendered/HomeView.png');
|
|
1032
|
-
// The rendered file now holds the trim helper's output, not the raw render.
|
|
1036
|
+
// The rendered file now holds the trim helper's output, not the raw render
|
|
1037
|
+
// (the fake ci overwrites in place, proving the in/out in-place contract).
|
|
1033
1038
|
expect(isPng(artifact(project, 'ui-fidelity/rendered/HomeView.png'))).toBe(true);
|
|
1034
1039
|
expect(readArtifact(project, 'ui-fidelity/rendered/HomeView.png')).toContain('trimmed:HomeView.png');
|
|
1035
1040
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@invarn/cibuild",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "CI Build CLI — local pipeline orchestration and validation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.cjs",
|
|
@@ -55,12 +55,14 @@
|
|
|
55
55
|
"homepage": "https://github.com/invarnhq/cibuild",
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"js-yaml": "^4.1.0",
|
|
58
|
+
"pngjs": "7.0.0",
|
|
58
59
|
"prompts": "^2.4.2"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"@types/jest": "^29.5.14",
|
|
62
63
|
"@types/js-yaml": "^4.0.9",
|
|
63
64
|
"@types/node": "^22.10.1",
|
|
65
|
+
"@types/pngjs": "6.0.5",
|
|
64
66
|
"@types/prompts": "^2.4.9",
|
|
65
67
|
"@yao-pkg/pkg": "^6.14.1",
|
|
66
68
|
"esbuild": "^0.27.3",
|