@invarn/cibuild 2.9.4 → 2.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (547) hide show
  1. package/dist/chunk-35SI42CD.mjs +1 -0
  2. package/dist/chunk-IC45KVLJ.mjs +1 -0
  3. package/dist/chunk-XDY4V23V.mjs +1 -0
  4. package/dist/cli.cjs +14 -14
  5. package/dist/commands.mjs +1 -0
  6. package/dist/lib.mjs +3934 -0
  7. package/package.json +6 -10
  8. package/dist/src/cli.d.ts +0 -3
  9. package/dist/src/cli.d.ts.map +0 -1
  10. package/dist/src/cli.js +0 -399
  11. package/dist/src/commands/a-credential-target-follows-the-flavor-source-set.test.d.ts +0 -38
  12. package/dist/src/commands/a-credential-target-follows-the-flavor-source-set.test.d.ts.map +0 -1
  13. package/dist/src/commands/a-credential-target-follows-the-flavor-source-set.test.js +0 -222
  14. package/dist/src/commands/a-credential-two-workflows-cannot-share-is-declared-per-workflow.test.d.ts +0 -41
  15. package/dist/src/commands/a-credential-two-workflows-cannot-share-is-declared-per-workflow.test.d.ts.map +0 -1
  16. package/dist/src/commands/a-credential-two-workflows-cannot-share-is-declared-per-workflow.test.js +0 -324
  17. package/dist/src/commands/a-properties-stand-in-declares-the-keys-the-build-reads.test.d.ts +0 -2
  18. package/dist/src/commands/a-properties-stand-in-declares-the-keys-the-build-reads.test.d.ts.map +0 -1
  19. package/dist/src/commands/a-properties-stand-in-declares-the-keys-the-build-reads.test.js +0 -382
  20. package/dist/src/commands/an-already-stored-value-does-not-answer-the-target-question.test.d.ts +0 -29
  21. package/dist/src/commands/an-already-stored-value-does-not-answer-the-target-question.test.d.ts.map +0 -1
  22. package/dist/src/commands/an-already-stored-value-does-not-answer-the-target-question.test.js +0 -160
  23. package/dist/src/commands/android-gms-guard.test.d.ts +0 -9
  24. package/dist/src/commands/android-gms-guard.test.d.ts.map +0 -1
  25. package/dist/src/commands/android-gms-guard.test.js +0 -78
  26. package/dist/src/commands/android-java-version.test.d.ts +0 -12
  27. package/dist/src/commands/android-java-version.test.d.ts.map +0 -1
  28. package/dist/src/commands/android-java-version.test.js +0 -209
  29. package/dist/src/commands/android-scanner-java.test.d.ts +0 -2
  30. package/dist/src/commands/android-scanner-java.test.d.ts.map +0 -1
  31. package/dist/src/commands/android-scanner-java.test.js +0 -130
  32. package/dist/src/commands/android-scanner.d.ts +0 -250
  33. package/dist/src/commands/android-scanner.d.ts.map +0 -1
  34. package/dist/src/commands/android-scanner.js +0 -1639
  35. package/dist/src/commands/build.d.ts +0 -215
  36. package/dist/src/commands/build.d.ts.map +0 -1
  37. package/dist/src/commands/build.js +0 -1433
  38. package/dist/src/commands/build.test.d.ts +0 -13
  39. package/dist/src/commands/build.test.d.ts.map +0 -1
  40. package/dist/src/commands/build.test.js +0 -121
  41. package/dist/src/commands/detect-platform.d.ts +0 -13
  42. package/dist/src/commands/detect-platform.d.ts.map +0 -1
  43. package/dist/src/commands/detect-platform.js +0 -51
  44. package/dist/src/commands/detect-project.d.ts +0 -7
  45. package/dist/src/commands/detect-project.d.ts.map +0 -1
  46. package/dist/src/commands/detect-project.js +0 -12
  47. package/dist/src/commands/each-flavor-is-asked-for-its-own-properties-file.test.d.ts +0 -26
  48. package/dist/src/commands/each-flavor-is-asked-for-its-own-properties-file.test.d.ts.map +0 -1
  49. package/dist/src/commands/each-flavor-is-asked-for-its-own-properties-file.test.js +0 -196
  50. package/dist/src/commands/edit.d.ts +0 -12
  51. package/dist/src/commands/edit.d.ts.map +0 -1
  52. package/dist/src/commands/edit.js +0 -652
  53. package/dist/src/commands/edit.test.d.ts +0 -6
  54. package/dist/src/commands/edit.test.d.ts.map +0 -1
  55. package/dist/src/commands/edit.test.js +0 -45
  56. package/dist/src/commands/fidelity-trim.d.ts +0 -13
  57. package/dist/src/commands/fidelity-trim.d.ts.map +0 -1
  58. package/dist/src/commands/fidelity-trim.js +0 -21
  59. package/dist/src/commands/fidelity-trim.test.d.ts +0 -8
  60. package/dist/src/commands/fidelity-trim.test.d.ts.map +0 -1
  61. package/dist/src/commands/fidelity-trim.test.js +0 -79
  62. package/dist/src/commands/file-secret-collector.d.ts +0 -50
  63. package/dist/src/commands/file-secret-collector.d.ts.map +0 -1
  64. package/dist/src/commands/file-secret-collector.js +0 -217
  65. package/dist/src/commands/flavors-a-convention-plugin-creates-are-still-found.test.d.ts +0 -38
  66. package/dist/src/commands/flavors-a-convention-plugin-creates-are-still-found.test.d.ts.map +0 -1
  67. package/dist/src/commands/flavors-a-convention-plugin-creates-are-still-found.test.js +0 -300
  68. package/dist/src/commands/github-workflow.d.ts +0 -5
  69. package/dist/src/commands/github-workflow.d.ts.map +0 -1
  70. package/dist/src/commands/github-workflow.js +0 -45
  71. package/dist/src/commands/index.d.ts +0 -33
  72. package/dist/src/commands/index.d.ts.map +0 -1
  73. package/dist/src/commands/index.js +0 -33
  74. package/dist/src/commands/init.d.ts +0 -20
  75. package/dist/src/commands/init.d.ts.map +0 -1
  76. package/dist/src/commands/init.js +0 -264
  77. package/dist/src/commands/ios-scanner.d.ts +0 -104
  78. package/dist/src/commands/ios-scanner.d.ts.map +0 -1
  79. package/dist/src/commands/ios-scanner.js +0 -492
  80. package/dist/src/commands/ios-scheme-ranking.test.d.ts +0 -2
  81. package/dist/src/commands/ios-scheme-ranking.test.d.ts.map +0 -1
  82. package/dist/src/commands/ios-scheme-ranking.test.js +0 -264
  83. package/dist/src/commands/local-properties-reaches-every-workflow.test.d.ts +0 -30
  84. package/dist/src/commands/local-properties-reaches-every-workflow.test.d.ts.map +0 -1
  85. package/dist/src/commands/local-properties-reaches-every-workflow.test.js +0 -146
  86. package/dist/src/commands/reset.d.ts +0 -7
  87. package/dist/src/commands/reset.d.ts.map +0 -1
  88. package/dist/src/commands/reset.js +0 -81
  89. package/dist/src/commands/run.d.ts +0 -22
  90. package/dist/src/commands/run.d.ts.map +0 -1
  91. package/dist/src/commands/run.js +0 -141
  92. package/dist/src/commands/secrets-sync-workflow.d.ts +0 -15
  93. package/dist/src/commands/secrets-sync-workflow.d.ts.map +0 -1
  94. package/dist/src/commands/secrets-sync-workflow.js +0 -255
  95. package/dist/src/commands/secrets-upload.d.ts +0 -21
  96. package/dist/src/commands/secrets-upload.d.ts.map +0 -1
  97. package/dist/src/commands/secrets-upload.js +0 -177
  98. package/dist/src/commands/secrets-upload.test.d.ts +0 -5
  99. package/dist/src/commands/secrets-upload.test.d.ts.map +0 -1
  100. package/dist/src/commands/secrets-upload.test.js +0 -60
  101. package/dist/src/commands/validate.d.ts +0 -10
  102. package/dist/src/commands/validate.d.ts.map +0 -1
  103. package/dist/src/commands/validate.js +0 -46
  104. package/dist/src/config.d.ts +0 -3
  105. package/dist/src/config.d.ts.map +0 -1
  106. package/dist/src/config.js +0 -47
  107. package/dist/src/envman/cli.d.ts +0 -21
  108. package/dist/src/envman/cli.d.ts.map +0 -1
  109. package/dist/src/envman/cli.js +0 -240
  110. package/dist/src/envman/envman.d.ts +0 -83
  111. package/dist/src/envman/envman.d.ts.map +0 -1
  112. package/dist/src/envman/envman.js +0 -361
  113. package/dist/src/envman/envman.test.d.ts +0 -5
  114. package/dist/src/envman/envman.test.d.ts.map +0 -1
  115. package/dist/src/envman/envman.test.js +0 -236
  116. package/dist/src/envman/envstore-round-trip.test.d.ts +0 -27
  117. package/dist/src/envman/envstore-round-trip.test.d.ts.map +0 -1
  118. package/dist/src/envman/envstore-round-trip.test.js +0 -130
  119. package/dist/src/envman/index.d.ts +0 -23
  120. package/dist/src/envman/index.d.ts.map +0 -1
  121. package/dist/src/envman/index.js +0 -23
  122. package/dist/src/envman/shim.d.ts +0 -16
  123. package/dist/src/envman/shim.d.ts.map +0 -1
  124. package/dist/src/envman/shim.js +0 -66
  125. package/dist/src/envman/types.d.ts +0 -55
  126. package/dist/src/envman/types.d.ts.map +0 -1
  127. package/dist/src/envman/types.js +0 -12
  128. package/dist/src/lib.d.ts +0 -33
  129. package/dist/src/lib.d.ts.map +0 -1
  130. package/dist/src/lib.js +0 -37
  131. package/dist/src/pipeline.d.ts +0 -3
  132. package/dist/src/pipeline.d.ts.map +0 -1
  133. package/dist/src/pipeline.js +0 -57
  134. package/dist/src/runner-node-step.test.d.ts +0 -12
  135. package/dist/src/runner-node-step.test.d.ts.map +0 -1
  136. package/dist/src/runner-node-step.test.js +0 -61
  137. package/dist/src/runner.d.ts +0 -31
  138. package/dist/src/runner.d.ts.map +0 -1
  139. package/dist/src/runner.js +0 -240
  140. package/dist/src/shared/detect-project.d.ts +0 -57
  141. package/dist/src/shared/detect-project.d.ts.map +0 -1
  142. package/dist/src/shared/detect-project.js +0 -219
  143. package/dist/src/shared/detect-project.test.d.ts +0 -2
  144. package/dist/src/shared/detect-project.test.d.ts.map +0 -1
  145. package/dist/src/shared/detect-project.test.js +0 -161
  146. package/dist/src/shared/git.d.ts +0 -25
  147. package/dist/src/shared/git.d.ts.map +0 -1
  148. package/dist/src/shared/git.js +0 -53
  149. package/dist/src/shared/git.test.d.ts +0 -9
  150. package/dist/src/shared/git.test.d.ts.map +0 -1
  151. package/dist/src/shared/git.test.js +0 -66
  152. package/dist/src/shared/gitignore.d.ts +0 -6
  153. package/dist/src/shared/gitignore.d.ts.map +0 -1
  154. package/dist/src/shared/gitignore.js +0 -26
  155. package/dist/src/shared/gradle-settings.d.ts +0 -49
  156. package/dist/src/shared/gradle-settings.d.ts.map +0 -1
  157. package/dist/src/shared/gradle-settings.js +0 -138
  158. package/dist/src/shared/gradle-settings.test.d.ts +0 -2
  159. package/dist/src/shared/gradle-settings.test.d.ts.map +0 -1
  160. package/dist/src/shared/gradle-settings.test.js +0 -65
  161. package/dist/src/shared/prompts.d.ts +0 -30
  162. package/dist/src/shared/prompts.d.ts.map +0 -1
  163. package/dist/src/shared/prompts.js +0 -121
  164. package/dist/src/shared/xcode-container.test.d.ts +0 -2
  165. package/dist/src/shared/xcode-container.test.d.ts.map +0 -1
  166. package/dist/src/shared/xcode-container.test.js +0 -123
  167. package/dist/src/step-marker.d.ts +0 -12
  168. package/dist/src/step-marker.d.ts.map +0 -1
  169. package/dist/src/step-marker.js +0 -29
  170. package/dist/src/step-marker.test.d.ts +0 -11
  171. package/dist/src/step-marker.test.d.ts.map +0 -1
  172. package/dist/src/step-marker.test.js +0 -45
  173. package/dist/src/types.d.ts +0 -58
  174. package/dist/src/types.d.ts.map +0 -1
  175. package/dist/src/types.js +0 -2
  176. package/dist/src/yaml/a-cache-path-must-not-swallow-a-credential.test.d.ts +0 -28
  177. package/dist/src/yaml/a-cache-path-must-not-swallow-a-credential.test.d.ts.map +0 -1
  178. package/dist/src/yaml/a-cache-path-must-not-swallow-a-credential.test.js +0 -223
  179. package/dist/src/yaml/a-declared-secret-reaches-the-file-step.test.d.ts +0 -20
  180. package/dist/src/yaml/a-declared-secret-reaches-the-file-step.test.d.ts.map +0 -1
  181. package/dist/src/yaml/a-declared-secret-reaches-the-file-step.test.js +0 -201
  182. package/dist/src/yaml/a-declared-slot-may-name-the-workflow-it-belongs-to.test.d.ts +0 -37
  183. package/dist/src/yaml/a-declared-slot-may-name-the-workflow-it-belongs-to.test.d.ts.map +0 -1
  184. package/dist/src/yaml/a-declared-slot-may-name-the-workflow-it-belongs-to.test.js +0 -255
  185. package/dist/src/yaml/a-missing-credential-is-loud.test.d.ts +0 -32
  186. package/dist/src/yaml/a-missing-credential-is-loud.test.d.ts.map +0 -1
  187. package/dist/src/yaml/a-missing-credential-is-loud.test.js +0 -301
  188. package/dist/src/yaml/a-runtime-requirement-names-a-real-provider.test.d.ts +0 -18
  189. package/dist/src/yaml/a-runtime-requirement-names-a-real-provider.test.d.ts.map +0 -1
  190. package/dist/src/yaml/a-runtime-requirement-names-a-real-provider.test.js +0 -66
  191. package/dist/src/yaml/a-scoped-slot-must-name-a-workflow-the-pipeline-has.test.d.ts +0 -34
  192. package/dist/src/yaml/a-scoped-slot-must-name-a-workflow-the-pipeline-has.test.d.ts.map +0 -1
  193. package/dist/src/yaml/a-scoped-slot-must-name-a-workflow-the-pipeline-has.test.js +0 -218
  194. package/dist/src/yaml/a-value-this-instance-stored-is-a-value-it-has.test.d.ts +0 -27
  195. package/dist/src/yaml/a-value-this-instance-stored-is-a-value-it-has.test.d.ts.map +0 -1
  196. package/dist/src/yaml/a-value-this-instance-stored-is-a-value-it-has.test.js +0 -126
  197. package/dist/src/yaml/bitrise-compat.d.ts +0 -65
  198. package/dist/src/yaml/bitrise-compat.d.ts.map +0 -1
  199. package/dist/src/yaml/bitrise-compat.js +0 -206
  200. package/dist/src/yaml/bitrise-compat.test.d.ts +0 -5
  201. package/dist/src/yaml/bitrise-compat.test.d.ts.map +0 -1
  202. package/dist/src/yaml/bitrise-compat.test.js +0 -347
  203. package/dist/src/yaml/cache-key-missing-file.test.d.ts +0 -12
  204. package/dist/src/yaml/cache-key-missing-file.test.d.ts.map +0 -1
  205. package/dist/src/yaml/cache-key-missing-file.test.js +0 -116
  206. package/dist/src/yaml/converter.d.ts +0 -103
  207. package/dist/src/yaml/converter.d.ts.map +0 -1
  208. package/dist/src/yaml/converter.js +0 -420
  209. package/dist/src/yaml/converter.test.d.ts +0 -5
  210. package/dist/src/yaml/converter.test.d.ts.map +0 -1
  211. package/dist/src/yaml/converter.test.js +0 -548
  212. package/dist/src/yaml/e2e.test.d.ts +0 -6
  213. package/dist/src/yaml/e2e.test.d.ts.map +0 -1
  214. package/dist/src/yaml/e2e.test.js +0 -446
  215. package/dist/src/yaml/env-resolver.d.ts +0 -218
  216. package/dist/src/yaml/env-resolver.d.ts.map +0 -1
  217. package/dist/src/yaml/env-resolver.js +0 -591
  218. package/dist/src/yaml/env-resolver.test.d.ts +0 -5
  219. package/dist/src/yaml/env-resolver.test.d.ts.map +0 -1
  220. package/dist/src/yaml/env-resolver.test.js +0 -502
  221. package/dist/src/yaml/every-build-log-witnesses-the-commit-on-disk.test.d.ts +0 -16
  222. package/dist/src/yaml/every-build-log-witnesses-the-commit-on-disk.test.d.ts.map +0 -1
  223. package/dist/src/yaml/every-build-log-witnesses-the-commit-on-disk.test.js +0 -126
  224. package/dist/src/yaml/fidelity-input-digest.d.ts +0 -37
  225. package/dist/src/yaml/fidelity-input-digest.d.ts.map +0 -1
  226. package/dist/src/yaml/fidelity-input-digest.js +0 -208
  227. package/dist/src/yaml/fidelity-input-digest.test.d.ts +0 -2
  228. package/dist/src/yaml/fidelity-input-digest.test.d.ts.map +0 -1
  229. package/dist/src/yaml/fidelity-input-digest.test.js +0 -167
  230. package/dist/src/yaml/fidelity-manifest.d.ts +0 -126
  231. package/dist/src/yaml/fidelity-manifest.d.ts.map +0 -1
  232. package/dist/src/yaml/fidelity-manifest.js +0 -134
  233. package/dist/src/yaml/fidelity-manifest.test.d.ts +0 -12
  234. package/dist/src/yaml/fidelity-manifest.test.d.ts.map +0 -1
  235. package/dist/src/yaml/fidelity-manifest.test.js +0 -251
  236. package/dist/src/yaml/interactive-prompts.d.ts +0 -71
  237. package/dist/src/yaml/interactive-prompts.d.ts.map +0 -1
  238. package/dist/src/yaml/interactive-prompts.js +0 -260
  239. package/dist/src/yaml/meta-helpers.d.ts +0 -28
  240. package/dist/src/yaml/meta-helpers.d.ts.map +0 -1
  241. package/dist/src/yaml/meta-helpers.js +0 -46
  242. package/dist/src/yaml/missing-env-handler.d.ts +0 -45
  243. package/dist/src/yaml/missing-env-handler.d.ts.map +0 -1
  244. package/dist/src/yaml/missing-env-handler.js +0 -64
  245. package/dist/src/yaml/parser.d.ts +0 -33
  246. package/dist/src/yaml/parser.d.ts.map +0 -1
  247. package/dist/src/yaml/parser.js +0 -148
  248. package/dist/src/yaml/parser.test.d.ts +0 -5
  249. package/dist/src/yaml/parser.test.d.ts.map +0 -1
  250. package/dist/src/yaml/parser.test.js +0 -83
  251. package/dist/src/yaml/pipeline-with-secrets.d.ts +0 -25
  252. package/dist/src/yaml/pipeline-with-secrets.d.ts.map +0 -1
  253. package/dist/src/yaml/pipeline-with-secrets.js +0 -76
  254. package/dist/src/yaml/platform-detector.d.ts +0 -83
  255. package/dist/src/yaml/platform-detector.d.ts.map +0 -1
  256. package/dist/src/yaml/platform-detector.js +0 -189
  257. package/dist/src/yaml/platform-detector.test.d.ts +0 -5
  258. package/dist/src/yaml/platform-detector.test.d.ts.map +0 -1
  259. package/dist/src/yaml/platform-detector.test.js +0 -525
  260. package/dist/src/yaml/preflight-validation.d.ts +0 -29
  261. package/dist/src/yaml/preflight-validation.d.ts.map +0 -1
  262. package/dist/src/yaml/preflight-validation.js +0 -21
  263. package/dist/src/yaml/secrets-manager.d.ts +0 -87
  264. package/dist/src/yaml/secrets-manager.d.ts.map +0 -1
  265. package/dist/src/yaml/secrets-manager.js +0 -230
  266. package/dist/src/yaml/shell-assignments.d.ts +0 -40
  267. package/dist/src/yaml/shell-assignments.d.ts.map +0 -1
  268. package/dist/src/yaml/shell-assignments.js +0 -77
  269. package/dist/src/yaml/step-validator-check-failure.test.d.ts +0 -24
  270. package/dist/src/yaml/step-validator-check-failure.test.d.ts.map +0 -1
  271. package/dist/src/yaml/step-validator-check-failure.test.js +0 -130
  272. package/dist/src/yaml/step-validator-self-assigned.test.d.ts +0 -23
  273. package/dist/src/yaml/step-validator-self-assigned.test.d.ts.map +0 -1
  274. package/dist/src/yaml/step-validator-self-assigned.test.js +0 -191
  275. package/dist/src/yaml/step-validator.d.ts +0 -67
  276. package/dist/src/yaml/step-validator.d.ts.map +0 -1
  277. package/dist/src/yaml/step-validator.js +0 -466
  278. package/dist/src/yaml/step-validator.test.d.ts +0 -18
  279. package/dist/src/yaml/step-validator.test.d.ts.map +0 -1
  280. package/dist/src/yaml/step-validator.test.js +0 -140
  281. package/dist/src/yaml/steps/android-sign.d.ts +0 -35
  282. package/dist/src/yaml/steps/android-sign.d.ts.map +0 -1
  283. package/dist/src/yaml/steps/android-sign.js +0 -147
  284. package/dist/src/yaml/steps/android-variant-resolution.test.d.ts +0 -2
  285. package/dist/src/yaml/steps/android-variant-resolution.test.d.ts.map +0 -1
  286. package/dist/src/yaml/steps/android-variant-resolution.test.js +0 -260
  287. package/dist/src/yaml/steps/android-version.d.ts +0 -26
  288. package/dist/src/yaml/steps/android-version.d.ts.map +0 -1
  289. package/dist/src/yaml/steps/android-version.js +0 -128
  290. package/dist/src/yaml/steps/android-version.test.d.ts +0 -5
  291. package/dist/src/yaml/steps/android-version.test.d.ts.map +0 -1
  292. package/dist/src/yaml/steps/android-version.test.js +0 -196
  293. package/dist/src/yaml/steps/android.d.ts +0 -156
  294. package/dist/src/yaml/steps/android.d.ts.map +0 -1
  295. package/dist/src/yaml/steps/android.js +0 -1084
  296. package/dist/src/yaml/steps/app-store-deploy.d.ts +0 -48
  297. package/dist/src/yaml/steps/app-store-deploy.d.ts.map +0 -1
  298. package/dist/src/yaml/steps/app-store-deploy.js +0 -167
  299. package/dist/src/yaml/steps/base.d.ts +0 -263
  300. package/dist/src/yaml/steps/base.d.ts.map +0 -1
  301. package/dist/src/yaml/steps/base.js +0 -380
  302. package/dist/src/yaml/steps/bitrise-android-tools.d.ts +0 -26
  303. package/dist/src/yaml/steps/bitrise-android-tools.d.ts.map +0 -1
  304. package/dist/src/yaml/steps/bitrise-android-tools.js +0 -200
  305. package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts +0 -5
  306. package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts.map +0 -1
  307. package/dist/src/yaml/steps/bitrise-android-tools.test.js +0 -280
  308. package/dist/src/yaml/steps/bitrise-apk-info.d.ts +0 -22
  309. package/dist/src/yaml/steps/bitrise-apk-info.d.ts.map +0 -1
  310. package/dist/src/yaml/steps/bitrise-apk-info.js +0 -144
  311. package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts +0 -5
  312. package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts.map +0 -1
  313. package/dist/src/yaml/steps/bitrise-apk-info.test.js +0 -331
  314. package/dist/src/yaml/steps/bitrise-slack.d.ts +0 -49
  315. package/dist/src/yaml/steps/bitrise-slack.d.ts.map +0 -1
  316. package/dist/src/yaml/steps/bitrise-slack.js +0 -280
  317. package/dist/src/yaml/steps/bitrise-slack.test.d.ts +0 -5
  318. package/dist/src/yaml/steps/bitrise-slack.test.d.ts.map +0 -1
  319. package/dist/src/yaml/steps/bitrise-slack.test.js +0 -484
  320. package/dist/src/yaml/steps/bitrise-ssh.d.ts +0 -27
  321. package/dist/src/yaml/steps/bitrise-ssh.d.ts.map +0 -1
  322. package/dist/src/yaml/steps/bitrise-ssh.js +0 -134
  323. package/dist/src/yaml/steps/bitrise-ssh.test.d.ts +0 -5
  324. package/dist/src/yaml/steps/bitrise-ssh.test.d.ts.map +0 -1
  325. package/dist/src/yaml/steps/bitrise-ssh.test.js +0 -205
  326. package/dist/src/yaml/steps/cache-pull-daemon.test.d.ts +0 -27
  327. package/dist/src/yaml/steps/cache-pull-daemon.test.d.ts.map +0 -1
  328. package/dist/src/yaml/steps/cache-pull-daemon.test.js +0 -212
  329. package/dist/src/yaml/steps/cache-pull-restore-roots.test.d.ts +0 -42
  330. package/dist/src/yaml/steps/cache-pull-restore-roots.test.d.ts.map +0 -1
  331. package/dist/src/yaml/steps/cache-pull-restore-roots.test.js +0 -209
  332. package/dist/src/yaml/steps/cache-push-daemon.test.d.ts +0 -27
  333. package/dist/src/yaml/steps/cache-push-daemon.test.d.ts.map +0 -1
  334. package/dist/src/yaml/steps/cache-push-daemon.test.js +0 -171
  335. package/dist/src/yaml/steps/cache.d.ts +0 -59
  336. package/dist/src/yaml/steps/cache.d.ts.map +0 -1
  337. package/dist/src/yaml/steps/cache.js +0 -1027
  338. package/dist/src/yaml/steps/cocoapods-deployment-floor.d.ts +0 -42
  339. package/dist/src/yaml/steps/cocoapods-deployment-floor.d.ts.map +0 -1
  340. package/dist/src/yaml/steps/cocoapods-deployment-floor.js +0 -140
  341. package/dist/src/yaml/steps/cocoapods-deployment-floor.test.d.ts +0 -11
  342. package/dist/src/yaml/steps/cocoapods-deployment-floor.test.d.ts.map +0 -1
  343. package/dist/src/yaml/steps/cocoapods-deployment-floor.test.js +0 -176
  344. package/dist/src/yaml/steps/cocoapods-install-emits-valid-bash.test.d.ts +0 -22
  345. package/dist/src/yaml/steps/cocoapods-install-emits-valid-bash.test.d.ts.map +0 -1
  346. package/dist/src/yaml/steps/cocoapods-install-emits-valid-bash.test.js +0 -97
  347. package/dist/src/yaml/steps/cocoapods-locked-bundler.test.d.ts +0 -17
  348. package/dist/src/yaml/steps/cocoapods-locked-bundler.test.d.ts.map +0 -1
  349. package/dist/src/yaml/steps/cocoapods-locked-bundler.test.js +0 -282
  350. package/dist/src/yaml/steps/cocoapods-skip-if-absent.test.d.ts +0 -17
  351. package/dist/src/yaml/steps/cocoapods-skip-if-absent.test.d.ts.map +0 -1
  352. package/dist/src/yaml/steps/cocoapods-skip-if-absent.test.js +0 -132
  353. package/dist/src/yaml/steps/envstore-loader.test.d.ts +0 -15
  354. package/dist/src/yaml/steps/envstore-loader.test.d.ts.map +0 -1
  355. package/dist/src/yaml/steps/envstore-loader.test.js +0 -143
  356. package/dist/src/yaml/steps/fastlane.d.ts +0 -27
  357. package/dist/src/yaml/steps/fastlane.d.ts.map +0 -1
  358. package/dist/src/yaml/steps/fastlane.js +0 -79
  359. package/dist/src/yaml/steps/fidelity-aspect-guard.d.ts +0 -53
  360. package/dist/src/yaml/steps/fidelity-aspect-guard.d.ts.map +0 -1
  361. package/dist/src/yaml/steps/fidelity-aspect-guard.js +0 -72
  362. package/dist/src/yaml/steps/fidelity-aspect-guard.test.d.ts +0 -11
  363. package/dist/src/yaml/steps/fidelity-aspect-guard.test.d.ts.map +0 -1
  364. package/dist/src/yaml/steps/fidelity-aspect-guard.test.js +0 -50
  365. package/dist/src/yaml/steps/fidelity-reference-provenance.d.ts +0 -87
  366. package/dist/src/yaml/steps/fidelity-reference-provenance.d.ts.map +0 -1
  367. package/dist/src/yaml/steps/fidelity-reference-provenance.js +0 -111
  368. package/dist/src/yaml/steps/fidelity-reference-provenance.test.d.ts +0 -22
  369. package/dist/src/yaml/steps/fidelity-reference-provenance.test.d.ts.map +0 -1
  370. package/dist/src/yaml/steps/fidelity-reference-provenance.test.js +0 -118
  371. package/dist/src/yaml/steps/file.d.ts +0 -52
  372. package/dist/src/yaml/steps/file.d.ts.map +0 -1
  373. package/dist/src/yaml/steps/file.js +0 -108
  374. package/dist/src/yaml/steps/flutter.d.ts +0 -63
  375. package/dist/src/yaml/steps/flutter.d.ts.map +0 -1
  376. package/dist/src/yaml/steps/flutter.js +0 -215
  377. package/dist/src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.d.ts +0 -16
  378. package/dist/src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.d.ts.map +0 -1
  379. package/dist/src/yaml/steps/git-clone-names-the-inputs-it-ignores.test.js +0 -127
  380. package/dist/src/yaml/steps/git-clone.d.ts +0 -32
  381. package/dist/src/yaml/steps/git-clone.d.ts.map +0 -1
  382. package/dist/src/yaml/steps/git-clone.js +0 -171
  383. package/dist/src/yaml/steps/git-fetch-retry-exec.test.d.ts +0 -10
  384. package/dist/src/yaml/steps/git-fetch-retry-exec.test.d.ts.map +0 -1
  385. package/dist/src/yaml/steps/git-fetch-retry-exec.test.js +0 -162
  386. package/dist/src/yaml/steps/git-fetch-retry.d.ts +0 -62
  387. package/dist/src/yaml/steps/git-fetch-retry.d.ts.map +0 -1
  388. package/dist/src/yaml/steps/git-fetch-retry.js +0 -155
  389. package/dist/src/yaml/steps/git-fetch-retry.test.d.ts +0 -5
  390. package/dist/src/yaml/steps/git-fetch-retry.test.d.ts.map +0 -1
  391. package/dist/src/yaml/steps/git-fetch-retry.test.js +0 -86
  392. package/dist/src/yaml/steps/google-play-deploy.d.ts +0 -37
  393. package/dist/src/yaml/steps/google-play-deploy.d.ts.map +0 -1
  394. package/dist/src/yaml/steps/google-play-deploy.js +0 -193
  395. package/dist/src/yaml/steps/google-play-deploy.test.d.ts +0 -5
  396. package/dist/src/yaml/steps/google-play-deploy.test.d.ts.map +0 -1
  397. package/dist/src/yaml/steps/google-play-deploy.test.js +0 -310
  398. package/dist/src/yaml/steps/gradle-memory.d.ts +0 -61
  399. package/dist/src/yaml/steps/gradle-memory.d.ts.map +0 -1
  400. package/dist/src/yaml/steps/gradle-memory.js +0 -311
  401. package/dist/src/yaml/steps/gradle-memory.test.d.ts +0 -2
  402. package/dist/src/yaml/steps/gradle-memory.test.d.ts.map +0 -1
  403. package/dist/src/yaml/steps/gradle-memory.test.js +0 -297
  404. package/dist/src/yaml/steps/gradle-sdk-cmake.d.ts +0 -28
  405. package/dist/src/yaml/steps/gradle-sdk-cmake.d.ts.map +0 -1
  406. package/dist/src/yaml/steps/gradle-sdk-cmake.js +0 -107
  407. package/dist/src/yaml/steps/gradle-sdk-cmake.test.d.ts +0 -2
  408. package/dist/src/yaml/steps/gradle-sdk-cmake.test.d.ts.map +0 -1
  409. package/dist/src/yaml/steps/gradle-sdk-cmake.test.js +0 -183
  410. package/dist/src/yaml/steps/index.d.ts +0 -10
  411. package/dist/src/yaml/steps/index.d.ts.map +0 -1
  412. package/dist/src/yaml/steps/index.js +0 -1461
  413. package/dist/src/yaml/steps/ios-deps.d.ts +0 -78
  414. package/dist/src/yaml/steps/ios-deps.d.ts.map +0 -1
  415. package/dist/src/yaml/steps/ios-deps.js +0 -279
  416. package/dist/src/yaml/steps/ios-deps.test.d.ts +0 -5
  417. package/dist/src/yaml/steps/ios-deps.test.d.ts.map +0 -1
  418. package/dist/src/yaml/steps/ios-deps.test.js +0 -90
  419. package/dist/src/yaml/steps/ios-signing.d.ts +0 -31
  420. package/dist/src/yaml/steps/ios-signing.d.ts.map +0 -1
  421. package/dist/src/yaml/steps/ios-signing.js +0 -144
  422. package/dist/src/yaml/steps/ios-version.d.ts +0 -47
  423. package/dist/src/yaml/steps/ios-version.d.ts.map +0 -1
  424. package/dist/src/yaml/steps/ios-version.js +0 -151
  425. package/dist/src/yaml/steps/java-home-version-spec.test.d.ts +0 -10
  426. package/dist/src/yaml/steps/java-home-version-spec.test.d.ts.map +0 -1
  427. package/dist/src/yaml/steps/java-home-version-spec.test.js +0 -58
  428. package/dist/src/yaml/steps/linting.d.ts +0 -47
  429. package/dist/src/yaml/steps/linting.d.ts.map +0 -1
  430. package/dist/src/yaml/steps/linting.js +0 -148
  431. package/dist/src/yaml/steps/phase2.test.d.ts +0 -6
  432. package/dist/src/yaml/steps/phase2.test.d.ts.map +0 -1
  433. package/dist/src/yaml/steps/phase2.test.js +0 -197
  434. package/dist/src/yaml/steps/phase3.test.d.ts +0 -5
  435. package/dist/src/yaml/steps/phase3.test.d.ts.map +0 -1
  436. package/dist/src/yaml/steps/phase3.test.js +0 -144
  437. package/dist/src/yaml/steps/phase4.test.d.ts +0 -5
  438. package/dist/src/yaml/steps/phase4.test.d.ts.map +0 -1
  439. package/dist/src/yaml/steps/phase4.test.js +0 -166
  440. package/dist/src/yaml/steps/phase5.test.d.ts +0 -6
  441. package/dist/src/yaml/steps/phase5.test.d.ts.map +0 -1
  442. package/dist/src/yaml/steps/phase5.test.js +0 -263
  443. package/dist/src/yaml/steps/registry.d.ts +0 -88
  444. package/dist/src/yaml/steps/registry.d.ts.map +0 -1
  445. package/dist/src/yaml/steps/registry.js +0 -125
  446. package/dist/src/yaml/steps/registry.test.d.ts +0 -5
  447. package/dist/src/yaml/steps/registry.test.d.ts.map +0 -1
  448. package/dist/src/yaml/steps/registry.test.js +0 -235
  449. package/dist/src/yaml/steps/release.d.ts +0 -50
  450. package/dist/src/yaml/steps/release.d.ts.map +0 -1
  451. package/dist/src/yaml/steps/release.js +0 -154
  452. package/dist/src/yaml/steps/render-post-processor.d.ts +0 -100
  453. package/dist/src/yaml/steps/render-post-processor.d.ts.map +0 -1
  454. package/dist/src/yaml/steps/render-post-processor.js +0 -270
  455. package/dist/src/yaml/steps/render-post-processor.test.d.ts +0 -13
  456. package/dist/src/yaml/steps/render-post-processor.test.d.ts.map +0 -1
  457. package/dist/src/yaml/steps/render-post-processor.test.js +0 -220
  458. package/dist/src/yaml/steps/script.d.ts +0 -23
  459. package/dist/src/yaml/steps/script.d.ts.map +0 -1
  460. package/dist/src/yaml/steps/script.js +0 -63
  461. package/dist/src/yaml/steps/spec-validation.test.d.ts +0 -6
  462. package/dist/src/yaml/steps/spec-validation.test.d.ts.map +0 -1
  463. package/dist/src/yaml/steps/spec-validation.test.js +0 -130
  464. package/dist/src/yaml/steps/steps.test.d.ts +0 -6
  465. package/dist/src/yaml/steps/steps.test.d.ts.map +0 -1
  466. package/dist/src/yaml/steps/steps.test.js +0 -881
  467. package/dist/src/yaml/steps/structural-facts.d.ts +0 -992
  468. package/dist/src/yaml/steps/structural-facts.d.ts.map +0 -1
  469. package/dist/src/yaml/steps/structural-facts.js +0 -3276
  470. package/dist/src/yaml/steps/structural-facts.test.d.ts +0 -12
  471. package/dist/src/yaml/steps/structural-facts.test.d.ts.map +0 -1
  472. package/dist/src/yaml/steps/structural-facts.test.js +0 -3039
  473. package/dist/src/yaml/steps/test-config.d.ts +0 -5
  474. package/dist/src/yaml/steps/test-config.d.ts.map +0 -1
  475. package/dist/src/yaml/steps/test-config.js +0 -25
  476. package/dist/src/yaml/steps/trim-align-corpus.test.d.ts +0 -28
  477. package/dist/src/yaml/steps/trim-align-corpus.test.d.ts.map +0 -1
  478. package/dist/src/yaml/steps/trim-align-corpus.test.js +0 -383
  479. package/dist/src/yaml/steps/trim-align.d.ts +0 -87
  480. package/dist/src/yaml/steps/trim-align.d.ts.map +0 -1
  481. package/dist/src/yaml/steps/trim-align.js +0 -367
  482. package/dist/src/yaml/steps/trim-align.test.d.ts +0 -11
  483. package/dist/src/yaml/steps/trim-align.test.d.ts.map +0 -1
  484. package/dist/src/yaml/steps/trim-align.test.js +0 -261
  485. package/dist/src/yaml/steps/ui-fidelity-preview-android.d.ts +0 -66
  486. package/dist/src/yaml/steps/ui-fidelity-preview-android.d.ts.map +0 -1
  487. package/dist/src/yaml/steps/ui-fidelity-preview-android.js +0 -251
  488. package/dist/src/yaml/steps/ui-fidelity-preview-android.test.d.ts +0 -13
  489. package/dist/src/yaml/steps/ui-fidelity-preview-android.test.d.ts.map +0 -1
  490. package/dist/src/yaml/steps/ui-fidelity-preview-android.test.js +0 -302
  491. package/dist/src/yaml/steps/ui-fidelity-preview.d.ts +0 -134
  492. package/dist/src/yaml/steps/ui-fidelity-preview.d.ts.map +0 -1
  493. package/dist/src/yaml/steps/ui-fidelity-preview.js +0 -173
  494. package/dist/src/yaml/steps/ui-fidelity-preview.test.d.ts +0 -11
  495. package/dist/src/yaml/steps/ui-fidelity-preview.test.d.ts.map +0 -1
  496. package/dist/src/yaml/steps/ui-fidelity-preview.test.js +0 -210
  497. package/dist/src/yaml/steps/ui-fidelity-render-android.d.ts +0 -155
  498. package/dist/src/yaml/steps/ui-fidelity-render-android.d.ts.map +0 -1
  499. package/dist/src/yaml/steps/ui-fidelity-render-android.js +0 -1389
  500. package/dist/src/yaml/steps/ui-fidelity-render-android.test.d.ts +0 -2
  501. package/dist/src/yaml/steps/ui-fidelity-render-android.test.d.ts.map +0 -1
  502. package/dist/src/yaml/steps/ui-fidelity-render-android.test.js +0 -1106
  503. package/dist/src/yaml/steps/ui-fidelity-render.d.ts +0 -230
  504. package/dist/src/yaml/steps/ui-fidelity-render.d.ts.map +0 -1
  505. package/dist/src/yaml/steps/ui-fidelity-render.js +0 -1597
  506. package/dist/src/yaml/steps/ui-fidelity-render.test.d.ts +0 -18
  507. package/dist/src/yaml/steps/ui-fidelity-render.test.d.ts.map +0 -1
  508. package/dist/src/yaml/steps/ui-fidelity-render.test.js +0 -1871
  509. package/dist/src/yaml/steps/xcode-app-product.d.ts +0 -90
  510. package/dist/src/yaml/steps/xcode-app-product.d.ts.map +0 -1
  511. package/dist/src/yaml/steps/xcode-app-product.js +0 -247
  512. package/dist/src/yaml/steps/xcode-app-product.test.d.ts +0 -2
  513. package/dist/src/yaml/steps/xcode-app-product.test.d.ts.map +0 -1
  514. package/dist/src/yaml/steps/xcode-app-product.test.js +0 -202
  515. package/dist/src/yaml/steps/xcode-derived-data.test.d.ts +0 -30
  516. package/dist/src/yaml/steps/xcode-derived-data.test.d.ts.map +0 -1
  517. package/dist/src/yaml/steps/xcode-derived-data.test.js +0 -253
  518. package/dist/src/yaml/steps/xcode-destination.d.ts +0 -47
  519. package/dist/src/yaml/steps/xcode-destination.d.ts.map +0 -1
  520. package/dist/src/yaml/steps/xcode-destination.js +0 -202
  521. package/dist/src/yaml/steps/xcode-destination.test.d.ts +0 -9
  522. package/dist/src/yaml/steps/xcode-destination.test.d.ts.map +0 -1
  523. package/dist/src/yaml/steps/xcode-destination.test.js +0 -227
  524. package/dist/src/yaml/steps/xcode-new.test.d.ts +0 -5
  525. package/dist/src/yaml/steps/xcode-new.test.d.ts.map +0 -1
  526. package/dist/src/yaml/steps/xcode-new.test.js +0 -211
  527. package/dist/src/yaml/steps/xcode-resolve-retry.test.d.ts +0 -9
  528. package/dist/src/yaml/steps/xcode-resolve-retry.test.d.ts.map +0 -1
  529. package/dist/src/yaml/steps/xcode-resolve-retry.test.js +0 -146
  530. package/dist/src/yaml/steps/xcode-simulator-archs.d.ts +0 -53
  531. package/dist/src/yaml/steps/xcode-simulator-archs.d.ts.map +0 -1
  532. package/dist/src/yaml/steps/xcode-simulator-archs.js +0 -98
  533. package/dist/src/yaml/steps/xcode-simulator-archs.test.d.ts +0 -21
  534. package/dist/src/yaml/steps/xcode-simulator-archs.test.d.ts.map +0 -1
  535. package/dist/src/yaml/steps/xcode-simulator-archs.test.js +0 -155
  536. package/dist/src/yaml/steps/xcode.d.ts +0 -230
  537. package/dist/src/yaml/steps/xcode.d.ts.map +0 -1
  538. package/dist/src/yaml/steps/xcode.js +0 -1340
  539. package/dist/src/yaml/types.d.ts +0 -76
  540. package/dist/src/yaml/types.d.ts.map +0 -1
  541. package/dist/src/yaml/types.js +0 -5
  542. package/dist/src/yaml/validation-types.d.ts +0 -102
  543. package/dist/src/yaml/validation-types.d.ts.map +0 -1
  544. package/dist/src/yaml/validation-types.js +0 -8
  545. package/dist/src/yaml/yaml-updater.d.ts +0 -24
  546. package/dist/src/yaml/yaml-updater.d.ts.map +0 -1
  547. package/dist/src/yaml/yaml-updater.js +0 -128
@@ -1,1340 +0,0 @@
1
- /**
2
- * Xcode step implementations (xcodebuild, xcode-test)
3
- */
4
- import { existsSync } from 'node:fs';
5
- import { BaseStepExecutor } from './base.js';
6
- import { resolveDestinationInput } from './xcode-destination.js';
7
- import { APP_PRODUCT_RESOLVER_SOURCE } from './xcode-app-product.js';
8
- import { pinsSimulatorArm64, simulatorArchsLines, withRuntimeSimulatorArchs } from './xcode-simulator-archs.js';
9
- import { refusedFetchHelpers, retryOnRefusedFetch } from './git-fetch-retry.js';
10
- /**
11
- * Where derived data goes: outside the source tree, keyed by the output dir.
12
- *
13
- * It used to be "$DERIVED_DATA_PATH", and OUTPUT_DIR is inside the
14
- * checkout — so every resolved SPM package sat in the working tree, where an
15
- * app's own lint or format build phase walks it. vinhnx/Clendar's SwiftLint
16
- * phase failed the build on 145 serious violations, all of them in
17
- * third-party packages under build/app/DerivedData/SourcePackages/checkouts.
18
- * A developer's Xcode keeps derived data under ~/Library, so no repository has
19
- * a reason to exclude that directory, and it should not have to.
20
- *
21
- * CIBUILD_SCRATCH is the runner's per-build local root, which holds the
22
- * checkout rather than sitting inside it; outside a sandbox it falls back to
23
- * TMPDIR. The key is a checksum of the absolute output dir, so two steps that
24
- * name the same output_dir still share derived data (the iOS template relies
25
- * on that to avoid compiling the app twice) and two that name different ones
26
- * stay apart, as they did before.
27
- *
28
- * The path is resolved to its real one. On macOS /tmp and TMPDIR's /var are
29
- * symlinks into /private, and analogcode/Swift-Radio-Pro's LNPopupController
30
- * lists header directories with FileManager (real paths) but strips
31
- * packageBase.path (the symlinked one) by text replacement: every header
32
- * search path came out eight characters short.
33
- */
34
- function derivedDataPathLines() {
35
- return [
36
- '# Derived data outside the source tree, keyed by the output dir',
37
- 'DERIVED_DATA_PATH="${CIBUILD_SCRATCH:-${TMPDIR:-/tmp}}/cibuild-derived-data/$(printf \'%s\' "$OUTPUT_DIR" | cksum | cut -d\' \' -f1)"',
38
- 'mkdir -p "$DERIVED_DATA_PATH"',
39
- '# Its real path: /tmp and TMPDIR are symlinks on macOS, and a package that builds paths by text arithmetic breaks on them',
40
- 'DERIVED_DATA_PATH="$(cd "$DERIVED_DATA_PATH" && pwd -P)"',
41
- 'echo "Derived data: $DERIVED_DATA_PATH"',
42
- ];
43
- }
44
- /**
45
- * Xcodebuild step executor
46
- * Builds iOS/macOS projects using xcodebuild
47
- */
48
- export class XcodeBuildStepExecutor extends BaseStepExecutor {
49
- getValidationRequirements(inputs, _env, _config) {
50
- const requirements = [];
51
- // xcodebuild command must exist
52
- requirements.push(this.requireCommand('xcodebuild', 'Xcode Command Line Tools are required for iOS builds', 'Install Xcode from the App Store, then run: xcode-select --install'));
53
- // Required inputs
54
- requirements.push(this.requireInput('project_path', inputs, 'Path to .xcodeproj or .xcworkspace', 'Provide project_path input in YAML'));
55
- requirements.push(this.requireInput('scheme', inputs, 'Xcode scheme name', 'Provide scheme input in YAML'));
56
- // Project file - runtime check only if it doesn't already exist locally
57
- if (inputs.project_path && !existsSync(inputs.project_path)) {
58
- requirements.push(this.runtimeRequirement(inputs.project_path, 'Xcode project/workspace file', 'file', 'the checkout'));
59
- }
60
- if (inputs.destination === 'auto') {
61
- requirements.push(this.requireCommand('xcrun', 'xcrun is required to resolve destination: auto via xcrun simctl', 'Install Xcode and run: xcode-select --install'));
62
- }
63
- return requirements;
64
- }
65
- async execute(inputs, env, config) {
66
- const stepName = 'xcodebuild';
67
- // Get project path - required
68
- let projectPath = this.getRequiredInput(inputs, 'project_path', stepName);
69
- // Resolve path identifiers
70
- if (projectPath.startsWith('builds:')) {
71
- projectPath = projectPath.replace('builds:', `${config.paths.buildsDir}/`);
72
- }
73
- // Get scheme - required
74
- const scheme = this.getRequiredInput(inputs, 'scheme', stepName);
75
- // Get configuration - defaults to Release
76
- const configuration = this.getInput(inputs, 'configuration', 'Release');
77
- // Get destination - defaults to generic/platform=iOS.
78
- // `auto` triggers runtime resolution via `xcrun simctl`.
79
- const destination = resolveDestinationInput(this.getInput(inputs, 'destination', 'generic/platform=iOS'));
80
- // Get output directory - defaults to build
81
- const outputDir = this.getInput(inputs, 'output_dir', 'build');
82
- // Get clean build flag
83
- const isCleanBuild = this.getInput(inputs, 'is_clean_build', false);
84
- // Get xcconfig content - optional
85
- const xcconfigContent = this.getInput(inputs, 'xcconfig_content', '');
86
- const commands = [];
87
- commands.push('# Xcode Build');
88
- commands.push(`echo "Building project: ${this.escapeBash(projectPath)}"`);
89
- commands.push(`echo "Scheme: ${this.escapeBash(scheme)}"`);
90
- commands.push(`echo "Configuration: ${this.escapeBash(configuration)}"`);
91
- // Create output directory and resolve to absolute path. The absolute path
92
- // is the load-bearing part: a relative one let xcodebuild create a `build`
93
- // directory inside each SPM package checkout in DerivedData, which fails
94
- // with "File exists but is not a directory" on repeated runs. That was
95
- // originally fixed by making CONFIGURATION_BUILD_DIR absolute; it is now
96
- // -derivedDataPath that is absolute instead, which fixes the same thing
97
- // without flattening the product tree.
98
- commands.push('');
99
- commands.push('# Create output directory and resolve to absolute path');
100
- commands.push(`mkdir -p '${this.escapeBash(outputDir)}'`);
101
- commands.push(`OUTPUT_DIR="$(cd '${this.escapeBash(outputDir)}' && pwd)"`);
102
- commands.push(...derivedDataPathLines());
103
- // Create xcconfig file if content provided
104
- if (xcconfigContent && xcconfigContent.trim() !== '') {
105
- commands.push('');
106
- commands.push('# Create custom xcconfig file');
107
- commands.push('XCCONFIG_FILE=".ci-custom.xcconfig"');
108
- commands.push('cat > "$XCCONFIG_FILE" << \'EOF\'');
109
- commands.push(xcconfigContent);
110
- commands.push('EOF');
111
- commands.push('echo "Custom xcconfig created"');
112
- }
113
- // Determine if workspace or project
114
- commands.push('');
115
- commands.push('# Determine project type');
116
- const escapedPath = this.escapeBash(projectPath);
117
- commands.push(`if [[ '${escapedPath}' == *.xcworkspace ]]; then`);
118
- commands.push(' PROJECT_TYPE="-workspace"');
119
- commands.push('else');
120
- commands.push(' PROJECT_TYPE="-project"');
121
- commands.push('fi');
122
- // Resolve the package graph before building, and retry that on a refused
123
- // fetch. Resolution is seconds and the build is minutes, so the retry is
124
- // spent on the cheap half. The two -derivedDataPath arguments move
125
- // together: the build below reads the same derived data and finds the
126
- // graph already resolved. Split them and the retry is spent on work the
127
- // build discards.
128
- commands.push('');
129
- commands.push('# Resolve package dependencies first — see git-fetch-retry');
130
- commands.push(...refusedFetchHelpers());
131
- commands.push(...retryOnRefusedFetch({
132
- label: 'Package resolution',
133
- command: 'xcodebuild -resolvePackageDependencies' +
134
- ` "$PROJECT_TYPE" '${escapedPath}'` +
135
- ` -scheme '${this.escapeBash(scheme)}'` +
136
- ' -derivedDataPath "$DERIVED_DATA_PATH"',
137
- }));
138
- // Build xcodebuild command
139
- commands.push('');
140
- commands.push('# Build xcodebuild command');
141
- let xcodebuildCmd = 'xcodebuild';
142
- // Add clean if requested
143
- if (isCleanBuild) {
144
- xcodebuildCmd += ' clean';
145
- }
146
- xcodebuildCmd += ' build';
147
- xcodebuildCmd += ` "$PROJECT_TYPE" '${escapedPath}'`;
148
- xcodebuildCmd += ` -scheme '${this.escapeBash(scheme)}'`;
149
- xcodebuildCmd += ` -configuration '${this.escapeBash(configuration)}'`;
150
- xcodebuildCmd += ` -destination '${this.escapeBash(destination)}'`;
151
- // A derived data path (see derivedDataPathLines), rather than CONFIGURATION_BUILD_DIR.
152
- // Same reasoning as XcodeBuildForSimulatorStepExecutor below, where the
153
- // full mechanism and the control are written up: the flat directory
154
- // collapses xcodebuild's per-configuration/per-platform product separation
155
- // and any graph with two tasks producing the same output name is refused
156
- // with "Multiple commands produce". It also desynchronises CocoaPods, whose
157
- // PODS_CONFIGURATION_BUILD_DIR follows BUILD_DIR and not this setting.
158
- xcodebuildCmd += ` -derivedDataPath "$DERIVED_DATA_PATH"`;
159
- // Add xcconfig if provided
160
- if (xcconfigContent && xcconfigContent.trim() !== '') {
161
- xcodebuildCmd += ' -xcconfig "$XCCONFIG_FILE"';
162
- }
163
- commands.push(xcodebuildCmd);
164
- // Show build results
165
- commands.push('');
166
- commands.push('# Build completed');
167
- commands.push('echo "Build completed successfully"');
168
- // Products live under the per-platform Products directory now, not flat in
169
- // $OUTPUT_DIR, so point the listing at where they actually are — otherwise
170
- // the log says "artifacts in build/" above an empty directory.
171
- commands.push('echo "Build artifacts in: $DERIVED_DATA_PATH/Build/Products"');
172
- commands.push('ls -lhR "$DERIVED_DATA_PATH/Build/Products" 2>/dev/null || true');
173
- const script = this.createBashScriptFromCommands(commands, stepName);
174
- return this.createScriptStep(script, stepName);
175
- }
176
- }
177
- /**
178
- * Xcode test step executor
179
- * Runs tests for iOS/macOS projects using xcodebuild test
180
- */
181
- export class XcodeTestStepExecutor extends BaseStepExecutor {
182
- getValidationRequirements(inputs, _env, _config) {
183
- const requirements = [];
184
- // xcodebuild command must exist
185
- requirements.push(this.requireCommand('xcodebuild', 'Xcode Command Line Tools are required for iOS tests', 'Install Xcode from the App Store, then run: xcode-select --install'));
186
- // Required inputs
187
- requirements.push(this.requireInput('project_path', inputs, 'Path to .xcodeproj or .xcworkspace', 'Provide project_path input in YAML'));
188
- requirements.push(this.requireInput('scheme', inputs, 'Xcode scheme name', 'Provide scheme input in YAML'));
189
- // Project file - runtime check only if it doesn't already exist locally
190
- if (inputs.project_path && !existsSync(inputs.project_path)) {
191
- requirements.push(this.runtimeRequirement(inputs.project_path, 'Xcode project/workspace file', 'file', 'the checkout'));
192
- }
193
- if (inputs.destination === 'auto') {
194
- requirements.push(this.requireCommand('xcrun', 'xcrun is required to resolve destination: auto via xcrun simctl', 'Install Xcode and run: xcode-select --install'));
195
- }
196
- return requirements;
197
- }
198
- async execute(inputs, env, config) {
199
- const stepName = 'xcode-test';
200
- // Get project path - required
201
- let projectPath = this.getRequiredInput(inputs, 'project_path', stepName);
202
- // Resolve path identifiers
203
- if (projectPath.startsWith('builds:')) {
204
- projectPath = projectPath.replace('builds:', `${config.paths.buildsDir}/`);
205
- }
206
- // Get scheme - required
207
- const scheme = this.getRequiredInput(inputs, 'scheme', stepName);
208
- // Get destination - defaults to platform=iOS Simulator.
209
- // `auto` triggers runtime resolution via `xcrun simctl`.
210
- const destination = resolveDestinationInput(this.getInput(inputs, 'destination', 'platform=iOS Simulator,name=iPhone 14,OS=latest'));
211
- // Get test plan - optional
212
- const testPlan = this.getInput(inputs, 'test_plan', '');
213
- // Get code coverage flag
214
- const isCodeCoverageEnabled = this.getInput(inputs, 'is_code_coverage_enabled', false);
215
- const commands = [];
216
- commands.push('# Xcode Test');
217
- commands.push(`echo "Testing project: ${this.escapeBash(projectPath)}"`);
218
- commands.push(`echo "Scheme: ${this.escapeBash(scheme)}"`);
219
- // Determine if workspace or project
220
- commands.push('');
221
- commands.push('# Determine project type');
222
- const escapedPath = this.escapeBash(projectPath);
223
- commands.push(`if [[ '${escapedPath}' == *.xcworkspace ]]; then`);
224
- commands.push(' PROJECT_TYPE="-workspace"');
225
- commands.push('else');
226
- commands.push(' PROJECT_TYPE="-project"');
227
- commands.push('fi');
228
- // Build xcodebuild test command
229
- commands.push('');
230
- commands.push('# Run tests');
231
- let xcodebuildCmd = 'xcodebuild test';
232
- xcodebuildCmd += ` "$PROJECT_TYPE" '${escapedPath}'`;
233
- xcodebuildCmd += ` -scheme '${this.escapeBash(scheme)}'`;
234
- xcodebuildCmd += ` -destination '${this.escapeBash(destination)}'`;
235
- // Add test plan if specified
236
- if (testPlan && testPlan.trim() !== '') {
237
- xcodebuildCmd += ` -testPlan '${this.escapeBash(testPlan)}'`;
238
- }
239
- // Add code coverage if enabled
240
- if (isCodeCoverageEnabled) {
241
- xcodebuildCmd += ' -enableCodeCoverage YES';
242
- }
243
- commands.push(xcodebuildCmd);
244
- // Show test results
245
- commands.push('');
246
- commands.push('# Tests completed');
247
- commands.push('echo "Tests completed successfully"');
248
- const script = this.createBashScriptFromCommands(commands, stepName);
249
- return this.createScriptStep(script, stepName);
250
- }
251
- }
252
- /**
253
- * xcode-archive step executor
254
- * Archives and exports an iOS app to IPA, mirroring bitrise xcode-archive@5.
255
- */
256
- export class XcodeArchiveStepExecutor extends BaseStepExecutor {
257
- getValidationRequirements(inputs, _env, _config) {
258
- const requirements = [];
259
- requirements.push(this.requireCommand('xcodebuild', 'Xcode Command Line Tools are required for iOS builds', 'Install Xcode from the App Store, then run: xcode-select --install'));
260
- requirements.push(this.requireInput('project_path', inputs, 'Path to .xcodeproj or .xcworkspace', 'Provide project_path input in YAML'));
261
- requirements.push(this.requireInput('scheme', inputs, 'Xcode scheme name', 'Provide scheme input in YAML'));
262
- // Project file - runtime check only if it doesn't already exist locally
263
- if (inputs.project_path && !existsSync(inputs.project_path)) {
264
- requirements.push(this.runtimeRequirement(inputs.project_path, 'Xcode project/workspace file', 'file', 'the checkout'));
265
- }
266
- return requirements;
267
- }
268
- getOutputs() {
269
- return [
270
- { name: 'CIBUILD_IPA_PATH', type: 'environment', description: 'Path to the exported IPA file' },
271
- { name: 'CIBUILD_XCARCHIVE_PATH', type: 'environment', description: 'Path to the generated .xcarchive' },
272
- { name: 'CIBUILD_DSYM_PATH', type: 'environment', description: 'Path to the zipped dSYM files' },
273
- { name: 'CIBUILD_APP_PATH', type: 'environment', description: 'Path to the .app inside the xcarchive (when code signing is off)' },
274
- ];
275
- }
276
- async execute(inputs, env, config) {
277
- const stepName = 'xcode-archive';
278
- let projectPath = this.getRequiredInput(inputs, 'project_path', stepName);
279
- if (projectPath.startsWith('builds:')) {
280
- projectPath = projectPath.replace('builds:', `${config.paths.buildsDir}/`);
281
- }
282
- const scheme = this.getRequiredInput(inputs, 'scheme', stepName);
283
- const configuration = this.getInput(inputs, 'configuration', 'Release');
284
- const platform = this.getInput(inputs, 'platform', 'iOS');
285
- const distributionMethod = this.getInput(inputs, 'distribution_method', 'development');
286
- const performClean = this.getInput(inputs, 'perform_clean_action', 'no');
287
- const compileBitcode = this.getInput(inputs, 'compile_bitcode', 'yes');
288
- const uploadBitcode = this.getInput(inputs, 'upload_bitcode', 'yes');
289
- const automaticCodeSigning = this.getInput(inputs, 'automatic_code_signing', 'off');
290
- const xcodebuildOptions = this.getInput(inputs, 'xcodebuild_options', '');
291
- const xcconfigContent = this.getInput(inputs, 'xcconfig_content', 'COMPILER_INDEX_STORE_ENABLE = NO');
292
- const exportOptionsPlistContent = this.getInput(inputs, 'export_options_plist_content', '');
293
- const signingStyleInput = this.getInput(inputs, 'signing_style', 'automatic');
294
- const provisioningProfilesInput = this.getInput(inputs, 'provisioning_profiles', '');
295
- const outputDir = this.getInput(inputs, 'output_dir', 'build/ipa');
296
- const artifactName = this.getInput(inputs, 'artifact_name', '');
297
- const escapedPath = this.escapeBash(projectPath);
298
- const escapedScheme = this.escapeBash(scheme);
299
- const escapedConfig = this.escapeBash(configuration);
300
- const commands = [];
301
- commands.push('# xcode-archive — archive and export iOS app to IPA');
302
- commands.push(`echo "Project: ${escapedPath}"`);
303
- commands.push(`echo "Scheme: ${escapedScheme}"`);
304
- commands.push(`echo "Configuration: ${escapedConfig}"`);
305
- commands.push(`echo "Distribution method: ${this.escapeBash(distributionMethod)}"`);
306
- commands.push('');
307
- // Determine project type
308
- commands.push('# Determine project type (-workspace vs -project)');
309
- commands.push(`if [[ '${escapedPath}' == *.xcworkspace ]]; then`);
310
- commands.push(' PROJECT_TYPE="-workspace"');
311
- commands.push('else');
312
- commands.push(' PROJECT_TYPE="-project"');
313
- commands.push('fi');
314
- commands.push('');
315
- // Derive artifact name
316
- if (artifactName) {
317
- commands.push(`ARTIFACT_NAME="${this.escapeBash(artifactName)}"`);
318
- }
319
- else {
320
- commands.push(`ARTIFACT_NAME="${escapedScheme}"`);
321
- }
322
- // Paths
323
- commands.push(`OUTPUT_DIR="${this.escapeBash(outputDir)}"`);
324
- commands.push('ARCHIVE_PATH="$OUTPUT_DIR/archive/${ARTIFACT_NAME}.xcarchive"');
325
- commands.push('mkdir -p "$(dirname "$ARCHIVE_PATH")"');
326
- commands.push('mkdir -p "$OUTPUT_DIR"');
327
- commands.push('');
328
- // Write xcconfig override
329
- commands.push('# Write xcconfig overrides');
330
- commands.push('XCCONFIG_PATH="$(mktemp -t cibuild-xcconfig).xcconfig"');
331
- // When automatic_code_signing is off (default), disable code signing so
332
- // archives succeed on CI without a development team / provisioning profile.
333
- let effectiveXcconfig = xcconfigContent.trim() || 'COMPILER_INDEX_STORE_ENABLE = NO';
334
- if (automaticCodeSigning === 'off') {
335
- effectiveXcconfig += '\nCODE_SIGNING_ALLOWED = NO';
336
- effectiveXcconfig += '\nCODE_SIGN_IDENTITY = -';
337
- }
338
- commands.push(`cat > "$XCCONFIG_PATH" << 'XCCONFIG_EOF'`);
339
- commands.push(effectiveXcconfig);
340
- commands.push('XCCONFIG_EOF');
341
- commands.push('');
342
- // Detect Apple API key for cloud-managed signing (xcodebuild
343
- // -allowProvisioningUpdates). When APPLE_API_KEY_ID/ISSUER_ID/KEY_PATH
344
- // are resolved by the env-resolver (from .cibuild-secrets.json or
345
- // CIBUILD_SW__* env vars), embed the .p8 into the generated script via
346
- // heredoc and bake the IDs as literals. Reading from $APPLE_API_KEY_ID
347
- // at script runtime would not work because cibuild's runner only
348
- // forwards process.env to spawned scripts, and EnvResolver-decoded
349
- // secrets live in its in-memory map, not process.env.
350
- let xcodeAuthFlags = '';
351
- if (automaticCodeSigning !== 'off') {
352
- const apiKeyId = (env['APPLE_API_KEY_ID'] || '').trim();
353
- const apiIssuerId = (env['APPLE_API_ISSUER_ID'] || '').trim();
354
- const apiKeySecret = env['APPLE_API_KEY_PATH'] || '';
355
- // Secret may be raw PEM (`-----BEGIN PRIVATE KEY-----…`) or base64-encoded.
356
- let p8Pem = '';
357
- if (apiKeySecret) {
358
- if (apiKeySecret.trimStart().startsWith('-----BEGIN')) {
359
- p8Pem = apiKeySecret;
360
- }
361
- else {
362
- try {
363
- p8Pem = Buffer.from(apiKeySecret, 'base64').toString('utf-8');
364
- }
365
- catch {
366
- p8Pem = '';
367
- }
368
- }
369
- }
370
- const p8LooksValid = p8Pem.includes('-----BEGIN') && p8Pem.includes('PRIVATE KEY');
371
- if (apiKeyId && apiIssuerId && p8LooksValid) {
372
- commands.push('# Apple API key resolved — embedding for cloud-managed signing');
373
- // BSD/macOS mktemp requires X's at the end of the template; any chars
374
- // after them are literal and not substituted. Don't add a .p8 suffix.
375
- commands.push('API_KEY_TEMP_FILE="$(mktemp /tmp/cibuild-api-key.XXXXXX)"');
376
- commands.push(`trap 'rm -f "$API_KEY_TEMP_FILE"' EXIT`);
377
- // Quoted heredoc so the PEM body isn't subject to shell expansion.
378
- commands.push(`cat > "$API_KEY_TEMP_FILE" << 'CIBUILD_API_KEY_EOF'`);
379
- commands.push(p8Pem.replace(/\r\n/g, '\n').replace(/\n+$/, ''));
380
- commands.push('CIBUILD_API_KEY_EOF');
381
- commands.push('echo "✓ Cloud-managed signing enabled (API key: '
382
- + this.escapeBash(apiKeyId) + ')"');
383
- commands.push('');
384
- // Build a bash-syntax fragment that gets concatenated directly into
385
- // the archive/export command lines. Single quotes here are real shell
386
- // quotes (consumed by bash) — unlike the previous approach that put
387
- // them inside a doubly-quoted variable assignment, where they would
388
- // become literal characters in the value.
389
- xcodeAuthFlags =
390
- ` -allowProvisioningUpdates` +
391
- ` -authenticationKeyPath "$API_KEY_TEMP_FILE"` +
392
- ` -authenticationKeyID '${this.escapeBash(apiKeyId)}'` +
393
- ` -authenticationKeyIssuerID '${this.escapeBash(apiIssuerId)}'`;
394
- }
395
- }
396
- // Build xcodebuild archive command
397
- commands.push('# Run xcodebuild archive');
398
- let archiveCmd = 'xcodebuild';
399
- if (performClean === 'yes')
400
- archiveCmd += ' clean';
401
- archiveCmd += ' archive';
402
- archiveCmd += ` "$PROJECT_TYPE" '${escapedPath}'`;
403
- archiveCmd += ` -scheme '${escapedScheme}'`;
404
- archiveCmd += ` -configuration '${escapedConfig}'`;
405
- archiveCmd += ` -destination 'generic/platform=${this.escapeBash(platform)}'`;
406
- archiveCmd += ' -archivePath "$ARCHIVE_PATH"';
407
- archiveCmd += ' -xcconfig "$XCCONFIG_PATH"';
408
- // When code signing is off, also pass settings as command-line build
409
- // settings so they take highest priority and override any target-level
410
- // signing configuration in the Xcode project.
411
- if (automaticCodeSigning === 'off') {
412
- archiveCmd += ' CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO';
413
- }
414
- else {
415
- archiveCmd += xcodeAuthFlags;
416
- // Don't override CODE_SIGN_IDENTITY here. Xcode 26.3+ rejects an explicit
417
- // identity when the project is configured for automatic signing
418
- // ("conflicting provisioning settings" at GatherProvisioningInputs).
419
- // Archive with the project's automatic identity (Development); the
420
- // exportArchive step re-signs with Distribution via exportOptionsPlist
421
- // (method=app-store + signingStyle=automatic), mirroring Xcode IDE's
422
- // Archive → Distribute flow. DEVELOPMENT_TEAM is still injected so SPM
423
- // frameworks without an explicit team in Package.swift can sign.
424
- const teamId = (env['APPLE_TEAM_ID'] || '').trim();
425
- if (teamId) {
426
- archiveCmd += ` DEVELOPMENT_TEAM='${this.escapeBash(teamId)}'`;
427
- }
428
- }
429
- if (xcodebuildOptions) {
430
- archiveCmd += ` ${xcodebuildOptions}`;
431
- }
432
- commands.push(archiveCmd);
433
- commands.push('');
434
- commands.push('echo "✓ Archive created: $ARCHIVE_PATH"');
435
- commands.push('');
436
- // Write output env var helper (used in both signing and non-signing paths)
437
- commands.push('# Export output environment variables');
438
- commands.push('ENVSTORE_FILE="${ENVMAN_ENVSTORE_PATH:-.ci/.envstore.json}"');
439
- commands.push('export_env() {');
440
- commands.push(' local key="$1" val="$2"');
441
- commands.push(' if [ -f "$ENVSTORE_FILE" ]; then');
442
- commands.push(' node -e "');
443
- commands.push(' const fs=require(\'fs\');');
444
- commands.push(' const s=JSON.parse(fs.readFileSync(process.argv[1],\'utf-8\'));');
445
- commands.push(' s.envs=s.envs||[];');
446
- commands.push(' s.envs=s.envs.filter(e=>e.key!==process.argv[2]);');
447
- commands.push(' s.envs.push({key:process.argv[2],value:process.argv[3]});');
448
- commands.push(' fs.writeFileSync(process.argv[1],JSON.stringify(s));');
449
- commands.push(' " "$ENVSTORE_FILE" "$key" "$val" 2>/dev/null || true');
450
- commands.push(' fi');
451
- commands.push(' export "$key=$val"');
452
- commands.push(' echo " $key=$val"');
453
- commands.push('}');
454
- commands.push('');
455
- if (automaticCodeSigning === 'off') {
456
- // Signing is disabled — skip IPA export (unsigned archives cannot be exported).
457
- // Output the xcarchive path and the .app inside it instead.
458
- commands.push('# Code signing disabled — export xcarchive path only');
459
- commands.push('export_env CIBUILD_XCARCHIVE_PATH "$(pwd)/$ARCHIVE_PATH"');
460
- commands.push('');
461
- commands.push('# Locate .app inside the xcarchive for downstream use');
462
- commands.push('APP_PATH=$(find "$ARCHIVE_PATH/Products" -name "*.app" -maxdepth 3 2>/dev/null | head -1 || true)');
463
- commands.push('[ -n "$APP_PATH" ] && export_env CIBUILD_APP_PATH "$(pwd)/$APP_PATH" || true');
464
- commands.push('');
465
- commands.push('echo "✓ xcode-archive complete (unsigned — code signing disabled)"');
466
- }
467
- else {
468
- // Signing enabled — generate ExportOptions.plist and export to IPA
469
- commands.push('# Generate ExportOptions.plist');
470
- commands.push('EXPORT_PLIST="$(mktemp -t ExportOptions).plist"');
471
- if (exportOptionsPlistContent.trim()) {
472
- commands.push(`cat > "$EXPORT_PLIST" << 'PLIST_EOF'`);
473
- commands.push(exportOptionsPlistContent);
474
- commands.push('PLIST_EOF');
475
- }
476
- else {
477
- // Map deprecated "development" method name to "debugging" (Apple renamed it in Xcode 15)
478
- const exportMethod = distributionMethod === 'development' ? 'debugging' : distributionMethod;
479
- const compileBitcodeVal = compileBitcode === 'yes' ? 'true' : 'false';
480
- const uploadBitcodeVal = uploadBitcode === 'yes' ? 'true' : 'false';
481
- const signingStyle = signingStyleInput === 'manual' ? 'manual' : 'automatic';
482
- // Parse provisioning_profiles input: each non-empty line is `bundleId=ProfileName`.
483
- // Lines starting with # are treated as comments. Whitespace is trimmed.
484
- const profileEntries = [];
485
- if (signingStyle === 'manual' && provisioningProfilesInput.trim()) {
486
- for (const rawLine of provisioningProfilesInput.split('\n')) {
487
- const line = rawLine.trim();
488
- if (!line || line.startsWith('#'))
489
- continue;
490
- const eq = line.indexOf('=');
491
- if (eq === -1)
492
- continue;
493
- const bundleId = line.slice(0, eq).trim();
494
- const profile = line.slice(eq + 1).trim();
495
- if (bundleId && profile)
496
- profileEntries.push({ bundleId, profile });
497
- }
498
- }
499
- if (signingStyle === 'manual') {
500
- if (profileEntries.length === 0) {
501
- throw new Error(`xcode-archive: signing_style=manual requires provisioning_profiles input ` +
502
- `(newline-separated 'bundleId=ProfileName' pairs).`);
503
- }
504
- // Manual export needs APPLE_TEAM_ID at runtime — fail fast with a clear message.
505
- commands.push('# signing_style=manual — verify APPLE_TEAM_ID is available');
506
- commands.push('if [ -z "${APPLE_TEAM_ID:-}" ]; then');
507
- commands.push(' echo "❌ Error: signing_style=manual requires APPLE_TEAM_ID env var." >&2');
508
- commands.push(' echo " Set via: ci secrets add APPLE_TEAM_ID -w <workflow>" >&2');
509
- commands.push(' exit 1');
510
- commands.push('fi');
511
- commands.push('');
512
- }
513
- // Manual mode references ${APPLE_TEAM_ID}, which requires an *unquoted* heredoc
514
- // delimiter so bash performs variable expansion. Automatic mode uses single-quoted
515
- // delimiter so the plist content is preserved literally.
516
- const heredocOpen = signingStyle === 'manual'
517
- ? `cat > "$EXPORT_PLIST" << PLIST_EOF`
518
- : `cat > "$EXPORT_PLIST" << 'PLIST_EOF'`;
519
- commands.push(heredocOpen);
520
- commands.push('<?xml version="1.0" encoding="UTF-8"?>');
521
- commands.push('<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">');
522
- commands.push('<plist version="1.0">');
523
- commands.push('<dict>');
524
- commands.push(' <key>method</key>');
525
- commands.push(` <string>${exportMethod}</string>`);
526
- commands.push(' <key>signingStyle</key>');
527
- commands.push(` <string>${signingStyle}</string>`);
528
- if (signingStyle === 'manual') {
529
- commands.push(' <key>teamID</key>');
530
- commands.push(' <string>${APPLE_TEAM_ID}</string>');
531
- commands.push(' <key>provisioningProfiles</key>');
532
- commands.push(' <dict>');
533
- for (const { bundleId, profile } of profileEntries) {
534
- commands.push(` <key>${bundleId}</key>`);
535
- commands.push(` <string>${profile}</string>`);
536
- }
537
- commands.push(' </dict>');
538
- }
539
- if (exportMethod !== 'app-store') {
540
- commands.push(' <key>compileBitcode</key>');
541
- commands.push(` <${compileBitcodeVal}/>`);
542
- }
543
- if (exportMethod === 'app-store') {
544
- commands.push(' <key>uploadBitcode</key>');
545
- commands.push(` <${uploadBitcodeVal}/>`);
546
- }
547
- commands.push('</dict>');
548
- commands.push('</plist>');
549
- commands.push('PLIST_EOF');
550
- }
551
- commands.push('');
552
- // Export archive to IPA
553
- commands.push('# Export archive to IPA');
554
- let exportCmd = 'xcodebuild -exportArchive';
555
- exportCmd += ' -archivePath "$ARCHIVE_PATH"';
556
- exportCmd += ' -exportOptionsPlist "$EXPORT_PLIST"';
557
- exportCmd += ' -exportPath "$OUTPUT_DIR"';
558
- exportCmd += xcodeAuthFlags;
559
- commands.push(exportCmd);
560
- commands.push('');
561
- // Locate generated IPA
562
- commands.push('# Locate generated IPA and export paths');
563
- commands.push('IPA_PATH=$(find "$OUTPUT_DIR" -name "*.ipa" | head -1)');
564
- commands.push('DSYM_PATH=$(find "$OUTPUT_DIR" -name "*.dSYM.zip" 2>/dev/null | head -1 || true)');
565
- commands.push('');
566
- commands.push('if [ -z "$IPA_PATH" ]; then');
567
- commands.push(' echo "Error: IPA not found in $OUTPUT_DIR" >&2');
568
- commands.push(' exit 1');
569
- commands.push('fi');
570
- commands.push('');
571
- commands.push('echo "✓ IPA created: $IPA_PATH"');
572
- commands.push('ls -lh "$IPA_PATH"');
573
- commands.push('');
574
- commands.push('export_env CIBUILD_IPA_PATH "$IPA_PATH"');
575
- commands.push('export_env CIBUILD_XCARCHIVE_PATH "$(pwd)/$ARCHIVE_PATH"');
576
- commands.push('[ -n "$DSYM_PATH" ] && export_env CIBUILD_DSYM_PATH "$DSYM_PATH" || true');
577
- commands.push('');
578
- commands.push('echo "✓ xcode-archive complete"');
579
- commands.push('rm -f "$EXPORT_PLIST"');
580
- }
581
- commands.push('rm -f "$XCCONFIG_PATH"');
582
- const script = this.createBashScriptFromCommands(commands, stepName);
583
- return this.createScriptStep(script, stepName);
584
- }
585
- }
586
- /**
587
- * iOS Archive step executor
588
- * Creates an IPA file from a .app bundle
589
- */
590
- export class IosArchiveStepExecutor extends BaseStepExecutor {
591
- getValidationRequirements(inputs, _env, _config) {
592
- const requirements = [];
593
- // Required input
594
- requirements.push(this.requireInput('app_path', inputs, 'Path to .app bundle', 'Provide app_path input pointing to your built .app file'));
595
- // zip command for creating IPA
596
- requirements.push(this.requireCommand('zip', 'zip utility for creating IPA files', 'zip should be pre-installed on macOS'));
597
- // .app file - runtime check (created by xcodebuild)
598
- if (inputs.app_path) {
599
- requirements.push(this.runtimeRequirement(inputs.app_path, '.app bundle file', 'directory', 'xcodebuild'));
600
- }
601
- return requirements;
602
- }
603
- async execute(inputs, env, config) {
604
- const stepName = 'ios-archive';
605
- // Get app path - required
606
- let appPath = this.getRequiredInput(inputs, 'app_path', stepName);
607
- // Resolve path identifiers
608
- if (appPath.startsWith('builds:')) {
609
- appPath = appPath.replace('builds:', `${config.paths.buildsDir}/`);
610
- }
611
- // Get output path - defaults to artifacts/
612
- const outputPath = this.getInput(inputs, 'output_path', 'artifacts');
613
- // Get output name - optional, will derive from .app name if not provided
614
- const outputName = this.getInput(inputs, 'output_name', '');
615
- const commands = [];
616
- commands.push('# iOS Archive - Create IPA');
617
- commands.push(`echo "Creating IPA from: ${this.escapeBash(appPath)}"`);
618
- // Check if .app exists
619
- commands.push('');
620
- commands.push('# Verify .app bundle exists');
621
- commands.push(`if [ ! -d '${this.escapeBash(appPath)}' ]; then`);
622
- commands.push(` echo "Error: .app bundle not found at ${this.escapeBash(appPath)}"`);
623
- commands.push(' exit 1');
624
- commands.push('fi');
625
- // Determine output IPA name
626
- commands.push('');
627
- commands.push('# Determine IPA name');
628
- if (outputName && outputName.trim() !== '') {
629
- // Use provided name
630
- const cleanName = outputName.replace(/\.ipa$/, '');
631
- commands.push(`IPA_NAME="${this.escapeBash(cleanName)}"`);
632
- }
633
- else {
634
- // Derive from .app bundle name
635
- commands.push(`APP_BUNDLE='${this.escapeBash(appPath)}'`);
636
- commands.push('IPA_NAME=$(basename "$APP_BUNDLE" .app)');
637
- }
638
- commands.push('echo "IPA name: $IPA_NAME.ipa"');
639
- // Create IPA
640
- commands.push('');
641
- commands.push('# Create IPA structure');
642
- commands.push('TEMP_DIR=$(mktemp -d)');
643
- commands.push('mkdir -p "$TEMP_DIR/Payload"');
644
- commands.push('');
645
- commands.push('# Copy .app to Payload directory');
646
- commands.push(`cp -r '${this.escapeBash(appPath)}' "$TEMP_DIR/Payload/"`);
647
- commands.push('');
648
- commands.push('# Create IPA (zip with .ipa extension)');
649
- commands.push('cd "$TEMP_DIR"');
650
- commands.push(`zip -r "$IPA_NAME.ipa" Payload -q`);
651
- commands.push('cd - > /dev/null');
652
- commands.push('');
653
- commands.push('# Create output directory and move IPA');
654
- commands.push(`mkdir -p '${this.escapeBash(outputPath)}'`);
655
- commands.push(`mv "$TEMP_DIR/$IPA_NAME.ipa" '${this.escapeBash(outputPath)}/'`);
656
- commands.push('');
657
- commands.push('# Cleanup temp directory');
658
- commands.push('rm -rf "$TEMP_DIR"');
659
- commands.push('');
660
- commands.push('# Show result');
661
- commands.push('echo "✓ IPA created successfully"');
662
- commands.push(`ls -lh '${this.escapeBash(outputPath)}'/"$IPA_NAME.ipa"`);
663
- const script = this.createBashScriptFromCommands(commands, stepName);
664
- return this.createScriptStep(script, stepName);
665
- }
666
- }
667
- /**
668
- * OTA install step executor.
669
- * Generates manifest.plist and a QR code for itms-services:// OTA installation.
670
- * The IPA and manifest must be hosted at user-provided HTTPS URLs.
671
- */
672
- export class OtaInstallStepExecutor extends BaseStepExecutor {
673
- getValidationRequirements(inputs, _env, _config) {
674
- return [
675
- this.requireInput('ipa_url', inputs, 'HTTPS URL where the IPA file will be hosted', 'Provide the full HTTPS URL to where the IPA will be uploaded'),
676
- this.requireInput('bundle_id', inputs, 'iOS bundle identifier (e.g. com.example.app)'),
677
- this.requireInput('bundle_version', inputs, 'App version string (e.g. 1.2.3)'),
678
- this.requireInput('title', inputs, 'App display name shown during install'),
679
- ];
680
- }
681
- getOutputs() {
682
- return [
683
- {
684
- name: 'CIBUILD_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL',
685
- type: 'environment',
686
- description: 'QR code image URL for the OTA install page (api.qrserver.com link)',
687
- },
688
- ];
689
- }
690
- async execute(inputs, _env, _config) {
691
- const stepName = 'ota-install';
692
- const ipaUrl = this.getRequiredInput(inputs, 'ipa_url', stepName);
693
- const bundleId = this.getRequiredInput(inputs, 'bundle_id', stepName);
694
- const bundleVersion = this.getRequiredInput(inputs, 'bundle_version', stepName);
695
- const title = this.getRequiredInput(inputs, 'title', stepName);
696
- const outputDir = this.getInput(inputs, 'output_dir', '.ci/artifacts');
697
- const manifestUrlInput = this.getInput(inputs, 'manifest_url', '');
698
- const escapedIpaUrl = this.escapeBash(ipaUrl);
699
- const escapedBundleId = this.escapeBash(bundleId);
700
- const escapedBundleVersion = this.escapeBash(bundleVersion);
701
- const escapedTitle = this.escapeBash(title);
702
- const escapedOutputDir = this.escapeBash(outputDir);
703
- const commands = [];
704
- commands.push('# ota-install — generate OTA manifest + QR code');
705
- commands.push(`IPA_URL='${escapedIpaUrl}'`);
706
- commands.push(`BUNDLE_ID='${escapedBundleId}'`);
707
- commands.push(`BUNDLE_VERSION='${escapedBundleVersion}'`);
708
- commands.push(`TITLE='${escapedTitle}'`);
709
- commands.push(`OUTPUT_DIR='${escapedOutputDir}'`);
710
- commands.push('');
711
- // Derive manifest URL if not provided
712
- if (manifestUrlInput.trim()) {
713
- commands.push(`MANIFEST_URL='${this.escapeBash(manifestUrlInput)}'`);
714
- }
715
- else {
716
- commands.push('# Derive manifest URL from IPA URL (same directory, manifest.plist filename)');
717
- commands.push('MANIFEST_URL="$(dirname "$IPA_URL")/manifest.plist"');
718
- }
719
- commands.push('');
720
- // Build OTA link
721
- commands.push('OTA_URL="itms-services://?action=download-manifest&url=${MANIFEST_URL}"');
722
- commands.push('');
723
- // Create output dir and write manifest.plist
724
- commands.push('mkdir -p "$OUTPUT_DIR"');
725
- commands.push('');
726
- commands.push('# Write manifest.plist');
727
- commands.push('cat > "$OUTPUT_DIR/manifest.plist" << PLIST_EOF');
728
- commands.push('<?xml version="1.0" encoding="UTF-8"?>');
729
- commands.push('<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">');
730
- commands.push('<plist version="1.0">');
731
- commands.push('<dict>');
732
- commands.push(' <key>items</key>');
733
- commands.push(' <array>');
734
- commands.push(' <dict>');
735
- commands.push(' <key>assets</key>');
736
- commands.push(' <array>');
737
- commands.push(' <dict>');
738
- commands.push(' <key>kind</key><string>software-package</string>');
739
- commands.push(' <key>url</key><string>${IPA_URL}</string>');
740
- commands.push(' </dict>');
741
- commands.push(' </array>');
742
- commands.push(' <key>metadata</key>');
743
- commands.push(' <dict>');
744
- commands.push(' <key>bundle-identifier</key><string>${BUNDLE_ID}</string>');
745
- commands.push(' <key>bundle-version</key><string>${BUNDLE_VERSION}</string>');
746
- commands.push(' <key>kind</key><string>software</string>');
747
- commands.push(' <key>title</key><string>${TITLE}</string>');
748
- commands.push(' </dict>');
749
- commands.push(' </dict>');
750
- commands.push(' </array>');
751
- commands.push('</dict>');
752
- commands.push('</plist>');
753
- commands.push('PLIST_EOF');
754
- commands.push('');
755
- commands.push('echo "✓ manifest.plist written to $OUTPUT_DIR/manifest.plist"');
756
- commands.push('');
757
- // Generate QR code (qrencode preferred; graceful fallback)
758
- commands.push('# Generate QR code');
759
- commands.push('if command -v qrencode &>/dev/null; then');
760
- commands.push(' echo ""');
761
- commands.push(' echo "Scan to install:"');
762
- commands.push(' qrencode -t ansiutf8 "$OTA_URL"');
763
- commands.push('else');
764
- commands.push(' echo "ℹ Install qrencode for terminal QR: brew install qrencode"');
765
- commands.push('fi');
766
- commands.push('');
767
- // Print summary
768
- commands.push('echo ""');
769
- commands.push('echo "─────────────────────────────────────────"');
770
- commands.push('echo "OTA Install Summary"');
771
- commands.push('echo "─────────────────────────────────────────"');
772
- commands.push('echo "IPA URL: $IPA_URL"');
773
- commands.push('echo "Manifest URL: $MANIFEST_URL"');
774
- commands.push('echo "OTA Link: $OTA_URL"');
775
- commands.push('echo ""');
776
- commands.push('echo "Host the IPA and manifest.plist at the URLs above, then share the OTA link."');
777
- commands.push('echo "─────────────────────────────────────────"');
778
- commands.push('');
779
- // Export QR image URL to envstore (api.qrserver.com image link, usable in notifications)
780
- commands.push('# Export QR image URL to envstore for downstream steps (e.g. Slack notifications)');
781
- commands.push('ENCODED_OTA="$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$OTA_URL" 2>/dev/null || printf "%s" "$OTA_URL" | sed \'s/ /%20/g; s/:/%3A/g; s|/|%2F|g; s/?/%3F/g; s/=/%3D/g; s/&/%26/g\')"');
782
- commands.push('QR_IMAGE_URL="https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${ENCODED_OTA}"');
783
- commands.push('');
784
- commands.push('ENVSTORE_FILE="${ENVMAN_ENVSTORE_PATH:-.ci/.envstore.json}"');
785
- commands.push('if [ -f "$ENVSTORE_FILE" ]; then');
786
- commands.push(' node -e "');
787
- commands.push(' const fs=require(\'fs\');');
788
- commands.push(' const s=JSON.parse(fs.readFileSync(process.argv[1],\'utf-8\'));');
789
- commands.push(' s.envs=s.envs||[];');
790
- commands.push(' s.envs=s.envs.filter(e=>e.key!==\'CIBUILD_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL\');');
791
- commands.push(' s.envs.push({key:\'CIBUILD_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL\',value:process.argv[2]});');
792
- commands.push(' fs.writeFileSync(process.argv[1],JSON.stringify(s));');
793
- commands.push(' " "$ENVSTORE_FILE" "$QR_IMAGE_URL" 2>/dev/null || true');
794
- commands.push('fi');
795
- commands.push('export CIBUILD_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL="$QR_IMAGE_URL"');
796
- const script = this.createBashScriptFromCommands(commands, stepName);
797
- return this.createScriptStep(script, stepName);
798
- }
799
- }
800
- /**
801
- * Builds the app and tests without executing them.
802
- * Produces an .xctestrun file for use with xcode-test-without-building.
803
- */
804
- export class XcodeBuildForTestStepExecutor extends BaseStepExecutor {
805
- getValidationRequirements(inputs, _env, _config) {
806
- const requirements = [];
807
- requirements.push(this.requireCommand('xcodebuild', 'Xcode Command Line Tools are required', 'Install Xcode, then run: xcode-select --install'));
808
- requirements.push(this.requireInput('project_path', inputs, 'Path to .xcodeproj or .xcworkspace'));
809
- requirements.push(this.requireInput('scheme', inputs, 'Xcode scheme name'));
810
- if (inputs.project_path && !existsSync(inputs.project_path)) {
811
- requirements.push(this.runtimeRequirement(inputs.project_path, 'Xcode project/workspace file', 'file', 'the checkout'));
812
- }
813
- if (inputs.destination === 'auto') {
814
- requirements.push(this.requireCommand('xcrun', 'xcrun is required to resolve destination: auto via xcrun simctl', 'Install Xcode and run: xcode-select --install'));
815
- }
816
- return requirements;
817
- }
818
- getOutputs() {
819
- return [
820
- { name: 'CIBUILD_TEST_BUNDLE_PATH', type: 'environment', description: 'Directory containing the built test bundle' },
821
- { name: 'CIBUILD_XCTESTRUN_FILE_PATH', type: 'environment', description: 'Path to the generated .xctestrun file' },
822
- ];
823
- }
824
- async execute(inputs, _env, _config) {
825
- const stepName = 'xcode-build-for-test';
826
- const projectPath = this.getRequiredInput(inputs, 'project_path', stepName);
827
- const scheme = this.getRequiredInput(inputs, 'scheme', stepName);
828
- const configuration = this.getInput(inputs, 'configuration', 'Debug');
829
- // `auto` triggers runtime resolution via `xcrun simctl`.
830
- const destination = resolveDestinationInput(this.getInput(inputs, 'destination', 'generic/platform=iOS Simulator'));
831
- const testPlan = this.getInput(inputs, 'test_plan', '');
832
- const xcconfigContent = this.getInput(inputs, 'xcconfig_content', '');
833
- const xcodebuildOptions = this.getInput(inputs, 'xcodebuild_options', '');
834
- const outputDir = this.getInput(inputs, 'output_dir', 'build');
835
- const escapedPath = this.escapeBash(projectPath);
836
- const escapedScheme = this.escapeBash(scheme);
837
- const commands = [];
838
- commands.push('# xcode-build-for-test — build-for-testing');
839
- commands.push(`echo "Building for testing: ${escapedPath}"`);
840
- commands.push(`echo "Scheme: ${escapedScheme}"`);
841
- commands.push('');
842
- // Output directory
843
- commands.push(`mkdir -p '${this.escapeBash(outputDir)}'`);
844
- commands.push(`OUTPUT_DIR="$(cd '${this.escapeBash(outputDir)}' && pwd)"`);
845
- commands.push(...derivedDataPathLines());
846
- commands.push('');
847
- // xcconfig
848
- if (xcconfigContent.trim()) {
849
- commands.push('XCCONFIG_FILE="$(mktemp -t cibuild-xcconfig).xcconfig"');
850
- commands.push(`cat > "$XCCONFIG_FILE" << 'XCCONFIG_EOF'`);
851
- commands.push(xcconfigContent);
852
- commands.push('XCCONFIG_EOF');
853
- commands.push('');
854
- }
855
- // Determine project type
856
- commands.push(`if [[ '${escapedPath}' == *.xcworkspace ]]; then`);
857
- commands.push(' PROJECT_TYPE="-workspace"');
858
- commands.push('else');
859
- commands.push(' PROJECT_TYPE="-project"');
860
- commands.push('fi');
861
- commands.push('');
862
- // Resolve the package graph on its own, ahead of the build, so a refused
863
- // fetch costs a retry of something that takes seconds rather than a re-run
864
- // of build-for-testing, which takes minutes. The build that follows reads
865
- // the same derived data and finds the graph already resolved.
866
- commands.push('# Resolve package dependencies first — see git-fetch-retry');
867
- commands.push(...refusedFetchHelpers());
868
- commands.push(...retryOnRefusedFetch({
869
- label: 'Package resolution',
870
- command: 'xcodebuild -resolvePackageDependencies' +
871
- ` "$PROJECT_TYPE" '${escapedPath}'` +
872
- ` -scheme '${escapedScheme}'` +
873
- ' -derivedDataPath "$DERIVED_DATA_PATH"',
874
- }));
875
- const pinsArm64 = pinsSimulatorArm64(xcodebuildOptions);
876
- if (pinsArm64) {
877
- commands.push(...simulatorArchsLines({
878
- projectPath: escapedPath,
879
- scheme: escapedScheme,
880
- configuration: this.escapeBash(configuration),
881
- destination: this.escapeBash(destination),
882
- xcconfig: Boolean(xcconfigContent.trim()),
883
- }));
884
- }
885
- // Build command
886
- let cmd = 'xcodebuild build-for-testing';
887
- cmd += ` "$PROJECT_TYPE" '${escapedPath}'`;
888
- cmd += ` -scheme '${escapedScheme}'`;
889
- cmd += ` -configuration '${this.escapeBash(configuration)}'`;
890
- cmd += ` -destination '${this.escapeBash(destination)}'`;
891
- cmd += ` -derivedDataPath "$DERIVED_DATA_PATH"`;
892
- if (testPlan) {
893
- cmd += ` -testPlan '${this.escapeBash(testPlan)}'`;
894
- }
895
- if (xcconfigContent.trim()) {
896
- cmd += ' -xcconfig "$XCCONFIG_FILE"';
897
- }
898
- if (xcodebuildOptions) {
899
- cmd += ` ${pinsArm64 ? withRuntimeSimulatorArchs(xcodebuildOptions) : xcodebuildOptions}`;
900
- }
901
- commands.push(cmd);
902
- commands.push('');
903
- // Locate .xctestrun file
904
- commands.push('# Locate generated .xctestrun file');
905
- commands.push('XCTESTRUN_PATH=$(find "$DERIVED_DATA_PATH/Build/Products" -name "*.xctestrun" | head -1)');
906
- commands.push('if [ -z "$XCTESTRUN_PATH" ]; then');
907
- commands.push(' echo "❌ Error: .xctestrun file not found"');
908
- commands.push(' exit 1');
909
- commands.push('fi');
910
- commands.push('');
911
- commands.push('TEST_BUNDLE_DIR="$(dirname "$XCTESTRUN_PATH")"');
912
- commands.push('echo "✅ Build for testing complete"');
913
- commands.push('echo "xctestrun: $XCTESTRUN_PATH"');
914
- commands.push('');
915
- // Export env vars
916
- commands.push('envman add --key CIBUILD_TEST_BUNDLE_PATH --value "$TEST_BUNDLE_DIR"');
917
- commands.push('envman add --key CIBUILD_XCTESTRUN_FILE_PATH --value "$XCTESTRUN_PATH"');
918
- if (xcconfigContent.trim()) {
919
- commands.push('rm -f "$XCCONFIG_FILE"');
920
- }
921
- const script = this.createBashScriptFromCommands(commands, stepName);
922
- return this.createScriptStep(script, stepName);
923
- }
924
- }
925
- /**
926
- * Runs pre-compiled tests from an .xctestrun file.
927
- */
928
- export class XcodeTestWithoutBuildingStepExecutor extends BaseStepExecutor {
929
- getValidationRequirements(inputs, _env, _config) {
930
- const requirements = [
931
- this.requireCommand('xcodebuild', 'Xcode Command Line Tools are required', 'Install Xcode, then run: xcode-select --install'),
932
- ];
933
- if (inputs.destination === 'auto') {
934
- requirements.push(this.requireCommand('xcrun', 'xcrun is required to resolve destination: auto via xcrun simctl', 'Install Xcode and run: xcode-select --install'));
935
- }
936
- return requirements;
937
- }
938
- getOutputs() {
939
- return [
940
- { name: 'CIBUILD_XCRESULT_PATH', type: 'environment', description: 'Path to the .xcresult test result bundle' },
941
- ];
942
- }
943
- async execute(inputs, _env, _config) {
944
- const stepName = 'xcode-test-without-building';
945
- const xctestrun = this.getInput(inputs, 'xctestrun', '$CIBUILD_XCTESTRUN_FILE_PATH');
946
- // `auto` triggers runtime resolution via `xcrun simctl`.
947
- const destination = resolveDestinationInput(this.getInput(inputs, 'destination', 'platform=iOS Simulator,name=iPhone 15,OS=latest'));
948
- const onlyTesting = this.getInput(inputs, 'only_testing', '');
949
- const skipTesting = this.getInput(inputs, 'skip_testing', '');
950
- const repetitionMode = this.getInput(inputs, 'test_repetition_mode', 'none');
951
- const maxRepetitions = this.getInput(inputs, 'maximum_test_repetitions', '3');
952
- const xcodebuildOptions = this.getInput(inputs, 'xcodebuild_options', '');
953
- const commands = [];
954
- commands.push('# xcode-test-without-building');
955
- commands.push('echo "Running pre-built tests..."');
956
- commands.push('');
957
- // Resolve xctestrun path
958
- commands.push(`XCTESTRUN_FILE="${xctestrun}"`);
959
- commands.push('if [ -z "$XCTESTRUN_FILE" ]; then');
960
- commands.push(' echo "❌ Error: xctestrun file path is empty. Run xcode-build-for-test first."');
961
- commands.push(' exit 1');
962
- commands.push('fi');
963
- commands.push('if [ ! -f "$XCTESTRUN_FILE" ]; then');
964
- commands.push(' echo "❌ Error: xctestrun file not found: $XCTESTRUN_FILE"');
965
- commands.push(' exit 1');
966
- commands.push('fi');
967
- commands.push('echo "xctestrun: $XCTESTRUN_FILE"');
968
- commands.push('');
969
- // Result bundle path
970
- commands.push('RESULT_BUNDLE_PATH="build/test-results/$(date +%Y%m%d_%H%M%S).xcresult"');
971
- commands.push('mkdir -p "$(dirname "$RESULT_BUNDLE_PATH")"');
972
- commands.push('');
973
- // Build command
974
- let cmd = 'xcodebuild test-without-building';
975
- cmd += ' -xctestrun "$XCTESTRUN_FILE"';
976
- cmd += ` -destination '${this.escapeBash(destination)}'`;
977
- cmd += ' -resultBundlePath "$RESULT_BUNDLE_PATH"';
978
- // Test filtering
979
- if (onlyTesting) {
980
- for (const test of onlyTesting.split('\n').filter(Boolean)) {
981
- cmd += ` -only-testing:'${this.escapeBash(test.trim())}'`;
982
- }
983
- }
984
- if (skipTesting) {
985
- for (const test of skipTesting.split('\n').filter(Boolean)) {
986
- cmd += ` -skip-testing:'${this.escapeBash(test.trim())}'`;
987
- }
988
- }
989
- // Repetition
990
- if (repetitionMode && repetitionMode !== 'none') {
991
- if (repetitionMode === 'until_failure') {
992
- cmd += ' -run-tests-until-failure';
993
- }
994
- else if (repetitionMode === 'retry_on_failure') {
995
- cmd += ' -retry-tests-on-failure';
996
- }
997
- cmd += ` -test-iterations ${maxRepetitions}`;
998
- }
999
- if (xcodebuildOptions) {
1000
- cmd += ` ${xcodebuildOptions}`;
1001
- }
1002
- commands.push(cmd);
1003
- commands.push('');
1004
- commands.push('echo "✅ Tests completed"');
1005
- commands.push('echo "Result bundle: $RESULT_BUNDLE_PATH"');
1006
- commands.push('');
1007
- // Export
1008
- commands.push('envman add --key CIBUILD_XCRESULT_PATH --value "$RESULT_BUNDLE_PATH"');
1009
- const script = this.createBashScriptFromCommands(commands, stepName);
1010
- return this.createScriptStep(script, stepName);
1011
- }
1012
- }
1013
- /**
1014
- * Builds an iOS/tvOS/watchOS app for the simulator.
1015
- * Produces a .app bundle with code signing disabled by default.
1016
- */
1017
- export class XcodeBuildForSimulatorStepExecutor extends BaseStepExecutor {
1018
- getValidationRequirements(inputs, _env, _config) {
1019
- const requirements = [];
1020
- requirements.push(this.requireCommand('xcodebuild', 'Xcode Command Line Tools are required', 'Install Xcode, then run: xcode-select --install'));
1021
- requirements.push(this.requireInput('project_path', inputs, 'Path to .xcodeproj or .xcworkspace'));
1022
- requirements.push(this.requireInput('scheme', inputs, 'Xcode scheme name'));
1023
- if (inputs.project_path && !existsSync(inputs.project_path)) {
1024
- requirements.push(this.runtimeRequirement(inputs.project_path, 'Xcode project/workspace file', 'file', 'the checkout'));
1025
- }
1026
- if (inputs.destination === 'auto') {
1027
- requirements.push(this.requireCommand('xcrun', 'xcrun is required to resolve destination: auto via xcrun simctl', 'Install Xcode and run: xcode-select --install'));
1028
- }
1029
- return requirements;
1030
- }
1031
- getOutputs() {
1032
- return [
1033
- { name: 'CIBUILD_APP_DIR_PATH', type: 'environment', description: 'Path to the generated .app directory' },
1034
- ];
1035
- }
1036
- async execute(inputs, _env, _config) {
1037
- const stepName = 'xcode-build-for-simulator';
1038
- const projectPath = this.getRequiredInput(inputs, 'project_path', stepName);
1039
- const scheme = this.getRequiredInput(inputs, 'scheme', stepName);
1040
- const configuration = this.getInput(inputs, 'configuration', '');
1041
- // `auto` triggers runtime resolution via `xcrun simctl`.
1042
- const destination = resolveDestinationInput(this.getInput(inputs, 'destination', 'generic/platform=iOS Simulator'));
1043
- const performClean = this.getInput(inputs, 'perform_clean_action', 'no');
1044
- const xcconfigContent = this.getInput(inputs, 'xcconfig_content', 'CODE_SIGNING_ALLOWED=NO');
1045
- const xcodebuildOptions = this.getInput(inputs, 'xcodebuild_options', '');
1046
- const outputDir = this.getInput(inputs, 'output_dir', 'build');
1047
- const escapedPath = this.escapeBash(projectPath);
1048
- const escapedScheme = this.escapeBash(scheme);
1049
- const commands = [];
1050
- commands.push('# xcode-build-for-simulator');
1051
- commands.push(`echo "Building for simulator: ${escapedPath}"`);
1052
- commands.push(`echo "Scheme: ${escapedScheme}"`);
1053
- commands.push('');
1054
- // Output dir
1055
- commands.push(`mkdir -p '${this.escapeBash(outputDir)}'`);
1056
- commands.push(`OUTPUT_DIR="$(cd '${this.escapeBash(outputDir)}' && pwd)"`);
1057
- commands.push(...derivedDataPathLines());
1058
- commands.push('');
1059
- // xcconfig
1060
- commands.push('XCCONFIG_FILE="$(mktemp -t cibuild-xcconfig).xcconfig"');
1061
- if (xcconfigContent.trim()) {
1062
- commands.push(`cat > "$XCCONFIG_FILE" << 'XCCONFIG_EOF'`);
1063
- commands.push(xcconfigContent);
1064
- commands.push('XCCONFIG_EOF');
1065
- }
1066
- else {
1067
- commands.push('echo "CODE_SIGNING_ALLOWED=NO" > "$XCCONFIG_FILE"');
1068
- }
1069
- commands.push('');
1070
- // Project type
1071
- commands.push(`if [[ '${escapedPath}' == *.xcworkspace ]]; then`);
1072
- commands.push(' PROJECT_TYPE="-workspace"');
1073
- commands.push('else');
1074
- commands.push(' PROJECT_TYPE="-project"');
1075
- commands.push('fi');
1076
- commands.push('');
1077
- // Resolve the package graph before building, under the refused-fetch
1078
- // retry. This is the step an iOS app is normally built with, so it is the
1079
- // one a refused dependency fetch lands on first. The build below reads the
1080
- // same derived data and finds the graph already resolved — the two
1081
- // -derivedDataPath arguments have to move together, or the resolve
1082
- // populates one location and the build re-resolves into another, which
1083
- // silently spends the retry on work the build then throws away.
1084
- commands.push('# Resolve package dependencies first — see git-fetch-retry');
1085
- commands.push(...refusedFetchHelpers());
1086
- commands.push(...retryOnRefusedFetch({
1087
- label: 'Package resolution',
1088
- command: 'xcodebuild -resolvePackageDependencies' +
1089
- ` "$PROJECT_TYPE" '${escapedPath}'` +
1090
- ` -scheme '${escapedScheme}'` +
1091
- ' -derivedDataPath "$DERIVED_DATA_PATH"',
1092
- }));
1093
- const pinsArm64 = pinsSimulatorArm64(xcodebuildOptions);
1094
- if (pinsArm64) {
1095
- commands.push(...simulatorArchsLines({
1096
- projectPath: escapedPath,
1097
- scheme: escapedScheme,
1098
- configuration: configuration ? this.escapeBash(configuration) : '',
1099
- destination: this.escapeBash(destination),
1100
- xcconfig: true,
1101
- }));
1102
- }
1103
- // Build command
1104
- let cmd = 'xcodebuild';
1105
- if (performClean === 'yes') {
1106
- cmd += ' clean';
1107
- }
1108
- cmd += ' build';
1109
- cmd += ` "$PROJECT_TYPE" '${escapedPath}'`;
1110
- cmd += ` -scheme '${escapedScheme}'`;
1111
- if (configuration) {
1112
- cmd += ` -configuration '${this.escapeBash(configuration)}'`;
1113
- }
1114
- cmd += ` -destination '${this.escapeBash(destination)}'`;
1115
- // -derivedDataPath rather than CONFIGURATION_BUILD_DIR. The latter was set
1116
- // to keep xcodebuild from writing a `build` directory inside each SPM
1117
- // package checkout in DerivedData ("File exists but is not a directory" on
1118
- // repeated runs) — but note what that fix actually was: making the path
1119
- // ABSOLUTE. Pointing derived data somewhere writable achieves the same
1120
- // thing without the cost below, and matches xcode-build-for-test.
1121
- //
1122
- // The cost, measured 2026-09-09 on four of the six iOS corpus rows:
1123
- // CONFIGURATION_BUILD_DIR overrides the per-configuration/per-platform
1124
- // product separation xcodebuild normally provides under
1125
- // DerivedData/Build/Products/<config>-<platform>/, flattening every target
1126
- // in the graph into ONE directory. Two build tasks for the same target then
1127
- // declare the same absolute output path and xcodebuild refuses the whole
1128
- // build with "Multiple commands produce". Read the notes it prints: they
1129
- // name the SAME target twice. It is not two packages colliding on a name,
1130
- // it is one target built twice into one directory. 16 collisions on
1131
- // jellyfin/Swiftfin, 266 on Automattic/pocket-casts-ios, 425 on
1132
- // home-assistant/iOS.
1133
- //
1134
- // It also breaks CocoaPods, which is the same defect wearing a disguise.
1135
- // CocoaPods derives PODS_CONFIGURATION_BUILD_DIR from BUILD_DIR, and
1136
- // BUILD_DIR is NOT what CONFIGURATION_BUILD_DIR overrides — so pod products
1137
- // are written to the flat directory while every generated copy-resources
1138
- // script and linker search path still points into DerivedData. On
1139
- // shenruisi/Stay that surfaced as "Resource SDWebImage.bundle not found.
1140
- // Run pod install", for a bundle that had in fact been built, two
1141
- // directories away.
1142
- //
1143
- // Proved by control, same repo and image and flags, only this line
1144
- // differing: CONFIGURATION_BUILD_DIR reproduced the collision and exit 65
1145
- // with no .app; -derivedDataPath reached BUILD SUCCEEDED in 2m06s and left
1146
- // both Debug and Debug-iphonesimulator under Products — the separation the
1147
- // flat directory destroys.
1148
- cmd += ` -derivedDataPath "$DERIVED_DATA_PATH"`;
1149
- cmd += ' -xcconfig "$XCCONFIG_FILE"';
1150
- if (xcodebuildOptions) {
1151
- cmd += ` ${pinsArm64 ? withRuntimeSimulatorArchs(xcodebuildOptions) : xcodebuildOptions}`;
1152
- }
1153
- commands.push(cmd);
1154
- commands.push('');
1155
- // Locate .app. It now lands under the per-platform Products directory
1156
- // rather than flat in $OUTPUT_DIR, so the guard has to follow it — at
1157
- // maxdepth 1 this found nothing and the step would fail every build with
1158
- // ".app not found" while the app had compiled perfectly.
1159
- //
1160
- // Following the products is not enough on its own, though, because a scheme
1161
- // that builds a watchOS or tvOS companion produces more than one bundle and
1162
- // a scan has no way to tell them apart. Ask the scheme, which knows: see
1163
- // xcode-app-product.ts. The scan below is what runs when the scheme cannot
1164
- // answer — a project with no shared scheme is ordinary and builds fine, so
1165
- // this resolves the same bundle it always did there.
1166
- commands.push('# Locate generated .app — the one this scheme builds');
1167
- commands.push('PRODUCTS_DIR="$DERIVED_DATA_PATH/Build/Products"');
1168
- commands.push('APP_RESOLVER="$(mktemp -t cibuild-app-product).cjs"');
1169
- commands.push(`cat > "$APP_RESOLVER" << 'CIBUILD_APP_PRODUCT_EOF'`);
1170
- commands.push(APP_PRODUCT_RESOLVER_SOURCE.trim());
1171
- commands.push('CIBUILD_APP_PRODUCT_EOF');
1172
- commands.push('APP_PATH=$(node "$APP_RESOLVER" "$PRODUCTS_DIR"' +
1173
- ` '${escapedPath}' '${escapedScheme}' '${this.escapeBash(destination)}' 2>/dev/null || true)`);
1174
- commands.push('rm -f "$APP_RESOLVER"');
1175
- commands.push('if [ -z "$APP_PATH" ]; then');
1176
- commands.push(' APP_PATH=$(find "$PRODUCTS_DIR" -maxdepth 2 -name "*.app" -type d 2>/dev/null | head -1)');
1177
- commands.push('fi');
1178
- commands.push('if [ -z "$APP_PATH" ]; then');
1179
- commands.push(' echo "❌ Error: .app not found under $PRODUCTS_DIR"');
1180
- commands.push(' exit 1');
1181
- commands.push('fi');
1182
- commands.push('');
1183
- commands.push('echo "✅ Simulator build complete"');
1184
- commands.push('echo "App: $APP_PATH"');
1185
- commands.push('');
1186
- // Export
1187
- commands.push('envman add --key CIBUILD_APP_DIR_PATH --value "$APP_PATH"');
1188
- commands.push('');
1189
- // Deliver it, the way gradle-build delivers its .apk.
1190
- //
1191
- // gradle-build copies its own output into the artifacts directory; this
1192
- // step located the bundle, exported the path and left it in DerivedData —
1193
- // which the runner excludes from artifact discovery. So the app was
1194
- // findable and deliberately not found, and an iOS proof could go green
1195
- // handing the user nothing to install. Pipelines that added a collecting
1196
- // step of their own delivered; every other one did not, which made
1197
- // delivery a property of the pipeline rather than of the build.
1198
- //
1199
- // It zips rather than copying the bundle in, and that is not cosmetic. A
1200
- // .app is a directory: staged as a directory it becomes one artifact per
1201
- // file inside it — every asset, nib and framework separately — and an
1202
- // internal symlink pointing outside the workspace fails the stage
1203
- // outright. A .zip is a plain file, stages as exactly one artifact, and is
1204
- // what someone downloading it wants anyway. ditto is the macOS-native
1205
- // archiver and preserves the bundle's permissions and symlinks, which a
1206
- // plain recursive zip does not do faithfully.
1207
- commands.push('# Deliver the app as one artifact');
1208
- commands.push('ARTIFACTS_DIR="${CIBUILD_ARTIFACTS_DIR:-.ci/artifacts}"');
1209
- commands.push('mkdir -p "$ARTIFACTS_DIR"');
1210
- commands.push('APP_NAME="$(basename "$APP_PATH")"');
1211
- commands.push('rm -f "$ARTIFACTS_DIR/$APP_NAME.zip"');
1212
- commands.push('ditto -c -k --keepParent "$APP_PATH" "$ARTIFACTS_DIR/$APP_NAME.zip"');
1213
- commands.push('echo " → Collected: $APP_NAME.zip"');
1214
- commands.push('echo "✅ Artifacts copied to: $ARTIFACTS_DIR"');
1215
- commands.push('ls -lh "$ARTIFACTS_DIR"');
1216
- commands.push('');
1217
- commands.push('rm -f "$XCCONFIG_FILE"');
1218
- const script = this.createBashScriptFromCommands(commands, stepName);
1219
- return this.createScriptStep(script, stepName);
1220
- }
1221
- }
1222
- /**
1223
- * Exports an IPA from an existing .xcarchive using xcodebuild -exportArchive.
1224
- */
1225
- export class ExportXcarchiveStepExecutor extends BaseStepExecutor {
1226
- getValidationRequirements(_inputs, _env, _config) {
1227
- return [
1228
- this.requireCommand('xcodebuild', 'Xcode is required for archive export'),
1229
- ];
1230
- }
1231
- getOutputs() {
1232
- return [
1233
- { name: 'CIBUILD_IPA_PATH', type: 'environment', description: 'Path to the exported IPA file' },
1234
- { name: 'CIBUILD_DSYM_PATH', type: 'environment', description: 'Path to the zipped dSYM files' },
1235
- ];
1236
- }
1237
- async execute(inputs, _env, _config) {
1238
- const stepName = 'export-xcarchive';
1239
- const archivePath = this.getRequiredInput(inputs, 'archive_path', stepName);
1240
- const product = this.getInput(inputs, 'product', 'app');
1241
- const distributionMethod = this.getInput(inputs, 'distribution_method', 'development');
1242
- const compileBitcode = this.getInput(inputs, 'compile_bitcode', 'yes') === 'yes';
1243
- const uploadBitcode = this.getInput(inputs, 'upload_bitcode', 'yes') === 'yes';
1244
- const exportOptionsPlistContent = this.getInput(inputs, 'export_options_plist_content', '');
1245
- const verbose = this.getInput(inputs, 'verbose_log', 'no') === 'yes';
1246
- const commands = [];
1247
- commands.push('# export-xcarchive — export IPA from .xcarchive');
1248
- commands.push('echo "📦 Exporting IPA from xcarchive..."');
1249
- commands.push('');
1250
- commands.push(`ARCHIVE_PATH='${this.escapeBash(archivePath)}'`);
1251
- commands.push('');
1252
- // Validate archive exists
1253
- commands.push('if [ ! -d "$ARCHIVE_PATH" ]; then');
1254
- commands.push(' echo "❌ Error: Archive not found: $ARCHIVE_PATH"');
1255
- commands.push(' exit 1');
1256
- commands.push('fi');
1257
- commands.push('');
1258
- // Set up export directory
1259
- commands.push('EXPORT_DIR="${CIBUILD_DEPLOY_DIR:-./artifacts}/export"');
1260
- commands.push('mkdir -p "$EXPORT_DIR"');
1261
- commands.push('');
1262
- // Generate or use provided ExportOptions.plist
1263
- commands.push('EXPORT_OPTIONS="$EXPORT_DIR/ExportOptions.plist"');
1264
- if (exportOptionsPlistContent) {
1265
- commands.push('cat > "$EXPORT_OPTIONS" << \'PLIST_EOF\'');
1266
- commands.push(exportOptionsPlistContent);
1267
- commands.push('PLIST_EOF');
1268
- }
1269
- else {
1270
- // Map distribution method for Xcode 15.3+
1271
- commands.push('# Determine distribution method');
1272
- commands.push(`METHOD='${this.escapeBash(distributionMethod)}'`);
1273
- commands.push('XCODE_VERSION=$(xcodebuild -version | head -1 | grep -oE "[0-9]+\\.[0-9]+" || echo "0.0")');
1274
- commands.push('XCODE_MAJOR=$(echo "$XCODE_VERSION" | cut -d. -f1)');
1275
- commands.push('XCODE_MINOR=$(echo "$XCODE_VERSION" | cut -d. -f2)');
1276
- commands.push('if [ "$XCODE_MAJOR" -ge 16 ] || ([ "$XCODE_MAJOR" -eq 15 ] && [ "$XCODE_MINOR" -ge 3 ]); then');
1277
- commands.push(' case "$METHOD" in');
1278
- commands.push(' development) METHOD="debugging" ;;');
1279
- commands.push(' app-store) METHOD="app-store-connect" ;;');
1280
- commands.push(' ad-hoc) METHOD="release-testing" ;;');
1281
- commands.push(' esac');
1282
- commands.push('fi');
1283
- commands.push('');
1284
- commands.push('cat > "$EXPORT_OPTIONS" << PLIST_EOF');
1285
- commands.push('<?xml version="1.0" encoding="UTF-8"?>');
1286
- commands.push('<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">');
1287
- commands.push('<plist version="1.0">');
1288
- commands.push('<dict>');
1289
- commands.push(' <key>method</key>');
1290
- commands.push(' <string>$METHOD</string>');
1291
- commands.push(` <key>compileBitcode</key>`);
1292
- commands.push(` <${compileBitcode}/>`);
1293
- commands.push(` <key>uploadBitcode</key>`);
1294
- commands.push(` <${uploadBitcode}/>`);
1295
- if (product === 'app-clip') {
1296
- commands.push(' <key>exportForThinning</key>');
1297
- commands.push(' <string>app-clip</string>');
1298
- }
1299
- commands.push('</dict>');
1300
- commands.push('</plist>');
1301
- commands.push('PLIST_EOF');
1302
- }
1303
- commands.push('');
1304
- // Run xcodebuild -exportArchive
1305
- const verboseFlag = verbose ? '' : ' -quiet';
1306
- commands.push('echo "Exporting with method: $METHOD"');
1307
- commands.push(`xcodebuild -exportArchive \\`);
1308
- commands.push(` -archivePath "$ARCHIVE_PATH" \\`);
1309
- commands.push(` -exportPath "$EXPORT_DIR" \\`);
1310
- commands.push(` -exportOptionsPlist "$EXPORT_OPTIONS"${verboseFlag}`);
1311
- commands.push('');
1312
- // Find IPA
1313
- commands.push('# Find exported IPA');
1314
- commands.push('IPA_PATH=$(find "$EXPORT_DIR" -name "*.ipa" | head -1)');
1315
- commands.push('if [ -z "$IPA_PATH" ]; then');
1316
- commands.push(' echo "❌ Error: No IPA found in export directory"');
1317
- commands.push(' exit 1');
1318
- commands.push('fi');
1319
- commands.push('echo "✅ Exported IPA: $IPA_PATH"');
1320
- commands.push('');
1321
- // Collect dSYMs
1322
- commands.push('# Collect dSYMs');
1323
- commands.push('DSYM_DIR="$ARCHIVE_PATH/dSYMs"');
1324
- commands.push('DSYM_ZIP=""');
1325
- commands.push('if [ -d "$DSYM_DIR" ] && [ "$(ls -A "$DSYM_DIR" 2>/dev/null)" ]; then');
1326
- commands.push(' DSYM_ZIP="$EXPORT_DIR/dSYMs.zip"');
1327
- commands.push(' cd "$DSYM_DIR" && zip -r "$DSYM_ZIP" . && cd -');
1328
- commands.push(' echo "dSYMs: $DSYM_ZIP"');
1329
- commands.push('fi');
1330
- commands.push('');
1331
- // Export env vars
1332
- commands.push('envman add --key CIBUILD_IPA_PATH --value "$IPA_PATH"');
1333
- commands.push('if [ -n "$DSYM_ZIP" ]; then');
1334
- commands.push(' envman add --key CIBUILD_DSYM_PATH --value "$DSYM_ZIP"');
1335
- commands.push('fi');
1336
- const script = this.createBashScriptFromCommands(commands, stepName);
1337
- return this.createScriptStep(script, stepName);
1338
- }
1339
- }
1340
- //# sourceMappingURL=xcode.js.map