@invarn/cibuild 1.3.15 → 1.3.17

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 (242) hide show
  1. package/dist/cli.cjs +1 -1
  2. package/dist/src/cli.d.ts +3 -0
  3. package/dist/src/cli.d.ts.map +1 -0
  4. package/dist/src/cli.js +987 -0
  5. package/dist/src/commands/android-scanner.d.ts +32 -0
  6. package/dist/src/commands/android-scanner.d.ts.map +1 -0
  7. package/dist/src/commands/android-scanner.js +667 -0
  8. package/dist/src/commands/build.d.ts +5 -0
  9. package/dist/src/commands/build.d.ts.map +1 -0
  10. package/dist/src/commands/build.js +1096 -0
  11. package/dist/src/commands/edit.d.ts +3 -0
  12. package/dist/src/commands/edit.d.ts.map +1 -0
  13. package/dist/src/commands/edit.js +651 -0
  14. package/dist/src/commands/file-secret-collector.d.ts +37 -0
  15. package/dist/src/commands/file-secret-collector.d.ts.map +1 -0
  16. package/dist/src/commands/file-secret-collector.js +199 -0
  17. package/dist/src/commands/github-workflow.d.ts +5 -0
  18. package/dist/src/commands/github-workflow.d.ts.map +1 -0
  19. package/dist/src/commands/github-workflow.js +45 -0
  20. package/dist/src/commands/ios-scanner.d.ts +27 -0
  21. package/dist/src/commands/ios-scanner.d.ts.map +1 -0
  22. package/dist/src/commands/ios-scanner.js +337 -0
  23. package/dist/src/commands/reset.d.ts +7 -0
  24. package/dist/src/commands/reset.d.ts.map +1 -0
  25. package/dist/src/commands/reset.js +81 -0
  26. package/dist/src/commands/secrets-sync-workflow.d.ts +15 -0
  27. package/dist/src/commands/secrets-sync-workflow.d.ts.map +1 -0
  28. package/dist/src/commands/secrets-sync-workflow.js +255 -0
  29. package/dist/src/commands/secrets-upload.d.ts +21 -0
  30. package/dist/src/commands/secrets-upload.d.ts.map +1 -0
  31. package/dist/src/commands/secrets-upload.js +177 -0
  32. package/dist/src/commands/secrets-upload.test.d.ts +5 -0
  33. package/dist/src/commands/secrets-upload.test.d.ts.map +1 -0
  34. package/dist/src/commands/secrets-upload.test.js +60 -0
  35. package/dist/src/config.d.ts +3 -0
  36. package/dist/src/config.d.ts.map +1 -0
  37. package/dist/src/config.js +46 -0
  38. package/dist/src/envman/cli.d.ts +21 -0
  39. package/dist/src/envman/cli.d.ts.map +1 -0
  40. package/dist/src/envman/cli.js +240 -0
  41. package/dist/src/envman/envman.d.ts +83 -0
  42. package/dist/src/envman/envman.d.ts.map +1 -0
  43. package/dist/src/envman/envman.js +361 -0
  44. package/dist/src/envman/envman.test.d.ts +5 -0
  45. package/dist/src/envman/envman.test.d.ts.map +1 -0
  46. package/dist/src/envman/envman.test.js +236 -0
  47. package/dist/src/envman/index.d.ts +23 -0
  48. package/dist/src/envman/index.d.ts.map +1 -0
  49. package/dist/src/envman/index.js +23 -0
  50. package/dist/src/envman/types.d.ts +55 -0
  51. package/dist/src/envman/types.d.ts.map +1 -0
  52. package/dist/src/envman/types.js +12 -0
  53. package/dist/src/lib.d.ts +27 -0
  54. package/dist/src/lib.d.ts.map +1 -0
  55. package/dist/src/lib.js +32 -0
  56. package/dist/src/pipeline.d.ts +3 -0
  57. package/dist/src/pipeline.d.ts.map +1 -0
  58. package/dist/src/pipeline.js +57 -0
  59. package/dist/src/runner.d.ts +17 -0
  60. package/dist/src/runner.d.ts.map +1 -0
  61. package/dist/src/runner.js +234 -0
  62. package/dist/src/types.d.ts +57 -0
  63. package/dist/src/types.d.ts.map +1 -0
  64. package/dist/src/types.js +2 -0
  65. package/dist/src/yaml/bitrise-compat.d.ts +65 -0
  66. package/dist/src/yaml/bitrise-compat.d.ts.map +1 -0
  67. package/dist/src/yaml/bitrise-compat.js +206 -0
  68. package/dist/src/yaml/bitrise-compat.test.d.ts +5 -0
  69. package/dist/src/yaml/bitrise-compat.test.d.ts.map +1 -0
  70. package/dist/src/yaml/bitrise-compat.test.js +347 -0
  71. package/dist/src/yaml/converter.d.ts +33 -0
  72. package/dist/src/yaml/converter.d.ts.map +1 -0
  73. package/dist/src/yaml/converter.js +222 -0
  74. package/dist/src/yaml/converter.test.d.ts +5 -0
  75. package/dist/src/yaml/converter.test.d.ts.map +1 -0
  76. package/dist/src/yaml/converter.test.js +348 -0
  77. package/dist/src/yaml/e2e.test.d.ts +6 -0
  78. package/dist/src/yaml/e2e.test.d.ts.map +1 -0
  79. package/dist/src/yaml/e2e.test.js +446 -0
  80. package/dist/src/yaml/env-resolver.d.ts +120 -0
  81. package/dist/src/yaml/env-resolver.d.ts.map +1 -0
  82. package/dist/src/yaml/env-resolver.js +405 -0
  83. package/dist/src/yaml/env-resolver.test.d.ts +5 -0
  84. package/dist/src/yaml/env-resolver.test.d.ts.map +1 -0
  85. package/dist/src/yaml/env-resolver.test.js +502 -0
  86. package/dist/src/yaml/interactive-prompts.d.ts +71 -0
  87. package/dist/src/yaml/interactive-prompts.d.ts.map +1 -0
  88. package/dist/src/yaml/interactive-prompts.js +258 -0
  89. package/dist/src/yaml/missing-env-handler.d.ts +45 -0
  90. package/dist/src/yaml/missing-env-handler.d.ts.map +1 -0
  91. package/dist/src/yaml/missing-env-handler.js +64 -0
  92. package/dist/src/yaml/parser.d.ts +33 -0
  93. package/dist/src/yaml/parser.d.ts.map +1 -0
  94. package/dist/src/yaml/parser.js +145 -0
  95. package/dist/src/yaml/pipeline-with-secrets.d.ts +25 -0
  96. package/dist/src/yaml/pipeline-with-secrets.d.ts.map +1 -0
  97. package/dist/src/yaml/pipeline-with-secrets.js +76 -0
  98. package/dist/src/yaml/platform-detector.d.ts +83 -0
  99. package/dist/src/yaml/platform-detector.d.ts.map +1 -0
  100. package/dist/src/yaml/platform-detector.js +188 -0
  101. package/dist/src/yaml/platform-detector.test.d.ts +5 -0
  102. package/dist/src/yaml/platform-detector.test.d.ts.map +1 -0
  103. package/dist/src/yaml/platform-detector.test.js +414 -0
  104. package/dist/src/yaml/preflight-validation.d.ts +40 -0
  105. package/dist/src/yaml/preflight-validation.d.ts.map +1 -0
  106. package/dist/src/yaml/preflight-validation.js +152 -0
  107. package/dist/src/yaml/secrets-manager.d.ts +77 -0
  108. package/dist/src/yaml/secrets-manager.d.ts.map +1 -0
  109. package/dist/src/yaml/secrets-manager.js +219 -0
  110. package/dist/src/yaml/step-validator.d.ts +54 -0
  111. package/dist/src/yaml/step-validator.d.ts.map +1 -0
  112. package/dist/src/yaml/step-validator.js +403 -0
  113. package/dist/src/yaml/steps/android-sign.d.ts +35 -0
  114. package/dist/src/yaml/steps/android-sign.d.ts.map +1 -0
  115. package/dist/src/yaml/steps/android-sign.js +147 -0
  116. package/dist/src/yaml/steps/android-version.d.ts +26 -0
  117. package/dist/src/yaml/steps/android-version.d.ts.map +1 -0
  118. package/dist/src/yaml/steps/android-version.js +128 -0
  119. package/dist/src/yaml/steps/android-version.test.d.ts +5 -0
  120. package/dist/src/yaml/steps/android-version.test.d.ts.map +1 -0
  121. package/dist/src/yaml/steps/android-version.test.js +196 -0
  122. package/dist/src/yaml/steps/android.d.ts +95 -0
  123. package/dist/src/yaml/steps/android.d.ts.map +1 -0
  124. package/dist/src/yaml/steps/android.js +916 -0
  125. package/dist/src/yaml/steps/app-store-deploy.d.ts +48 -0
  126. package/dist/src/yaml/steps/app-store-deploy.d.ts.map +1 -0
  127. package/dist/src/yaml/steps/app-store-deploy.js +162 -0
  128. package/dist/src/yaml/steps/base.d.ts +238 -0
  129. package/dist/src/yaml/steps/base.d.ts.map +1 -0
  130. package/dist/src/yaml/steps/base.js +345 -0
  131. package/dist/src/yaml/steps/bitrise-android-tools.d.ts +26 -0
  132. package/dist/src/yaml/steps/bitrise-android-tools.d.ts.map +1 -0
  133. package/dist/src/yaml/steps/bitrise-android-tools.js +198 -0
  134. package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts +5 -0
  135. package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts.map +1 -0
  136. package/dist/src/yaml/steps/bitrise-android-tools.test.js +280 -0
  137. package/dist/src/yaml/steps/bitrise-apk-info.d.ts +22 -0
  138. package/dist/src/yaml/steps/bitrise-apk-info.d.ts.map +1 -0
  139. package/dist/src/yaml/steps/bitrise-apk-info.js +144 -0
  140. package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts +5 -0
  141. package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts.map +1 -0
  142. package/dist/src/yaml/steps/bitrise-apk-info.test.js +331 -0
  143. package/dist/src/yaml/steps/bitrise-slack.d.ts +49 -0
  144. package/dist/src/yaml/steps/bitrise-slack.d.ts.map +1 -0
  145. package/dist/src/yaml/steps/bitrise-slack.js +280 -0
  146. package/dist/src/yaml/steps/bitrise-slack.test.d.ts +5 -0
  147. package/dist/src/yaml/steps/bitrise-slack.test.d.ts.map +1 -0
  148. package/dist/src/yaml/steps/bitrise-slack.test.js +484 -0
  149. package/dist/src/yaml/steps/bitrise-ssh.d.ts +27 -0
  150. package/dist/src/yaml/steps/bitrise-ssh.d.ts.map +1 -0
  151. package/dist/src/yaml/steps/bitrise-ssh.js +134 -0
  152. package/dist/src/yaml/steps/bitrise-ssh.test.d.ts +5 -0
  153. package/dist/src/yaml/steps/bitrise-ssh.test.d.ts.map +1 -0
  154. package/dist/src/yaml/steps/bitrise-ssh.test.js +205 -0
  155. package/dist/src/yaml/steps/cache.d.ts +52 -0
  156. package/dist/src/yaml/steps/cache.d.ts.map +1 -0
  157. package/dist/src/yaml/steps/cache.js +351 -0
  158. package/dist/src/yaml/steps/fastlane.d.ts +27 -0
  159. package/dist/src/yaml/steps/fastlane.d.ts.map +1 -0
  160. package/dist/src/yaml/steps/fastlane.js +79 -0
  161. package/dist/src/yaml/steps/file.d.ts +27 -0
  162. package/dist/src/yaml/steps/file.d.ts.map +1 -0
  163. package/dist/src/yaml/steps/file.js +35 -0
  164. package/dist/src/yaml/steps/flutter.d.ts +63 -0
  165. package/dist/src/yaml/steps/flutter.d.ts.map +1 -0
  166. package/dist/src/yaml/steps/flutter.js +215 -0
  167. package/dist/src/yaml/steps/git-clone.d.ts +26 -0
  168. package/dist/src/yaml/steps/git-clone.d.ts.map +1 -0
  169. package/dist/src/yaml/steps/git-clone.js +111 -0
  170. package/dist/src/yaml/steps/google-play-deploy.d.ts +37 -0
  171. package/dist/src/yaml/steps/google-play-deploy.d.ts.map +1 -0
  172. package/dist/src/yaml/steps/google-play-deploy.js +193 -0
  173. package/dist/src/yaml/steps/google-play-deploy.test.d.ts +5 -0
  174. package/dist/src/yaml/steps/google-play-deploy.test.d.ts.map +1 -0
  175. package/dist/src/yaml/steps/google-play-deploy.test.js +310 -0
  176. package/dist/src/yaml/steps/index.d.ts +10 -0
  177. package/dist/src/yaml/steps/index.d.ts.map +1 -0
  178. package/dist/src/yaml/steps/index.js +1361 -0
  179. package/dist/src/yaml/steps/ios-deps.d.ts +43 -0
  180. package/dist/src/yaml/steps/ios-deps.d.ts.map +1 -0
  181. package/dist/src/yaml/steps/ios-deps.js +141 -0
  182. package/dist/src/yaml/steps/ios-deps.test.d.ts +5 -0
  183. package/dist/src/yaml/steps/ios-deps.test.d.ts.map +1 -0
  184. package/dist/src/yaml/steps/ios-deps.test.js +90 -0
  185. package/dist/src/yaml/steps/ios-signing.d.ts +31 -0
  186. package/dist/src/yaml/steps/ios-signing.d.ts.map +1 -0
  187. package/dist/src/yaml/steps/ios-signing.js +144 -0
  188. package/dist/src/yaml/steps/ios-version.d.ts +47 -0
  189. package/dist/src/yaml/steps/ios-version.d.ts.map +1 -0
  190. package/dist/src/yaml/steps/ios-version.js +151 -0
  191. package/dist/src/yaml/steps/linting.d.ts +47 -0
  192. package/dist/src/yaml/steps/linting.d.ts.map +1 -0
  193. package/dist/src/yaml/steps/linting.js +148 -0
  194. package/dist/src/yaml/steps/phase2.test.d.ts +6 -0
  195. package/dist/src/yaml/steps/phase2.test.d.ts.map +1 -0
  196. package/dist/src/yaml/steps/phase2.test.js +197 -0
  197. package/dist/src/yaml/steps/phase3.test.d.ts +5 -0
  198. package/dist/src/yaml/steps/phase3.test.d.ts.map +1 -0
  199. package/dist/src/yaml/steps/phase3.test.js +144 -0
  200. package/dist/src/yaml/steps/phase4.test.d.ts +5 -0
  201. package/dist/src/yaml/steps/phase4.test.d.ts.map +1 -0
  202. package/dist/src/yaml/steps/phase4.test.js +166 -0
  203. package/dist/src/yaml/steps/phase5.test.d.ts +6 -0
  204. package/dist/src/yaml/steps/phase5.test.d.ts.map +1 -0
  205. package/dist/src/yaml/steps/phase5.test.js +263 -0
  206. package/dist/src/yaml/steps/registry.d.ts +88 -0
  207. package/dist/src/yaml/steps/registry.d.ts.map +1 -0
  208. package/dist/src/yaml/steps/registry.js +125 -0
  209. package/dist/src/yaml/steps/registry.test.d.ts +5 -0
  210. package/dist/src/yaml/steps/registry.test.d.ts.map +1 -0
  211. package/dist/src/yaml/steps/registry.test.js +235 -0
  212. package/dist/src/yaml/steps/release.d.ts +50 -0
  213. package/dist/src/yaml/steps/release.d.ts.map +1 -0
  214. package/dist/src/yaml/steps/release.js +154 -0
  215. package/dist/src/yaml/steps/script.d.ts +23 -0
  216. package/dist/src/yaml/steps/script.d.ts.map +1 -0
  217. package/dist/src/yaml/steps/script.js +63 -0
  218. package/dist/src/yaml/steps/spec-validation.test.d.ts +6 -0
  219. package/dist/src/yaml/steps/spec-validation.test.d.ts.map +1 -0
  220. package/dist/src/yaml/steps/spec-validation.test.js +130 -0
  221. package/dist/src/yaml/steps/steps.test.d.ts +6 -0
  222. package/dist/src/yaml/steps/steps.test.d.ts.map +1 -0
  223. package/dist/src/yaml/steps/steps.test.js +474 -0
  224. package/dist/src/yaml/steps/test-config.d.ts +3 -0
  225. package/dist/src/yaml/steps/test-config.d.ts.map +1 -0
  226. package/dist/src/yaml/steps/test-config.js +16 -0
  227. package/dist/src/yaml/steps/xcode-new.test.d.ts +5 -0
  228. package/dist/src/yaml/steps/xcode-new.test.d.ts.map +1 -0
  229. package/dist/src/yaml/steps/xcode-new.test.js +211 -0
  230. package/dist/src/yaml/steps/xcode.d.ts +222 -0
  231. package/dist/src/yaml/steps/xcode.d.ts.map +1 -0
  232. package/dist/src/yaml/steps/xcode.js +999 -0
  233. package/dist/src/yaml/types.d.ts +68 -0
  234. package/dist/src/yaml/types.d.ts.map +1 -0
  235. package/dist/src/yaml/types.js +5 -0
  236. package/dist/src/yaml/validation-types.d.ts +96 -0
  237. package/dist/src/yaml/validation-types.d.ts.map +1 -0
  238. package/dist/src/yaml/validation-types.js +8 -0
  239. package/dist/src/yaml/yaml-updater.d.ts +24 -0
  240. package/dist/src/yaml/yaml-updater.d.ts.map +1 -0
  241. package/dist/src/yaml/yaml-updater.js +128 -0
  242. package/package.json +16 -4
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Base interfaces and utilities for YAML step executors
3
+ */
4
+ import { execSync } from 'node:child_process';
5
+ import { existsSync } from 'node:fs';
6
+ /**
7
+ * Base class for step executors providing common utilities
8
+ */
9
+ export class BaseStepExecutor {
10
+ /**
11
+ * Creates a script-based StepDef
12
+ * @param script Bash script content
13
+ * @param name Step name
14
+ * @returns StepDef with kind 'script'
15
+ */
16
+ createScriptStep(script, name) {
17
+ return {
18
+ id: '', // Will be set by converter
19
+ name,
20
+ kind: 'script',
21
+ shell: 'bash',
22
+ script,
23
+ };
24
+ }
25
+ /**
26
+ * Creates a Python-based StepDef
27
+ * @param script Python script content
28
+ * @param name Step name
29
+ * @returns StepDef with kind 'python'
30
+ */
31
+ createPythonStep(script, name) {
32
+ return {
33
+ id: '', // Will be set by converter
34
+ name,
35
+ kind: 'python',
36
+ script,
37
+ };
38
+ }
39
+ /**
40
+ * Creates a Node.js-based StepDef
41
+ * @param script Node.js script content
42
+ * @param name Step name
43
+ * @returns StepDef with kind 'node'
44
+ */
45
+ createNodeStep(script, name) {
46
+ return {
47
+ id: '', // Will be set by converter
48
+ name,
49
+ kind: 'node',
50
+ script,
51
+ };
52
+ }
53
+ /**
54
+ * Creates a Ruby-based StepDef
55
+ * @param script Ruby script content
56
+ * @param name Step name
57
+ * @returns StepDef with kind 'ruby'
58
+ */
59
+ createRubyStep(script, name) {
60
+ return {
61
+ id: '', // Will be set by converter
62
+ name,
63
+ kind: 'ruby',
64
+ script,
65
+ };
66
+ }
67
+ /**
68
+ * Gets an input value with a default fallback
69
+ * @param inputs Input object
70
+ * @param key Input key
71
+ * @param defaultValue Default value if not found
72
+ * @returns Input value or default
73
+ */
74
+ getInput(inputs, key, defaultValue) {
75
+ if (inputs && key in inputs && inputs[key] !== undefined) {
76
+ return inputs[key];
77
+ }
78
+ return defaultValue;
79
+ }
80
+ /**
81
+ * Gets a required input value, throws if not found
82
+ * @param inputs Input object
83
+ * @param key Input key
84
+ * @param stepName Step name for error message
85
+ * @returns Input value
86
+ * @throws Error if input not found
87
+ */
88
+ getRequiredInput(inputs, key, stepName) {
89
+ if (!inputs || !(key in inputs) || inputs[key] === undefined) {
90
+ throw new Error(`Missing required input '${key}' for step '${stepName}'`);
91
+ }
92
+ return inputs[key];
93
+ }
94
+ /**
95
+ * Escapes a string for safe use in bash scripts
96
+ * @param str String to escape
97
+ * @returns Escaped string safe for bash
98
+ */
99
+ escapeBash(str) {
100
+ // Escape single quotes by replacing ' with '\''
101
+ return str.replace(/'/g, "'\\''");
102
+ }
103
+ /**
104
+ * Interpolates environment variables in a string at runtime
105
+ * Supports ${VAR} and $VAR formats
106
+ * @param str String to interpolate
107
+ * @param env Environment variables
108
+ * @returns Interpolated string
109
+ */
110
+ interpolateString(str, env) {
111
+ let result = str;
112
+ // Format 1: ${VAR}
113
+ result = result.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/g, (match, varName) => {
114
+ return env[varName] || '';
115
+ });
116
+ // Format 2: $VAR (must not be followed by alphanumeric or underscore)
117
+ result = result.replace(/\$([A-Z_][A-Z0-9_]*)(?![A-Z0-9_])/g, (match, varName) => {
118
+ return env[varName] || '';
119
+ });
120
+ return result;
121
+ }
122
+ /**
123
+ * Creates a bash script with proper error handling
124
+ * Automatically sources envman store to load variables from previous steps
125
+ * @param scriptContent Main script content
126
+ * @param stepName Step name for error messages
127
+ * @returns Complete bash script with error handling
128
+ */
129
+ createBashScript(scriptContent, stepName) {
130
+ return `#!/bin/bash
131
+ set -e # Exit on error
132
+ set -o pipefail # Catch errors in pipes
133
+
134
+ # Step: ${stepName}
135
+
136
+ # Load environment variables from envman store (set by previous steps)
137
+ ENVSTORE_FILE="\${ENVMAN_ENVSTORE_PATH:-.ci/.envstore.json}"
138
+ if [ -f "$ENVSTORE_FILE" ]; then
139
+ while IFS='=' read -r key value; do
140
+ [ -n "$key" ] && export "$key=$value"
141
+ done < <(node -e "const fs=require('fs');try{const s=JSON.parse(fs.readFileSync('$ENVSTORE_FILE','utf-8'));(s.envs||[]).forEach(e=>console.log(e.key+'='+e.value))}catch(err){}" 2>/dev/null || true)
142
+ fi
143
+
144
+ ${scriptContent}
145
+ `;
146
+ }
147
+ /**
148
+ * Creates a multiline bash script from an array of commands
149
+ * @param commands Array of bash commands
150
+ * @param stepName Step name for error messages
151
+ * @returns Complete bash script
152
+ */
153
+ createBashScriptFromCommands(commands, stepName) {
154
+ const scriptContent = commands.join('\n');
155
+ return this.createBashScript(scriptContent, stepName);
156
+ }
157
+ // ========== VALIDATION METHODS ==========
158
+ // These methods are READ-ONLY and safe to run on user's machine
159
+ /**
160
+ * Default implementation - no validation requirements
161
+ * Override in subclasses to add step-specific validations
162
+ */
163
+ getValidationRequirements(_inputs, _env, _config) {
164
+ return [];
165
+ }
166
+ /**
167
+ * Default implementation - no outputs
168
+ * Override in subclasses to declare step outputs
169
+ */
170
+ getOutputs() {
171
+ return [];
172
+ }
173
+ /**
174
+ * Returns true if this step will be skipped entirely in local mode.
175
+ * When true, the validator skips all validation (requirements + auto-discovery).
176
+ * Override in steps that check config.local in execute() and skip.
177
+ */
178
+ isSkippedInLocalMode() {
179
+ return false;
180
+ }
181
+ /**
182
+ * Creates a requirement for an external command to exist
183
+ * Uses 'which' to check - READ-ONLY operation
184
+ */
185
+ requireCommand(command, description, hint) {
186
+ return {
187
+ category: 'command',
188
+ name: command,
189
+ description,
190
+ timing: 'pre-execution',
191
+ severity: 'error',
192
+ hint,
193
+ check: async () => this.checkCommandExists(command),
194
+ };
195
+ }
196
+ /**
197
+ * Creates a requirement for an environment variable to be set
198
+ * Reads process.env - READ-ONLY operation
199
+ */
200
+ requireEnvVar(varName, description, env, hint) {
201
+ return {
202
+ category: 'environment',
203
+ name: varName,
204
+ description,
205
+ timing: 'pre-execution',
206
+ severity: 'error',
207
+ hint,
208
+ check: async () => ({
209
+ passed: !!(env[varName] || process.env[varName]),
210
+ message: env[varName] || process.env[varName]
211
+ ? `${varName} is set`
212
+ : `${varName} is not set`,
213
+ }),
214
+ };
215
+ }
216
+ /**
217
+ * Creates a requirement for a file to exist
218
+ * Uses existsSync - READ-ONLY operation
219
+ */
220
+ requireFile(path, description, hint) {
221
+ return {
222
+ category: 'file',
223
+ name: path,
224
+ description,
225
+ timing: 'pre-execution',
226
+ severity: 'error',
227
+ hint,
228
+ check: async () => ({
229
+ passed: existsSync(path),
230
+ message: existsSync(path)
231
+ ? `File exists: ${path}`
232
+ : `File not found: ${path}`,
233
+ }),
234
+ };
235
+ }
236
+ /**
237
+ * Creates a requirement for a directory to exist
238
+ * Uses existsSync - READ-ONLY operation
239
+ */
240
+ requireDirectory(path, description, hint) {
241
+ return {
242
+ category: 'directory',
243
+ name: path,
244
+ description,
245
+ timing: 'pre-execution',
246
+ severity: 'error',
247
+ hint,
248
+ check: async () => ({
249
+ passed: existsSync(path),
250
+ message: existsSync(path)
251
+ ? `Directory exists: ${path}`
252
+ : `Directory not found: ${path}`,
253
+ }),
254
+ };
255
+ }
256
+ /**
257
+ * Creates a requirement for a YAML input
258
+ * Just checks object property - READ-ONLY operation
259
+ */
260
+ requireInput(inputName, inputs, description, hint) {
261
+ return {
262
+ category: 'input',
263
+ name: inputName,
264
+ description,
265
+ timing: 'pre-execution',
266
+ severity: 'error',
267
+ hint,
268
+ check: async () => ({
269
+ passed: inputs && inputName in inputs && inputs[inputName] !== undefined,
270
+ message: inputs && inputs[inputName] !== undefined
271
+ ? `Input '${inputName}' is provided`
272
+ : `Missing required input '${inputName}'`,
273
+ }),
274
+ };
275
+ }
276
+ /**
277
+ * Creates a runtime-only requirement (checked at step execution time)
278
+ * Used for files/directories that will be created by earlier steps
279
+ */
280
+ runtimeRequirement(name, description, category = 'file', providedBy) {
281
+ return {
282
+ category,
283
+ name,
284
+ description,
285
+ timing: 'runtime',
286
+ severity: 'info',
287
+ providedBy,
288
+ };
289
+ }
290
+ /**
291
+ * Checks if a command exists on the system
292
+ * Uses 'which' command - READ-ONLY operation
293
+ */
294
+ async checkCommandExists(command) {
295
+ try {
296
+ // Use 'which' on macOS/Linux, 'where' on Windows
297
+ const whichCmd = process.platform === 'win32' ? 'where' : 'which';
298
+ execSync(`${whichCmd} ${command}`, { stdio: 'pipe' });
299
+ return {
300
+ passed: true,
301
+ message: `Command '${command}' is available`,
302
+ };
303
+ }
304
+ catch {
305
+ return {
306
+ passed: false,
307
+ message: `Command '${command}' not found in PATH`,
308
+ };
309
+ }
310
+ }
311
+ /**
312
+ * Checks if Java is installed at a specific version
313
+ * Uses java_home or checks directory existence - READ-ONLY operation
314
+ */
315
+ async checkJavaVersion(version) {
316
+ try {
317
+ if (process.platform === 'darwin') {
318
+ // macOS: use java_home
319
+ execSync(`/usr/libexec/java_home -v "${version}"`, { stdio: 'pipe' });
320
+ }
321
+ else {
322
+ // Linux: check common paths
323
+ const paths = [
324
+ `/usr/lib/jvm/java-${version}-openjdk-amd64`,
325
+ `/usr/lib/jvm/java-${version}-openjdk`,
326
+ `/usr/lib/jvm/temurin-${version}-jdk-amd64`,
327
+ ];
328
+ const exists = paths.some((p) => existsSync(p));
329
+ if (!exists)
330
+ throw new Error('Not found');
331
+ }
332
+ return { passed: true, message: `Java ${version} is available` };
333
+ }
334
+ catch {
335
+ return {
336
+ passed: false,
337
+ message: `Java ${version} not found`,
338
+ details: process.platform === 'darwin'
339
+ ? `Install: brew install openjdk@${version}`
340
+ : `Install: sudo apt install openjdk-${version}-jdk`,
341
+ };
342
+ }
343
+ }
344
+ }
345
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Bitrise install-missing-android-tools step implementation
3
+ * Maps Bitrise install-missing-android-tools@* to CI Build Android environment setup
4
+ */
5
+ import { BaseStepExecutor } from './base.js';
6
+ import type { StepDef, CIConfig } from '../../types.js';
7
+ import type { ValidationRequirement, StepOutput } from '../validation-types.js';
8
+ /**
9
+ * Inputs for install-missing-android-tools step
10
+ */
11
+ export interface BitriseAndroidToolsInputs {
12
+ gradlew_path?: string;
13
+ ndk_revision?: string;
14
+ }
15
+ /**
16
+ * Bitrise install-missing-android-tools step executor (FR-3)
17
+ * Ensures Android development environment is properly configured
18
+ *
19
+ * Supports Bitrise step versions: install-missing-android-tools@1, @2, @3, @4
20
+ */
21
+ export declare class BitriseAndroidToolsStepExecutor extends BaseStepExecutor {
22
+ getValidationRequirements(_inputs: BitriseAndroidToolsInputs, env: Record<string, string>, _config: CIConfig): ValidationRequirement[];
23
+ getOutputs(): StepOutput[];
24
+ execute(inputs: BitriseAndroidToolsInputs, env: Record<string, string>, config: CIConfig): Promise<StepDef>;
25
+ }
26
+ //# sourceMappingURL=bitrise-android-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitrise-android-tools.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/bitrise-android-tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,qBAAa,+BAAgC,SAAQ,gBAAgB;IACnE,yBAAyB,CACvB,OAAO,EAAE,yBAAyB,EAClC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAiD1B,UAAU,IAAI,UAAU,EAAE;IAMpB,OAAO,CAAC,MAAM,EAAE,yBAAyB,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;CAyJlH"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Bitrise install-missing-android-tools step implementation
3
+ * Maps Bitrise install-missing-android-tools@* to CI Build Android environment setup
4
+ */
5
+ import { BaseStepExecutor } from './base.js';
6
+ /**
7
+ * Bitrise install-missing-android-tools step executor (FR-3)
8
+ * Ensures Android development environment is properly configured
9
+ *
10
+ * Supports Bitrise step versions: install-missing-android-tools@1, @2, @3, @4
11
+ */
12
+ export class BitriseAndroidToolsStepExecutor extends BaseStepExecutor {
13
+ getValidationRequirements(_inputs, env, _config) {
14
+ // Check if ANDROID_HOME is set OR can be auto-detected
15
+ const androidHomeSet = !!(env.ANDROID_HOME || process.env.ANDROID_HOME);
16
+ return [
17
+ {
18
+ category: 'environment',
19
+ name: 'ANDROID_HOME',
20
+ description: 'Android SDK installation directory',
21
+ timing: 'pre-execution',
22
+ severity: 'info', // Info because we can auto-detect
23
+ check: async () => {
24
+ if (androidHomeSet) {
25
+ return {
26
+ passed: true,
27
+ message: 'ANDROID_HOME is set',
28
+ };
29
+ }
30
+ // Check if we can auto-detect
31
+ const { existsSync } = await import('node:fs');
32
+ const { homedir } = await import('node:os');
33
+ const homeDir = homedir();
34
+ const commonPaths = [
35
+ `${homeDir}/Library/Android/sdk`, // macOS
36
+ `${homeDir}/Android/Sdk`, // Linux
37
+ '/usr/local/android-sdk',
38
+ ];
39
+ const foundPath = commonPaths.find(p => existsSync(p));
40
+ if (foundPath) {
41
+ return {
42
+ passed: true,
43
+ message: `ANDROID_HOME not set, but will auto-detect at: ${foundPath}`,
44
+ };
45
+ }
46
+ return {
47
+ passed: false,
48
+ message: 'ANDROID_HOME not set and Android SDK not found in common locations',
49
+ };
50
+ },
51
+ },
52
+ this.runtimeRequirement('gradlew', 'Gradle wrapper', 'file', 'git-clone'),
53
+ ];
54
+ }
55
+ getOutputs() {
56
+ return [
57
+ { name: 'ANDROID_HOME', type: 'environment', description: 'Android SDK installation directory' },
58
+ ];
59
+ }
60
+ async execute(inputs, env, config) {
61
+ const stepName = 'install-missing-android-tools';
62
+ // Get gradlew path (FR-3.4)
63
+ const gradlewPath = this.getInput(inputs, 'gradlew_path', './gradlew');
64
+ // Get NDK revision (optional)
65
+ const ndkRevision = this.getInput(inputs, 'ndk_revision', '');
66
+ const commands = [];
67
+ commands.push('# Bitrise install-missing-android-tools step → CI Build Android environment setup');
68
+ commands.push('echo "📋 Verifying Android development environment..."');
69
+ commands.push('');
70
+ // Verify or auto-detect ANDROID_HOME (FR-3.3, FR-3.6)
71
+ commands.push('# Verify or auto-detect ANDROID_HOME environment variable');
72
+ commands.push('if [ -z "$ANDROID_HOME" ]; then');
73
+ commands.push(' echo "⚠️ ANDROID_HOME is not set, checking common locations..."');
74
+ commands.push(' ');
75
+ commands.push(' # Common Android SDK locations');
76
+ commands.push(' if [ -d "$HOME/Library/Android/sdk" ]; then');
77
+ commands.push(' export ANDROID_HOME="$HOME/Library/Android/sdk"');
78
+ commands.push(' echo "✅ Found Android SDK at: $ANDROID_HOME (macOS default)"');
79
+ commands.push(' elif [ -d "$HOME/Android/Sdk" ]; then');
80
+ commands.push(' export ANDROID_HOME="$HOME/Android/Sdk"');
81
+ commands.push(' echo "✅ Found Android SDK at: $ANDROID_HOME (Linux default)"');
82
+ commands.push(' elif [ -d "/usr/local/android-sdk" ]; then');
83
+ commands.push(' export ANDROID_HOME="/usr/local/android-sdk"');
84
+ commands.push(' echo "✅ Found Android SDK at: $ANDROID_HOME"');
85
+ commands.push(' else');
86
+ commands.push(' echo ""');
87
+ commands.push(' echo "❌ Android SDK not found in common locations:"');
88
+ commands.push(' echo " - ~/Library/Android/sdk (macOS)"');
89
+ commands.push(' echo " - ~/Android/Sdk (Linux)"');
90
+ commands.push(' echo " - /usr/local/android-sdk"');
91
+ commands.push(' echo ""');
92
+ commands.push(' echo "Please install Android Studio or set ANDROID_HOME manually:"');
93
+ commands.push(' echo " export ANDROID_HOME=/path/to/android-sdk"');
94
+ commands.push(' exit 1');
95
+ commands.push(' fi');
96
+ commands.push(' ');
97
+ commands.push(' # Persist ANDROID_HOME for subsequent steps');
98
+ commands.push(' envman add --key ANDROID_HOME --value "$ANDROID_HOME"');
99
+ commands.push('else');
100
+ commands.push(' echo "✅ ANDROID_HOME is set to: $ANDROID_HOME"');
101
+ commands.push('fi');
102
+ commands.push('');
103
+ // Verify ANDROID_HOME directory exists
104
+ commands.push('# Verify ANDROID_HOME directory exists');
105
+ commands.push('if [ ! -d "$ANDROID_HOME" ]; then');
106
+ commands.push(' echo "❌ Error: ANDROID_HOME directory does not exist: $ANDROID_HOME"');
107
+ commands.push(' exit 1');
108
+ commands.push('fi');
109
+ commands.push('');
110
+ // Display Android SDK information
111
+ commands.push('# Display Android SDK information');
112
+ commands.push('echo "Android SDK location: $ANDROID_HOME"');
113
+ commands.push('if [ -d "$ANDROID_HOME/platform-tools" ]; then');
114
+ commands.push(' echo "Platform tools: Available"');
115
+ commands.push('fi');
116
+ commands.push('if [ -d "$ANDROID_HOME/build-tools" ]; then');
117
+ commands.push(' echo "Build tools: Available"');
118
+ commands.push('fi');
119
+ commands.push('');
120
+ // Validate JAVA_HOME before using Gradle
121
+ commands.push('# Validate JAVA_HOME for Gradle (optional check)');
122
+ commands.push('if [ -n "$JAVA_HOME" ] && [ ! -d "$JAVA_HOME" ]; then');
123
+ commands.push(' echo ""');
124
+ commands.push(' echo "⚠️ Warning: JAVA_HOME is set but points to invalid directory:"');
125
+ commands.push(' echo " $JAVA_HOME"');
126
+ commands.push(' echo ""');
127
+ commands.push(' echo "This may cause Gradle to fail. Common fixes:"');
128
+ commands.push(' echo " 1. Unset JAVA_HOME: unset JAVA_HOME"');
129
+ commands.push(' echo " 2. Run set-java-version step before this step"');
130
+ commands.push(' echo " 3. Set correct JAVA_HOME for your OS"');
131
+ commands.push(' echo ""');
132
+ commands.push(' echo "Skipping Gradle verification due to invalid JAVA_HOME..."');
133
+ commands.push(' SKIP_GRADLE_CHECK=1');
134
+ commands.push('fi');
135
+ commands.push('');
136
+ // Make gradlew executable (FR-3.4)
137
+ commands.push('# Make gradlew executable');
138
+ commands.push('# Check in project directory if CIBUILD_SOURCE_DIR is set');
139
+ commands.push('if [ -n "$CIBUILD_SOURCE_DIR" ]; then');
140
+ commands.push(` GRADLEW_FULL_PATH="$CIBUILD_SOURCE_DIR/${this.escapeBash(gradlewPath)}"`);
141
+ commands.push('else');
142
+ commands.push(` GRADLEW_FULL_PATH="${this.escapeBash(gradlewPath)}"`);
143
+ commands.push('fi');
144
+ commands.push('');
145
+ commands.push('if [ -f "$GRADLEW_FULL_PATH" ]; then');
146
+ commands.push(' echo "Making gradlew executable: $GRADLEW_FULL_PATH"');
147
+ commands.push(' chmod +x "$GRADLEW_FULL_PATH"');
148
+ commands.push(' echo "✅ gradlew is now executable"');
149
+ commands.push('else');
150
+ commands.push(' echo "ℹ️ gradlew not found at $GRADLEW_FULL_PATH (will be checked at runtime by gradle steps)"');
151
+ commands.push('fi');
152
+ commands.push('');
153
+ // Verify Gradle works (FR-3.5)
154
+ commands.push('# Verify Gradle is working');
155
+ commands.push('if [ -f "$GRADLEW_FULL_PATH" ] && [ -z "$SKIP_GRADLE_CHECK" ]; then');
156
+ commands.push(' echo "Testing Gradle..."');
157
+ commands.push(' cd "$(dirname "$GRADLEW_FULL_PATH")"');
158
+ commands.push(' if ./gradlew --version 2>/dev/null; then');
159
+ commands.push(' echo "✅ Gradle is working correctly"');
160
+ commands.push(' else');
161
+ commands.push(' echo ""');
162
+ commands.push(' echo "⚠️ Warning: Gradle test failed"');
163
+ commands.push(' echo " This usually means JAVA_HOME is not set correctly."');
164
+ commands.push(' echo " Make sure to run the set-java-version step before this step."');
165
+ commands.push(' echo ""');
166
+ commands.push(' echo "Continuing anyway (Gradle will be needed for build steps)..."');
167
+ commands.push(' fi');
168
+ commands.push('fi');
169
+ commands.push('');
170
+ // Display NDK information if specified
171
+ if (ndkRevision) {
172
+ commands.push('# NDK information');
173
+ commands.push(`echo "Requested NDK revision: ${this.escapeBash(ndkRevision)}"`);
174
+ commands.push('if [ -d "$ANDROID_HOME/ndk" ]; then');
175
+ commands.push(' echo "NDK directory: $ANDROID_HOME/ndk"');
176
+ commands.push(' ls -1 "$ANDROID_HOME/ndk" 2>/dev/null || echo " (empty)"');
177
+ commands.push('fi');
178
+ commands.push('');
179
+ }
180
+ // Set up Android SDK path in PATH
181
+ commands.push('# Add Android SDK tools to PATH');
182
+ commands.push('export PATH="$ANDROID_HOME/platform-tools:$PATH"');
183
+ commands.push('export PATH="$ANDROID_HOME/tools:$PATH"');
184
+ commands.push('export PATH="$ANDROID_HOME/tools/bin:$PATH"');
185
+ commands.push('');
186
+ // Display ADB version if available
187
+ commands.push('# Display ADB version if available');
188
+ commands.push('if command -v adb >/dev/null 2>&1; then');
189
+ commands.push(' echo "ADB version:"');
190
+ commands.push(' adb version');
191
+ commands.push('fi');
192
+ commands.push('');
193
+ commands.push('echo "✅ Android development environment verified successfully"');
194
+ const script = this.createBashScriptFromCommands(commands, stepName);
195
+ return this.createScriptStep(script, stepName);
196
+ }
197
+ }
198
+ //# sourceMappingURL=bitrise-android-tools.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Unit tests for Bitrise install-missing-android-tools step
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=bitrise-android-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitrise-android-tools.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/bitrise-android-tools.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}