@invarn/cibuild 2.0.6 → 2.0.8
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 +6 -141
- package/dist/src/lib.d.ts +2 -0
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +2 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.d.ts +99 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.d.ts.map +1 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.js +152 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.test.d.ts +11 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/ui-fidelity-preview.test.js +168 -0
- package/dist/src/yaml/steps/ui-fidelity-render.d.ts +28 -0
- package/dist/src/yaml/steps/ui-fidelity-render.d.ts.map +1 -1
- package/dist/src/yaml/steps/ui-fidelity-render.js +160 -135
- package/dist/src/yaml/steps/ui-fidelity-render.test.js +57 -1
- package/package.json +1 -1
package/dist/src/lib.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export { loadYAMLPipeline, getWorkflowNames, hasWorkflow, YAMLParseError, YAMLVa
|
|
|
19
19
|
export { convertYAMLToPipelineDef, getAvailableWorkflows, YAMLConversionError, } from './yaml/converter.js';
|
|
20
20
|
export type { ConversionResult } from './yaml/converter.js';
|
|
21
21
|
export { pipeline } from './pipeline.js';
|
|
22
|
+
export { renderUiFidelityPreview } from './yaml/steps/ui-fidelity-preview.js';
|
|
23
|
+
export type { UiFidelityPreviewOptions, UiFidelityPreviewScreen, UiFidelityPreviewResult, UiFidelityPreviewScreenResult, UiFidelityPreviewDimensions, } from './yaml/steps/ui-fidelity-preview.js';
|
|
22
24
|
export { getStepExecutor, hasStep, getAvailableSteps, registerStep, getStepMetadata, } from './yaml/steps/registry.js';
|
|
23
25
|
export type { StepDef, PipelineDef, CIConfig, PipelineFactory, PipelineContext, StepBuilders, } from './types.js';
|
|
24
26
|
export type { StepExecutor, StepMetadata, StepPlatform, StepExecutionContext, } from './yaml/steps/base.js';
|
package/dist/src/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/lib.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,uBAAuB,CAAC;AAI/B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAI5D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EACL,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,YAAY,EACZ,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAIlC,YAAY,EACV,OAAO,EACP,WAAW,EACX,QAAQ,EACR,eAAe,EACf,eAAe,EACf,YAAY,GACb,MAAM,YAAY,CAAC;AAIpB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAI9B,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/lib.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,uBAAuB,CAAC;AAI/B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAI5D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,qCAAqC,CAAC;AAI7C,OAAO,EACL,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,YAAY,EACZ,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAIlC,YAAY,EACV,OAAO,EACP,WAAW,EACX,QAAQ,EACR,eAAe,EACf,eAAe,EACf,YAAY,GACb,MAAM,YAAY,CAAC;AAIpB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAI9B,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/src/lib.js
CHANGED
|
@@ -25,6 +25,8 @@ export { loadYAMLPipeline, getWorkflowNames, hasWorkflow, YAMLParseError, YAMLVa
|
|
|
25
25
|
export { convertYAMLToPipelineDef, getAvailableWorkflows, YAMLConversionError, } from './yaml/converter.js';
|
|
26
26
|
// ─── Pipeline DSL factory ───────────────────────────────────────────────
|
|
27
27
|
export { pipeline } from './pipeline.js';
|
|
28
|
+
// ─── UI fidelity local preview ──────────────────────────────────────────
|
|
29
|
+
export { renderUiFidelityPreview } from './yaml/steps/ui-fidelity-preview.js';
|
|
28
30
|
// ─── Step registry ──────────────────────────────────────────────────────
|
|
29
31
|
export { getStepExecutor, hasStep, getAvailableSteps, registerStep, getStepMetadata, } from './yaml/steps/registry.js';
|
|
30
32
|
// ─── Error types ────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local ui-fidelity render preview.
|
|
3
|
+
*
|
|
4
|
+
* Runs the EXACT same render path the runner uses -- the generated
|
|
5
|
+
* `ui-fidelity-render` node script in `package_source: "inputs"` mode (harness
|
|
6
|
+
* synthesis, asset-catalog compile, content trim, reference alignment, dimension
|
|
7
|
+
* reporting) -- but locally, against a SwiftPM package the caller already has on
|
|
8
|
+
* disk. This lets an agent eyeball the wrapper in seconds before dispatching a
|
|
9
|
+
* remote run, so the remote pass becomes a one-shot authoritative render rather
|
|
10
|
+
* than the inner loop of an iterate cycle.
|
|
11
|
+
*
|
|
12
|
+
* It is a faithful mirror, not a re-implementation: the package directory is
|
|
13
|
+
* archived to a temp `package.tar.gz` and fed through the same
|
|
14
|
+
* `generateRenderScript` output, so the target is auto-discovered, the archive
|
|
15
|
+
* is validated, and the produced rendered/aligned images and dimensions match
|
|
16
|
+
* what a remote run would produce on the same toolchain.
|
|
17
|
+
*/
|
|
18
|
+
/** One wrapper view to render, paired with the reference image to align to. */
|
|
19
|
+
export interface UiFidelityPreviewScreen {
|
|
20
|
+
/** Wrapper view type name (e.g. the public, parameterless `XProof`). */
|
|
21
|
+
screen: string;
|
|
22
|
+
/** Path to the reference image; copied into the inputs by basename. */
|
|
23
|
+
reference: string;
|
|
24
|
+
}
|
|
25
|
+
export interface UiFidelityPreviewOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Local SwiftPM package directory to render. Archived to a temp
|
|
28
|
+
* package.tar.gz and rendered in inputs mode. Mutually exclusive with
|
|
29
|
+
* packageArchive.
|
|
30
|
+
*/
|
|
31
|
+
packagePath?: string;
|
|
32
|
+
/**
|
|
33
|
+
* A prebuilt package.tar.gz to render as-is (preview the exact artifact a
|
|
34
|
+
* remote run would receive). Mutually exclusive with packagePath.
|
|
35
|
+
*/
|
|
36
|
+
packageArchive?: string;
|
|
37
|
+
/** Screens to render, each mapped to a reference image path. */
|
|
38
|
+
screens: UiFidelityPreviewScreen[];
|
|
39
|
+
/**
|
|
40
|
+
* SPM library target to import. Auto-discovered from the shipped manifest
|
|
41
|
+
* when omitted (the package must declare exactly one library product).
|
|
42
|
+
*/
|
|
43
|
+
target?: string;
|
|
44
|
+
/** Render size in device points, "<width>x<height>" (default 393x852). */
|
|
45
|
+
renderSize?: string;
|
|
46
|
+
/** Display scale (default 2). */
|
|
47
|
+
scale?: number | string;
|
|
48
|
+
/** Directory to receive the artifacts; a temp dir is used when omitted. */
|
|
49
|
+
outDir?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Extra entries prepended to PATH for the render child process, so callers
|
|
52
|
+
* (and tests) can supply a specific swift/xcrun/tar toolchain. Optional.
|
|
53
|
+
*/
|
|
54
|
+
toolchainPath?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface UiFidelityPreviewDimensions {
|
|
57
|
+
rendered_px: [number, number];
|
|
58
|
+
logical_pt: [number, number];
|
|
59
|
+
reference_px: [number, number] | null;
|
|
60
|
+
}
|
|
61
|
+
export interface UiFidelityPreviewScreenResult {
|
|
62
|
+
screen: string;
|
|
63
|
+
/** "rendered" when the screen rendered; otherwise "render_failed". */
|
|
64
|
+
status: string;
|
|
65
|
+
error: {
|
|
66
|
+
code: string;
|
|
67
|
+
message: string;
|
|
68
|
+
} | null;
|
|
69
|
+
/** Absolute path to the (per-screen) reference copy, or null. */
|
|
70
|
+
referenceImagePath: string | null;
|
|
71
|
+
/** Absolute path to the trimmed rendered image, or null. */
|
|
72
|
+
renderedImagePath: string | null;
|
|
73
|
+
/** Absolute path to the reference-aligned image, or null. */
|
|
74
|
+
alignedImagePath: string | null;
|
|
75
|
+
dimensions: UiFidelityPreviewDimensions | null;
|
|
76
|
+
}
|
|
77
|
+
export interface UiFidelityPreviewResult {
|
|
78
|
+
/** Always "inputs": the preview mirrors a shipped-package remote run. */
|
|
79
|
+
packageSource: 'inputs';
|
|
80
|
+
/** Per-build package error (archive/target validation), or null. */
|
|
81
|
+
buildError: {
|
|
82
|
+
code: string;
|
|
83
|
+
message: string;
|
|
84
|
+
} | null;
|
|
85
|
+
/** One entry per requested screen, in request order. */
|
|
86
|
+
screens: UiFidelityPreviewScreenResult[];
|
|
87
|
+
/** Absolute path to the artifacts directory holding the images. */
|
|
88
|
+
artifactsDir: string;
|
|
89
|
+
/** True only when every screen rendered and there was no build error. */
|
|
90
|
+
ok: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Render the requested screens locally and return the produced image paths and
|
|
94
|
+
* dimensions. Throws only on caller errors (bad options) or when the render
|
|
95
|
+
* script could not run at all; per-screen and per-build render failures are
|
|
96
|
+
* reported in the returned result (mirroring the remote result document).
|
|
97
|
+
*/
|
|
98
|
+
export declare function renderUiFidelityPreview(options: UiFidelityPreviewOptions): UiFidelityPreviewResult;
|
|
99
|
+
//# sourceMappingURL=ui-fidelity-preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-fidelity-preview.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAwBH,+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;CAChD;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;AAkCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAoIzB"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local ui-fidelity render preview.
|
|
3
|
+
*
|
|
4
|
+
* Runs the EXACT same render path the runner uses -- the generated
|
|
5
|
+
* `ui-fidelity-render` node script in `package_source: "inputs"` mode (harness
|
|
6
|
+
* synthesis, asset-catalog compile, content trim, reference alignment, dimension
|
|
7
|
+
* reporting) -- but locally, against a SwiftPM package the caller already has on
|
|
8
|
+
* disk. This lets an agent eyeball the wrapper in seconds before dispatching a
|
|
9
|
+
* remote run, so the remote pass becomes a one-shot authoritative render rather
|
|
10
|
+
* than the inner loop of an iterate cycle.
|
|
11
|
+
*
|
|
12
|
+
* It is a faithful mirror, not a re-implementation: the package directory is
|
|
13
|
+
* archived to a temp `package.tar.gz` and fed through the same
|
|
14
|
+
* `generateRenderScript` output, so the target is auto-discovered, the archive
|
|
15
|
+
* is validated, and the produced rendered/aligned images and dimensions match
|
|
16
|
+
* what a remote run would produce on the same toolchain.
|
|
17
|
+
*/
|
|
18
|
+
import { spawnSync } from 'node:child_process';
|
|
19
|
+
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, statSync, writeFileSync, } from 'node:fs';
|
|
20
|
+
import { tmpdir } from 'node:os';
|
|
21
|
+
import { basename, join, resolve } from 'node:path';
|
|
22
|
+
import { DEFAULT_RENDER_SIZE, DEFAULT_SCALE, generateRenderScript, parseRenderSize, parseScale, } from './ui-fidelity-render.js';
|
|
23
|
+
function runTar(args, pathPrepend) {
|
|
24
|
+
const env = pathPrepend
|
|
25
|
+
? { ...process.env, PATH: pathPrepend + ':' + (process.env.PATH ?? '') }
|
|
26
|
+
: process.env;
|
|
27
|
+
const result = spawnSync('tar', args, { encoding: 'utf-8', env, maxBuffer: 64 * 1024 * 1024 });
|
|
28
|
+
if (result.status !== 0) {
|
|
29
|
+
const detail = (result.stderr || result.error?.message || '').toString().trim();
|
|
30
|
+
throw new Error(`failed to archive the package (tar exited ${result.status}): ${detail}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Resolve an artifact-relative path to absolute, or null. */
|
|
34
|
+
function absOrNull(artifactsDir, relative) {
|
|
35
|
+
return typeof relative === 'string' && relative !== '' ? resolve(artifactsDir, relative) : null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Render the requested screens locally and return the produced image paths and
|
|
39
|
+
* dimensions. Throws only on caller errors (bad options) or when the render
|
|
40
|
+
* script could not run at all; per-screen and per-build render failures are
|
|
41
|
+
* reported in the returned result (mirroring the remote result document).
|
|
42
|
+
*/
|
|
43
|
+
export function renderUiFidelityPreview(options) {
|
|
44
|
+
if (!options || typeof options !== 'object') {
|
|
45
|
+
throw new Error('renderUiFidelityPreview: options are required');
|
|
46
|
+
}
|
|
47
|
+
const hasDir = typeof options.packagePath === 'string' && options.packagePath !== '';
|
|
48
|
+
const hasArchive = typeof options.packageArchive === 'string' && options.packageArchive !== '';
|
|
49
|
+
if (hasDir === hasArchive) {
|
|
50
|
+
throw new Error('renderUiFidelityPreview: provide exactly one of packagePath or packageArchive');
|
|
51
|
+
}
|
|
52
|
+
if (!Array.isArray(options.screens) || options.screens.length === 0) {
|
|
53
|
+
throw new Error('renderUiFidelityPreview: at least one screen is required');
|
|
54
|
+
}
|
|
55
|
+
const { width, height } = parseRenderSize(options.renderSize ?? DEFAULT_RENDER_SIZE);
|
|
56
|
+
const scale = parseScale(options.scale ?? DEFAULT_SCALE);
|
|
57
|
+
const workDir = mkdtempSync(join(tmpdir(), 'ui-fidelity-preview-'));
|
|
58
|
+
const inputsDir = join(workDir, '.ci', 'inputs');
|
|
59
|
+
mkdirSync(inputsDir, { recursive: true });
|
|
60
|
+
// Stage references by basename and build the screens -> basename map, exactly
|
|
61
|
+
// as a remote caller would pass params.screens.
|
|
62
|
+
const screensParam = {};
|
|
63
|
+
for (const entry of options.screens) {
|
|
64
|
+
if (!entry || typeof entry.screen !== 'string' || entry.screen === '') {
|
|
65
|
+
throw new Error('renderUiFidelityPreview: each screen needs a non-empty screen name');
|
|
66
|
+
}
|
|
67
|
+
if (typeof entry.reference !== 'string' || entry.reference === '') {
|
|
68
|
+
throw new Error(`renderUiFidelityPreview: screen ${entry.screen} needs a reference path`);
|
|
69
|
+
}
|
|
70
|
+
if (!existsSync(entry.reference) || !statSync(entry.reference).isFile()) {
|
|
71
|
+
throw new Error(`renderUiFidelityPreview: reference for ${entry.screen} not found: ${entry.reference}`);
|
|
72
|
+
}
|
|
73
|
+
const base = basename(entry.reference);
|
|
74
|
+
copyFileSync(entry.reference, join(inputsDir, base));
|
|
75
|
+
screensParam[entry.screen] = base;
|
|
76
|
+
}
|
|
77
|
+
const archivePath = join(inputsDir, 'package.tar.gz');
|
|
78
|
+
if (hasArchive) {
|
|
79
|
+
const src = options.packageArchive;
|
|
80
|
+
if (!existsSync(src) || !statSync(src).isFile()) {
|
|
81
|
+
throw new Error(`renderUiFidelityPreview: packageArchive not found: ${src}`);
|
|
82
|
+
}
|
|
83
|
+
copyFileSync(src, archivePath);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const dir = options.packagePath;
|
|
87
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory()) {
|
|
88
|
+
throw new Error(`renderUiFidelityPreview: packagePath is not a directory: ${dir}`);
|
|
89
|
+
}
|
|
90
|
+
// Archive with Package.swift at the archive root; exclude build/VCS noise so
|
|
91
|
+
// the upload stays lean and matches what a careful caller would ship.
|
|
92
|
+
runTar([
|
|
93
|
+
'--exclude',
|
|
94
|
+
'.build',
|
|
95
|
+
'--exclude',
|
|
96
|
+
'.git',
|
|
97
|
+
'--exclude',
|
|
98
|
+
'.DS_Store',
|
|
99
|
+
'-czf',
|
|
100
|
+
archivePath,
|
|
101
|
+
'-C',
|
|
102
|
+
dir,
|
|
103
|
+
'.',
|
|
104
|
+
], options.toolchainPath);
|
|
105
|
+
}
|
|
106
|
+
// The standard params.json the render script reads: screen -> reference basename.
|
|
107
|
+
writeFileSync(join(inputsDir, 'params.json'), JSON.stringify({ screens: screensParam }, null, 2) + '\n');
|
|
108
|
+
const artifactsDir = options.outDir ? resolve(options.outDir) : join(workDir, '.ci', 'artifacts');
|
|
109
|
+
mkdirSync(artifactsDir, { recursive: true });
|
|
110
|
+
const config = {
|
|
111
|
+
packagePath: null,
|
|
112
|
+
target: options.target ?? null,
|
|
113
|
+
width,
|
|
114
|
+
height,
|
|
115
|
+
scale,
|
|
116
|
+
packageSource: 'inputs',
|
|
117
|
+
};
|
|
118
|
+
const script = generateRenderScript(config);
|
|
119
|
+
const env = {
|
|
120
|
+
...process.env,
|
|
121
|
+
CIBUILD_ARTIFACTS_DIR: artifactsDir,
|
|
122
|
+
};
|
|
123
|
+
if (options.toolchainPath) {
|
|
124
|
+
env.PATH = options.toolchainPath + ':' + (process.env.PATH ?? '');
|
|
125
|
+
}
|
|
126
|
+
const run = spawnSync('node', ['-e', script], {
|
|
127
|
+
cwd: workDir,
|
|
128
|
+
env,
|
|
129
|
+
encoding: 'utf-8',
|
|
130
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
131
|
+
});
|
|
132
|
+
const resultPath = join(artifactsDir, 'protocol-result.json');
|
|
133
|
+
if (!existsSync(resultPath)) {
|
|
134
|
+
const detail = ((run.stdout || '') + '\n' + (run.stderr || '')).trim();
|
|
135
|
+
throw new Error(`renderUiFidelityPreview: render script produced no result document` +
|
|
136
|
+
(detail ? `:\n${detail}` : ''));
|
|
137
|
+
}
|
|
138
|
+
const raw = JSON.parse(readFileSync(resultPath, 'utf-8'));
|
|
139
|
+
const screens = (raw.screens || []).map((s) => ({
|
|
140
|
+
screen: s.screen,
|
|
141
|
+
status: s.status,
|
|
142
|
+
error: s.error ?? null,
|
|
143
|
+
referenceImagePath: absOrNull(artifactsDir, s.reference_image_path),
|
|
144
|
+
renderedImagePath: absOrNull(artifactsDir, s.rendered_image_path),
|
|
145
|
+
alignedImagePath: absOrNull(artifactsDir, s.aligned_image_path),
|
|
146
|
+
dimensions: s.dimensions ?? null,
|
|
147
|
+
}));
|
|
148
|
+
const buildError = raw.error ?? null;
|
|
149
|
+
const ok = buildError === null && screens.length > 0 && screens.every((s) => s.status === 'rendered');
|
|
150
|
+
return { packageSource: 'inputs', buildError, screens, artifactsDir, ok };
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=ui-fidelity-preview.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the local ui-fidelity render preview engine.
|
|
3
|
+
*
|
|
4
|
+
* Validation and result-shaping run with a PATH-shimmed fake `swift`/`xcrun`
|
|
5
|
+
* (the engine spawns the real generated render script, which spawns the
|
|
6
|
+
* toolchain). The CoreGraphics render itself is covered by an opt-in
|
|
7
|
+
* real-toolchain test, gated on CIBUILD_UI_FIDELITY_REAL_SWIFT, since the fake
|
|
8
|
+
* toolchain cannot exercise the actual pixel render/trim.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=ui-fidelity-preview.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-fidelity-preview.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-preview.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the local ui-fidelity render preview engine.
|
|
3
|
+
*
|
|
4
|
+
* Validation and result-shaping run with a PATH-shimmed fake `swift`/`xcrun`
|
|
5
|
+
* (the engine spawns the real generated render script, which spawns the
|
|
6
|
+
* toolchain). The CoreGraphics render itself is covered by an opt-in
|
|
7
|
+
* real-toolchain test, gated on CIBUILD_UI_FIDELITY_REAL_SWIFT, since the fake
|
|
8
|
+
* toolchain cannot exercise the actual pixel render/trim.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, expect, test, afterAll } from '@jest/globals';
|
|
11
|
+
import { chmodSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
|
|
12
|
+
import { tmpdir } from 'node:os';
|
|
13
|
+
import { dirname, join, resolve } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { renderUiFidelityPreview } from './ui-fidelity-preview.js';
|
|
16
|
+
const FIXTURE_PACKAGE = resolve(dirname(fileURLToPath(import.meta.url)), '../../../test/fixtures/ui-fidelity-package');
|
|
17
|
+
const PNG_MAGIC = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
18
|
+
// A real, decodable 1x1 transparent PNG, used as the reference for the
|
|
19
|
+
// real-toolchain test so the aligned step has something to read.
|
|
20
|
+
const ONE_BY_ONE_PNG = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==', 'base64');
|
|
21
|
+
const tempDirs = [];
|
|
22
|
+
afterAll(() => {
|
|
23
|
+
for (const dir of tempDirs) {
|
|
24
|
+
try {
|
|
25
|
+
rmSync(dir, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// best effort
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
function tempDir(prefix) {
|
|
33
|
+
const dir = mkdtempSync(join(tmpdir(), prefix));
|
|
34
|
+
tempDirs.push(dir);
|
|
35
|
+
return dir;
|
|
36
|
+
}
|
|
37
|
+
// Compact fake toolchain: enough of `swift`/`xcrun` for the inputs-mode render
|
|
38
|
+
// script to discover the target, "build", "render" a PNG stub, and "trim" it.
|
|
39
|
+
const FAKE_SWIFT = [
|
|
40
|
+
'#!/bin/bash',
|
|
41
|
+
'cmd="$1"; shift',
|
|
42
|
+
'case "$cmd" in',
|
|
43
|
+
' package)',
|
|
44
|
+
' printf \'{"name":"shipped","products":[{"name":"FixtureViews","type":{"library":["automatic"]}}]}\\n\'',
|
|
45
|
+
' exit 0 ;;',
|
|
46
|
+
' build)',
|
|
47
|
+
' while [ $# -gt 0 ]; do case "$1" in --show-bin-path) echo "$PWD/.build/debug"; exit 0 ;; *) shift ;; esac; done',
|
|
48
|
+
' exit 0 ;;',
|
|
49
|
+
' run)',
|
|
50
|
+
' pos=()',
|
|
51
|
+
' while [ $# -gt 0 ]; do case "$1" in --package-path) shift 2 ;; --skip-build) shift ;; *) pos+=("$1"); shift ;; esac; done',
|
|
52
|
+
' out="${pos[1]}"',
|
|
53
|
+
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out\"; printf 'fake-render' >> \"$out\"",
|
|
54
|
+
' exit 0 ;;',
|
|
55
|
+
' *.swift)',
|
|
56
|
+
' out_png="$2"; aligned_png="$3"',
|
|
57
|
+
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$out_png\"; printf 'trimmed' >> \"$out_png\"",
|
|
58
|
+
' if [ -n "$aligned_png" ]; then printf \'\\x89PNG\\r\\n\\x1a\\n\' > "$aligned_png"; printf \'aligned\' >> "$aligned_png"; fi',
|
|
59
|
+
' echo "TRIMDIMS 320 640 160 320 400 800"',
|
|
60
|
+
' exit 0 ;;',
|
|
61
|
+
' *) exit 0 ;;',
|
|
62
|
+
'esac',
|
|
63
|
+
].join('\n');
|
|
64
|
+
const FAKE_XCRUN = ['#!/bin/bash', 'exit 0'].join('\n');
|
|
65
|
+
function fakeToolchain() {
|
|
66
|
+
const bin = tempDir('ui-fidelity-fakebin-');
|
|
67
|
+
const swiftPath = join(bin, 'swift');
|
|
68
|
+
writeFileSync(swiftPath, FAKE_SWIFT + '\n');
|
|
69
|
+
chmodSync(swiftPath, 0o755);
|
|
70
|
+
const xcrunPath = join(bin, 'xcrun');
|
|
71
|
+
writeFileSync(xcrunPath, FAKE_XCRUN + '\n');
|
|
72
|
+
chmodSync(xcrunPath, 0o755);
|
|
73
|
+
return bin;
|
|
74
|
+
}
|
|
75
|
+
function writeReference() {
|
|
76
|
+
const dir = tempDir('ui-fidelity-ref-');
|
|
77
|
+
const ref = join(dir, 'reference.png');
|
|
78
|
+
writeFileSync(ref, Buffer.concat([PNG_MAGIC, Buffer.from('ref')]));
|
|
79
|
+
return ref;
|
|
80
|
+
}
|
|
81
|
+
function isPng(filePath) {
|
|
82
|
+
return readFileSync(filePath).subarray(0, PNG_MAGIC.length).equals(PNG_MAGIC);
|
|
83
|
+
}
|
|
84
|
+
describe('renderUiFidelityPreview — option validation', () => {
|
|
85
|
+
test('requires exactly one of packagePath or packageArchive', () => {
|
|
86
|
+
expect(() => renderUiFidelityPreview({ screens: [] })).toThrow(/exactly one/);
|
|
87
|
+
expect(() => renderUiFidelityPreview({
|
|
88
|
+
packagePath: FIXTURE_PACKAGE,
|
|
89
|
+
packageArchive: '/tmp/x.tar.gz',
|
|
90
|
+
screens: [{ screen: 'HomeView', reference: writeReference() }],
|
|
91
|
+
})).toThrow(/exactly one/);
|
|
92
|
+
});
|
|
93
|
+
test('requires at least one screen', () => {
|
|
94
|
+
expect(() => renderUiFidelityPreview({ packagePath: FIXTURE_PACKAGE, screens: [] })).toThrow(/at least one screen/);
|
|
95
|
+
});
|
|
96
|
+
test('rejects a missing reference image', () => {
|
|
97
|
+
expect(() => renderUiFidelityPreview({
|
|
98
|
+
packagePath: FIXTURE_PACKAGE,
|
|
99
|
+
screens: [{ screen: 'HomeView', reference: '/no/such/reference.png' }],
|
|
100
|
+
})).toThrow(/reference for HomeView not found/);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('renderUiFidelityPreview — fake toolchain', () => {
|
|
104
|
+
test('archives the package, renders in inputs mode, and returns image paths + dims', () => {
|
|
105
|
+
const result = renderUiFidelityPreview({
|
|
106
|
+
packagePath: FIXTURE_PACKAGE,
|
|
107
|
+
screens: [{ screen: 'HomeView', reference: writeReference() }],
|
|
108
|
+
toolchainPath: fakeToolchain(),
|
|
109
|
+
});
|
|
110
|
+
expect(result.packageSource).toBe('inputs');
|
|
111
|
+
expect(result.buildError).toBeNull();
|
|
112
|
+
expect(result.ok).toBe(true);
|
|
113
|
+
expect(result.screens).toHaveLength(1);
|
|
114
|
+
const [screen] = result.screens;
|
|
115
|
+
expect(screen.screen).toBe('HomeView');
|
|
116
|
+
expect(screen.status).toBe('rendered');
|
|
117
|
+
expect(screen.error).toBeNull();
|
|
118
|
+
// Paths are absolute and point at real files the caller can read.
|
|
119
|
+
expect(screen.renderedImagePath && isPng(screen.renderedImagePath)).toBe(true);
|
|
120
|
+
expect(screen.alignedImagePath && isPng(screen.alignedImagePath)).toBe(true);
|
|
121
|
+
expect(screen.referenceImagePath && isPng(screen.referenceImagePath)).toBe(true);
|
|
122
|
+
expect(screen.dimensions).toEqual({
|
|
123
|
+
rendered_px: [320, 640],
|
|
124
|
+
logical_pt: [160, 320],
|
|
125
|
+
reference_px: [160, 320],
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
test('writes images under the requested outDir', () => {
|
|
129
|
+
const outDir = tempDir('ui-fidelity-out-');
|
|
130
|
+
const result = renderUiFidelityPreview({
|
|
131
|
+
packagePath: FIXTURE_PACKAGE,
|
|
132
|
+
screens: [{ screen: 'HomeView', reference: writeReference() }],
|
|
133
|
+
outDir,
|
|
134
|
+
toolchainPath: fakeToolchain(),
|
|
135
|
+
});
|
|
136
|
+
expect(result.artifactsDir).toBe(resolve(outDir));
|
|
137
|
+
expect(result.screens[0].renderedImagePath?.startsWith(resolve(outDir))).toBe(true);
|
|
138
|
+
expect(existsSync(join(outDir, 'ui-fidelity', 'rendered', 'HomeView.png'))).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// Opt-in: renders the fixture with the real Swift toolchain and asserts the
|
|
142
|
+
// content trim actually crops below the forced device canvas. Requires macOS
|
|
143
|
+
// with Xcode; skipped unless explicitly requested.
|
|
144
|
+
describe('renderUiFidelityPreview — real toolchain', () => {
|
|
145
|
+
const realTest = process.env.CIBUILD_UI_FIDELITY_REAL_SWIFT === '1' ? test : test.skip;
|
|
146
|
+
realTest('renders the fixture and trims the filled canvas down to its content', () => {
|
|
147
|
+
const refDir = tempDir('ui-fidelity-realref-');
|
|
148
|
+
const reference = join(refDir, 'reference.png');
|
|
149
|
+
writeFileSync(reference, ONE_BY_ONE_PNG);
|
|
150
|
+
const result = renderUiFidelityPreview({
|
|
151
|
+
packagePath: FIXTURE_PACKAGE,
|
|
152
|
+
screens: [{ screen: 'HomeView', reference }],
|
|
153
|
+
renderSize: '393x852',
|
|
154
|
+
scale: 2,
|
|
155
|
+
});
|
|
156
|
+
expect(result.ok).toBe(true);
|
|
157
|
+
const [screen] = result.screens;
|
|
158
|
+
expect(screen.status).toBe('rendered');
|
|
159
|
+
expect(screen.renderedImagePath && isPng(screen.renderedImagePath)).toBe(true);
|
|
160
|
+
// HomeView fills the canvas with a uniform translucent background and a
|
|
161
|
+
// little text; the content trim must crop well below the 786x1704 (@2x)
|
|
162
|
+
// device canvas to the text region.
|
|
163
|
+
const [rw, rh] = screen.dimensions.rendered_px;
|
|
164
|
+
expect(rw).toBeLessThan(786);
|
|
165
|
+
expect(rh).toBeLessThan(1704);
|
|
166
|
+
}, 600_000);
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=ui-fidelity-preview.test.js.map
|
|
@@ -157,6 +157,34 @@ export interface RenderScriptInternals {
|
|
|
157
157
|
generateProbeSwift(options: HarnessGeneratorOptions): string;
|
|
158
158
|
generateScreenSwift(screen: string, options: HarnessGeneratorOptions): string;
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Runtime support for trimming the rendered output (package_source variants).
|
|
162
|
+
*
|
|
163
|
+
* The render entry forces the view into a fixed device-sized frame, so a
|
|
164
|
+
* component smaller than the canvas renders with transparent margins. After a
|
|
165
|
+
* screen renders, crop the PNG in place to the bounding box of its
|
|
166
|
+
* non-transparent pixels, so the rendered artifact is the component itself,
|
|
167
|
+
* tight -- no canvas, no background ambiguity for the human comparing screens.
|
|
168
|
+
*
|
|
169
|
+
* The crop is done by a small CoreGraphics helper run in Swift's
|
|
170
|
+
* script-interpreter mode (so it needs no extra harness target and reuses the
|
|
171
|
+
* one `swift` the runner already has). Best-effort: a trim failure is logged
|
|
172
|
+
* (warn-and-continue) and the untrimmed render is kept -- a cosmetic post-step
|
|
173
|
+
* never fails an otherwise good render. This is prep, not scoring: it produces
|
|
174
|
+
* a tighter image for the human's judgment and computes nothing about
|
|
175
|
+
* fidelity.
|
|
176
|
+
*/
|
|
177
|
+
/**
|
|
178
|
+
* The CoreGraphics trim/align helper source, run via
|
|
179
|
+
* `swift <Trim.swift> <in> <out> <aligned> <ref>` (script-interpreter mode).
|
|
180
|
+
* Crops a PNG to its content bounding box (transparent or uniform-background
|
|
181
|
+
* margins), writes a reference-sized aligned copy, and prints a TRIMDIMS line.
|
|
182
|
+
*
|
|
183
|
+
* Exported so a real-toolchain test can exercise the pixel logic directly --
|
|
184
|
+
* the fake `swift` in the unit tests cannot, which is why a background-detection
|
|
185
|
+
* bug shipped twice undetected before a real-pixel guard existed.
|
|
186
|
+
*/
|
|
187
|
+
export declare const TRIM_HELPER_SWIFT_SOURCE: string;
|
|
160
188
|
/**
|
|
161
189
|
* Evaluates the embedded generator source and returns the real functions, so
|
|
162
190
|
* unit tests exercise exactly the code that ships inside the runtime script.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-fidelity-render.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;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;AAEpE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C,mFAAmF;AACnF,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,iDAAiD;AACjD,eAAO,MAAM,eAAe,6BAA8B,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,EAAE,aAAsB,CAAC;AAE5D,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,QAAmB,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAWzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAQzD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,yEAAyE;IACzE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,4DAA4D;AAC5D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC;IACzF,kBAAkB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC;IAC7D,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC;CAC/E;
|
|
1
|
+
{"version":3,"file":"ui-fidelity-render.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render.ts"],"names":[],"mappings":"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"}
|