@invarn/cibuild 2.6.7 → 2.6.9

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 (42) hide show
  1. package/dist/cli.cjs +10 -10
  2. package/dist/src/commands/android-java-version.test.js +55 -24
  3. package/dist/src/commands/android-scanner-java.test.d.ts +2 -0
  4. package/dist/src/commands/android-scanner-java.test.d.ts.map +1 -0
  5. package/dist/src/commands/android-scanner-java.test.js +130 -0
  6. package/dist/src/commands/android-scanner.d.ts +47 -22
  7. package/dist/src/commands/android-scanner.d.ts.map +1 -1
  8. package/dist/src/commands/android-scanner.js +187 -52
  9. package/dist/src/commands/ios-scanner.d.ts +42 -1
  10. package/dist/src/commands/ios-scanner.d.ts.map +1 -1
  11. package/dist/src/commands/ios-scanner.js +123 -3
  12. package/dist/src/commands/ios-scheme-ranking.test.d.ts +2 -0
  13. package/dist/src/commands/ios-scheme-ranking.test.d.ts.map +1 -0
  14. package/dist/src/commands/ios-scheme-ranking.test.js +152 -0
  15. package/dist/src/shared/detect-project.d.ts +15 -3
  16. package/dist/src/shared/detect-project.d.ts.map +1 -1
  17. package/dist/src/shared/detect-project.js +126 -15
  18. package/dist/src/shared/detect-project.test.d.ts +2 -0
  19. package/dist/src/shared/detect-project.test.d.ts.map +1 -0
  20. package/dist/src/shared/detect-project.test.js +126 -0
  21. package/dist/src/shared/gradle-settings.d.ts +32 -0
  22. package/dist/src/shared/gradle-settings.d.ts.map +1 -0
  23. package/dist/src/shared/gradle-settings.js +66 -0
  24. package/dist/src/yaml/step-validator-self-assigned.test.d.ts +23 -0
  25. package/dist/src/yaml/step-validator-self-assigned.test.d.ts.map +1 -0
  26. package/dist/src/yaml/step-validator-self-assigned.test.js +129 -0
  27. package/dist/src/yaml/step-validator.d.ts +32 -0
  28. package/dist/src/yaml/step-validator.d.ts.map +1 -1
  29. package/dist/src/yaml/step-validator.js +72 -0
  30. package/dist/src/yaml/steps/android-variant-resolution.test.d.ts +2 -0
  31. package/dist/src/yaml/steps/android-variant-resolution.test.d.ts.map +1 -0
  32. package/dist/src/yaml/steps/android-variant-resolution.test.js +117 -0
  33. package/dist/src/yaml/steps/android.d.ts +37 -0
  34. package/dist/src/yaml/steps/android.d.ts.map +1 -1
  35. package/dist/src/yaml/steps/android.js +130 -17
  36. package/dist/src/yaml/steps/base.d.ts +20 -0
  37. package/dist/src/yaml/steps/base.d.ts.map +1 -1
  38. package/dist/src/yaml/steps/base.js +24 -1
  39. package/dist/src/yaml/steps/java-home-version-spec.test.d.ts +10 -0
  40. package/dist/src/yaml/steps/java-home-version-spec.test.d.ts.map +1 -0
  41. package/dist/src/yaml/steps/java-home-version-spec.test.js +58 -0
  42. package/package.json +1 -1
@@ -8,7 +8,7 @@
8
8
  // for one never runs on a runner.
9
9
  import { existsSync, readFileSync } from 'node:fs';
10
10
  import { execSync } from 'node:child_process';
11
- import { BaseStepExecutor } from './base.js';
11
+ import { BaseStepExecutor, javaHomeVersionSpec } from './base.js';
12
12
  /**
13
13
  * Set Java version step executor
14
14
  * Sets the Java version to use for Android builds
@@ -72,14 +72,17 @@ export class SetJavaVersionStepExecutor extends BaseStepExecutor {
72
72
  }
73
73
  // Try java_home utility on macOS
74
74
  if (process.platform === 'darwin') {
75
+ // java_home wants `1.8` for Java 8, and answers a wrong request with the
76
+ // newest JDK rather than an error -- see javaHomeVersionSpec.
77
+ const spec = javaHomeVersionSpec(version);
75
78
  try {
76
- execSync(`/usr/libexec/java_home -v "${version}"`, { stdio: 'pipe' });
79
+ execSync(`/usr/libexec/java_home -v "${spec}"`, { stdio: 'pipe' });
77
80
  return { passed: true, message: `Java ${version} is available` };
78
81
  }
79
82
  catch {
80
83
  // Try with pattern
81
84
  try {
82
- execSync(`/usr/libexec/java_home -v "${version}.*"`, { stdio: 'pipe' });
85
+ execSync(`/usr/libexec/java_home -v "${spec}.*"`, { stdio: 'pipe' });
83
86
  return { passed: true, message: `Java ${version} is available` };
84
87
  }
85
88
  catch {
@@ -167,10 +170,19 @@ export class SetJavaVersionStepExecutor extends BaseStepExecutor {
167
170
  commands.push('fi');
168
171
  commands.push('');
169
172
  commands.push('# 4. macOS java_home utility');
173
+ commands.push('# java_home matches Java 8 only as 1.8 (it predates JEP 223), and it is');
174
+ commands.push('# permissive: an unmatched -v N returns the NEWEST JDK >= N instead of');
175
+ commands.push('# failing. Asking as "8" therefore does not miss, it silently returns the');
176
+ commands.push('# wrong JDK -- measured as OpenJDK 25 on an image where Corretto 8 was');
177
+ commands.push('# installed and found correctly by -v 1.8.');
178
+ commands.push('JAVA_HOME_SPEC="$JAVA_VERSION"');
179
+ commands.push('case "$JAVA_VERSION" in');
180
+ commands.push(' 1|2|3|4|5|6|7|8) JAVA_HOME_SPEC="1.$JAVA_VERSION" ;;');
181
+ commands.push('esac');
170
182
  commands.push('if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then');
171
- commands.push(' JAVA_HOME=$(/usr/libexec/java_home -v "$JAVA_VERSION" 2>/dev/null || true)');
183
+ commands.push(' JAVA_HOME=$(/usr/libexec/java_home -v "$JAVA_HOME_SPEC" 2>/dev/null || true)');
172
184
  commands.push(' if [ -z "$JAVA_HOME" ]; then');
173
- commands.push(' JAVA_HOME=$(/usr/libexec/java_home -v "${JAVA_VERSION}.*" 2>/dev/null || true)');
185
+ commands.push(' JAVA_HOME=$(/usr/libexec/java_home -v "${JAVA_HOME_SPEC}.*" 2>/dev/null || true)');
174
186
  commands.push(' fi');
175
187
  commands.push(' if [ -n "$JAVA_HOME" ]; then');
176
188
  commands.push(' echo "Found Java at: $JAVA_HOME (java_home)"');
@@ -340,9 +352,14 @@ export class GradleBuildStepExecutor extends BaseStepExecutor {
340
352
  commands.push(' fi');
341
353
  commands.push(' # Try macOS java_home utility for specific version');
342
354
  commands.push(' elif [ -x "/usr/libexec/java_home" ]; then');
343
- commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQUESTED_VERSION}" 2>/dev/null || true)');
355
+ commands.push(' # java_home names Java 8 as 1.8, and answers an unmatched request');
356
+ commands.push(' # with the newest JDK rather than failing -- ask the right way or');
357
+ commands.push(' # silently get the wrong JDK.');
358
+ commands.push(' REQ_SPEC="$REQUESTED_VERSION"');
359
+ commands.push(' case "$REQUESTED_VERSION" in 1|2|3|4|5|6|7|8) REQ_SPEC="1.$REQUESTED_VERSION" ;; esac');
360
+ commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "$REQ_SPEC" 2>/dev/null || true)');
344
361
  commands.push(' if [ -z "$DETECTED_JAVA_HOME" ]; then');
345
- commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQUESTED_VERSION}.*" 2>/dev/null || true)');
362
+ commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQ_SPEC}.*" 2>/dev/null || true)');
346
363
  commands.push(' fi');
347
364
  commands.push(' if [ -n "$DETECTED_JAVA_HOME" ]; then');
348
365
  commands.push(' echo "✅ Found Java $REQUESTED_VERSION at: $DETECTED_JAVA_HOME (java_home utility)"');
@@ -499,6 +516,81 @@ export class GradleBuildStepExecutor extends BaseStepExecutor {
499
516
  * Android lint step executor
500
517
  * Runs Android lint checks
501
518
  */
519
+ /**
520
+ * Bash that picks a real variant task out of Gradle's own ambiguity error.
521
+ *
522
+ * `android/nowinandroid` declares its product flavors as an enum in
523
+ * `build-logic/convention/…/NiaFlavor.kt` and applies them through a
524
+ * convention plugin, so `app/build.gradle.kts` has no `productFlavors {}`
525
+ * block for the literal scan to find. `VARIANT` stayed `debug` and Gradle
526
+ * refused the very first Android step:
527
+ *
528
+ * Cannot locate tasks that match ':app:lintDebug' as task 'lintDebug' is
529
+ * ambiguous in project ':app'. Candidates are: 'lintDemoDebug',
530
+ * 'lintProdDebug', …
531
+ *
532
+ * Gradle has just listed the answer. Reading it back costs one extra
533
+ * invocation on the failing case and nothing at all on a flavourless project,
534
+ * which is why this is the fallback rather than an up-front `tasks --all`.
535
+ *
536
+ * Written as a shell function so what ships is what the test runs.
537
+ */
538
+ export const PICK_VARIANT_TASK_FUNCTION = `cibuild_pick_variant_task() {
539
+ # $1 task prefix (lint, test), $2 task suffix (empty, UnitTest),
540
+ # $3 the build type to prefer (Debug). Gradle's output arrives on stdin.
541
+ awk '/Candidates are:/ { sub(/.*Candidates are:/, ""); print; exit }' |
542
+ tr ',' '\\n' |
543
+ tr -d " '\\"." |
544
+ grep -E "^\${1}[A-Za-z0-9]*\${3}\${2}$" |
545
+ head -1
546
+ }`;
547
+ /**
548
+ * The commands that run a variant-specific Gradle task and, if the variant
549
+ * turns out to be a guess Gradle cannot resolve, resolve it and retry once.
550
+ *
551
+ * The resolved variant is exported with `envman`, so the *other*
552
+ * variant-specific step in the same pipeline does not repeat the discovery —
553
+ * whichever of lint and unit tests runs first pays for it.
554
+ */
555
+ export function variantTaskCommands(options) {
556
+ const { module, variant, prefix, suffix, gradleArgs = '', escape } = options;
557
+ const capitalized = variant.charAt(0).toUpperCase() + variant.slice(1);
558
+ const task = `:${escape(module)}:${prefix}${capitalized}${suffix}`;
559
+ const args = gradleArgs === '' ? '' : ` ${gradleArgs}`;
560
+ return [
561
+ '',
562
+ PICK_VARIANT_TASK_FUNCTION,
563
+ '',
564
+ `VARIANT_LOG=$(mktemp)`,
565
+ 'set +e',
566
+ `$GRADLE_CMD ${task}${args} 2>&1 | tee "$VARIANT_LOG"`,
567
+ 'VARIANT_STATUS=${PIPESTATUS[0]}',
568
+ 'set -e',
569
+ '',
570
+ 'if [ "$VARIANT_STATUS" -ne 0 ] && grep -q "is ambiguous in project" "$VARIANT_LOG"; then',
571
+ ` echo ""`,
572
+ ` echo "Gradle says ${task} is ambiguous, so this project has product flavors the pipeline did not know about."`,
573
+ ` BUILD_TYPE_WANTED="\${BUILD_TYPE:-${capitalized}}"`,
574
+ ` RESOLVED_TASK=$(cibuild_pick_variant_task "${prefix}" "${suffix}" "$BUILD_TYPE_WANTED" < "$VARIANT_LOG")`,
575
+ ' if [ -z "$RESOLVED_TASK" ]; then',
576
+ ' echo "None of the candidates Gradle listed ends in $BUILD_TYPE_WANTED, so there is nothing safe to retry with."',
577
+ ' rm -f "$VARIANT_LOG"',
578
+ ' exit "$VARIANT_STATUS"',
579
+ ' fi',
580
+ ` RESOLVED_VARIANT=\${RESOLVED_TASK#${prefix}}`,
581
+ ...(suffix === '' ? [] : [` RESOLVED_VARIANT=\${RESOLVED_VARIANT%${suffix}}`]),
582
+ ` RESOLVED_VARIANT="$(echo "\${RESOLVED_VARIANT:0:1}" | tr '[:upper:]' '[:lower:]')\${RESOLVED_VARIANT:1}"`,
583
+ ` echo "Using :${escape(module)}:$RESOLVED_TASK — resolved VARIANT=$RESOLVED_VARIANT"`,
584
+ // Best-effort: the discovery is worth having even where envman is not.
585
+ ' envman add --key VARIANT --value "$RESOLVED_VARIANT" || true',
586
+ ` $GRADLE_CMD :${escape(module)}:$RESOLVED_TASK${args}`,
587
+ 'elif [ "$VARIANT_STATUS" -ne 0 ]; then',
588
+ ' rm -f "$VARIANT_LOG"',
589
+ ' exit "$VARIANT_STATUS"',
590
+ 'fi',
591
+ 'rm -f "$VARIANT_LOG"',
592
+ ];
593
+ }
502
594
  export class AndroidLintStepExecutor extends BaseStepExecutor {
503
595
  getValidationRequirements(_inputs, env, _config) {
504
596
  return [
@@ -559,9 +651,14 @@ export class AndroidLintStepExecutor extends BaseStepExecutor {
559
651
  commands.push(' fi');
560
652
  commands.push(' # Try macOS java_home utility for specific version');
561
653
  commands.push(' elif [ -x "/usr/libexec/java_home" ]; then');
562
- commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQUESTED_VERSION}" 2>/dev/null || true)');
654
+ commands.push(' # java_home names Java 8 as 1.8, and answers an unmatched request');
655
+ commands.push(' # with the newest JDK rather than failing -- ask the right way or');
656
+ commands.push(' # silently get the wrong JDK.');
657
+ commands.push(' REQ_SPEC="$REQUESTED_VERSION"');
658
+ commands.push(' case "$REQUESTED_VERSION" in 1|2|3|4|5|6|7|8) REQ_SPEC="1.$REQUESTED_VERSION" ;; esac');
659
+ commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "$REQ_SPEC" 2>/dev/null || true)');
563
660
  commands.push(' if [ -z "$DETECTED_JAVA_HOME" ]; then');
564
- commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQUESTED_VERSION}.*" 2>/dev/null || true)');
661
+ commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQ_SPEC}.*" 2>/dev/null || true)');
565
662
  commands.push(' fi');
566
663
  commands.push(' if [ -n "$DETECTED_JAVA_HOME" ]; then');
567
664
  commands.push(' echo "✅ Found Java $REQUESTED_VERSION at: $DETECTED_JAVA_HOME (java_home utility)"');
@@ -662,8 +759,13 @@ export class AndroidLintStepExecutor extends BaseStepExecutor {
662
759
  commands.push('');
663
760
  commands.push('# Run lint');
664
761
  const variantCapitalized = variant.charAt(0).toUpperCase() + variant.slice(1);
665
- const lintTask = `:${this.escapeBash(module)}:lint${variantCapitalized}`;
666
- commands.push(`$GRADLE_CMD ${lintTask}`);
762
+ commands.push(...variantTaskCommands({
763
+ module,
764
+ variant,
765
+ prefix: 'lint',
766
+ suffix: '',
767
+ escape: (value) => this.escapeBash(value),
768
+ }));
667
769
  commands.push('');
668
770
  commands.push('# Lint completed');
669
771
  commands.push('echo "Lint analysis completed successfully"');
@@ -738,9 +840,14 @@ export class AndroidUnitTestStepExecutor extends BaseStepExecutor {
738
840
  commands.push(' fi');
739
841
  commands.push(' # Try macOS java_home utility for specific version');
740
842
  commands.push(' elif [ -x "/usr/libexec/java_home" ]; then');
741
- commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQUESTED_VERSION}" 2>/dev/null || true)');
843
+ commands.push(' # java_home names Java 8 as 1.8, and answers an unmatched request');
844
+ commands.push(' # with the newest JDK rather than failing -- ask the right way or');
845
+ commands.push(' # silently get the wrong JDK.');
846
+ commands.push(' REQ_SPEC="$REQUESTED_VERSION"');
847
+ commands.push(' case "$REQUESTED_VERSION" in 1|2|3|4|5|6|7|8) REQ_SPEC="1.$REQUESTED_VERSION" ;; esac');
848
+ commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "$REQ_SPEC" 2>/dev/null || true)');
742
849
  commands.push(' if [ -z "$DETECTED_JAVA_HOME" ]; then');
743
- commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQUESTED_VERSION}.*" 2>/dev/null || true)');
850
+ commands.push(' DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v "${REQ_SPEC}.*" 2>/dev/null || true)');
744
851
  commands.push(' fi');
745
852
  commands.push(' if [ -n "$DETECTED_JAVA_HOME" ]; then');
746
853
  commands.push(' echo "✅ Found Java $REQUESTED_VERSION at: $DETECTED_JAVA_HOME (java_home utility)"');
@@ -841,13 +948,19 @@ export class AndroidUnitTestStepExecutor extends BaseStepExecutor {
841
948
  commands.push('');
842
949
  commands.push('# Run unit tests');
843
950
  const variantCapitalized = variant.charAt(0).toUpperCase() + variant.slice(1);
844
- const testTask = `:${this.escapeBash(module)}:test${variantCapitalized}UnitTest`;
845
- let gradleCmd = `$GRADLE_CMD ${testTask}`;
846
951
  // Add test filter if specified
952
+ let gradleArgs = '';
847
953
  if (testFilter && testFilter.trim() !== '') {
848
- gradleCmd += ` --tests '${this.escapeBash(testFilter)}'`;
954
+ gradleArgs = `--tests '${this.escapeBash(testFilter)}'`;
849
955
  }
850
- commands.push(gradleCmd);
956
+ commands.push(...variantTaskCommands({
957
+ module,
958
+ variant,
959
+ prefix: 'test',
960
+ suffix: 'UnitTest',
961
+ gradleArgs,
962
+ escape: (value) => this.escapeBash(value),
963
+ }));
851
964
  commands.push('');
852
965
  commands.push('# Tests completed');
853
966
  commands.push('echo "Unit tests completed successfully"');
@@ -3,6 +3,26 @@
3
3
  */
4
4
  import type { StepDef, CIConfig } from '../../types.js';
5
5
  import type { ValidationRequirement, ValidationCheckResult, ValidationCategory, StepOutput } from '../validation-types.js';
6
+ /**
7
+ * The version string `/usr/libexec/java_home -v` expects for a JDK major.
8
+ *
9
+ * Java 8 predates JEP 223 and calls itself `1.8.0_x`, so java_home matches it
10
+ * only as `1.8` — `-v 8` does not match it. That would be a harmless miss if
11
+ * java_home then failed, but **it is permissive**: an unmatched `-v N` returns
12
+ * the newest JDK that is >= N instead of erroring. Asking the wrong way does
13
+ * not report "not found"; it silently hands back the wrong JDK.
14
+ *
15
+ * Measured on macOS 15.7.3 inside the runner image, with Corretto 8 and
16
+ * OpenJDK 25 both installed:
17
+ *
18
+ * -v 8 -> OpenJDK 25.0.2 wrong, and reported as success
19
+ * -v 1.8 -> Amazon Corretto 8 right
20
+ *
21
+ * Without this, a Gradle 4.x project — the only kind that ever selects Java 8,
22
+ * because selection takes the newest JDK the wrapper allows — would be handed
23
+ * JDK 25 and fail for a reason with nothing to do with its own configuration.
24
+ */
25
+ export declare function javaHomeVersionSpec(version: string | number): string;
6
26
  /**
7
27
  * Context provided to step executors
8
28
  */
@@ -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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"}
@@ -3,6 +3,29 @@
3
3
  */
4
4
  import { execSync } from 'node:child_process';
5
5
  import { existsSync } from 'node:fs';
6
+ /**
7
+ * The version string `/usr/libexec/java_home -v` expects for a JDK major.
8
+ *
9
+ * Java 8 predates JEP 223 and calls itself `1.8.0_x`, so java_home matches it
10
+ * only as `1.8` — `-v 8` does not match it. That would be a harmless miss if
11
+ * java_home then failed, but **it is permissive**: an unmatched `-v N` returns
12
+ * the newest JDK that is >= N instead of erroring. Asking the wrong way does
13
+ * not report "not found"; it silently hands back the wrong JDK.
14
+ *
15
+ * Measured on macOS 15.7.3 inside the runner image, with Corretto 8 and
16
+ * OpenJDK 25 both installed:
17
+ *
18
+ * -v 8 -> OpenJDK 25.0.2 wrong, and reported as success
19
+ * -v 1.8 -> Amazon Corretto 8 right
20
+ *
21
+ * Without this, a Gradle 4.x project — the only kind that ever selects Java 8,
22
+ * because selection takes the newest JDK the wrapper allows — would be handed
23
+ * JDK 25 and fail for a reason with nothing to do with its own configuration.
24
+ */
25
+ export function javaHomeVersionSpec(version) {
26
+ const major = Number(version);
27
+ return Number.isInteger(major) && major > 0 && major < 9 ? `1.${major}` : String(version);
28
+ }
6
29
  /**
7
30
  * Base class for step executors providing common utilities
8
31
  */
@@ -323,7 +346,7 @@ ${scriptContent}
323
346
  try {
324
347
  if (process.platform === 'darwin') {
325
348
  // macOS: use java_home
326
- execSync(`/usr/libexec/java_home -v "${version}"`, { stdio: 'pipe' });
349
+ execSync(`/usr/libexec/java_home -v "${javaHomeVersionSpec(version)}"`, { stdio: 'pipe' });
327
350
  }
328
351
  else {
329
352
  // Linux: check common paths
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `/usr/libexec/java_home -v` is permissive, so asking it the wrong way does
3
+ * not fail — it returns the wrong JDK and reports success. These tests pin the
4
+ * one version where the spec differs from the major.
5
+ *
6
+ * Measured on macOS 15.7.3 in the runner image with Corretto 8 and OpenJDK 25
7
+ * both installed: `-v 8` -> OpenJDK 25.0.2, `-v 1.8` -> Amazon Corretto 8.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=java-home-version-spec.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"java-home-version-spec.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/java-home-version-spec.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `/usr/libexec/java_home -v` is permissive, so asking it the wrong way does
3
+ * not fail — it returns the wrong JDK and reports success. These tests pin the
4
+ * one version where the spec differs from the major.
5
+ *
6
+ * Measured on macOS 15.7.3 in the runner image with Corretto 8 and OpenJDK 25
7
+ * both installed: `-v 8` -> OpenJDK 25.0.2, `-v 1.8` -> Amazon Corretto 8.
8
+ */
9
+ import { describe, test, expect } from '@jest/globals';
10
+ import { javaHomeVersionSpec } from './base.js';
11
+ import { SetJavaVersionStepExecutor } from './android.js';
12
+ describe('javaHomeVersionSpec', () => {
13
+ test('Java 8 is asked for as 1.8, not 8', () => {
14
+ expect(javaHomeVersionSpec(8)).toBe('1.8');
15
+ expect(javaHomeVersionSpec('8')).toBe('1.8');
16
+ });
17
+ test('every JDK from 9 up is asked for by its major', () => {
18
+ for (const v of [9, 11, 17, 21, 24, 25]) {
19
+ expect(javaHomeVersionSpec(v)).toBe(String(v));
20
+ }
21
+ });
22
+ test('the legacy 1.x scheme covers every pre-9 major', () => {
23
+ expect(javaHomeVersionSpec(7)).toBe('1.7');
24
+ expect(javaHomeVersionSpec(6)).toBe('1.6');
25
+ });
26
+ test('a non-numeric version is passed through untouched', () => {
27
+ expect(javaHomeVersionSpec('zulu-8')).toBe('zulu-8');
28
+ expect(javaHomeVersionSpec('')).toBe('');
29
+ });
30
+ });
31
+ describe('set-java-version generates a java_home request that can find Java 8', () => {
32
+ const script = async (javaVersion) => {
33
+ const executor = new SetJavaVersionStepExecutor();
34
+ const step = await executor.execute({ java_version: javaVersion }, { workingDir: '/repo', env: {} }, { artifactsDir: '/ci/artifacts' });
35
+ return step.script;
36
+ };
37
+ test('the generated script maps a pre-9 major onto the 1.x java_home name', async () => {
38
+ const s = await script('8');
39
+ expect(s).toContain('JAVA_HOME_SPEC="1.$JAVA_VERSION"');
40
+ expect(s).toContain('1|2|3|4|5|6|7|8)');
41
+ });
42
+ test('java_home is never asked for the bare major', async () => {
43
+ // This is the whole bug: `-v 8` does not miss, it returns the newest JDK.
44
+ for (const v of ['8', '17', '25']) {
45
+ const s = await script(v);
46
+ expect(s).toContain('java_home -v "$JAVA_HOME_SPEC"');
47
+ expect(s).not.toContain('java_home -v "$JAVA_VERSION"');
48
+ expect(s).not.toContain('java_home -v "${JAVA_VERSION}.*"');
49
+ }
50
+ });
51
+ test('the recovery path also asks by spec, not by bare major', async () => {
52
+ const s = await script('8');
53
+ if (s.includes('REQUESTED_VERSION')) {
54
+ expect(s).not.toContain('java_home -v "${REQUESTED_VERSION}"');
55
+ }
56
+ });
57
+ });
58
+ //# sourceMappingURL=java-home-version-spec.test.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.6.7",
3
+ "version": "2.6.9",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",