@invarn/cibuild 1.3.18 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve, extname } from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
- import { existsSync, readdirSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, appendFileSync } from "node:fs";
4
+ import { existsSync, readdirSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, appendFileSync, statSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { execSync } from "node:child_process";
7
7
  import prompts from "prompts";
@@ -26,7 +26,7 @@ import { generateGitHubActionsWorkflow } from "./commands/github-workflow.js";
26
26
  * Returns the detected project type, or null if neither is found.
27
27
  */
28
28
  function detectMobileProjectRoot(dir) {
29
- // Android: must have build.gradle or build.gradle.kts at root
29
+ // Android/KMM: must have build.gradle or build.gradle.kts at root
30
30
  const androidIndicators = [
31
31
  "build.gradle",
32
32
  "build.gradle.kts",
@@ -35,7 +35,22 @@ function detectMobileProjectRoot(dir) {
35
35
  "gradlew",
36
36
  ];
37
37
  const hasAndroidIndicator = androidIndicators.some((f) => existsSync(resolve(dir, f)));
38
+ // KMM: Gradle project with an iosApp/ directory or shared/ multiplatform module
39
+ // Must check before plain Android since KMM also has Gradle files
38
40
  if (hasAndroidIndicator) {
41
+ const kmmIndicators = ["iosApp", "shared", "composeApp"];
42
+ const hasKmmIndicator = kmmIndicators.some((d) => {
43
+ const fullPath = resolve(dir, d);
44
+ try {
45
+ return existsSync(fullPath) && statSync(fullPath).isDirectory();
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ });
51
+ if (hasKmmIndicator) {
52
+ return "kmm";
53
+ }
39
54
  return "android";
40
55
  }
41
56
  // iOS: must have a .xcodeproj or .xcworkspace directory, or a Podfile
@@ -88,9 +103,10 @@ async function handleInitCommand(opts = {}) {
88
103
  const projectType = detectMobileProjectRoot(cwd);
89
104
  if (!projectType) {
90
105
  console.error("Error: Not a mobile project root.");
91
- console.error("ci init must be run from the root folder of an Android or iOS project.");
92
- console.error("\nAndroid projects must contain one of:");
106
+ console.error("ci init must be run from the root folder of an Android, iOS, or KMM project.");
107
+ console.error("\nAndroid/KMM projects must contain one of:");
93
108
  console.error(" build.gradle, build.gradle.kts, settings.gradle, settings.gradle.kts, gradlew");
109
+ console.error("\nKMM projects additionally need: iosApp/, shared/, or composeApp/ directory");
94
110
  console.error("\niOS projects must contain one of:");
95
111
  console.error(" *.xcodeproj, *.xcworkspace, Podfile");
96
112
  process.exit(1);
@@ -104,7 +120,8 @@ async function handleInitCommand(opts = {}) {
104
120
  process.exit(1);
105
121
  }
106
122
  }
107
- console.log(`\nDetected project type: ${projectType === "android" ? "Android" : "iOS"}`);
123
+ const projectTypeLabel = projectType === "kmm" ? "KMM (Kotlin Multiplatform)" : projectType === "android" ? "Android" : "iOS";
124
+ console.log(`\nDetected project type: ${projectTypeLabel}`);
108
125
  console.log(`
109
126
  ╔══════════════════════════════════════════════════════════════╗
110
127
  ║ CI Build - Dependency Check ║
@@ -163,7 +180,7 @@ async function handleInitCommand(opts = {}) {
163
180
  ];
164
181
  const dependencies = [
165
182
  ...commonDependencies,
166
- ...(projectType === "android" ? androidDependencies : iosDependencies),
183
+ ...(projectType === "android" ? androidDependencies : projectType === "kmm" ? [...androidDependencies, ...iosDependencies] : iosDependencies),
167
184
  ];
168
185
  let allRequired = true;
169
186
  let missingOptional = false;
@@ -301,8 +318,8 @@ async function handleInitCommand(opts = {}) {
301
318
  try {
302
319
  const yamlPipeline = loadYAMLPipeline(destPath);
303
320
  const meta = yamlPipeline.meta?.["cibuild.io"];
304
- if (meta?.platform === "ios" || meta?.platform === "android") {
305
- importedPlatform = meta.platform;
321
+ if (meta?.platform === "ios" || meta?.platform === "android" || meta?.platform === "kmm") {
322
+ importedPlatform = meta.platform === "kmm" ? "ios" : meta.platform;
306
323
  }
307
324
  }
308
325
  catch { /* ignore parse errors — default to macos-latest */ }
@@ -438,6 +455,7 @@ Usage:
438
455
  ci run <path> [-w <name>] --skip-validation Skip validation, run with interactive prompts
439
456
  ci validate <path> [-w <name>] Validate pipeline (alias for --validate-only)
440
457
  ci detect-platform <path> [-w <name>] Detect platform from YAML pipeline
458
+ ci detect-project Detect project type (android, ios, kmm)
441
459
  ci reset [--force] Remove all cibuild files and folders
442
460
  ci edit <path> [-w <name>] View pipeline and edit step inputs
443
461
  ci secrets add <var_name> <path> [-w <name>] Add a secret (prompted interactively)
@@ -485,6 +503,12 @@ Examples:
485
503
  await import("./envman/cli.js");
486
504
  return;
487
505
  }
506
+ // Handle detect-project command
507
+ if (args[0] === "detect-project") {
508
+ const projectType = detectMobileProjectRoot(process.cwd());
509
+ console.log(projectType ?? "unknown");
510
+ process.exit(projectType ? 0 : 1);
511
+ }
488
512
  // Handle init command
489
513
  if (args[0] === "init") {
490
514
  const importIdx = args.indexOf("--import");
@@ -1,4 +1,4 @@
1
- export declare function handleBuildCommand(detectMobileProjectRoot: (dir: string) => "android" | "ios" | null, options?: {
1
+ export declare function handleBuildCommand(detectMobileProjectRoot: (dir: string) => "android" | "ios" | "kmm" | null, options?: {
2
2
  createPipelinesDir?: boolean;
3
3
  nonInteractive?: boolean;
4
4
  }): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/commands/build.ts"],"names":[],"mappings":"AAw9BA,wBAAsB,kBAAkB,CACtC,uBAAuB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,GAAG,KAAK,GAAG,IAAI,EAClE,OAAO,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GACvE,OAAO,CAAC,IAAI,CAAC,CAqRf"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/commands/build.ts"],"names":[],"mappings":"AAk8BA,wBAAsB,kBAAkB,CACtC,uBAAuB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,EAC1E,OAAO,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GACvE,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
@@ -122,7 +122,7 @@ function detectSetupNeeds(warnings) {
122
122
  artifactType: 'apk',
123
123
  };
124
124
  }
125
- function generateAndroidPipeline(javaVersion = 17, setup = { keystore: false, keystoreProperties: false, googleServices: false, googlePlayDeploy: false, googlePlayPackageName: '', artifactType: 'apk', keystorePaths: {} }, variants = DEFAULT_VARIANTS) {
125
+ function generateAndroidPipeline(javaVersion = 17, setup = { keystore: false, keystoreProperties: false, googleServices: false, googlePlayDeploy: false, googlePlayPackageName: '', artifactType: 'apk', keystorePaths: {} }, variants = DEFAULT_VARIANTS, cacheTechnology = "gradle") {
126
126
  const keystoreStepFor = (wf) => {
127
127
  if (!setup.keystore)
128
128
  return "";
@@ -199,13 +199,15 @@ function generateAndroidPipeline(javaVersion = 17, setup = { keystore: false, ke
199
199
  const releaseGradleTask = isAab ? `bundle${rv.buildType}` : rv.gradleTask;
200
200
  const releaseArtifactLabel = isAab ? 'AAB' : 'APK';
201
201
  const releaseArtifactExt = isAab ? '*.aab' : '*.apk';
202
+ const stack = cacheTechnology === "kmm" ? "macos-xcode-26.4" : "linux-docker-android-22.04";
203
+ const platformMeta = cacheTechnology === "kmm" ? "kmm" : "android";
202
204
  return `format_version: '1'
203
205
 
204
206
  meta:
205
207
  cibuild.io:
206
- stack: linux-docker-android-22.04
208
+ stack: ${stack}
207
209
  machine_type: standard
208
- platform: android
210
+ platform: ${platformMeta}
209
211
 
210
212
  app:
211
213
  envs:
@@ -227,11 +229,7 @@ ${keystoreStepFor("primary")}${googleServicesStep}
227
229
 
228
230
  - cache-pull@1.0.0:
229
231
  inputs:
230
- cache_key: gradle-\$MODULE
231
- cache_paths:
232
- - ~/.gradle/caches
233
- - ~/.gradle/wrapper
234
- - .gradle
232
+ technology: ${cacheTechnology}
235
233
 
236
234
  - android-lint@1.0.0:
237
235
  is_skippable: true
@@ -257,11 +255,7 @@ ${keystoreStepFor("primary")}${googleServicesStep}
257
255
 
258
256
  - cache-push@1.0.0:
259
257
  inputs:
260
- cache_key: gradle-\$MODULE
261
- cache_paths:
262
- - ~/.gradle/caches
263
- - ~/.gradle/wrapper
264
- - .gradle
258
+ technology: ${cacheTechnology}
265
259
 
266
260
  pull-request:
267
261
  envs:
@@ -275,10 +269,7 @@ ${keystoreStepFor("pull-request")}${googleServicesStep}
275
269
 
276
270
  - cache-pull@1.0.0:
277
271
  inputs:
278
- cache_key: gradle-pr-\$MODULE
279
- cache_paths:
280
- - ~/.gradle/caches
281
- - ~/.gradle/wrapper
272
+ technology: ${cacheTechnology}
282
273
 
283
274
  - android-lint@1.0.0:
284
275
  is_skippable: true
@@ -303,10 +294,7 @@ ${keystoreStepFor("pull-request")}${googleServicesStep}
303
294
 
304
295
  - cache-push@1.0.0:
305
296
  inputs:
306
- cache_key: gradle-pr-\$MODULE
307
- cache_paths:
308
- - ~/.gradle/caches
309
- - ~/.gradle/wrapper
297
+ technology: ${cacheTechnology}
310
298
 
311
299
  release:
312
300
  envs:
@@ -416,10 +404,8 @@ function generateIosPipeline(projectPath, setup, variants) {
416
404
  submit_for_review: 'no'
417
405
  `
418
406
  : "";
419
- // Cache paths depend on whether CocoaPods is used
420
- const cachePaths = setup.cocoaPods
421
- ? ` - Pods\n - Podfile.lock`
422
- : ` - .build`;
407
+ // Cache technology depends on whether CocoaPods is used
408
+ const iosCacheTechnology = setup.cocoaPods ? "cocoapods" : "spm";
423
409
  return `format_version: '1'
424
410
 
425
411
  meta:
@@ -441,9 +427,7 @@ ${schemeEnvFor(pv.scheme)}${configEnvFor(pv.configuration)}
441
427
  steps:
442
428
  - cache-pull@1.0.0:
443
429
  inputs:
444
- cache_key: pods-\$SCHEME
445
- cache_paths:
446
- ${cachePaths}
430
+ technology: ${iosCacheTechnology}
447
431
  ${podInstallStep}
448
432
  - xcode-archive@1.0.0:
449
433
  inputs:
@@ -463,9 +447,7 @@ ${podInstallStep}
463
447
 
464
448
  - cache-push@1.0.0:
465
449
  inputs:
466
- cache_key: pods-\$SCHEME
467
- cache_paths:
468
- ${cachePaths}
450
+ technology: ${iosCacheTechnology}
469
451
 
470
452
  pull-request:
471
453
  envs:
@@ -473,9 +455,7 @@ ${schemeEnvFor(prv.scheme)}${configEnvFor(prv.configuration)}
473
455
  steps:
474
456
  - cache-pull@1.0.0:
475
457
  inputs:
476
- cache_key: pods-pr-\$SCHEME
477
- cache_paths:
478
- ${cachePaths}
458
+ technology: ${iosCacheTechnology}
479
459
  ${podInstallStepPR}
480
460
  - xcode-test@1.0.0:
481
461
  is_skippable: true
@@ -493,9 +473,7 @@ ${podInstallStepPR}
493
473
 
494
474
  - cache-push@1.0.0:
495
475
  inputs:
496
- cache_key: pods-pr-\$SCHEME
497
- cache_paths:
498
- ${cachePaths}
476
+ technology: ${iosCacheTechnology}
499
477
 
500
478
  release:
501
479
  envs:
@@ -505,9 +483,7 @@ ${schemeEnvFor(rv.scheme)}
505
483
  ${codeSigningStep}
506
484
  - cache-pull@1.0.0:
507
485
  inputs:
508
- cache_key: pods-\$SCHEME
509
- cache_paths:
510
- ${cachePaths}
486
+ technology: ${iosCacheTechnology}
511
487
  ${podInstallStep}
512
488
  - xcode-archive@1.0.0:
513
489
  inputs:
@@ -848,17 +824,23 @@ export async function handleBuildCommand(detectMobileProjectRoot, options = {})
848
824
  await handleIosBuildCommand(cwd, options);
849
825
  return;
850
826
  }
851
- if (projectType !== "android") {
852
- console.error("Error: Not a mobile project root.");
853
- console.error("'ci build' must be run from the root folder of an Android or iOS project.");
854
- console.error("\nAndroid projects must contain one of:");
855
- console.error(" build.gradle, build.gradle.kts, settings.gradle, settings.gradle.kts, gradlew");
856
- console.error("\niOS projects must contain one of:");
857
- console.error(" *.xcodeproj, *.xcworkspace, Podfile");
858
- process.exit(1);
827
+ if (projectType === "kmm" || projectType === "android") {
828
+ await handleAndroidBuildCommand(cwd, options, projectType === "kmm" ? "kmm" : "gradle");
829
+ return;
859
830
  }
831
+ console.error("Error: Not a mobile project root.");
832
+ console.error("'ci build' must be run from the root folder of an Android, iOS, or KMM project.");
833
+ console.error("\nAndroid/KMM projects must contain one of:");
834
+ console.error(" build.gradle, build.gradle.kts, settings.gradle, settings.gradle.kts, gradlew");
835
+ console.error("\nKMM projects additionally need: iosApp/, shared/, or composeApp/ directory");
836
+ console.error("\niOS projects must contain one of:");
837
+ console.error(" *.xcodeproj, *.xcworkspace, Podfile");
838
+ process.exit(1);
839
+ }
840
+ async function handleAndroidBuildCommand(cwd, options, cacheTechnology) {
841
+ const platformLabel = cacheTechnology === "kmm" ? "KMM (Kotlin Multiplatform)" : "Android";
860
842
  // 2. Scan the project for potential unknowns
861
- console.log("\n🔍 Scanning Android project for potential unknowns...\n");
843
+ console.log(`\n🔍 Scanning ${platformLabel} project for potential unknowns...\n`);
862
844
  const scanResult = await scanAndroidProject(cwd);
863
845
  console.log(formatScanResult(scanResult));
864
846
  // 3. Prompt for build variants per workflow
@@ -1059,10 +1041,10 @@ export async function handleBuildCommand(detectMobileProjectRoot, options = {})
1059
1041
  // that exact JDK — a newer JDK can cross-compile. Enforce a minimum of 17
1060
1042
  // since ubuntu-latest runners ship with JDK 17+ and JDK <17 is unavailable.
1061
1043
  const javaVersion = Math.max(scanResult.detectedJavaVersion ?? 17, 17);
1062
- const yaml = generateAndroidPipeline(javaVersion, setupOptions, variants);
1044
+ const yaml = generateAndroidPipeline(javaVersion, setupOptions, variants, cacheTechnology);
1063
1045
  writeFileSync(outputPath, yaml, "utf-8");
1064
1046
  console.log("\n✅ Generated .ci/pipelines/cibuild.yml");
1065
- console.log(" Platform: Android");
1047
+ console.log(` Platform: ${platformLabel}`);
1066
1048
  console.log(` Workflows: primary (${variants.primary.variant}), pull-request (${variants.pullRequest.variant}), release (${variants.release.variant})`);
1067
1049
  if (setupOptions.keystore || setupOptions.keystoreProperties || setupOptions.googleServices || setupOptions.googlePlayDeploy) {
1068
1050
  console.log(" Setup steps included:");
@@ -293,8 +293,8 @@ async function handleAddRegisteredStep(pipelinePath, workflowName, _pipeline, st
293
293
  function detectWorkflowPlatform(pipeline, workflowName) {
294
294
  // 1. Explicit platform declaration in meta
295
295
  const metaPlatform = pipeline.meta?.['cibuild.io']?.platform;
296
- if (metaPlatform === 'ios' || metaPlatform === 'android')
297
- return metaPlatform;
296
+ if (metaPlatform === 'ios' || metaPlatform === 'android' || metaPlatform === 'kmm')
297
+ return metaPlatform === 'kmm' ? 'ios' : metaPlatform;
298
298
  // 2. Scan existing steps as fallback
299
299
  const workflow = pipeline.workflows[workflowName];
300
300
  if (!workflow)
@@ -97,7 +97,7 @@ function validateYAMLPipeline(parsed, filePath) {
97
97
  }
98
98
  // Validate platform if specified
99
99
  if (parsed.meta.platform) {
100
- const validPlatforms = ['macos', 'linux', 'windows'];
100
+ const validPlatforms = ['macos', 'linux'];
101
101
  if (!validPlatforms.includes(parsed.meta.platform)) {
102
102
  throw new YAMLValidationError(`Invalid platform '${parsed.meta.platform}' in ${filePath}. Must be one of: ${validPlatforms.join(', ')}`);
103
103
  }
@@ -110,9 +110,9 @@ function validateYAMLPipeline(parsed, filePath) {
110
110
  }
111
111
  // Validate stack pattern if specified
112
112
  if (cibuildMeta.stack && typeof cibuildMeta.stack === 'string') {
113
- const stackPattern = /^(macos|linux|windows)-/;
113
+ const stackPattern = /^(macos|linux)-/;
114
114
  if (cibuildMeta.stack !== 'local' && !stackPattern.test(cibuildMeta.stack)) {
115
- throw new YAMLValidationError(`Invalid stack '${cibuildMeta.stack}' in ${filePath}. Stack must be 'local' or start with 'macos-', 'linux-', or 'windows-'`);
115
+ throw new YAMLValidationError(`Invalid stack '${cibuildMeta.stack}' in ${filePath}. Stack must be 'local' or start with 'macos-' or 'linux-'`);
116
116
  }
117
117
  }
118
118
  // Validate machine_type if specified
@@ -20,7 +20,7 @@ export declare class PlatformDetector {
20
20
  * Priority 2: meta.platform
21
21
  * Priority 3: auto-detect from workflow steps
22
22
  *
23
- * @returns Detected platform ('macos', 'linux', or 'windows')
23
+ * @returns Detected platform ('macos' or 'linux')
24
24
  * @throws PlatformDetectionError if detection fails or mixed platforms detected
25
25
  */
26
26
  getPlatform(): Platform;
@@ -29,7 +29,7 @@ export class PlatformDetector {
29
29
  * Priority 2: meta.platform
30
30
  * Priority 3: auto-detect from workflow steps
31
31
  *
32
- * @returns Detected platform ('macos', 'linux', or 'windows')
32
+ * @returns Detected platform ('macos' or 'linux')
33
33
  * @throws PlatformDetectionError if detection fails or mixed platforms detected
34
34
  */
35
35
  getPlatform() {
@@ -84,7 +84,7 @@ export class PlatformDetector {
84
84
  return null;
85
85
  }
86
86
  const platformPrefix = parts[0];
87
- if (platformPrefix === 'macos' || platformPrefix === 'linux' || platformPrefix === 'windows') {
87
+ if (platformPrefix === 'macos' || platformPrefix === 'linux') {
88
88
  return platformPrefix;
89
89
  }
90
90
  return null;
@@ -45,25 +45,6 @@ describe('PlatformDetector', () => {
45
45
  expect(detector.getStack()).toBe('linux-docker-android-22.04');
46
46
  expect(detector.getMachineType()).toBe('standard');
47
47
  });
48
- test('should detect windows from stack', () => {
49
- const pipeline = {
50
- format_version: '4',
51
- meta: {
52
- 'cibuild.io': {
53
- stack: 'windows-server-2022',
54
- },
55
- },
56
- workflows: {
57
- primary: {
58
- steps: [{ 'script@1.0.0': { inputs: { content: 'echo "test"' } } }],
59
- },
60
- },
61
- };
62
- const detector = new PlatformDetector(pipeline, pipeline.workflows.primary, 'primary');
63
- expect(detector.getPlatform()).toBe('windows');
64
- expect(detector.getStack()).toBe('windows-server-2022');
65
- expect(detector.getMachineType()).toBeNull();
66
- });
67
48
  });
68
49
  describe('Priority 2: Use meta.platform field', () => {
69
50
  test('should use meta.platform when stack not specified', () => {
@@ -80,7 +80,7 @@ export class CachePullStepExecutor extends BaseStepExecutor {
80
80
  commands.push(' echo "Restored paths:"');
81
81
  for (const path of cachePaths) {
82
82
  commands.push(` EXPANDED_PATH="${this.escapeBash(path)}"`);
83
- commands.push(' EXPANDED_PATH="${EXPANDED_PATH/#~/$HOME}"');
83
+ commands.push(' EXPANDED_PATH="${EXPANDED_PATH/#~/${CIBUILD_USER_HOME:-$HOME}}"');
84
84
  commands.push(' if [ -e "$EXPANDED_PATH" ]; then');
85
85
  commands.push(' echo " ✓ $EXPANDED_PATH"');
86
86
  commands.push(' else');
@@ -137,7 +137,7 @@ export class CachePullStepExecutor extends BaseStepExecutor {
137
137
  commands.push(' echo "Restored paths:"');
138
138
  for (const p of preset.paths) {
139
139
  commands.push(` EXPANDED="${this.escapeBash(p)}"`);
140
- commands.push(' EXPANDED="${EXPANDED/#~/$HOME}"');
140
+ commands.push(' EXPANDED="${EXPANDED/#~/${CIBUILD_USER_HOME:-$HOME}}"');
141
141
  commands.push(' if [ -e "$EXPANDED" ]; then');
142
142
  commands.push(' echo " ✓ $EXPANDED"');
143
143
  commands.push(' else');
@@ -234,7 +234,7 @@ export class CachePushStepExecutor extends BaseStepExecutor {
234
234
  }
235
235
  // Expand tilde by using parameter expansion
236
236
  commands.push(`EXPANDED_PATH="${this.escapeBash(resolvedPath)}"`);
237
- commands.push('EXPANDED_PATH="${EXPANDED_PATH/#~/$HOME}"');
237
+ commands.push('EXPANDED_PATH="${EXPANDED_PATH/#~/${CIBUILD_USER_HOME:-$HOME}}"');
238
238
  commands.push('');
239
239
  commands.push('# Expand glob patterns and check each match');
240
240
  commands.push('FOUND_MATCH=false');
@@ -319,7 +319,7 @@ export class CachePushStepExecutor extends BaseStepExecutor {
319
319
  commands.push('PATHS_TO_CACHE=()');
320
320
  for (const p of preset.paths) {
321
321
  commands.push(`EXPANDED="${this.escapeBash(p)}"`);
322
- commands.push('EXPANDED="${EXPANDED/#~/$HOME}"');
322
+ commands.push('EXPANDED="${EXPANDED/#~/${CIBUILD_USER_HOME:-$HOME}}"');
323
323
  commands.push('if [ -e "$EXPANDED" ]; then');
324
324
  commands.push(' PATHS_TO_CACHE+=("$EXPANDED")');
325
325
  if (isDebugMode) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TypeScript interfaces for Bitrise-compatible YAML pipeline structure
3
3
  */
4
- export type Platform = 'macos' | 'linux' | 'windows';
4
+ export type Platform = 'macos' | 'linux';
5
5
  export type MachineType = 'standard' | 'performance';
6
6
  export interface YAMLEnvVar {
7
7
  [key: string]: string;
@@ -10,7 +10,7 @@ export interface YAMLCIBuildMeta {
10
10
  stack?: string;
11
11
  machine_type?: MachineType;
12
12
  machine_type_id?: string;
13
- platform?: 'ios' | 'android';
13
+ platform?: 'ios' | 'android' | 'kmm';
14
14
  }
15
15
  export interface YAMLMeta {
16
16
  'cibuild.io'?: YAMLCIBuildMeta;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/yaml/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAGD,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,MAAM,WAAW,QAAQ;IACvB,CAAC,mBAAmB,EAAE,MAAM,GAAG;QAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,cAAc,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC;CACH;AAGD,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAGD,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;CACrB;AAGD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAA;KAAE,CAAC;IAC5C,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;CAC7B;AAGD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAGD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/yaml/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AACzC,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,KAAK,CAAC;CACtC;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAGD,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,MAAM,WAAW,QAAQ;IACvB,CAAC,mBAAmB,EAAE,MAAM,GAAG;QAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,cAAc,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC;CACH;AAGD,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAGD,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;CACrB;AAGD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAA;KAAE,CAAC;IAC5C,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;CAC7B;AAGD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAGD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "1.3.18",
3
+ "version": "1.4.0",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",