@invarn/cibuild 2.0.2 → 2.0.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.
|
@@ -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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"}
|
|
@@ -865,6 +865,127 @@ function cleanupShippedPackage() {
|
|
|
865
865
|
shippedExtractDir = null;
|
|
866
866
|
}
|
|
867
867
|
`;
|
|
868
|
+
/**
|
|
869
|
+
* Runtime support for asset catalogs (package_source variants only).
|
|
870
|
+
*
|
|
871
|
+
* `swift build` copies a target's .xcassets into its resource bundle but never
|
|
872
|
+
* runs actool, so SwiftUI's Image("name") finds no compiled catalog and the
|
|
873
|
+
* image does not resolve. After the harness builds, compile every .xcassets in
|
|
874
|
+
* the package with actool into the harness bin directory (= the render
|
|
875
|
+
* executable's Bundle.main), so unmodified Image("name") references resolve.
|
|
876
|
+
* One actool invocation over all catalogs (it merges them). Best-effort:
|
|
877
|
+
* a compile failure is logged and rendering continues -- the affected images
|
|
878
|
+
* simply will not appear, which the human comparing the screens will see.
|
|
879
|
+
*/
|
|
880
|
+
const RENDER_SCRIPT_ASSET_CATALOG_STAGE = String.raw `
|
|
881
|
+
// ---- asset-catalog stage (package_source variants) ----
|
|
882
|
+
|
|
883
|
+
var ASSET_CATALOG_MIN_MACOS = '13.0';
|
|
884
|
+
|
|
885
|
+
// Recursively collect *.xcassets directories under root, skipping .build and
|
|
886
|
+
// the catalogs' own contents (a catalog is a leaf for this scan).
|
|
887
|
+
function findAssetCatalogs(root) {
|
|
888
|
+
var found = [];
|
|
889
|
+
var stack = [root];
|
|
890
|
+
while (stack.length > 0) {
|
|
891
|
+
var dir = stack.pop();
|
|
892
|
+
var entries;
|
|
893
|
+
try {
|
|
894
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
895
|
+
} catch (readError) {
|
|
896
|
+
continue;
|
|
897
|
+
}
|
|
898
|
+
for (var i = 0; i < entries.length; i++) {
|
|
899
|
+
var entry = entries[i];
|
|
900
|
+
if (!entry.isDirectory()) continue;
|
|
901
|
+
if (entry.name === '.build') continue;
|
|
902
|
+
var full = path.join(dir, entry.name);
|
|
903
|
+
if (entry.name.slice(-9) === '.xcassets') {
|
|
904
|
+
found.push(full);
|
|
905
|
+
} else {
|
|
906
|
+
stack.push(full);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return found.sort();
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Run actool over the given catalogs, emitting Assets.car into outDir.
|
|
914
|
+
// Best-effort: a failure is logged (warn-and-continue) and rendering proceeds.
|
|
915
|
+
function compileCatalogsInto(catalogs, outDir, label) {
|
|
916
|
+
try {
|
|
917
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
918
|
+
} catch (mkdirError) {
|
|
919
|
+
// best effort -- actool reports a missing output dir itself
|
|
920
|
+
}
|
|
921
|
+
var args = ['actool'].concat(catalogs);
|
|
922
|
+
args.push(
|
|
923
|
+
'--compile', outDir,
|
|
924
|
+
'--platform', 'macosx',
|
|
925
|
+
'--minimum-deployment-target', ASSET_CATALOG_MIN_MACOS,
|
|
926
|
+
'--output-format', 'human-readable-text'
|
|
927
|
+
);
|
|
928
|
+
log('xcrun ' + args.join(' '));
|
|
929
|
+
var result = cp.spawnSync('xcrun', args, {
|
|
930
|
+
encoding: 'utf-8',
|
|
931
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
932
|
+
});
|
|
933
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
934
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
935
|
+
if (result.error || result.status !== 0) {
|
|
936
|
+
var detail = (result.stderr || '') +
|
|
937
|
+
(result.error ? String(result.error.message || result.error) : '');
|
|
938
|
+
logError(
|
|
939
|
+
'asset-catalog compile failed for ' + label + ' (continuing; catalog ' +
|
|
940
|
+
'images may not resolve): ' + sanitizeMessage(detail.trim())
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// SwiftUI resolves Image("name") against Bundle.main and
|
|
946
|
+
// Image("name", bundle: .module) against a target's own resource bundle.
|
|
947
|
+
// swift build copies a .process'd .xcassets into the module bundle but never
|
|
948
|
+
// compiles it, and a loose catalog is copied nowhere. So compile twice:
|
|
949
|
+
// the package's source catalogs into the bin dir (= Bundle.main), AND each
|
|
950
|
+
// module bundle's copied catalog in place (= Bundle.module). This covers both
|
|
951
|
+
// reference idioms, so the agent need not know which bundle the renderer uses.
|
|
952
|
+
function compileAssetCatalogs(packageDir, harnessDir) {
|
|
953
|
+
var sourceCatalogs = findAssetCatalogs(packageDir);
|
|
954
|
+
if (sourceCatalogs.length === 0) return;
|
|
955
|
+
|
|
956
|
+
var binResult = runSwift(['build', '--package-path', harnessDir, '--show-bin-path']);
|
|
957
|
+
if (binResult.status !== 0) {
|
|
958
|
+
logError('asset-catalog compile skipped: could not resolve the build bin path');
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
var binPath = String(binResult.stdout || '').trim().split('\n').pop().trim();
|
|
962
|
+
if (!binPath) {
|
|
963
|
+
logError('asset-catalog compile skipped: empty build bin path');
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// Bundle.main: the package's source catalogs, merged into the bin dir.
|
|
968
|
+
compileCatalogsInto(sourceCatalogs, binPath, 'Bundle.main');
|
|
969
|
+
|
|
970
|
+
// Bundle.module: each *.bundle in the bin dir that carries a copied catalog,
|
|
971
|
+
// compiled in place so Image(..., bundle: .module) resolves.
|
|
972
|
+
var entries;
|
|
973
|
+
try {
|
|
974
|
+
entries = fs.readdirSync(binPath, { withFileTypes: true });
|
|
975
|
+
} catch (readError) {
|
|
976
|
+
entries = [];
|
|
977
|
+
}
|
|
978
|
+
for (var i = 0; i < entries.length; i++) {
|
|
979
|
+
var entry = entries[i];
|
|
980
|
+
if (!entry.isDirectory() || entry.name.slice(-7) !== '.bundle') continue;
|
|
981
|
+
var bundleDir = path.join(binPath, entry.name);
|
|
982
|
+
var bundleCatalogs = findAssetCatalogs(bundleDir);
|
|
983
|
+
if (bundleCatalogs.length > 0) {
|
|
984
|
+
compileCatalogsInto(bundleCatalogs, bundleDir, entry.name);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
`;
|
|
868
989
|
/**
|
|
869
990
|
* Replaces exactly one occurrence of `anchor` in `source`. Throws when the
|
|
870
991
|
* anchor is missing or ambiguous, so any drift between the v1 runtime text
|
|
@@ -966,6 +1087,12 @@ function buildPackageSourceMain() {
|
|
|
966
1087
|
' }\n');
|
|
967
1088
|
// The shipped-package stage is defined ahead of main().
|
|
968
1089
|
main = replaceOnce(main, 'function main() {', RENDER_SCRIPT_PACKAGE_STAGE + '\nfunction main() {');
|
|
1090
|
+
// Asset-catalog stage: define the helpers ahead of renderWithHarness, then
|
|
1091
|
+
// compile any catalogs once the package has proven it builds (after the
|
|
1092
|
+
// probe) and before the per-screen renders that depend on the images.
|
|
1093
|
+
main = replaceOnce(main, 'function renderWithHarness(renderable, packagePath) {', RENDER_SCRIPT_ASSET_CATALOG_STAGE + '\nfunction renderWithHarness(renderable, packagePath) {');
|
|
1094
|
+
main = replaceOnce(main, ' renderable.forEach(function (entry) {', ' compileAssetCatalogs(packagePath, harnessDir);\n\n' +
|
|
1095
|
+
' renderable.forEach(function (entry) {');
|
|
969
1096
|
return main;
|
|
970
1097
|
}
|
|
971
1098
|
const RENDER_SCRIPT_MAIN_WITH_PACKAGE_SOURCE = buildPackageSourceMain();
|
|
@@ -58,15 +58,21 @@ const FAKE_SWIFT_LINES = [
|
|
|
58
58
|
' printf \'{"name":"shipped-package","products":[%s]}\\n\' "$json"',
|
|
59
59
|
' exit 0 ;;',
|
|
60
60
|
' build)',
|
|
61
|
-
' product=""; target=""; pkg=""',
|
|
61
|
+
' product=""; target=""; pkg=""; showbin=""',
|
|
62
62
|
' while [ $# -gt 0 ]; do',
|
|
63
63
|
' case "$1" in',
|
|
64
64
|
' --product) product="$2"; shift 2 ;;',
|
|
65
65
|
' --target) target="$2"; shift 2 ;;',
|
|
66
66
|
' --package-path) pkg="$2"; shift 2 ;;',
|
|
67
|
+
' --show-bin-path) showbin=1; shift ;;',
|
|
67
68
|
' *) shift ;;',
|
|
68
69
|
' esac',
|
|
69
70
|
' done',
|
|
71
|
+
' if [ -n "$showbin" ]; then',
|
|
72
|
+
' bp="$pkg/.build/debug"',
|
|
73
|
+
' [ -n "$FAKE_SWIFT_MODULE_CATALOG" ] && mkdir -p "$bp/$FAKE_SWIFT_MODULE_CATALOG.bundle/Media.xcassets"',
|
|
74
|
+
' echo "$bp"; exit 0',
|
|
75
|
+
' fi',
|
|
70
76
|
' name="${product:-$target}"',
|
|
71
77
|
' if [ "$name" = "RenderProbe" ]; then',
|
|
72
78
|
' if [ -n "$FAKE_SWIFT_PROBE_FAIL" ]; then',
|
|
@@ -109,6 +115,35 @@ const FAKE_SWIFT_LINES = [
|
|
|
109
115
|
' exit 0 ;;',
|
|
110
116
|
'esac',
|
|
111
117
|
];
|
|
118
|
+
/**
|
|
119
|
+
* PATH-shimmed fake `xcrun` covering `xcrun actool`. Logs its args to
|
|
120
|
+
* $FAKE_XCRUN_LOG, writes a stub Assets.car into the --compile directory,
|
|
121
|
+
* and fails (exit 1) when FAKE_ACTOOL_FAIL is set so the warn-and-continue
|
|
122
|
+
* path is exercisable.
|
|
123
|
+
*/
|
|
124
|
+
const FAKE_XCRUN_LINES = [
|
|
125
|
+
'#!/bin/bash',
|
|
126
|
+
'[ -n "$FAKE_XCRUN_LOG" ] && echo "$*" >> "$FAKE_XCRUN_LOG"',
|
|
127
|
+
'sub="$1"; shift',
|
|
128
|
+
'case "$sub" in',
|
|
129
|
+
' actool)',
|
|
130
|
+
' out=""',
|
|
131
|
+
' while [ $# -gt 0 ]; do',
|
|
132
|
+
' case "$1" in',
|
|
133
|
+
' --compile) out="$2"; shift 2 ;;',
|
|
134
|
+
' *) shift ;;',
|
|
135
|
+
' esac',
|
|
136
|
+
' done',
|
|
137
|
+
' if [ -n "$FAKE_ACTOOL_FAIL" ]; then',
|
|
138
|
+
' echo "error: actool: malformed asset catalog" >&2',
|
|
139
|
+
' exit 1',
|
|
140
|
+
' fi',
|
|
141
|
+
' [ -n "$out" ] && mkdir -p "$out" && printf \'fake-car\' > "$out/Assets.car"',
|
|
142
|
+
' exit 0 ;;',
|
|
143
|
+
' *)',
|
|
144
|
+
' exit 0 ;;',
|
|
145
|
+
'esac',
|
|
146
|
+
];
|
|
112
147
|
const tempDirs = [];
|
|
113
148
|
afterAll(() => {
|
|
114
149
|
for (const dir of tempDirs) {
|
|
@@ -131,6 +166,9 @@ function makeProject(params) {
|
|
|
131
166
|
const swiftPath = join(binDir, 'swift');
|
|
132
167
|
writeFileSync(swiftPath, FAKE_SWIFT_LINES.join('\n') + '\n');
|
|
133
168
|
chmodSync(swiftPath, 0o755);
|
|
169
|
+
const xcrunPath = join(binDir, 'xcrun');
|
|
170
|
+
writeFileSync(xcrunPath, FAKE_XCRUN_LINES.join('\n') + '\n');
|
|
171
|
+
chmodSync(xcrunPath, 0o755);
|
|
134
172
|
if (params !== undefined) {
|
|
135
173
|
writeFileSync(join(dir, '.ci', 'inputs', 'params.json'), typeof params === 'string' ? params : JSON.stringify(params));
|
|
136
174
|
}
|
|
@@ -862,6 +900,70 @@ describe('render script runtime (package_source: repo)', () => {
|
|
|
862
900
|
],
|
|
863
901
|
});
|
|
864
902
|
});
|
|
903
|
+
test('compiles asset catalogs found in the package before rendering', async () => {
|
|
904
|
+
const project = makeProject({ screens: { HomeView: 'home.png' } });
|
|
905
|
+
writeReference(project, 'home.png');
|
|
906
|
+
// A catalog at the package root: SwiftPM ignores it, so the renderer must
|
|
907
|
+
// compile it with actool for Image("name") to resolve at render time.
|
|
908
|
+
const catalog = join(project.packageDir, 'Assets', 'Media.xcassets');
|
|
909
|
+
mkdirSync(catalog, { recursive: true });
|
|
910
|
+
writeFileSync(join(catalog, 'Contents.json'), '{}');
|
|
911
|
+
const script = await buildScript(project, { package_source: 'repo' });
|
|
912
|
+
const xcrunLog = join(project.dir, 'xcrun-invocations.log');
|
|
913
|
+
const run = runScript(project, script, { FAKE_XCRUN_LOG: xcrunLog });
|
|
914
|
+
expect(run.status).toBe(0);
|
|
915
|
+
expect(isPng(artifact(project, 'ui-fidelity/rendered/HomeView.png'))).toBe(true);
|
|
916
|
+
const xcrunCalls = readFileSync(xcrunLog, 'utf-8');
|
|
917
|
+
expect(xcrunCalls).toContain('actool');
|
|
918
|
+
expect(xcrunCalls).toContain('Media.xcassets');
|
|
919
|
+
expect(xcrunCalls).toContain('--compile');
|
|
920
|
+
expect(xcrunCalls).toContain('--platform macosx');
|
|
921
|
+
});
|
|
922
|
+
test('also compiles catalogs in module bundles for Bundle.module references', async () => {
|
|
923
|
+
const project = makeProject({ screens: { HomeView: 'home.png' } });
|
|
924
|
+
writeReference(project, 'home.png');
|
|
925
|
+
// Source catalog drives the main-bundle (Bundle.main) compile. The module
|
|
926
|
+
// bundle — which the fake toolchain materializes to mimic `swift build`
|
|
927
|
+
// copying a .process resource — must ALSO be compiled in place, or an
|
|
928
|
+
// Image("name", bundle: .module) reference finds only the raw catalog.
|
|
929
|
+
const catalog = join(project.packageDir, 'Assets', 'Media.xcassets');
|
|
930
|
+
mkdirSync(catalog, { recursive: true });
|
|
931
|
+
writeFileSync(join(catalog, 'Contents.json'), '{}');
|
|
932
|
+
const script = await buildScript(project, { package_source: 'repo' });
|
|
933
|
+
const xcrunLog = join(project.dir, 'xcrun-invocations.log');
|
|
934
|
+
const run = runScript(project, script, {
|
|
935
|
+
FAKE_XCRUN_LOG: xcrunLog,
|
|
936
|
+
FAKE_SWIFT_MODULE_CATALOG: 'FixtureViews',
|
|
937
|
+
});
|
|
938
|
+
expect(run.status).toBe(0);
|
|
939
|
+
const calls = readFileSync(xcrunLog, 'utf-8').trim().split('\n');
|
|
940
|
+
// The module bundle's own catalog is compiled into the bundle directory.
|
|
941
|
+
const moduleCompile = calls.find((c) => c.includes('.bundle/Media.xcassets'));
|
|
942
|
+
expect(moduleCompile).toBeTruthy();
|
|
943
|
+
expect(moduleCompile).toMatch(/--compile \S+\.bundle(\s|$)/);
|
|
944
|
+
});
|
|
945
|
+
test('does not invoke actool when the package has no asset catalogs', async () => {
|
|
946
|
+
const project = makeProject({ screens: { HomeView: 'home.png' } });
|
|
947
|
+
writeReference(project, 'home.png');
|
|
948
|
+
const script = await buildScript(project, { package_source: 'repo' });
|
|
949
|
+
const xcrunLog = join(project.dir, 'xcrun-invocations.log');
|
|
950
|
+
const run = runScript(project, script, { FAKE_XCRUN_LOG: xcrunLog });
|
|
951
|
+
expect(run.status).toBe(0);
|
|
952
|
+
expect(isPng(artifact(project, 'ui-fidelity/rendered/HomeView.png'))).toBe(true);
|
|
953
|
+
expect(existsSync(xcrunLog)).toBe(false);
|
|
954
|
+
});
|
|
955
|
+
test('a failing asset-catalog compile warns but still renders (warn-and-continue)', async () => {
|
|
956
|
+
const project = makeProject({ screens: { HomeView: 'home.png' } });
|
|
957
|
+
writeReference(project, 'home.png');
|
|
958
|
+
const catalog = join(project.packageDir, 'Media.xcassets');
|
|
959
|
+
mkdirSync(catalog, { recursive: true });
|
|
960
|
+
writeFileSync(join(catalog, 'Contents.json'), '{}');
|
|
961
|
+
const script = await buildScript(project, { package_source: 'repo' });
|
|
962
|
+
const run = runScript(project, script, { FAKE_ACTOOL_FAIL: '1' });
|
|
963
|
+
expect(run.status).toBe(0);
|
|
964
|
+
expect(isPng(artifact(project, 'ui-fidelity/rendered/HomeView.png'))).toBe(true);
|
|
965
|
+
expect(run.stderr).toContain('asset-catalog compile failed');
|
|
966
|
+
});
|
|
865
967
|
});
|
|
866
968
|
describe('render script runtime (package_source: inputs)', () => {
|
|
867
969
|
test('renders every screen from a shipped archive with a single package root', async () => {
|