@invarn/cibuild 2.7.6 → 2.7.7

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 (32) hide show
  1. package/dist/cli.cjs +9 -9
  2. package/dist/src/commands/run.d.ts.map +1 -1
  3. package/dist/src/commands/run.js +1 -1
  4. package/dist/src/runner.d.ts +15 -1
  5. package/dist/src/runner.d.ts.map +1 -1
  6. package/dist/src/runner.js +24 -1
  7. package/dist/src/yaml/a-runtime-requirement-names-a-real-provider.test.d.ts +18 -0
  8. package/dist/src/yaml/a-runtime-requirement-names-a-real-provider.test.d.ts.map +1 -0
  9. package/dist/src/yaml/a-runtime-requirement-names-a-real-provider.test.js +66 -0
  10. package/dist/src/yaml/converter.d.ts +22 -0
  11. package/dist/src/yaml/converter.d.ts.map +1 -1
  12. package/dist/src/yaml/converter.js +26 -0
  13. package/dist/src/yaml/every-build-log-witnesses-the-commit-on-disk.test.d.ts +16 -0
  14. package/dist/src/yaml/every-build-log-witnesses-the-commit-on-disk.test.d.ts.map +1 -0
  15. package/dist/src/yaml/every-build-log-witnesses-the-commit-on-disk.test.js +126 -0
  16. package/dist/src/yaml/step-validator.d.ts.map +1 -1
  17. package/dist/src/yaml/step-validator.js +6 -2
  18. package/dist/src/yaml/steps/android.js +3 -3
  19. package/dist/src/yaml/steps/base.d.ts +6 -1
  20. package/dist/src/yaml/steps/base.d.ts.map +1 -1
  21. package/dist/src/yaml/steps/base.js +6 -1
  22. package/dist/src/yaml/steps/bitrise-android-tools.js +1 -1
  23. package/dist/src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.d.ts +16 -0
  24. package/dist/src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.d.ts.map +1 -0
  25. package/dist/src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.js +127 -0
  26. package/dist/src/yaml/steps/git-clone.d.ts +1 -1
  27. package/dist/src/yaml/steps/git-clone.d.ts.map +1 -1
  28. package/dist/src/yaml/steps/git-clone.js +56 -2
  29. package/dist/src/yaml/steps/xcode.js +5 -5
  30. package/dist/src/yaml/validation-types.d.ts +7 -1
  31. package/dist/src/yaml/validation-types.d.ts.map +1 -1
  32. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/run.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiJ3E"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/run.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkJ3E"}
@@ -106,7 +106,7 @@ export async function handleRunCommand(opts = {}) {
106
106
  interactive: isInteractiveTTY(),
107
107
  });
108
108
  pipeline = conversionResult.pipeline;
109
- await runner.runPipeline(pipeline, conversionResult.warnings, conversionResult.skippedSteps);
109
+ await runner.runPipeline(pipeline, conversionResult.warnings, conversionResult.skippedSteps, conversionResult.checkout);
110
110
  }
111
111
  else if (isJavaScriptModule) {
112
112
  // The one dynamic import that has to stay dynamic: the specifier is a
@@ -1,4 +1,5 @@
1
1
  import type { StepDef, PipelineDef, CIConfig } from "./types.js";
2
+ import type { CheckoutWitness } from "./yaml/converter.js";
2
3
  export declare class StepExecutionError extends Error {
3
4
  stepId: string;
4
5
  stepName: string;
@@ -12,6 +13,19 @@ export declare class PipelineRunner {
12
13
  private formatDuration;
13
14
  validatePipeline(pipeline: PipelineDef): void;
14
15
  displayWarnings(warnings: string[], skippedSteps: number): void;
15
- runPipeline(pipeline: PipelineDef, warnings?: string[], skippedSteps?: number): Promise<void>;
16
+ /**
17
+ * The commit this build compiled, printed under the banner.
18
+ *
19
+ * Every build carries it, whatever steps it declares. The dashboard's sha is
20
+ * the one that was *dispatched*; this one was read off the disk the compiler
21
+ * is about to read, and it is what a later argument about which code shipped
22
+ * has to be settled against. It used to live only in `git-clone`'s echo,
23
+ * which is optional and no longer in the curated templates.
24
+ *
25
+ * Labels match that echo's on purpose — where both appear they are the same
26
+ * three facts, and they have to agree.
27
+ */
28
+ displayCheckout(checkout: CheckoutWitness): void;
29
+ runPipeline(pipeline: PipelineDef, warnings?: string[], skippedSteps?: number, checkout?: CheckoutWitness): Promise<void>;
16
30
  }
17
31
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOjE,qBAAa,kBAAmB,SAAQ,KAAK;IAElC,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;gBAFhB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAK1B;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,QAAQ;IAE9B,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiHhE,OAAO,CAAC,cAAc;IAYtB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAwB7C,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAczD,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA2CpG"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAO3D,qBAAa,kBAAmB,SAAQ,KAAK;IAElC,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;gBAFhB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAK1B;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,QAAQ;IAE9B,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiHhE,OAAO,CAAC,cAAc;IAYtB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAwB7C,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAc/D;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAO1C,WAAW,CACf,QAAQ,EAAE,WAAW,EACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,EACnB,YAAY,CAAC,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,IAAI,CAAC;CA+CjB"}
@@ -175,7 +175,27 @@ export class PipelineRunner {
175
175
  console.log(`ℹ️ Skipped ${skippedSteps} unsupported step${skippedSteps !== 1 ? 's' : ''}. Build will continue.`);
176
176
  console.log("═".repeat(60) + "\n");
177
177
  }
178
- async runPipeline(pipeline, warnings, skippedSteps) {
178
+ /**
179
+ * The commit this build compiled, printed under the banner.
180
+ *
181
+ * Every build carries it, whatever steps it declares. The dashboard's sha is
182
+ * the one that was *dispatched*; this one was read off the disk the compiler
183
+ * is about to read, and it is what a later argument about which code shipped
184
+ * has to be settled against. It used to live only in `git-clone`'s echo,
185
+ * which is optional and no longer in the curated templates.
186
+ *
187
+ * Labels match that echo's on purpose — where both appear they are the same
188
+ * three facts, and they have to agree.
189
+ */
190
+ displayCheckout(checkout) {
191
+ console.log(`Commit: ${checkout.commit}`);
192
+ if (checkout.author)
193
+ console.log(`Author: ${checkout.author}`);
194
+ if (checkout.subject)
195
+ console.log(`Message: ${checkout.subject}`);
196
+ console.log("");
197
+ }
198
+ async runPipeline(pipeline, warnings, skippedSteps, checkout) {
179
199
  // Ensure .ci directory exists (envstore lives there)
180
200
  mkdirSync(resolve(process.cwd(), ".ci"), { recursive: true });
181
201
  // Clear envstore at the start of each build for a clean slate
@@ -185,6 +205,9 @@ export class PipelineRunner {
185
205
  console.log(`\n╔═════════════════════════════════════════════════════════╗`);
186
206
  console.log(`║ Pipeline: ${pipeline.name.padEnd(42)} ║`);
187
207
  console.log(`╚═════════════════════════════════════════════════════════╝\n`);
208
+ if (checkout) {
209
+ this.displayCheckout(checkout);
210
+ }
188
211
  // Display warnings if provided
189
212
  if (warnings && warnings.length > 0) {
190
213
  this.displayWarnings(warnings, skippedSteps || 0);
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A requirement that cannot be checked yet must not name a step as its source
3
+ * unless a step is its source.
4
+ *
5
+ * Nine runtime requirements — `gradlew` in the three Android steps and the
6
+ * Bitrise gradle wrapper, `project_path` in five Xcode steps — carried
7
+ * `providedBy: 'git-clone'`. The lookup behind `providedBy` is keyed by step
8
+ * *output names* (`CIBUILD_SOURCE_DIR`, `GIT_CLONE_COMMIT_HASH`, …) and these
9
+ * requirements are named after a path or a command, so it could never match:
10
+ * every Android validation printed "'gradlew' will be provided by 'git-clone'
11
+ * step at runtime" whether the step was in the workflow or not.
12
+ *
13
+ * `git-clone` provides no files at all — the runner's checkout does, before
14
+ * any step runs — and once it is out of the curated templates the sentence
15
+ * names a step the pipeline does not contain.
16
+ */
17
+ import './steps/index.js';
18
+ //# sourceMappingURL=a-runtime-requirement-names-a-real-provider.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a-runtime-requirement-names-a-real-provider.test.d.ts","sourceRoot":"","sources":["../../../src/yaml/a-runtime-requirement-names-a-real-provider.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,kBAAkB,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * A requirement that cannot be checked yet must not name a step as its source
3
+ * unless a step is its source.
4
+ *
5
+ * Nine runtime requirements — `gradlew` in the three Android steps and the
6
+ * Bitrise gradle wrapper, `project_path` in five Xcode steps — carried
7
+ * `providedBy: 'git-clone'`. The lookup behind `providedBy` is keyed by step
8
+ * *output names* (`CIBUILD_SOURCE_DIR`, `GIT_CLONE_COMMIT_HASH`, …) and these
9
+ * requirements are named after a path or a command, so it could never match:
10
+ * every Android validation printed "'gradlew' will be provided by 'git-clone'
11
+ * step at runtime" whether the step was in the workflow or not.
12
+ *
13
+ * `git-clone` provides no files at all — the runner's checkout does, before
14
+ * any step runs — and once it is out of the curated templates the sentence
15
+ * names a step the pipeline does not contain.
16
+ */
17
+ import { describe, test, expect } from '@jest/globals';
18
+ import './steps/index.js';
19
+ import { StepValidator } from './step-validator.js';
20
+ import { loadConfig } from '../config.js';
21
+ const config = loadConfig();
22
+ /** An Android workflow with no `git-clone` step, as issue 05 leaves it. */
23
+ function gradlePipeline() {
24
+ return {
25
+ format_version: '1',
26
+ meta: { invarn: { stack: 'linux-android-35' } },
27
+ app: { envs: [{ JAVA_HOME: '/usr/lib/jvm/java-21' }] },
28
+ workflows: {
29
+ primary: {
30
+ steps: [
31
+ {
32
+ 'gradle-build@1.0.0': {
33
+ title: 'Build Debug APK',
34
+ inputs: { gradle_task: 'assembleDebug' },
35
+ },
36
+ },
37
+ ],
38
+ },
39
+ },
40
+ };
41
+ }
42
+ describe('a runtime requirement names a real provider', () => {
43
+ test('a clone-free workflow never mentions git-clone', async () => {
44
+ const validator = new StepValidator(gradlePipeline(), 'primary', config);
45
+ const result = await validator.validateWorkflow();
46
+ const messages = result.issues.map((i) => i.result.message ?? '').join('\n');
47
+ expect(messages).not.toContain('git-clone');
48
+ });
49
+ test('the checkout is named as the source of the gradle wrapper', async () => {
50
+ const validator = new StepValidator(gradlePipeline(), 'primary', config);
51
+ const result = await validator.validateWorkflow();
52
+ const gradlew = result.issues.find((i) => i.requirement.name === 'gradlew');
53
+ expect(gradlew).toBeDefined();
54
+ expect(gradlew.requirement.severity).toBe('info');
55
+ expect(gradlew.result.message).toContain('the checkout');
56
+ // The wording must not promise a step: no step puts the wrapper on disk.
57
+ expect(gradlew.result.message).not.toMatch(/'the checkout' step/);
58
+ });
59
+ test('the info does not fail validation', async () => {
60
+ const validator = new StepValidator(gradlePipeline(), 'primary', config);
61
+ const result = await validator.validateWorkflow();
62
+ expect(result.valid).toBe(true);
63
+ expect(result.counts.errors).toBe(0);
64
+ });
65
+ });
66
+ //# sourceMappingURL=a-runtime-requirement-names-a-real-provider.test.js.map
@@ -10,10 +10,32 @@ export declare class YAMLConversionError extends Error {
10
10
  /**
11
11
  * Result of YAML to PipelineDef conversion
12
12
  */
13
+ /**
14
+ * What was on disk when the pipeline was converted — the only thing that can
15
+ * say which commit a build actually compiled.
16
+ *
17
+ * A dashboard's sha is the one that was *dispatched*. Between dispatch and
18
+ * checkout a branch can move, a tag can be re-pointed, and a shared checkout
19
+ * can be pushed over. Until now the sole in-log evidence was `git-clone`'s
20
+ * own echo, which is optional and on its way out of the templates.
21
+ */
22
+ export interface CheckoutWitness {
23
+ /** Full SHA of HEAD. */
24
+ commit: string;
25
+ /** `Name <email>` of the commit's author, empty when unknown. */
26
+ author: string;
27
+ /** First line of the commit message, empty when unknown. */
28
+ subject: string;
29
+ }
13
30
  export interface ConversionResult {
14
31
  pipeline: PipelineDef;
15
32
  warnings: string[];
16
33
  skippedSteps: number;
34
+ /**
35
+ * Absent only when the working directory is not a git checkout — a local
36
+ * `ci run` in a plain directory, never a runner.
37
+ */
38
+ checkout?: CheckoutWitness;
17
39
  }
18
40
  /**
19
41
  * A credential a `file@` step writes, and where it goes.
@@ -1 +1 @@
1
- {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../../src/yaml/converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAC;AAMzE,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAaD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CASjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,SAAS,gBAAgB,EAAE,EACxC,MAAM,EAAE,SAAS,oBAAoB,EAAE,GACtC,mBAAmB,EAAE,CAgBvB;AAED,qDAAqD;AACrD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,mBAAmB,GAC7B,MAAM,CAaR;AAkCD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,QAAQ,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAyM3B;AAwGD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE,CAEtE"}
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../../src/yaml/converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAC;AAMzE,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAaD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CASjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,SAAS,gBAAgB,EAAE,EACxC,MAAM,EAAE,SAAS,oBAAoB,EAAE,GACtC,mBAAmB,EAAE,CAgBvB;AAED,qDAAqD;AACrD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,mBAAmB,GAC7B,MAAM,CAaR;AA6DD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,QAAQ,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA0M3B;AAwGD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE,CAEtE"}
@@ -132,6 +132,31 @@ const BITRISE_TO_CIBUILD = {
132
132
  'android-detekt': 'detekt',
133
133
  'bitrise-step-flutter-installer': 'flutter-installer',
134
134
  };
135
+ /**
136
+ * Reads the checkout's identity back out of the resolver, which computed it
137
+ * from the very working directory the build is about to run in.
138
+ *
139
+ * Read through `getAll()` rather than `get()`: the latter records every name
140
+ * it is asked for in `referencedVars`, and a pipeline is refused when a
141
+ * referenced name has no value. Nothing here is a variable the pipeline
142
+ * referenced.
143
+ *
144
+ * `EnvResolver` falls back to the literal string `HEAD` when `git rev-parse`
145
+ * fails, so the shape of the hash — not a second question to git — is what
146
+ * tells a real checkout from a plain directory.
147
+ */
148
+ function checkoutWitnessFrom(env) {
149
+ const commit = env['CIBUILD_GIT_COMMIT'] ?? '';
150
+ if (!/^[0-9a-f]{7,40}$/.test(commit))
151
+ return undefined;
152
+ const name = env['GIT_CLONE_COMMIT_AUTHOR_NAME'] ?? '';
153
+ const email = env['GIT_CLONE_COMMIT_AUTHOR_EMAIL'] ?? '';
154
+ return {
155
+ commit,
156
+ author: name && email ? `${name} <${email}>` : name || email,
157
+ subject: env['GIT_CLONE_COMMIT_MESSAGE_SUBJECT'] ?? '',
158
+ };
159
+ }
135
160
  /**
136
161
  * Converts a YAML pipeline workflow to PipelineDef format
137
162
  * @param pipeline Parsed YAML pipeline
@@ -302,6 +327,7 @@ export async function convertYAMLToPipelineDef(pipeline, config, workflowName, y
302
327
  pipeline: pipelineDef,
303
328
  warnings,
304
329
  skippedSteps,
330
+ checkout: checkoutWitnessFrom(envResolver.getAll()),
305
331
  };
306
332
  }
307
333
  /**
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Every build log says which commit was on disk.
3
+ *
4
+ * The dashboard's sha is the one that was *dispatched*. The only in-log
5
+ * evidence of what was actually compiled was `git-clone`'s echo of
6
+ * `Commit:` / `Author:` / `Message:` — and that step is optional, does not
7
+ * appear in a `ci init` pipeline or a protocol pipeline, and is being taken
8
+ * out of the curated templates. A pipeline written after that would have
9
+ * carried no witness at all.
10
+ *
11
+ * The run banner now carries it, from the values `EnvResolver` already read
12
+ * off the same checkout, so it does not depend on which steps a workflow
13
+ * declares.
14
+ */
15
+ import './steps/index.js';
16
+ //# sourceMappingURL=every-build-log-witnesses-the-commit-on-disk.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"every-build-log-witnesses-the-commit-on-disk.test.d.ts","sourceRoot":"","sources":["../../../src/yaml/every-build-log-witnesses-the-commit-on-disk.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,kBAAkB,CAAC"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Every build log says which commit was on disk.
3
+ *
4
+ * The dashboard's sha is the one that was *dispatched*. The only in-log
5
+ * evidence of what was actually compiled was `git-clone`'s echo of
6
+ * `Commit:` / `Author:` / `Message:` — and that step is optional, does not
7
+ * appear in a `ci init` pipeline or a protocol pipeline, and is being taken
8
+ * out of the curated templates. A pipeline written after that would have
9
+ * carried no witness at all.
10
+ *
11
+ * The run banner now carries it, from the values `EnvResolver` already read
12
+ * off the same checkout, so it does not depend on which steps a workflow
13
+ * declares.
14
+ */
15
+ import { describe, test, expect } from '@jest/globals';
16
+ import { execFileSync } from 'node:child_process';
17
+ import { mkdtempSync, rmSync } from 'node:fs';
18
+ import { tmpdir } from 'node:os';
19
+ import { join } from 'node:path';
20
+ import './steps/index.js';
21
+ import { convertYAMLToPipelineDef } from './converter.js';
22
+ import { PipelineRunner } from '../runner.js';
23
+ import { loadConfig } from '../config.js';
24
+ const config = loadConfig();
25
+ /** The three marker contracts Invarn's log parser reads. */
26
+ const STEP_MARKER = /▸ INVARN_STEP:(\d+):(.+)/;
27
+ const PHASE_MARKER = /▸ INVARN_PHASE:([a-z0-9_-]+):(start|ok|fail)\b/;
28
+ const STEP_HEADING = /^\[step_\d+\] Running: /;
29
+ function pipelineWith(steps) {
30
+ return {
31
+ format_version: '1',
32
+ meta: { invarn: { stack: 'macos-xcode-26.4' } },
33
+ workflows: { primary: { steps } },
34
+ };
35
+ }
36
+ /** What `git` says, asked directly rather than through the resolver. */
37
+ function git(...args) {
38
+ return execFileSync('git', args, { encoding: 'utf8' }).trim();
39
+ }
40
+ /** Everything `runPipeline` printed, for a workflow with no steps. */
41
+ async function bannerOf(checkout) {
42
+ const lines = [];
43
+ const original = console.log;
44
+ const cwd = process.cwd();
45
+ // `runPipeline` creates `.ci/` beside the working directory for the
46
+ // envstore. Somewhere disposable, so a test never leaves one in the repo.
47
+ const scratch = mkdtempSync(join(tmpdir(), 'cibuild-banner-'));
48
+ console.log = (...args) => {
49
+ lines.push(args.map(String).join(' '));
50
+ };
51
+ try {
52
+ process.chdir(scratch);
53
+ const runner = new PipelineRunner(config);
54
+ await runner.runPipeline({ name: 'primary (YAML)', artifacts: [], steps: [], stepsOrder: [] }, undefined, undefined, checkout);
55
+ }
56
+ finally {
57
+ console.log = original;
58
+ process.chdir(cwd);
59
+ rmSync(scratch, { recursive: true, force: true });
60
+ }
61
+ return lines;
62
+ }
63
+ const witness = {
64
+ commit: '0123456789abcdef0123456789abcdef01234567',
65
+ author: 'Ada Lovelace <ada@example.com>',
66
+ subject: 'the subject line',
67
+ };
68
+ describe('every build log witnesses the commit on disk', () => {
69
+ test('the conversion carries the commit that is on disk', async () => {
70
+ const result = await convertYAMLToPipelineDef(pipelineWith([{ 'git-clone@1.0.0': {} }]), config, 'primary');
71
+ expect(result.checkout).toBeDefined();
72
+ expect(result.checkout.commit).toBe(git('rev-parse', 'HEAD'));
73
+ expect(result.checkout.subject).toBe(git('log', '-1', '--format=%s'));
74
+ expect(result.checkout.author).toBe(`${git('log', '-1', '--format=%an')} <${git('log', '-1', '--format=%ae')}>`);
75
+ });
76
+ test('a workflow with no git-clone step carries it just the same', async () => {
77
+ // The whole point: the witness must not depend on a declared step.
78
+ const result = await convertYAMLToPipelineDef(pipelineWith([{ 'script@1.0.0': { inputs: { content: 'true' } } }]), config, 'primary');
79
+ expect(result.checkout?.commit).toBe(git('rev-parse', 'HEAD'));
80
+ });
81
+ test('the banner prints hash, author and subject exactly once', async () => {
82
+ const lines = await bannerOf(witness);
83
+ expect(lines.filter((l) => l.includes(witness.commit))).toHaveLength(1);
84
+ expect(lines.filter((l) => l.includes(witness.author))).toHaveLength(1);
85
+ expect(lines.filter((l) => l.includes(witness.subject))).toHaveLength(1);
86
+ });
87
+ test('the banner is at the top, before anything a step prints', async () => {
88
+ const lines = await bannerOf(witness);
89
+ const pipelineLine = lines.findIndex((l) => l.includes('Pipeline:'));
90
+ const commitLine = lines.findIndex((l) => l.includes(witness.commit));
91
+ expect(pipelineLine).toBeGreaterThanOrEqual(0);
92
+ expect(commitLine).toBeGreaterThan(pipelineLine);
93
+ });
94
+ test('a run with no witness prints no empty Commit line', async () => {
95
+ // `EnvResolver` falls back to the literal `HEAD`, so a plain directory
96
+ // would otherwise produce `Commit: HEAD` — worse than saying nothing.
97
+ const lines = await bannerOf(undefined);
98
+ expect(lines.filter((l) => l.startsWith('Commit:'))).toHaveLength(0);
99
+ expect(lines.filter((l) => l.startsWith('Author:'))).toHaveLength(0);
100
+ });
101
+ test('an author or subject git could not read is left out', async () => {
102
+ const lines = await bannerOf({ commit: witness.commit, author: '', subject: '' });
103
+ expect(lines.filter((l) => l.startsWith('Commit:'))).toHaveLength(1);
104
+ expect(lines.filter((l) => l.startsWith('Author:'))).toHaveLength(0);
105
+ expect(lines.filter((l) => l.startsWith('Message:'))).toHaveLength(0);
106
+ });
107
+ test('no line of the banner can be read as a marker or a step heading', async () => {
108
+ // Invarn's step-progress parser splits a build log on these. A banner line
109
+ // that matched one would invent a step or move a boundary.
110
+ for (const line of await bannerOf(witness)) {
111
+ expect(line).not.toMatch(STEP_MARKER);
112
+ expect(line).not.toMatch(PHASE_MARKER);
113
+ expect(line).not.toMatch(STEP_HEADING);
114
+ }
115
+ });
116
+ test('the banner and git-clone read the same commit', async () => {
117
+ // Where both appear they must agree. The step echoes `git rev-parse HEAD`
118
+ // from the shell; the banner reports what the resolver read from the same
119
+ // checkout in the same directory.
120
+ const result = await convertYAMLToPipelineDef(pipelineWith([{ 'git-clone@1.0.0': {} }]), config, 'primary');
121
+ const step = result.pipeline.steps.find((s) => s.name === 'git-clone');
122
+ expect(step.script).toContain('COMMIT_HASH="$(git rev-parse HEAD)"');
123
+ expect(result.checkout.commit).toBe(git('rev-parse', 'HEAD'));
124
+ });
125
+ });
126
+ //# sourceMappingURL=every-build-log-witnesses-the-commit-on-disk.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"step-validator.d.ts","sourceRoot":"","sources":["../../../src/yaml/step-validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAGV,wBAAwB,EAGzB,MAAM,uBAAuB,CAAC;AAwB/B;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAC,CAAS;IAG9B,OAAO,CAAC,gBAAgB,CAAoE;IAG5F,OAAO,CAAC,mBAAmB,CAA6B;IAKxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;gBAGvC,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,QAAQ,EAChB,YAAY,CAAC,EAAE,MAAM;IA0BvB;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAwN3D;;OAEG;YACW,mBAAmB;IAmEjC;;;;;;;;;OASG;IACH,OAAO,CAAC,yBAAyB;IAsBjC;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;OAEG;IACH,OAAO,CAAC,SAAS;CA8BlB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CA4D/E"}
1
+ {"version":3,"file":"step-validator.d.ts","sourceRoot":"","sources":["../../../src/yaml/step-validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAGV,wBAAwB,EAGzB,MAAM,uBAAuB,CAAC;AAwB/B;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAC,CAAS;IAG9B,OAAO,CAAC,gBAAgB,CAAoE;IAG5F,OAAO,CAAC,mBAAmB,CAA6B;IAKxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;gBAGvC,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,QAAQ,EAChB,YAAY,CAAC,EAAE,MAAM;IA0BvB;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAwN3D;;OAEG;YACW,mBAAmB;IAuEjC;;;;;;;;;OASG;IACH,OAAO,CAAC,yBAAyB;IAsBjC;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;OAEG;IACH,OAAO,CAAC,SAAS;CA8BlB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CA4D/E"}
@@ -260,14 +260,18 @@ export class StepValidator {
260
260
  if (requirement.providedBy) {
261
261
  const provider = this.availableOutputs.get(requirement.name);
262
262
  if (!provider) {
263
- // Output not provided by any earlier step - this is an info message
263
+ // Nothing declares this name as an output, so say where it does come
264
+ // from and leave it at that. `providedBy` is prose: most of these
265
+ // requirements are named after a path or a command rather than a
266
+ // step output, so the lookup above was never going to match one, and
267
+ // the sentence must stay true when the source is not a step at all.
264
268
  return {
265
269
  stepName,
266
270
  stepIndex,
267
271
  requirement,
268
272
  result: {
269
273
  passed: false,
270
- message: `'${requirement.name}' will be provided by '${requirement.providedBy}' step at runtime`,
274
+ message: `'${requirement.name}' is not here yet — expected from ${requirement.providedBy} at runtime`,
271
275
  },
272
276
  };
273
277
  }
@@ -270,7 +270,7 @@ export class GradleBuildStepExecutor extends BaseStepExecutor {
270
270
  getValidationRequirements(_inputs, env, _config) {
271
271
  return [
272
272
  this.requireEnvVar('JAVA_HOME', 'Java installation directory', env, 'Add a set-java-version step before gradle-build, or set JAVA_HOME env var'),
273
- this.runtimeRequirement('gradlew', 'Gradle wrapper (./gradlew) or gradle command', 'file', 'git-clone'),
273
+ this.runtimeRequirement('gradlew', 'Gradle wrapper (./gradlew) or gradle command', 'file', 'the checkout'),
274
274
  ];
275
275
  }
276
276
  async execute(inputs, env, config) {
@@ -595,7 +595,7 @@ export class AndroidLintStepExecutor extends BaseStepExecutor {
595
595
  getValidationRequirements(_inputs, env, _config) {
596
596
  return [
597
597
  this.requireEnvVar('JAVA_HOME', 'Java installation directory', env, 'Add a set-java-version step before android-lint, or set JAVA_HOME env var'),
598
- this.runtimeRequirement('gradlew', 'Gradle wrapper (./gradlew) or gradle command', 'file', 'git-clone'),
598
+ this.runtimeRequirement('gradlew', 'Gradle wrapper (./gradlew) or gradle command', 'file', 'the checkout'),
599
599
  ];
600
600
  }
601
601
  async execute(inputs, env, config) {
@@ -782,7 +782,7 @@ export class AndroidUnitTestStepExecutor extends BaseStepExecutor {
782
782
  getValidationRequirements(_inputs, env, _config) {
783
783
  return [
784
784
  this.requireEnvVar('JAVA_HOME', 'Java installation directory', env, 'Add a set-java-version step before android-unit-test, or set JAVA_HOME env var'),
785
- this.runtimeRequirement('gradlew', 'Gradle wrapper (./gradlew) or gradle command', 'file', 'git-clone'),
785
+ this.runtimeRequirement('gradlew', 'Gradle wrapper (./gradlew) or gradle command', 'file', 'the checkout'),
786
786
  ];
787
787
  }
788
788
  async execute(inputs, env, config) {
@@ -193,7 +193,12 @@ export declare abstract class BaseStepExecutor implements StepExecutor {
193
193
  protected requireInput(inputName: string, inputs: any, description: string, hint?: string): ValidationRequirement;
194
194
  /**
195
195
  * Creates a runtime-only requirement (checked at step execution time)
196
- * Used for files/directories that will be created by earlier steps
196
+ * Used for files/directories that are not on disk when validation runs.
197
+ *
198
+ * `providedBy` is the sentence a reader gets — an earlier step's name, or
199
+ * `'the checkout'` for anything the runner lays down before step 1. Naming
200
+ * a step that does not declare `name` as one of its outputs just makes the
201
+ * sentence wrong; nothing checks it.
197
202
  */
198
203
  protected runtimeRequirement(name: string, description: string, category?: ValidationCategory, providedBy?: string): ValidationRequirement;
199
204
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/base.ts"],"names":[],"mappings":"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"}
@@ -305,7 +305,12 @@ ${scriptContent}
305
305
  }
306
306
  /**
307
307
  * Creates a runtime-only requirement (checked at step execution time)
308
- * Used for files/directories that will be created by earlier steps
308
+ * Used for files/directories that are not on disk when validation runs.
309
+ *
310
+ * `providedBy` is the sentence a reader gets — an earlier step's name, or
311
+ * `'the checkout'` for anything the runner lays down before step 1. Naming
312
+ * a step that does not declare `name` as one of its outputs just makes the
313
+ * sentence wrong; nothing checks it.
309
314
  */
310
315
  runtimeRequirement(name, description, category = 'file', providedBy) {
311
316
  return {
@@ -51,7 +51,7 @@ export class BitriseAndroidToolsStepExecutor extends BaseStepExecutor {
51
51
  };
52
52
  },
53
53
  },
54
- this.runtimeRequirement('gradlew', 'Gradle wrapper', 'file', 'git-clone'),
54
+ this.runtimeRequirement('gradlew', 'Gradle wrapper', 'file', 'the checkout'),
55
55
  ];
56
56
  }
57
57
  getOutputs() {
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `git-clone` reads none of its inputs, and said nothing about it.
3
+ *
4
+ * The step does not clone. By the time it runs, the runner has already checked
5
+ * the dispatched ref out — `git-clone` locates that checkout and republishes
6
+ * its commit metadata. `execute()` takes `_inputs` and never opens it. So
7
+ * `branch: release/2.0` parsed, validated, ran green, and built `main`; a
8
+ * Bitrise-migrated `git-clone@8` carried `clone_depth: 0`, `fetch_tags` and
9
+ * `submodule_update_depth` through the converter and into nothing.
10
+ *
11
+ * Accepting configuration that has no effect is the defect. The step now names
12
+ * every input it was handed, at warning severity: every pipeline written to
13
+ * date carries some of these, and all of them must keep building.
14
+ */
15
+ import './index.js';
16
+ //# sourceMappingURL=git-clone-names-the-inputs-it-ignores.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-clone-names-the-inputs-it-ignores.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,YAAY,CAAC"}