@invarn/cibuild 2.7.3 → 2.7.5

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.
Files changed (54) hide show
  1. package/dist/cli.cjs +10 -10
  2. package/dist/src/commands/a-credential-target-follows-the-flavor-source-set.test.d.ts +38 -0
  3. package/dist/src/commands/a-credential-target-follows-the-flavor-source-set.test.d.ts.map +1 -0
  4. package/dist/src/commands/a-credential-target-follows-the-flavor-source-set.test.js +219 -0
  5. package/dist/src/commands/a-credential-two-workflows-cannot-share-is-declared-per-workflow.test.d.ts +41 -0
  6. package/dist/src/commands/a-credential-two-workflows-cannot-share-is-declared-per-workflow.test.d.ts.map +1 -0
  7. package/dist/src/commands/a-credential-two-workflows-cannot-share-is-declared-per-workflow.test.js +291 -0
  8. package/dist/src/commands/build.d.ts +144 -0
  9. package/dist/src/commands/build.d.ts.map +1 -1
  10. package/dist/src/commands/build.js +317 -22
  11. package/dist/src/commands/each-flavor-is-asked-for-its-own-properties-file.test.d.ts +26 -0
  12. package/dist/src/commands/each-flavor-is-asked-for-its-own-properties-file.test.d.ts.map +1 -0
  13. package/dist/src/commands/each-flavor-is-asked-for-its-own-properties-file.test.js +196 -0
  14. package/dist/src/commands/file-secret-collector.d.ts +13 -0
  15. package/dist/src/commands/file-secret-collector.d.ts.map +1 -1
  16. package/dist/src/commands/file-secret-collector.js +3 -2
  17. package/dist/src/commands/local-properties-reaches-every-workflow.test.d.ts +30 -0
  18. package/dist/src/commands/local-properties-reaches-every-workflow.test.d.ts.map +1 -0
  19. package/dist/src/commands/local-properties-reaches-every-workflow.test.js +146 -0
  20. package/dist/src/yaml/a-cache-path-must-not-swallow-a-credential.test.d.ts +28 -0
  21. package/dist/src/yaml/a-cache-path-must-not-swallow-a-credential.test.d.ts.map +1 -0
  22. package/dist/src/yaml/a-cache-path-must-not-swallow-a-credential.test.js +223 -0
  23. package/dist/src/yaml/a-declared-slot-may-name-the-workflow-it-belongs-to.test.d.ts +37 -0
  24. package/dist/src/yaml/a-declared-slot-may-name-the-workflow-it-belongs-to.test.d.ts.map +1 -0
  25. package/dist/src/yaml/a-declared-slot-may-name-the-workflow-it-belongs-to.test.js +255 -0
  26. package/dist/src/yaml/a-scoped-slot-must-name-a-workflow-the-pipeline-has.test.d.ts +34 -0
  27. package/dist/src/yaml/a-scoped-slot-must-name-a-workflow-the-pipeline-has.test.d.ts.map +1 -0
  28. package/dist/src/yaml/a-scoped-slot-must-name-a-workflow-the-pipeline-has.test.js +218 -0
  29. package/dist/src/yaml/a-value-this-instance-stored-is-a-value-it-has.test.d.ts +27 -0
  30. package/dist/src/yaml/a-value-this-instance-stored-is-a-value-it-has.test.d.ts.map +1 -0
  31. package/dist/src/yaml/a-value-this-instance-stored-is-a-value-it-has.test.js +126 -0
  32. package/dist/src/yaml/converter.d.ts +48 -0
  33. package/dist/src/yaml/converter.d.ts.map +1 -1
  34. package/dist/src/yaml/converter.js +117 -0
  35. package/dist/src/yaml/env-resolver.d.ts +52 -0
  36. package/dist/src/yaml/env-resolver.d.ts.map +1 -1
  37. package/dist/src/yaml/env-resolver.js +99 -1
  38. package/dist/src/yaml/secrets-manager.d.ts +13 -3
  39. package/dist/src/yaml/secrets-manager.d.ts.map +1 -1
  40. package/dist/src/yaml/secrets-manager.js +25 -14
  41. package/dist/src/yaml/steps/cocoapods-skip-if-absent.test.d.ts +17 -0
  42. package/dist/src/yaml/steps/cocoapods-skip-if-absent.test.d.ts.map +1 -0
  43. package/dist/src/yaml/steps/cocoapods-skip-if-absent.test.js +132 -0
  44. package/dist/src/yaml/steps/index.d.ts.map +1 -1
  45. package/dist/src/yaml/steps/index.js +9 -0
  46. package/dist/src/yaml/steps/ios-deps.d.ts +35 -0
  47. package/dist/src/yaml/steps/ios-deps.d.ts.map +1 -1
  48. package/dist/src/yaml/steps/ios-deps.js +18 -3
  49. package/dist/src/yaml/steps/xcode-derived-data.test.d.ts +30 -0
  50. package/dist/src/yaml/steps/xcode-derived-data.test.d.ts.map +1 -0
  51. package/dist/src/yaml/steps/xcode-derived-data.test.js +103 -0
  52. package/dist/src/yaml/steps/xcode.d.ts.map +1 -1
  53. package/dist/src/yaml/steps/xcode.js +73 -20
  54. package/package.json +1 -1
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Products go under a derived data path, never into one flat directory.
3
+ *
4
+ * `CONFIGURATION_BUILD_DIR` overrides the per-configuration/per-platform
5
+ * product separation xcodebuild provides under
6
+ * `DerivedData/Build/Products/<config>-<platform>/`, flattening every target in
7
+ * the graph into a single directory. Two build tasks for the same target then
8
+ * declare the same absolute output path and xcodebuild refuses the entire build
9
+ * with "Multiple commands produce". The notes it prints name the SAME target
10
+ * twice, which is the tell: one target built twice into one directory, not two
11
+ * packages colliding on a name.
12
+ *
13
+ * Measured 2026-09-09 on the iOS corpus rows, all on the template's must-pass
14
+ * "Build App" step: 16 collisions on jellyfin/Swiftfin, 266 on
15
+ * Automattic/pocket-casts-ios, 425 on home-assistant/iOS.
16
+ *
17
+ * A fourth row failed differently for the same reason. CocoaPods derives
18
+ * `PODS_CONFIGURATION_BUILD_DIR` from `BUILD_DIR`, which `CONFIGURATION_BUILD_DIR`
19
+ * does NOT override — so pod products land in the flat directory while every
20
+ * generated copy-resources script and linker search path still points into
21
+ * DerivedData. shenruisi/Stay reported "Resource SDWebImage.bundle not found.
22
+ * Run pod install" for a bundle that had been built two directories away.
23
+ *
24
+ * Proved by control on a runner guest, same repo and image and flags with only
25
+ * this setting differing: `CONFIGURATION_BUILD_DIR` reproduced the collision and
26
+ * exit 65 with no .app, `-derivedDataPath` reached BUILD SUCCEEDED in 2m06s and
27
+ * left both `Debug` and `Debug-iphonesimulator` under Products.
28
+ */
29
+ import { describe, test, expect } from '@jest/globals';
30
+ import { XcodeBuildStepExecutor, XcodeBuildForTestStepExecutor, XcodeBuildForSimulatorStepExecutor, } from './xcode.js';
31
+ import { testConfig } from './test-config.js';
32
+ const DERIVED = '-derivedDataPath "$OUTPUT_DIR/DerivedData"';
33
+ const scriptFor = async (executor, inputs) => {
34
+ const result = await executor.execute({ project_path: 'MyApp.xcodeproj', scheme: 'MyApp', ...inputs }, {}, testConfig);
35
+ return result.script;
36
+ };
37
+ const buildingExecutors = () => [
38
+ ['xcodebuild', new XcodeBuildStepExecutor()],
39
+ ['xcode-build-for-test', new XcodeBuildForTestStepExecutor()],
40
+ ['xcode-build-for-simulator', new XcodeBuildForSimulatorStepExecutor()],
41
+ ];
42
+ describe('no xcode step flattens the product tree', () => {
43
+ test.each(buildingExecutors())('%s never passes CONFIGURATION_BUILD_DIR', async (_name, executor) => {
44
+ expect(await scriptFor(executor, {})).not.toContain('CONFIGURATION_BUILD_DIR');
45
+ });
46
+ test.each(buildingExecutors())('%s builds into a derived data path', async (_name, executor) => {
47
+ expect(await scriptFor(executor, {})).toContain(DERIVED);
48
+ });
49
+ });
50
+ describe('the resolve and the build read the same derived data', () => {
51
+ // If they diverge, the retried resolve populates one location and the build
52
+ // re-resolves into another — the retry is spent on work that is thrown away,
53
+ // and a refused fetch fails the expensive half anyway.
54
+ test.each(buildingExecutors())('%s', async (_name, executor) => {
55
+ const script = await scriptFor(executor, {});
56
+ const lines = script.split('\n');
57
+ const resolveLine = lines.find((l) => l.includes('-resolvePackageDependencies'));
58
+ const buildLine = lines.find((l) => /^xcodebuild (build|clean build|build-for-testing)/.test(l.trim()));
59
+ expect(resolveLine).toBeDefined();
60
+ expect(buildLine).toBeDefined();
61
+ expect(resolveLine).toContain(DERIVED);
62
+ expect(buildLine).toContain(DERIVED);
63
+ });
64
+ });
65
+ describe('xcode-build-for-simulator finds the .app where it now lands', () => {
66
+ // The guard is the step's strongest statement that the app compiled, so it
67
+ // has to follow the products. Left at `find "$OUTPUT_DIR" -maxdepth 1` it
68
+ // matches nothing and fails every build with ".app not found" while the app
69
+ // has in fact built perfectly.
70
+ const build = (inputs = {}) => scriptFor(new XcodeBuildForSimulatorStepExecutor(), inputs);
71
+ test('searches under the per-platform Products directory', async () => {
72
+ const script = await build();
73
+ expect(script).toContain('find "$OUTPUT_DIR/DerivedData/Build/Products"');
74
+ });
75
+ test('searches deep enough to reach <config>-<platform>/Foo.app', async () => {
76
+ // Products/Debug-iphonesimulator/MyApp.app is two levels down. maxdepth 1
77
+ // would find the configuration directory and no .app at all.
78
+ const findLine = (await build())
79
+ .split('\n')
80
+ .find((l) => l.includes('-name "*.app"'));
81
+ expect(findLine).toContain('-maxdepth 2');
82
+ });
83
+ test('still fails the step when nothing landed', async () => {
84
+ const script = await build();
85
+ expect(script).toContain('if [ -z "$APP_PATH" ]; then');
86
+ expect(script).toContain('exit 1');
87
+ });
88
+ test('still exports the app path for later steps', async () => {
89
+ expect(await build()).toContain('envman add --key CIBUILD_APP_DIR_PATH');
90
+ });
91
+ });
92
+ describe('the output_dir input still steers where everything goes', () => {
93
+ // The template gives "Build App" its own output_dir, so derived data has to
94
+ // follow that input rather than a hardcoded path.
95
+ test('a custom output_dir is what OUTPUT_DIR resolves to', async () => {
96
+ const script = await scriptFor(new XcodeBuildForSimulatorStepExecutor(), {
97
+ output_dir: 'build/app',
98
+ });
99
+ expect(script).toContain(`OUTPUT_DIR="$(cd 'build/app' && pwd)"`);
100
+ expect(script).toContain(DERIVED);
101
+ });
102
+ });
103
+ //# sourceMappingURL=xcode-derived-data.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"xcode.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/xcode.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"xcode.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/xcode.ts"],"names":[],"mappings":"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"}
@@ -52,10 +52,13 @@ export class XcodeBuildStepExecutor extends BaseStepExecutor {
52
52
  commands.push(`echo "Building project: ${this.escapeBash(projectPath)}"`);
53
53
  commands.push(`echo "Scheme: ${this.escapeBash(scheme)}"`);
54
54
  commands.push(`echo "Configuration: ${this.escapeBash(configuration)}"`);
55
- // Create output directory and resolve to absolute path
56
- // Using an absolute path for CONFIGURATION_BUILD_DIR prevents xcodebuild from
57
- // creating a 'build' directory inside each SPM package checkout in DerivedData,
58
- // which causes "File exists but is not a directory" errors on repeated runs.
55
+ // Create output directory and resolve to absolute path. The absolute path
56
+ // is the load-bearing part: a relative one let xcodebuild create a `build`
57
+ // directory inside each SPM package checkout in DerivedData, which fails
58
+ // with "File exists but is not a directory" on repeated runs. That was
59
+ // originally fixed by making CONFIGURATION_BUILD_DIR absolute; it is now
60
+ // -derivedDataPath that is absolute instead, which fixes the same thing
61
+ // without flattening the product tree.
59
62
  commands.push('');
60
63
  commands.push('# Create output directory and resolve to absolute path');
61
64
  commands.push(`mkdir -p '${this.escapeBash(outputDir)}'`);
@@ -81,9 +84,10 @@ export class XcodeBuildStepExecutor extends BaseStepExecutor {
81
84
  commands.push('fi');
82
85
  // Resolve the package graph before building, and retry that on a refused
83
86
  // fetch. Resolution is seconds and the build is minutes, so the retry is
84
- // spent on the cheap half. No -derivedDataPath here: this step does not
85
- // set one for the build either, so both use the default location and the
86
- // build finds the graph this just resolved.
87
+ // spent on the cheap half. The two -derivedDataPath arguments move
88
+ // together: the build below reads the same derived data and finds the
89
+ // graph already resolved. Split them and the retry is spent on work the
90
+ // build discards.
87
91
  commands.push('');
88
92
  commands.push('# Resolve package dependencies first — see git-fetch-retry');
89
93
  commands.push(...refusedFetchHelpers());
@@ -91,7 +95,8 @@ export class XcodeBuildStepExecutor extends BaseStepExecutor {
91
95
  label: 'Package resolution',
92
96
  command: 'xcodebuild -resolvePackageDependencies' +
93
97
  ` "$PROJECT_TYPE" '${escapedPath}'` +
94
- ` -scheme '${this.escapeBash(scheme)}'`,
98
+ ` -scheme '${this.escapeBash(scheme)}'` +
99
+ ' -derivedDataPath "$OUTPUT_DIR/DerivedData"',
95
100
  }));
96
101
  // Build xcodebuild command
97
102
  commands.push('');
@@ -106,8 +111,14 @@ export class XcodeBuildStepExecutor extends BaseStepExecutor {
106
111
  xcodebuildCmd += ` -scheme '${this.escapeBash(scheme)}'`;
107
112
  xcodebuildCmd += ` -configuration '${this.escapeBash(configuration)}'`;
108
113
  xcodebuildCmd += ` -destination '${this.escapeBash(destination)}'`;
109
- // Add build path (absolute, resolved above)
110
- xcodebuildCmd += ` CONFIGURATION_BUILD_DIR="$OUTPUT_DIR"`;
114
+ // Derived data under the output dir, rather than CONFIGURATION_BUILD_DIR.
115
+ // Same reasoning as XcodeBuildForSimulatorStepExecutor below, where the
116
+ // full mechanism and the control are written up: the flat directory
117
+ // collapses xcodebuild's per-configuration/per-platform product separation
118
+ // and any graph with two tasks producing the same output name is refused
119
+ // with "Multiple commands produce". It also desynchronises CocoaPods, whose
120
+ // PODS_CONFIGURATION_BUILD_DIR follows BUILD_DIR and not this setting.
121
+ xcodebuildCmd += ` -derivedDataPath "$OUTPUT_DIR/DerivedData"`;
111
122
  // Add xcconfig if provided
112
123
  if (xcconfigContent && xcconfigContent.trim() !== '') {
113
124
  xcodebuildCmd += ' -xcconfig "$XCCONFIG_FILE"';
@@ -117,8 +128,11 @@ export class XcodeBuildStepExecutor extends BaseStepExecutor {
117
128
  commands.push('');
118
129
  commands.push('# Build completed');
119
130
  commands.push('echo "Build completed successfully"');
120
- commands.push('echo "Build artifacts in: $OUTPUT_DIR"');
121
- commands.push('ls -lh "$OUTPUT_DIR" || true');
131
+ // Products live under the per-platform Products directory now, not flat in
132
+ // $OUTPUT_DIR, so point the listing at where they actually are — otherwise
133
+ // the log says "artifacts in build/" above an empty directory.
134
+ commands.push('echo "Build artifacts in: $OUTPUT_DIR/DerivedData/Build/Products"');
135
+ commands.push('ls -lhR "$OUTPUT_DIR/DerivedData/Build/Products" 2>/dev/null || true');
122
136
  const script = this.createBashScriptFromCommands(commands, stepName);
123
137
  return this.createScriptStep(script, stepName);
124
138
  }
@@ -1013,16 +1027,19 @@ export class XcodeBuildForSimulatorStepExecutor extends BaseStepExecutor {
1013
1027
  commands.push('');
1014
1028
  // Resolve the package graph before building, under the refused-fetch
1015
1029
  // retry. This is the step an iOS app is normally built with, so it is the
1016
- // one a refused dependency fetch lands on first. No -derivedDataPath: the
1017
- // build below does not set one either, so both use the default location
1018
- // and the build finds the graph this just resolved.
1030
+ // one a refused dependency fetch lands on first. The build below reads the
1031
+ // same derived data and finds the graph already resolved — the two
1032
+ // -derivedDataPath arguments have to move together, or the resolve
1033
+ // populates one location and the build re-resolves into another, which
1034
+ // silently spends the retry on work the build then throws away.
1019
1035
  commands.push('# Resolve package dependencies first — see git-fetch-retry');
1020
1036
  commands.push(...refusedFetchHelpers());
1021
1037
  commands.push(...retryOnRefusedFetch({
1022
1038
  label: 'Package resolution',
1023
1039
  command: 'xcodebuild -resolvePackageDependencies' +
1024
1040
  ` "$PROJECT_TYPE" '${escapedPath}'` +
1025
- ` -scheme '${escapedScheme}'`,
1041
+ ` -scheme '${escapedScheme}'` +
1042
+ ' -derivedDataPath "$OUTPUT_DIR/DerivedData"',
1026
1043
  }));
1027
1044
  // Build command
1028
1045
  let cmd = 'xcodebuild';
@@ -1036,18 +1053,54 @@ export class XcodeBuildForSimulatorStepExecutor extends BaseStepExecutor {
1036
1053
  cmd += ` -configuration '${this.escapeBash(configuration)}'`;
1037
1054
  }
1038
1055
  cmd += ` -destination '${this.escapeBash(destination)}'`;
1039
- cmd += ` CONFIGURATION_BUILD_DIR="$OUTPUT_DIR"`;
1056
+ // -derivedDataPath rather than CONFIGURATION_BUILD_DIR. The latter was set
1057
+ // to keep xcodebuild from writing a `build` directory inside each SPM
1058
+ // package checkout in DerivedData ("File exists but is not a directory" on
1059
+ // repeated runs) — but note what that fix actually was: making the path
1060
+ // ABSOLUTE. Pointing derived data somewhere writable achieves the same
1061
+ // thing without the cost below, and matches xcode-build-for-test.
1062
+ //
1063
+ // The cost, measured 2026-09-09 on four of the six iOS corpus rows:
1064
+ // CONFIGURATION_BUILD_DIR overrides the per-configuration/per-platform
1065
+ // product separation xcodebuild normally provides under
1066
+ // DerivedData/Build/Products/<config>-<platform>/, flattening every target
1067
+ // in the graph into ONE directory. Two build tasks for the same target then
1068
+ // declare the same absolute output path and xcodebuild refuses the whole
1069
+ // build with "Multiple commands produce". Read the notes it prints: they
1070
+ // name the SAME target twice. It is not two packages colliding on a name,
1071
+ // it is one target built twice into one directory. 16 collisions on
1072
+ // jellyfin/Swiftfin, 266 on Automattic/pocket-casts-ios, 425 on
1073
+ // home-assistant/iOS.
1074
+ //
1075
+ // It also breaks CocoaPods, which is the same defect wearing a disguise.
1076
+ // CocoaPods derives PODS_CONFIGURATION_BUILD_DIR from BUILD_DIR, and
1077
+ // BUILD_DIR is NOT what CONFIGURATION_BUILD_DIR overrides — so pod products
1078
+ // are written to the flat directory while every generated copy-resources
1079
+ // script and linker search path still points into DerivedData. On
1080
+ // shenruisi/Stay that surfaced as "Resource SDWebImage.bundle not found.
1081
+ // Run pod install", for a bundle that had in fact been built, two
1082
+ // directories away.
1083
+ //
1084
+ // Proved by control, same repo and image and flags, only this line
1085
+ // differing: CONFIGURATION_BUILD_DIR reproduced the collision and exit 65
1086
+ // with no .app; -derivedDataPath reached BUILD SUCCEEDED in 2m06s and left
1087
+ // both Debug and Debug-iphonesimulator under Products — the separation the
1088
+ // flat directory destroys.
1089
+ cmd += ` -derivedDataPath "$OUTPUT_DIR/DerivedData"`;
1040
1090
  cmd += ' -xcconfig "$XCCONFIG_FILE"';
1041
1091
  if (xcodebuildOptions) {
1042
1092
  cmd += ` ${xcodebuildOptions}`;
1043
1093
  }
1044
1094
  commands.push(cmd);
1045
1095
  commands.push('');
1046
- // Locate .app
1096
+ // Locate .app. It now lands under the per-platform Products directory
1097
+ // rather than flat in $OUTPUT_DIR, so the guard has to follow it — at
1098
+ // maxdepth 1 this found nothing and the step would fail every build with
1099
+ // ".app not found" while the app had compiled perfectly.
1047
1100
  commands.push('# Locate generated .app');
1048
- commands.push('APP_PATH=$(find "$OUTPUT_DIR" -maxdepth 1 -name "*.app" -type d | head -1)');
1101
+ commands.push('APP_PATH=$(find "$OUTPUT_DIR/DerivedData/Build/Products" -maxdepth 2 -name "*.app" -type d 2>/dev/null | head -1)');
1049
1102
  commands.push('if [ -z "$APP_PATH" ]; then');
1050
- commands.push(' echo "❌ Error: .app not found in $OUTPUT_DIR"');
1103
+ commands.push(' echo "❌ Error: .app not found under $OUTPUT_DIR/DerivedData/Build/Products"');
1051
1104
  commands.push(' exit 1');
1052
1105
  commands.push('fi');
1053
1106
  commands.push('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.7.3",
3
+ "version": "2.7.5",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",