@tamagui/native-ci 1.139.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.
Files changed (81) hide show
  1. package/README.md +320 -0
  2. package/action.yml +98 -0
  3. package/actions/fingerprint/action.yml +110 -0
  4. package/actions/test-detox-android/action.yml +70 -0
  5. package/actions/test-detox-ios/action.yml +66 -0
  6. package/dist/cache.js +71 -0
  7. package/dist/cache.js.map +6 -0
  8. package/dist/cache.mjs +73 -0
  9. package/dist/cache.mjs.map +1 -0
  10. package/dist/cli.js +275 -0
  11. package/dist/cli.js.map +6 -0
  12. package/dist/cli.mjs +306 -0
  13. package/dist/cli.mjs.map +1 -0
  14. package/dist/constants.js +12 -0
  15. package/dist/constants.js.map +6 -0
  16. package/dist/constants.mjs +10 -0
  17. package/dist/constants.mjs.map +1 -0
  18. package/dist/deps.js +44 -0
  19. package/dist/deps.js.map +6 -0
  20. package/dist/deps.mjs +53 -0
  21. package/dist/deps.mjs.map +1 -0
  22. package/dist/detox.js +49 -0
  23. package/dist/detox.js.map +6 -0
  24. package/dist/detox.mjs +55 -0
  25. package/dist/detox.mjs.map +1 -0
  26. package/dist/fingerprint.js +43 -0
  27. package/dist/fingerprint.js.map +6 -0
  28. package/dist/fingerprint.mjs +40 -0
  29. package/dist/fingerprint.mjs.map +1 -0
  30. package/dist/index.js +90 -0
  31. package/dist/index.js.map +6 -0
  32. package/dist/index.mjs +11 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/dist/metro.js +79 -0
  35. package/dist/metro.js.map +6 -0
  36. package/dist/metro.mjs +75 -0
  37. package/dist/metro.mjs.map +1 -0
  38. package/dist/runner.js +73 -0
  39. package/dist/runner.js.map +6 -0
  40. package/dist/runner.mjs +73 -0
  41. package/dist/runner.mjs.map +1 -0
  42. package/package.json +50 -0
  43. package/src/android.ts +103 -0
  44. package/src/cache.ts +144 -0
  45. package/src/cli.ts +513 -0
  46. package/src/constants.ts +30 -0
  47. package/src/deps.ts +109 -0
  48. package/src/detox.ts +102 -0
  49. package/src/fingerprint.ts +77 -0
  50. package/src/index.ts +86 -0
  51. package/src/ios.ts +38 -0
  52. package/src/metro.ts +157 -0
  53. package/src/run-detox-android.ts +49 -0
  54. package/src/run-detox-ios.ts +40 -0
  55. package/src/runner.ts +123 -0
  56. package/types/android.d.ts +32 -0
  57. package/types/android.d.ts.map +1 -0
  58. package/types/cache.d.ts +41 -0
  59. package/types/cache.d.ts.map +1 -0
  60. package/types/cli.d.ts +11 -0
  61. package/types/cli.d.ts.map +1 -0
  62. package/types/constants.d.ts +18 -0
  63. package/types/constants.d.ts.map +1 -0
  64. package/types/deps.d.ts +32 -0
  65. package/types/deps.d.ts.map +1 -0
  66. package/types/detox.d.ts +39 -0
  67. package/types/detox.d.ts.map +1 -0
  68. package/types/fingerprint.d.ts +21 -0
  69. package/types/fingerprint.d.ts.map +1 -0
  70. package/types/index.d.ts +16 -0
  71. package/types/index.d.ts.map +1 -0
  72. package/types/ios.d.ts +18 -0
  73. package/types/ios.d.ts.map +1 -0
  74. package/types/metro.d.ts +51 -0
  75. package/types/metro.d.ts.map +1 -0
  76. package/types/run-detox-android.d.ts +15 -0
  77. package/types/run-detox-android.d.ts.map +1 -0
  78. package/types/run-detox-ios.d.ts +14 -0
  79. package/types/run-detox-ios.d.ts.map +1 -0
  80. package/types/runner.d.ts +35 -0
  81. package/types/runner.d.ts.map +1 -0
package/dist/cache.js ADDED
@@ -0,0 +1,71 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { DEFAULT_KV_TTL_SECONDS } from "./constants";
4
+ function createCacheKey(options) {
5
+ const { platform, fingerprint, prefix = "native-build" } = options;
6
+ return `${prefix}-${platform}-${fingerprint}`;
7
+ }
8
+ async function saveFingerprintToKV(kv, key, fingerprint, ttlSeconds = DEFAULT_KV_TTL_SECONDS) {
9
+ try {
10
+ const response = await fetch(`${kv.url}/SETEX/${key}/${ttlSeconds}/${fingerprint}`, {
11
+ method: "POST",
12
+ headers: {
13
+ Authorization: `Bearer ${kv.token}`
14
+ }
15
+ });
16
+ if (!response.ok)
17
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
18
+ } catch (error) {
19
+ throw error instanceof TypeError ? new Error(`Network error connecting to KV store: ${error.message}`) : new Error(`Failed to save fingerprint to KV: ${error.message}`);
20
+ }
21
+ }
22
+ async function getFingerprintFromKV(kv, key) {
23
+ try {
24
+ const response = await fetch(`${kv.url}/get/${key}`, {
25
+ headers: {
26
+ Authorization: `Bearer ${kv.token}`
27
+ }
28
+ });
29
+ if (!response.ok)
30
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
31
+ const data = await response.json();
32
+ return data.result === "null" ? null : data.result;
33
+ } catch (error) {
34
+ throw error instanceof TypeError ? new Error(`Network error connecting to KV store: ${error.message}`) : new Error(`Failed to get fingerprint from KV: ${error.message}`);
35
+ }
36
+ }
37
+ async function extendKVTTL(kv, key, ttlSeconds = DEFAULT_KV_TTL_SECONDS) {
38
+ try {
39
+ await fetch(`${kv.url}/EXPIRE/${key}/${ttlSeconds}`, {
40
+ method: "POST",
41
+ headers: {
42
+ Authorization: `Bearer ${kv.token}`
43
+ }
44
+ });
45
+ } catch (error) {
46
+ console.warn(`Failed to extend KV TTL: ${error.message}`);
47
+ }
48
+ }
49
+ function saveCache(filePath, data, options = {}) {
50
+ const { cacheDir } = options, cachePath = cacheDir ? join(process.cwd(), cacheDir, filePath) : join(process.cwd(), filePath);
51
+ mkdirSync(dirname(cachePath), { recursive: !0 }), writeFileSync(cachePath, JSON.stringify(data, null, 2));
52
+ }
53
+ function loadCache(filePath, options = {}) {
54
+ const { cacheDir } = options, cachePath = cacheDir ? join(process.cwd(), cacheDir, filePath) : join(process.cwd(), filePath);
55
+ if (!existsSync(cachePath))
56
+ return null;
57
+ try {
58
+ return JSON.parse(readFileSync(cachePath, "utf-8"));
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+ export {
64
+ createCacheKey,
65
+ extendKVTTL,
66
+ getFingerprintFromKV,
67
+ loadCache,
68
+ saveCache,
69
+ saveFingerprintToKV
70
+ };
71
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cache.ts"],
4
+ "mappings": "AAAA,SAAS,YAAY,cAAc,eAAe,iBAAiB;AACnE,SAAS,SAAS,YAAY;AAC9B,SAAS,8BAA6C;AAgB/C,SAAS,eAAe,SAA+B;AAC5D,QAAM,EAAE,UAAU,aAAa,SAAS,eAAe,IAAI;AAC3D,SAAO,GAAG,MAAM,IAAI,QAAQ,IAAI,WAAW;AAC7C;AAMA,eAAsB,oBACpB,IACA,KACA,aACA,aAAa,wBACE;AACf,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,GAAG,IAAI,UAAU,IAAI,WAAW,IAAI;AAAA,MAClF,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,GAAG,KAAK;AAAA,MACnC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,EAErE,SAAS,OAAO;AACd,UAAI,iBAAiB,YACb,IAAI,MAAM,yCAA0C,MAAgB,OAAO,EAAE,IAE/E,IAAI,MAAM,qCAAsC,MAAgB,OAAO,EAAE;AAAA,EACjF;AACF;AAKA,eAAsB,qBACpB,IACA,KACwB;AACxB,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,IAAI;AAAA,MACnD,SAAS;AAAA,QACP,eAAe,UAAU,GAAG,KAAK;AAAA,MACnC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAGnE,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,WAAO,KAAK,WAAW,SAAS,OAAO,KAAK;AAAA,EAC9C,SAAS,OAAO;AACd,UAAI,iBAAiB,YACb,IAAI,MAAM,yCAA0C,MAAgB,OAAO,EAAE,IAE/E,IAAI,MAAM,sCAAuC,MAAgB,OAAO,EAAE;AAAA,EAClF;AACF;AAKA,eAAsB,YACpB,IACA,KACA,aAAa,wBACE;AACf,MAAI;AACF,UAAM,MAAM,GAAG,GAAG,GAAG,WAAW,GAAG,IAAI,UAAU,IAAI;AAAA,MACnD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,GAAG,KAAK;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AAEd,YAAQ,KAAK,4BAA6B,MAAgB,OAAO,EAAE;AAAA,EACrE;AACF;AAYO,SAAS,UACd,UACA,MACA,UAA6B,CAAC,GACxB;AACN,QAAM,EAAE,SAAS,IAAI,SACf,YAAY,WAAW,KAAK,QAAQ,IAAI,GAAG,UAAU,QAAQ,IAAI,KAAK,QAAQ,IAAI,GAAG,QAAQ;AAEnG,YAAU,QAAQ,SAAS,GAAG,EAAE,WAAW,GAAK,CAAC,GACjD,cAAc,WAAW,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACxD;AAMO,SAAS,UACd,UACA,UAA6B,CAAC,GACpB;AACV,QAAM,EAAE,SAAS,IAAI,SACf,YAAY,WAAW,KAAK,QAAQ,IAAI,GAAG,UAAU,QAAQ,IAAI,KAAK,QAAQ,IAAI,GAAG,QAAQ;AAEnG,MAAI,CAAC,WAAW,SAAS;AACvB,WAAO;AAGT,MAAI;AACF,WAAO,KAAK,MAAM,aAAa,WAAW,OAAO,CAAC;AAAA,EACpD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
5
+ "names": []
6
+ }
package/dist/cache.mjs ADDED
@@ -0,0 +1,73 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { DEFAULT_KV_TTL_SECONDS } from "./constants.mjs";
4
+ function createCacheKey(options) {
5
+ const {
6
+ platform,
7
+ fingerprint,
8
+ prefix = "native-build"
9
+ } = options;
10
+ return `${prefix}-${platform}-${fingerprint}`;
11
+ }
12
+ async function saveFingerprintToKV(kv, key, fingerprint, ttlSeconds = DEFAULT_KV_TTL_SECONDS) {
13
+ try {
14
+ const response = await fetch(`${kv.url}/SETEX/${key}/${ttlSeconds}/${fingerprint}`, {
15
+ method: "POST",
16
+ headers: {
17
+ Authorization: `Bearer ${kv.token}`
18
+ }
19
+ });
20
+ if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
21
+ } catch (error) {
22
+ throw error instanceof TypeError ? new Error(`Network error connecting to KV store: ${error.message}`) : new Error(`Failed to save fingerprint to KV: ${error.message}`);
23
+ }
24
+ }
25
+ async function getFingerprintFromKV(kv, key) {
26
+ try {
27
+ const response = await fetch(`${kv.url}/get/${key}`, {
28
+ headers: {
29
+ Authorization: `Bearer ${kv.token}`
30
+ }
31
+ });
32
+ if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
33
+ const data = await response.json();
34
+ return data.result === "null" ? null : data.result;
35
+ } catch (error) {
36
+ throw error instanceof TypeError ? new Error(`Network error connecting to KV store: ${error.message}`) : new Error(`Failed to get fingerprint from KV: ${error.message}`);
37
+ }
38
+ }
39
+ async function extendKVTTL(kv, key, ttlSeconds = DEFAULT_KV_TTL_SECONDS) {
40
+ try {
41
+ await fetch(`${kv.url}/EXPIRE/${key}/${ttlSeconds}`, {
42
+ method: "POST",
43
+ headers: {
44
+ Authorization: `Bearer ${kv.token}`
45
+ }
46
+ });
47
+ } catch (error) {
48
+ console.warn(`Failed to extend KV TTL: ${error.message}`);
49
+ }
50
+ }
51
+ function saveCache(filePath, data, options = {}) {
52
+ const {
53
+ cacheDir
54
+ } = options,
55
+ cachePath = cacheDir ? join(process.cwd(), cacheDir, filePath) : join(process.cwd(), filePath);
56
+ mkdirSync(dirname(cachePath), {
57
+ recursive: !0
58
+ }), writeFileSync(cachePath, JSON.stringify(data, null, 2));
59
+ }
60
+ function loadCache(filePath, options = {}) {
61
+ const {
62
+ cacheDir
63
+ } = options,
64
+ cachePath = cacheDir ? join(process.cwd(), cacheDir, filePath) : join(process.cwd(), filePath);
65
+ if (!existsSync(cachePath)) return null;
66
+ try {
67
+ return JSON.parse(readFileSync(cachePath, "utf-8"));
68
+ } catch {
69
+ return null;
70
+ }
71
+ }
72
+ export { createCacheKey, extendKVTTL, getFingerprintFromKV, loadCache, saveCache, saveFingerprintToKV };
73
+ //# sourceMappingURL=cache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["existsSync","readFileSync","writeFileSync","mkdirSync","dirname","join","DEFAULT_KV_TTL_SECONDS","createCacheKey","options","platform","fingerprint","prefix","saveFingerprintToKV","kv","key","ttlSeconds","response","fetch","url","method","headers","Authorization","token","ok","Error","status","statusText","error","TypeError","message","getFingerprintFromKV","data","json","result","extendKVTTL","console","warn","saveCache","filePath","cacheDir","cachePath","process","cwd","recursive","JSON","stringify","loadCache","parse"],"sources":["../src/cache.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
package/dist/cli.js ADDED
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/env node
2
+ import { generateFingerprint, generatePreFingerprintHash } from "./fingerprint";
3
+ import { createCacheKey, saveFingerprintToKV, getFingerprintFromKV, saveCache, loadCache } from "./cache";
4
+ import { setGitHubOutput, isGitHubActions, isCI } from "./runner";
5
+ import { ensureIosDeps, ensureAndroidDeps, ensureMaestro, printDepsStatus } from "./deps";
6
+ import { withMetro } from "./metro";
7
+ import { runDetoxTests } from "./detox";
8
+ import { ensureIOSFolder } from "./ios";
9
+ import { setupAndroidDevice, ensureAndroidFolder } from "./android";
10
+ const HELP = `
11
+ native-ci - Native CI/CD helpers for Expo apps
12
+
13
+ COMMANDS:
14
+
15
+ Test Commands:
16
+ test ios [options] Run iOS Detox tests
17
+ test android [options] Run Android Detox tests
18
+ test maestro [flow] Run Maestro tests
19
+ test all Run all tests (iOS + Android)
20
+
21
+ Dependency Commands:
22
+ deps Show dependency status
23
+ deps install Install missing dependencies
24
+ deps install-ios Install iOS dependencies (macOS only)
25
+ deps install-android Install Android dependencies
26
+ deps install-maestro Install Maestro
27
+
28
+ Fingerprint Commands:
29
+ fingerprint <platform> Generate native build fingerprint
30
+ fingerprint-test Test fingerprint caching locally
31
+ pre-hash <files...> Generate quick pre-fingerprint hash
32
+ cache-key <platform> <fp> Generate cache key from fingerprint
33
+
34
+ KV Store Commands:
35
+ kv-get <key> Get value from KV store
36
+ kv-set <key> <value> Set value in KV store
37
+
38
+ OPTIONS:
39
+ --project-root <path> Project root directory (default: cwd)
40
+ --config <name> Detox configuration name
41
+ --record-logs <mode> Record logs: none, failing, all (default: all)
42
+ --retries <n> Number of retries for flaky tests (default: 0)
43
+ --headless Run in headless mode (Android only)
44
+ --prefix <prefix> Cache key prefix (default: native-build)
45
+ --github-output Output results for GitHub Actions
46
+ --json Output as JSON
47
+ --help Show this help message
48
+
49
+ ENVIRONMENT:
50
+ KV_STORE_REDIS_REST_URL Redis REST API URL for fingerprint caching
51
+ KV_STORE_REDIS_REST_TOKEN Redis REST API token
52
+
53
+ EXAMPLES:
54
+ native-ci test ios
55
+ native-ci test android --headless
56
+ native-ci test maestro
57
+ native-ci deps
58
+ native-ci deps install
59
+ native-ci fingerprint ios
60
+ native-ci fingerprint-test
61
+ `;
62
+ function parseArgs(argv) {
63
+ const args2 = [], options2 = {
64
+ projectRoot: process.cwd(),
65
+ config: "",
66
+ recordLogs: "all",
67
+ retries: 0,
68
+ headless: !1,
69
+ prefix: "native-build",
70
+ githubOutput: !1,
71
+ json: !1,
72
+ help: !1
73
+ };
74
+ let i = 0;
75
+ for (; i < argv.length; ) {
76
+ const arg = argv[i];
77
+ if (arg === "--project-root" && argv[i + 1])
78
+ options2.projectRoot = argv[++i];
79
+ else if (arg === "--config" && argv[i + 1])
80
+ options2.config = argv[++i];
81
+ else if (arg === "--record-logs" && argv[i + 1])
82
+ options2.recordLogs = argv[++i];
83
+ else if (arg === "--retries" && argv[i + 1]) {
84
+ const val = Number.parseInt(argv[++i], 10);
85
+ !Number.isNaN(val) && val >= 0 && (options2.retries = val);
86
+ } else arg === "--prefix" && argv[i + 1] ? options2.prefix = argv[++i] : arg === "--github-output" ? options2.githubOutput = !0 : arg === "--json" ? options2.json = !0 : arg === "--help" || arg === "-h" ? options2.help = !0 : arg.startsWith("-") || args2.push(arg);
87
+ i++;
88
+ }
89
+ return {
90
+ command: args2[0] || "",
91
+ subcommand: args2[1] || "",
92
+ args: args2.slice(2),
93
+ options: options2
94
+ };
95
+ }
96
+ function validatePlatform(value) {
97
+ return value !== "ios" && value !== "android" && (console.error('Error: platform must be "ios" or "android"'), process.exit(1)), value;
98
+ }
99
+ function getKVCredentials() {
100
+ const url = process.env.KV_STORE_REDIS_REST_URL, token = process.env.KV_STORE_REDIS_REST_TOKEN;
101
+ return (!url || !token) && (console.error("Error: KV_STORE_REDIS_REST_URL and KV_STORE_REDIS_REST_TOKEN required"), process.exit(1)), { url, token };
102
+ }
103
+ const { command, subcommand, args, options } = parseArgs(process.argv.slice(2));
104
+ (options.help || !command) && (console.info(HELP), process.exit(options.help ? 0 : 1));
105
+ try {
106
+ switch (command) {
107
+ // ========================================
108
+ // Test Commands
109
+ // ========================================
110
+ case "test": {
111
+ isCI() && !process.env.NATIVE_CI_FORCE_RUN && (console.info("Skipping native tests in CI (handled by separate workflow)"), console.info("Set NATIVE_CI_FORCE_RUN=1 to force run"), process.exit(0));
112
+ const platform = subcommand || "ios";
113
+ if (platform === "ios") {
114
+ await ensureIosDeps();
115
+ const config = options.config || "ios.sim.debug";
116
+ console.info("=== iOS Detox Test Runner ==="), console.info(`Config: ${config}`), console.info(`Project root: ${options.projectRoot}`), process.chdir(options.projectRoot), await ensureIOSFolder();
117
+ const exitCode = await withMetro("ios", async () => runDetoxTests({
118
+ config,
119
+ projectRoot: options.projectRoot,
120
+ recordLogs: options.recordLogs,
121
+ retries: options.retries
122
+ }));
123
+ process.exit(exitCode);
124
+ } else if (platform === "android") {
125
+ await ensureAndroidDeps();
126
+ const config = options.config || "android.emu.debug";
127
+ console.info("=== Android Detox Test Runner ==="), console.info(`Config: ${config}`), console.info(`Project root: ${options.projectRoot}`), console.info(`Headless: ${options.headless}`), process.chdir(options.projectRoot), await ensureAndroidFolder(), await setupAndroidDevice();
128
+ const exitCode = await withMetro("android", async () => runDetoxTests({
129
+ config,
130
+ projectRoot: options.projectRoot,
131
+ recordLogs: options.recordLogs,
132
+ retries: options.retries,
133
+ headless: options.headless
134
+ }));
135
+ process.exit(exitCode);
136
+ } else if (platform === "maestro") {
137
+ await ensureMaestro();
138
+ const flow = args[0] || "";
139
+ console.info("=== Maestro Test Runner ==="), console.info(`Flow: ${flow || "all"}`), console.info(`Project root: ${options.projectRoot}`), process.chdir(options.projectRoot);
140
+ const exitCode = await withMetro("ios", async () => {
141
+ const { $ } = await import("bun"), flowArg = flow ? `./flows/${flow}` : "./flows";
142
+ return (await $`maestro test ${flowArg} --exclude-tags=util --no-ansi`.nothrow()).exitCode;
143
+ });
144
+ process.exit(exitCode);
145
+ } else if (platform === "all") {
146
+ console.info(`=== Running All Native Tests ===
147
+ `), await ensureIosDeps(), console.info(`
148
+ --- iOS Tests ---
149
+ `), process.chdir(options.projectRoot), await ensureIOSFolder();
150
+ let iosExit = 0;
151
+ try {
152
+ iosExit = await withMetro("ios", async () => runDetoxTests({
153
+ config: options.config || "ios.sim.debug",
154
+ projectRoot: options.projectRoot,
155
+ recordLogs: options.recordLogs,
156
+ retries: options.retries
157
+ }));
158
+ } catch (err) {
159
+ console.error("iOS tests failed:", err), iosExit = 1;
160
+ }
161
+ await ensureAndroidDeps(), console.info(`
162
+ --- Android Tests ---
163
+ `), await ensureAndroidFolder(), await setupAndroidDevice();
164
+ let androidExit = 0;
165
+ try {
166
+ androidExit = await withMetro("android", async () => runDetoxTests({
167
+ config: options.config || "android.emu.debug",
168
+ projectRoot: options.projectRoot,
169
+ recordLogs: options.recordLogs,
170
+ retries: options.retries,
171
+ headless: options.headless
172
+ }));
173
+ } catch (err) {
174
+ console.error("Android tests failed:", err), androidExit = 1;
175
+ }
176
+ const success = iosExit === 0 && androidExit === 0;
177
+ console.info(`
178
+ === Test Results ===`), console.info(`iOS: ${iosExit === 0 ? "PASSED" : "FAILED"}`), console.info(`Android: ${androidExit === 0 ? "PASSED" : "FAILED"}`), process.exit(success ? 0 : 1);
179
+ } else
180
+ console.error(`Unknown test platform: ${platform}`), console.info("Usage: native-ci test [ios|android|maestro|all]"), process.exit(1);
181
+ break;
182
+ }
183
+ // ========================================
184
+ // Dependency Commands
185
+ // ========================================
186
+ case "deps": {
187
+ !subcommand || subcommand === "status" ? printDepsStatus() : subcommand === "install" ? (console.info(`Installing all dependencies...
188
+ `), await ensureIosDeps(), await ensureMaestro(), console.info(`
189
+ All dependencies installed!`)) : subcommand === "install-ios" ? await ensureIosDeps() : subcommand === "install-android" ? await ensureAndroidDeps() : subcommand === "install-maestro" ? await ensureMaestro() : (console.error(`Unknown deps subcommand: ${subcommand}`), process.exit(1));
190
+ break;
191
+ }
192
+ // ========================================
193
+ // Fingerprint Commands
194
+ // ========================================
195
+ case "fingerprint": {
196
+ const platform = validatePlatform(subcommand), result = await generateFingerprint({
197
+ platform,
198
+ projectRoot: options.projectRoot
199
+ });
200
+ (options.githubOutput || isGitHubActions()) && (setGitHubOutput("fingerprint", result.hash), setGitHubOutput(
201
+ "cache-key",
202
+ createCacheKey({
203
+ platform,
204
+ fingerprint: result.hash,
205
+ prefix: options.prefix
206
+ })
207
+ )), options.json ? console.info(JSON.stringify(result, null, 2)) : console.info(result.hash);
208
+ break;
209
+ }
210
+ case "fingerprint-test": {
211
+ const CACHE_FILE = ".fingerprint-cache.json";
212
+ console.info(`Generating fingerprints...
213
+ `);
214
+ const iosResult = await generateFingerprint({ platform: "ios", projectRoot: options.projectRoot }), androidResult = await generateFingerprint({ platform: "android", projectRoot: options.projectRoot }), iosFingerprint = iosResult.hash, androidFingerprint = androidResult.hash;
215
+ console.info("Current fingerprints:"), console.info(` iOS: ${iosFingerprint}`), console.info(` Android: ${androidFingerprint}`), console.info("");
216
+ const cache = loadCache(CACHE_FILE);
217
+ if (cache?.ios && cache?.android) {
218
+ console.info("Previous fingerprints (from cache):"), console.info(` iOS: ${cache.ios}`), console.info(` Android: ${cache.android}`), console.info("");
219
+ const iosChanged = cache.ios !== iosFingerprint, androidChanged = cache.android !== androidFingerprint;
220
+ iosChanged || androidChanged ? (console.info("Fingerprints changed!"), iosChanged && console.info(" - iOS fingerprint changed (would trigger iOS rebuild)"), androidChanged && console.info(" - Android fingerprint changed (would trigger Android rebuild)")) : console.info("Fingerprints match - no rebuild needed");
221
+ } else
222
+ console.info("No previous fingerprints cached.");
223
+ saveCache(CACHE_FILE, { ios: iosFingerprint, android: androidFingerprint, timestamp: (/* @__PURE__ */ new Date()).toISOString() }), console.info(`
224
+ Saved fingerprints to ${CACHE_FILE}`), console.info(`
225
+ To test cache invalidation:
226
+ 1. Add a native dependency: yarn add react-native-mmkv
227
+ 2. Run this script again: native-ci fingerprint-test
228
+ 3. Fingerprints should change!
229
+ 4. Remove the dependency: yarn remove react-native-mmkv
230
+ 5. Run this script again - fingerprints should match original
231
+ `);
232
+ break;
233
+ }
234
+ case "pre-hash": {
235
+ const files = [subcommand, ...args].filter(Boolean);
236
+ files.length === 0 && (console.error("Error: at least one file required"), process.exit(1));
237
+ const hash = generatePreFingerprintHash(files, options.projectRoot);
238
+ (options.githubOutput || isGitHubActions()) && setGitHubOutput("pre-fingerprint-hash", hash), options.json ? console.info(JSON.stringify({ hash, files }, null, 2)) : console.info(hash);
239
+ break;
240
+ }
241
+ case "cache-key": {
242
+ const platform = validatePlatform(subcommand), fingerprint = args[0];
243
+ fingerprint || (console.error("Error: fingerprint is required"), process.exit(1));
244
+ const cacheKey = createCacheKey({
245
+ platform,
246
+ fingerprint,
247
+ prefix: options.prefix
248
+ });
249
+ (options.githubOutput || isGitHubActions()) && setGitHubOutput("cache-key", cacheKey), console.info(cacheKey);
250
+ break;
251
+ }
252
+ // ========================================
253
+ // KV Store Commands
254
+ // ========================================
255
+ case "kv-get": {
256
+ const key = subcommand;
257
+ key || (console.error("Error: key is required"), process.exit(1));
258
+ const kv = getKVCredentials(), value = await getFingerprintFromKV(kv, key);
259
+ (options.githubOutput || isGitHubActions()) && (setGitHubOutput("value", value || ""), setGitHubOutput("found", value ? "true" : "false")), value ? console.info(value) : process.exit(1);
260
+ break;
261
+ }
262
+ case "kv-set": {
263
+ const key = subcommand, value = args[0];
264
+ (!key || !value) && (console.error("Error: key and value are required"), process.exit(1));
265
+ const kv = getKVCredentials();
266
+ await saveFingerprintToKV(kv, key, value), console.info("OK");
267
+ break;
268
+ }
269
+ default:
270
+ console.error(`Unknown command: ${command}`), console.info(HELP), process.exit(1);
271
+ }
272
+ } catch (error) {
273
+ console.error("Error:", error.message), process.exit(1);
274
+ }
275
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli.ts"],
4
+ "mappings": "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",
5
+ "names": ["args", "options"]
6
+ }