@invarn/cibuild 1.3.16 → 1.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/dist/cli.cjs +1 -1
  2. package/dist/src/cli.d.ts +3 -0
  3. package/dist/src/cli.d.ts.map +1 -0
  4. package/dist/src/cli.js +987 -0
  5. package/dist/src/commands/android-scanner.d.ts +32 -0
  6. package/dist/src/commands/android-scanner.d.ts.map +1 -0
  7. package/dist/src/commands/android-scanner.js +667 -0
  8. package/dist/src/commands/build.d.ts +5 -0
  9. package/dist/src/commands/build.d.ts.map +1 -0
  10. package/dist/src/commands/build.js +1096 -0
  11. package/dist/src/commands/edit.d.ts +3 -0
  12. package/dist/src/commands/edit.d.ts.map +1 -0
  13. package/dist/src/commands/edit.js +651 -0
  14. package/dist/src/commands/file-secret-collector.d.ts +37 -0
  15. package/dist/src/commands/file-secret-collector.d.ts.map +1 -0
  16. package/dist/src/commands/file-secret-collector.js +199 -0
  17. package/dist/src/commands/github-workflow.d.ts +5 -0
  18. package/dist/src/commands/github-workflow.d.ts.map +1 -0
  19. package/dist/src/commands/github-workflow.js +45 -0
  20. package/dist/src/commands/ios-scanner.d.ts +27 -0
  21. package/dist/src/commands/ios-scanner.d.ts.map +1 -0
  22. package/dist/src/commands/ios-scanner.js +337 -0
  23. package/dist/src/commands/reset.d.ts +7 -0
  24. package/dist/src/commands/reset.d.ts.map +1 -0
  25. package/dist/src/commands/reset.js +81 -0
  26. package/dist/src/commands/secrets-sync-workflow.d.ts +15 -0
  27. package/dist/src/commands/secrets-sync-workflow.d.ts.map +1 -0
  28. package/dist/src/commands/secrets-sync-workflow.js +255 -0
  29. package/dist/src/commands/secrets-upload.d.ts +21 -0
  30. package/dist/src/commands/secrets-upload.d.ts.map +1 -0
  31. package/dist/src/commands/secrets-upload.js +177 -0
  32. package/dist/src/commands/secrets-upload.test.d.ts +5 -0
  33. package/dist/src/commands/secrets-upload.test.d.ts.map +1 -0
  34. package/dist/src/commands/secrets-upload.test.js +60 -0
  35. package/dist/src/config.d.ts +3 -0
  36. package/dist/src/config.d.ts.map +1 -0
  37. package/dist/src/config.js +47 -0
  38. package/dist/src/envman/cli.d.ts +21 -0
  39. package/dist/src/envman/cli.d.ts.map +1 -0
  40. package/dist/src/envman/cli.js +240 -0
  41. package/dist/src/envman/envman.d.ts +83 -0
  42. package/dist/src/envman/envman.d.ts.map +1 -0
  43. package/dist/src/envman/envman.js +361 -0
  44. package/dist/src/envman/envman.test.d.ts +5 -0
  45. package/dist/src/envman/envman.test.d.ts.map +1 -0
  46. package/dist/src/envman/envman.test.js +236 -0
  47. package/dist/src/envman/index.d.ts +23 -0
  48. package/dist/src/envman/index.d.ts.map +1 -0
  49. package/dist/src/envman/index.js +23 -0
  50. package/dist/src/envman/types.d.ts +55 -0
  51. package/dist/src/envman/types.d.ts.map +1 -0
  52. package/dist/src/envman/types.js +12 -0
  53. package/dist/src/lib.d.ts +27 -0
  54. package/dist/src/lib.d.ts.map +1 -0
  55. package/dist/src/lib.js +32 -0
  56. package/dist/src/pipeline.d.ts +3 -0
  57. package/dist/src/pipeline.d.ts.map +1 -0
  58. package/dist/src/pipeline.js +57 -0
  59. package/dist/src/runner.d.ts +17 -0
  60. package/dist/src/runner.d.ts.map +1 -0
  61. package/dist/src/runner.js +234 -0
  62. package/dist/src/types.d.ts +58 -0
  63. package/dist/src/types.d.ts.map +1 -0
  64. package/dist/src/types.js +2 -0
  65. package/dist/src/yaml/bitrise-compat.d.ts +65 -0
  66. package/dist/src/yaml/bitrise-compat.d.ts.map +1 -0
  67. package/dist/src/yaml/bitrise-compat.js +206 -0
  68. package/dist/src/yaml/bitrise-compat.test.d.ts +5 -0
  69. package/dist/src/yaml/bitrise-compat.test.d.ts.map +1 -0
  70. package/dist/src/yaml/bitrise-compat.test.js +347 -0
  71. package/dist/src/yaml/converter.d.ts +33 -0
  72. package/dist/src/yaml/converter.d.ts.map +1 -0
  73. package/dist/src/yaml/converter.js +222 -0
  74. package/dist/src/yaml/converter.test.d.ts +5 -0
  75. package/dist/src/yaml/converter.test.d.ts.map +1 -0
  76. package/dist/src/yaml/converter.test.js +348 -0
  77. package/dist/src/yaml/e2e.test.d.ts +6 -0
  78. package/dist/src/yaml/e2e.test.d.ts.map +1 -0
  79. package/dist/src/yaml/e2e.test.js +446 -0
  80. package/dist/src/yaml/env-resolver.d.ts +120 -0
  81. package/dist/src/yaml/env-resolver.d.ts.map +1 -0
  82. package/dist/src/yaml/env-resolver.js +405 -0
  83. package/dist/src/yaml/env-resolver.test.d.ts +5 -0
  84. package/dist/src/yaml/env-resolver.test.d.ts.map +1 -0
  85. package/dist/src/yaml/env-resolver.test.js +502 -0
  86. package/dist/src/yaml/interactive-prompts.d.ts +71 -0
  87. package/dist/src/yaml/interactive-prompts.d.ts.map +1 -0
  88. package/dist/src/yaml/interactive-prompts.js +258 -0
  89. package/dist/src/yaml/missing-env-handler.d.ts +45 -0
  90. package/dist/src/yaml/missing-env-handler.d.ts.map +1 -0
  91. package/dist/src/yaml/missing-env-handler.js +64 -0
  92. package/dist/src/yaml/parser.d.ts +33 -0
  93. package/dist/src/yaml/parser.d.ts.map +1 -0
  94. package/dist/src/yaml/parser.js +145 -0
  95. package/dist/src/yaml/pipeline-with-secrets.d.ts +25 -0
  96. package/dist/src/yaml/pipeline-with-secrets.d.ts.map +1 -0
  97. package/dist/src/yaml/pipeline-with-secrets.js +76 -0
  98. package/dist/src/yaml/platform-detector.d.ts +83 -0
  99. package/dist/src/yaml/platform-detector.d.ts.map +1 -0
  100. package/dist/src/yaml/platform-detector.js +188 -0
  101. package/dist/src/yaml/platform-detector.test.d.ts +5 -0
  102. package/dist/src/yaml/platform-detector.test.d.ts.map +1 -0
  103. package/dist/src/yaml/platform-detector.test.js +414 -0
  104. package/dist/src/yaml/preflight-validation.d.ts +40 -0
  105. package/dist/src/yaml/preflight-validation.d.ts.map +1 -0
  106. package/dist/src/yaml/preflight-validation.js +152 -0
  107. package/dist/src/yaml/secrets-manager.d.ts +77 -0
  108. package/dist/src/yaml/secrets-manager.d.ts.map +1 -0
  109. package/dist/src/yaml/secrets-manager.js +219 -0
  110. package/dist/src/yaml/step-validator.d.ts +54 -0
  111. package/dist/src/yaml/step-validator.d.ts.map +1 -0
  112. package/dist/src/yaml/step-validator.js +403 -0
  113. package/dist/src/yaml/steps/android-sign.d.ts +35 -0
  114. package/dist/src/yaml/steps/android-sign.d.ts.map +1 -0
  115. package/dist/src/yaml/steps/android-sign.js +147 -0
  116. package/dist/src/yaml/steps/android-version.d.ts +26 -0
  117. package/dist/src/yaml/steps/android-version.d.ts.map +1 -0
  118. package/dist/src/yaml/steps/android-version.js +128 -0
  119. package/dist/src/yaml/steps/android-version.test.d.ts +5 -0
  120. package/dist/src/yaml/steps/android-version.test.d.ts.map +1 -0
  121. package/dist/src/yaml/steps/android-version.test.js +196 -0
  122. package/dist/src/yaml/steps/android.d.ts +95 -0
  123. package/dist/src/yaml/steps/android.d.ts.map +1 -0
  124. package/dist/src/yaml/steps/android.js +916 -0
  125. package/dist/src/yaml/steps/app-store-deploy.d.ts +48 -0
  126. package/dist/src/yaml/steps/app-store-deploy.d.ts.map +1 -0
  127. package/dist/src/yaml/steps/app-store-deploy.js +162 -0
  128. package/dist/src/yaml/steps/base.d.ts +238 -0
  129. package/dist/src/yaml/steps/base.d.ts.map +1 -0
  130. package/dist/src/yaml/steps/base.js +345 -0
  131. package/dist/src/yaml/steps/bitrise-android-tools.d.ts +26 -0
  132. package/dist/src/yaml/steps/bitrise-android-tools.d.ts.map +1 -0
  133. package/dist/src/yaml/steps/bitrise-android-tools.js +198 -0
  134. package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts +5 -0
  135. package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts.map +1 -0
  136. package/dist/src/yaml/steps/bitrise-android-tools.test.js +280 -0
  137. package/dist/src/yaml/steps/bitrise-apk-info.d.ts +22 -0
  138. package/dist/src/yaml/steps/bitrise-apk-info.d.ts.map +1 -0
  139. package/dist/src/yaml/steps/bitrise-apk-info.js +144 -0
  140. package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts +5 -0
  141. package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts.map +1 -0
  142. package/dist/src/yaml/steps/bitrise-apk-info.test.js +331 -0
  143. package/dist/src/yaml/steps/bitrise-slack.d.ts +49 -0
  144. package/dist/src/yaml/steps/bitrise-slack.d.ts.map +1 -0
  145. package/dist/src/yaml/steps/bitrise-slack.js +280 -0
  146. package/dist/src/yaml/steps/bitrise-slack.test.d.ts +5 -0
  147. package/dist/src/yaml/steps/bitrise-slack.test.d.ts.map +1 -0
  148. package/dist/src/yaml/steps/bitrise-slack.test.js +484 -0
  149. package/dist/src/yaml/steps/bitrise-ssh.d.ts +27 -0
  150. package/dist/src/yaml/steps/bitrise-ssh.d.ts.map +1 -0
  151. package/dist/src/yaml/steps/bitrise-ssh.js +134 -0
  152. package/dist/src/yaml/steps/bitrise-ssh.test.d.ts +5 -0
  153. package/dist/src/yaml/steps/bitrise-ssh.test.d.ts.map +1 -0
  154. package/dist/src/yaml/steps/bitrise-ssh.test.js +205 -0
  155. package/dist/src/yaml/steps/cache.d.ts +52 -0
  156. package/dist/src/yaml/steps/cache.d.ts.map +1 -0
  157. package/dist/src/yaml/steps/cache.js +352 -0
  158. package/dist/src/yaml/steps/fastlane.d.ts +27 -0
  159. package/dist/src/yaml/steps/fastlane.d.ts.map +1 -0
  160. package/dist/src/yaml/steps/fastlane.js +79 -0
  161. package/dist/src/yaml/steps/file.d.ts +27 -0
  162. package/dist/src/yaml/steps/file.d.ts.map +1 -0
  163. package/dist/src/yaml/steps/file.js +35 -0
  164. package/dist/src/yaml/steps/flutter.d.ts +63 -0
  165. package/dist/src/yaml/steps/flutter.d.ts.map +1 -0
  166. package/dist/src/yaml/steps/flutter.js +215 -0
  167. package/dist/src/yaml/steps/git-clone.d.ts +26 -0
  168. package/dist/src/yaml/steps/git-clone.d.ts.map +1 -0
  169. package/dist/src/yaml/steps/git-clone.js +111 -0
  170. package/dist/src/yaml/steps/google-play-deploy.d.ts +37 -0
  171. package/dist/src/yaml/steps/google-play-deploy.d.ts.map +1 -0
  172. package/dist/src/yaml/steps/google-play-deploy.js +193 -0
  173. package/dist/src/yaml/steps/google-play-deploy.test.d.ts +5 -0
  174. package/dist/src/yaml/steps/google-play-deploy.test.d.ts.map +1 -0
  175. package/dist/src/yaml/steps/google-play-deploy.test.js +310 -0
  176. package/dist/src/yaml/steps/index.d.ts +10 -0
  177. package/dist/src/yaml/steps/index.d.ts.map +1 -0
  178. package/dist/src/yaml/steps/index.js +1361 -0
  179. package/dist/src/yaml/steps/ios-deps.d.ts +43 -0
  180. package/dist/src/yaml/steps/ios-deps.d.ts.map +1 -0
  181. package/dist/src/yaml/steps/ios-deps.js +141 -0
  182. package/dist/src/yaml/steps/ios-deps.test.d.ts +5 -0
  183. package/dist/src/yaml/steps/ios-deps.test.d.ts.map +1 -0
  184. package/dist/src/yaml/steps/ios-deps.test.js +90 -0
  185. package/dist/src/yaml/steps/ios-signing.d.ts +31 -0
  186. package/dist/src/yaml/steps/ios-signing.d.ts.map +1 -0
  187. package/dist/src/yaml/steps/ios-signing.js +144 -0
  188. package/dist/src/yaml/steps/ios-version.d.ts +47 -0
  189. package/dist/src/yaml/steps/ios-version.d.ts.map +1 -0
  190. package/dist/src/yaml/steps/ios-version.js +151 -0
  191. package/dist/src/yaml/steps/linting.d.ts +47 -0
  192. package/dist/src/yaml/steps/linting.d.ts.map +1 -0
  193. package/dist/src/yaml/steps/linting.js +148 -0
  194. package/dist/src/yaml/steps/phase2.test.d.ts +6 -0
  195. package/dist/src/yaml/steps/phase2.test.d.ts.map +1 -0
  196. package/dist/src/yaml/steps/phase2.test.js +197 -0
  197. package/dist/src/yaml/steps/phase3.test.d.ts +5 -0
  198. package/dist/src/yaml/steps/phase3.test.d.ts.map +1 -0
  199. package/dist/src/yaml/steps/phase3.test.js +144 -0
  200. package/dist/src/yaml/steps/phase4.test.d.ts +5 -0
  201. package/dist/src/yaml/steps/phase4.test.d.ts.map +1 -0
  202. package/dist/src/yaml/steps/phase4.test.js +166 -0
  203. package/dist/src/yaml/steps/phase5.test.d.ts +6 -0
  204. package/dist/src/yaml/steps/phase5.test.d.ts.map +1 -0
  205. package/dist/src/yaml/steps/phase5.test.js +263 -0
  206. package/dist/src/yaml/steps/registry.d.ts +88 -0
  207. package/dist/src/yaml/steps/registry.d.ts.map +1 -0
  208. package/dist/src/yaml/steps/registry.js +125 -0
  209. package/dist/src/yaml/steps/registry.test.d.ts +5 -0
  210. package/dist/src/yaml/steps/registry.test.d.ts.map +1 -0
  211. package/dist/src/yaml/steps/registry.test.js +235 -0
  212. package/dist/src/yaml/steps/release.d.ts +50 -0
  213. package/dist/src/yaml/steps/release.d.ts.map +1 -0
  214. package/dist/src/yaml/steps/release.js +154 -0
  215. package/dist/src/yaml/steps/script.d.ts +23 -0
  216. package/dist/src/yaml/steps/script.d.ts.map +1 -0
  217. package/dist/src/yaml/steps/script.js +63 -0
  218. package/dist/src/yaml/steps/spec-validation.test.d.ts +6 -0
  219. package/dist/src/yaml/steps/spec-validation.test.d.ts.map +1 -0
  220. package/dist/src/yaml/steps/spec-validation.test.js +130 -0
  221. package/dist/src/yaml/steps/steps.test.d.ts +6 -0
  222. package/dist/src/yaml/steps/steps.test.d.ts.map +1 -0
  223. package/dist/src/yaml/steps/steps.test.js +505 -0
  224. package/dist/src/yaml/steps/test-config.d.ts +3 -0
  225. package/dist/src/yaml/steps/test-config.d.ts.map +1 -0
  226. package/dist/src/yaml/steps/test-config.js +17 -0
  227. package/dist/src/yaml/steps/xcode-new.test.d.ts +5 -0
  228. package/dist/src/yaml/steps/xcode-new.test.d.ts.map +1 -0
  229. package/dist/src/yaml/steps/xcode-new.test.js +211 -0
  230. package/dist/src/yaml/steps/xcode.d.ts +222 -0
  231. package/dist/src/yaml/steps/xcode.d.ts.map +1 -0
  232. package/dist/src/yaml/steps/xcode.js +999 -0
  233. package/dist/src/yaml/types.d.ts +68 -0
  234. package/dist/src/yaml/types.d.ts.map +1 -0
  235. package/dist/src/yaml/types.js +5 -0
  236. package/dist/src/yaml/validation-types.d.ts +96 -0
  237. package/dist/src/yaml/validation-types.d.ts.map +1 -0
  238. package/dist/src/yaml/validation-types.js +8 -0
  239. package/dist/src/yaml/yaml-updater.d.ts +24 -0
  240. package/dist/src/yaml/yaml-updater.d.ts.map +1 -0
  241. package/dist/src/yaml/yaml-updater.js +128 -0
  242. package/package.json +16 -4
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Unit tests for Bitrise activate-ssh-key step
3
+ */
4
+ import { describe, test, expect } from '@jest/globals';
5
+ import { BitriseSSHStepExecutor } from './bitrise-ssh.js';
6
+ describe('BitriseSSHStepExecutor', () => {
7
+ const mockConfig = {
8
+ artifactsDir: '/ci/artifacts',
9
+ interpreters: {
10
+ python: '/usr/bin/python3',
11
+ ruby: '/usr/bin/ruby',
12
+ node: '/usr/bin/node',
13
+ bash: '/bin/bash',
14
+ },
15
+ maxConcurrentJobs: 4,
16
+ paths: {
17
+ buildsDir: '/ci/builds',
18
+ cacheDir: '/ci/cache',
19
+ derivedDataDir: '/ci/derived_data',
20
+ },
21
+ };
22
+ describe('Basic functionality', () => {
23
+ test('should create SSH activation script with default values', async () => {
24
+ const executor = new BitriseSSHStepExecutor();
25
+ const env = {
26
+ SSH_RSA_PRIVATE_KEY: '-----BEGIN RSA PRIVATE KEY-----\ntest-key-content\n-----END RSA PRIVATE KEY-----',
27
+ };
28
+ const result = await executor.execute({}, env, mockConfig);
29
+ expect(result.kind).toBe('script');
30
+ expect(result.name).toBe('activate-ssh-key');
31
+ expect(result.script).toContain('mkdir -p ~/.ssh');
32
+ expect(result.script).toContain('chmod 700 ~/.ssh');
33
+ expect(result.script).toContain('echo "${SSH_RSA_PRIVATE_KEY}" | tr \'\\r\' \'\\n\' > ~/.ssh/default.pem');
34
+ expect(result.script).toContain('chmod 600 ~/.ssh/default.pem');
35
+ });
36
+ test('should include SSH agent commands', async () => {
37
+ const executor = new BitriseSSHStepExecutor();
38
+ const env = {
39
+ SSH_RSA_PRIVATE_KEY: '-----BEGIN RSA PRIVATE KEY-----\ntest-key\n-----END RSA PRIVATE KEY-----',
40
+ };
41
+ const result = await executor.execute({}, env, mockConfig);
42
+ expect(result.script).toContain('eval "$(ssh-agent -s)"');
43
+ expect(result.script).toContain('ssh-add ~/.ssh/default.pem');
44
+ });
45
+ test('should configure SSH client settings', async () => {
46
+ const executor = new BitriseSSHStepExecutor();
47
+ const env = {
48
+ SSH_RSA_PRIVATE_KEY: 'test-key',
49
+ };
50
+ const result = await executor.execute({}, env, mockConfig);
51
+ expect(result.script).toContain('cat >> ~/.ssh/config');
52
+ expect(result.script).toContain('StrictHostKeyChecking no');
53
+ expect(result.script).toContain('UserKnownHostsFile=/dev/null');
54
+ expect(result.script).toContain('chmod 600 ~/.ssh/config');
55
+ });
56
+ });
57
+ describe('Custom SSH key path', () => {
58
+ test('should use custom ssh_key_save_path when provided', async () => {
59
+ const executor = new BitriseSSHStepExecutor();
60
+ const env = {
61
+ SSH_RSA_PRIVATE_KEY: 'test-key',
62
+ };
63
+ const inputs = {
64
+ ssh_key_save_path: '~/.ssh/custom_key',
65
+ };
66
+ const result = await executor.execute(inputs, env, mockConfig);
67
+ expect(result.script).toContain('echo "${SSH_RSA_PRIVATE_KEY}" | tr \'\\r\' \'\\n\' > ~/.ssh/custom_key');
68
+ expect(result.script).toContain('chmod 600 ~/.ssh/custom_key');
69
+ expect(result.script).toContain('ssh-add ~/.ssh/custom_key');
70
+ });
71
+ });
72
+ describe('Remove other identities', () => {
73
+ test('should remove other SSH identities when is_remove_other_identities is true', async () => {
74
+ const executor = new BitriseSSHStepExecutor();
75
+ const env = {
76
+ SSH_RSA_PRIVATE_KEY: 'test-key',
77
+ };
78
+ const inputs = {
79
+ is_remove_other_identities: 'true',
80
+ };
81
+ const result = await executor.execute(inputs, env, mockConfig);
82
+ expect(result.script).toContain('ssh-add -D');
83
+ });
84
+ test('should remove other SSH identities when is_remove_other_identities is yes', async () => {
85
+ const executor = new BitriseSSHStepExecutor();
86
+ const env = {
87
+ SSH_RSA_PRIVATE_KEY: 'test-key',
88
+ };
89
+ const inputs = {
90
+ is_remove_other_identities: 'yes',
91
+ };
92
+ const result = await executor.execute(inputs, env, mockConfig);
93
+ expect(result.script).toContain('ssh-add -D');
94
+ });
95
+ test('should not remove other identities when is_remove_other_identities is false', async () => {
96
+ const executor = new BitriseSSHStepExecutor();
97
+ const env = {
98
+ SSH_RSA_PRIVATE_KEY: 'test-key',
99
+ };
100
+ const inputs = {
101
+ is_remove_other_identities: 'false',
102
+ };
103
+ const result = await executor.execute(inputs, env, mockConfig);
104
+ expect(result.script).not.toContain('ssh-add -D');
105
+ });
106
+ test('should remove other identities by default', async () => {
107
+ const executor = new BitriseSSHStepExecutor();
108
+ const env = {
109
+ SSH_RSA_PRIVATE_KEY: 'test-key',
110
+ };
111
+ const result = await executor.execute({}, env, mockConfig);
112
+ // Default is 'true'
113
+ expect(result.script).toContain('ssh-add -D');
114
+ });
115
+ });
116
+ describe('Error handling', () => {
117
+ test('should throw error when SSH_RSA_PRIVATE_KEY is missing', async () => {
118
+ const executor = new BitriseSSHStepExecutor();
119
+ const env = {}; // No SSH key
120
+ await expect(executor.execute({}, env, mockConfig)).rejects.toThrow(/Missing environment variable: 'SSH_RSA_PRIVATE_KEY'/);
121
+ });
122
+ test('should include helpful error message for missing SSH key', async () => {
123
+ const executor = new BitriseSSHStepExecutor();
124
+ const env = {};
125
+ await expect(executor.execute({}, env, mockConfig)).rejects.toThrow(/SSH private key used for Git authentication/);
126
+ });
127
+ test('should suggest how to configure SSH key in error message', async () => {
128
+ const executor = new BitriseSSHStepExecutor();
129
+ const env = {};
130
+ await expect(executor.execute({}, env, mockConfig)).rejects.toThrow(/Store private key in CI secrets/);
131
+ });
132
+ });
133
+ describe('Script structure', () => {
134
+ test('should include bash error handling directives', async () => {
135
+ const executor = new BitriseSSHStepExecutor();
136
+ const env = {
137
+ SSH_RSA_PRIVATE_KEY: 'test-key',
138
+ };
139
+ const result = await executor.execute({}, env, mockConfig);
140
+ expect(result.script).toContain('#!/bin/bash');
141
+ expect(result.script).toContain('set -e');
142
+ expect(result.script).toContain('set -o pipefail');
143
+ });
144
+ test('should include informative messages', async () => {
145
+ const executor = new BitriseSSHStepExecutor();
146
+ const env = {
147
+ SSH_RSA_PRIVATE_KEY: 'test-key',
148
+ };
149
+ const result = await executor.execute({}, env, mockConfig);
150
+ expect(result.script).toContain('Bitrise activate-ssh-key step → CI Build SSH activation');
151
+ expect(result.script).toContain('Setting up SSH key for Git operations');
152
+ expect(result.script).toContain('SSH key activated successfully');
153
+ });
154
+ });
155
+ describe('Integration scenarios', () => {
156
+ test('should handle complex SSH key with newlines', async () => {
157
+ const executor = new BitriseSSHStepExecutor();
158
+ const env = {
159
+ SSH_RSA_PRIVATE_KEY: `-----BEGIN RSA PRIVATE KEY-----
160
+ MIIEpAIBAAKCAQEA1234567890abcdef
161
+ ghijklmnopqrstuvwxyz0123456789
162
+ -----END RSA PRIVATE KEY-----`,
163
+ };
164
+ const result = await executor.execute({}, env, mockConfig);
165
+ expect(result.script).toContain('echo "${SSH_RSA_PRIVATE_KEY}"');
166
+ expect(result.kind).toBe('script');
167
+ });
168
+ test('should work with custom path and remove identities disabled', async () => {
169
+ const executor = new BitriseSSHStepExecutor();
170
+ const env = {
171
+ SSH_RSA_PRIVATE_KEY: 'custom-key-content',
172
+ };
173
+ const inputs = {
174
+ ssh_key_save_path: '~/.ssh/my_ssh_key',
175
+ is_remove_other_identities: 'false',
176
+ };
177
+ const result = await executor.execute(inputs, env, mockConfig);
178
+ expect(result.script).toContain('echo "${SSH_RSA_PRIVATE_KEY}" | tr \'\\r\' \'\\n\' > ~/.ssh/my_ssh_key');
179
+ expect(result.script).toContain('chmod 600 ~/.ssh/my_ssh_key');
180
+ expect(result.script).toContain('ssh-add ~/.ssh/my_ssh_key');
181
+ expect(result.script).not.toContain('ssh-add -D');
182
+ });
183
+ });
184
+ describe('Bitrise compatibility', () => {
185
+ test('should support Bitrise environment variable naming', async () => {
186
+ const executor = new BitriseSSHStepExecutor();
187
+ const env = {
188
+ SSH_RSA_PRIVATE_KEY: 'bitrise-compatible-key',
189
+ };
190
+ const result = await executor.execute({}, env, mockConfig);
191
+ // Should reference the exact environment variable name
192
+ expect(result.script).toContain('${SSH_RSA_PRIVATE_KEY}');
193
+ });
194
+ test('should map to CI Build SSH activation pattern', async () => {
195
+ const executor = new BitriseSSHStepExecutor();
196
+ const env = {
197
+ SSH_RSA_PRIVATE_KEY: 'test-key',
198
+ };
199
+ const result = await executor.execute({}, env, mockConfig);
200
+ // Should include CI Build branding
201
+ expect(result.script).toContain('CI Build SSH activation');
202
+ });
203
+ });
204
+ });
205
+ //# sourceMappingURL=bitrise-ssh.test.js.map
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Cache step implementations (cache-pull and cache-push)
3
+ */
4
+ import { BaseStepExecutor } from './base.js';
5
+ import type { StepDef, CIConfig } from '../../types.js';
6
+ /**
7
+ * Built-in cache presets per technology.
8
+ * When `technology` is set on a cache step, the lockfile is checksummed
9
+ * at runtime to produce the cache key, and the listed paths are cached/restored.
10
+ */
11
+ export interface CachePreset {
12
+ lockfile: string;
13
+ keyPrefix: string;
14
+ paths: string[];
15
+ }
16
+ export declare const CACHE_PRESETS: Record<string, CachePreset>;
17
+ /**
18
+ * Inputs for cache-pull step
19
+ */
20
+ export interface CachePullInputs {
21
+ technology?: string;
22
+ cache_paths?: string[];
23
+ cache_key?: string;
24
+ is_debug_mode?: boolean;
25
+ }
26
+ /**
27
+ * Inputs for cache-push step
28
+ */
29
+ export interface CachePushInputs {
30
+ technology?: string;
31
+ cache_paths?: string[];
32
+ cache_key?: string;
33
+ is_debug_mode?: boolean;
34
+ ignore_check_on_paths?: boolean;
35
+ }
36
+ /**
37
+ * Cache pull step executor
38
+ * Restores cached files from cache directory
39
+ */
40
+ export declare class CachePullStepExecutor extends BaseStepExecutor {
41
+ execute(inputs: CachePullInputs, env: Record<string, string>, config: CIConfig): Promise<StepDef>;
42
+ private executeWithPreset;
43
+ }
44
+ /**
45
+ * Cache push step executor
46
+ * Saves files to cache directory
47
+ */
48
+ export declare class CachePushStepExecutor extends BaseStepExecutor {
49
+ execute(inputs: CachePushInputs, env: Record<string, string>, config: CIConfig): Promise<StepDef>;
50
+ private executeWithPreset;
51
+ }
52
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CASrD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YAoGzF,iBAAiB;CAoEhC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YAwJzF,iBAAiB;CA0EhC"}
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Cache step implementations (cache-pull and cache-push)
3
+ */
4
+ import { BaseStepExecutor } from './base.js';
5
+ export const CACHE_PRESETS = {
6
+ cocoapods: { lockfile: 'Podfile.lock', keyPrefix: 'pods', paths: ['Pods'] },
7
+ carthage: { lockfile: 'Cartfile.resolved', keyPrefix: 'carthage', paths: ['Carthage'] },
8
+ spm: { lockfile: 'Package.resolved', keyPrefix: 'spm', paths: ['~/Library/Developer/Xcode/DerivedData/*/SourcePackages'] },
9
+ gradle: { lockfile: 'gradle/wrapper/gradle-wrapper.properties', keyPrefix: 'gradle', paths: ['~/.gradle/caches', '~/.gradle/wrapper/dists'] },
10
+ kmm: { lockfile: 'gradle/wrapper/gradle-wrapper.properties', keyPrefix: 'kmm', paths: ['~/.gradle/caches', '~/.gradle/wrapper/dists', '~/.konan'] },
11
+ npm: { lockfile: 'package-lock.json', keyPrefix: 'npm', paths: ['node_modules'] },
12
+ yarn: { lockfile: 'yarn.lock', keyPrefix: 'yarn', paths: ['node_modules'] },
13
+ dart: { lockfile: 'pubspec.lock', keyPrefix: 'dart', paths: ['.dart_tool', '.pub-cache'] },
14
+ };
15
+ /**
16
+ * Cache pull step executor
17
+ * Restores cached files from cache directory
18
+ */
19
+ export class CachePullStepExecutor extends BaseStepExecutor {
20
+ async execute(inputs, env, config) {
21
+ const stepName = 'cache-pull';
22
+ if (config.local) {
23
+ const script = this.createBashScriptFromCommands(['echo "⏭️ Cache pull skipped (local mode)"'], stepName);
24
+ return this.createScriptStep(script, stepName);
25
+ }
26
+ // Check for technology preset
27
+ const technology = this.getInput(inputs, 'technology', '').trim();
28
+ if (technology) {
29
+ return this.executeWithPreset(technology, inputs, config);
30
+ }
31
+ // Get cache key - optional (skip if not provided)
32
+ const cacheKey = this.getInput(inputs, 'cache_key', '');
33
+ // Skip if no cache key provided
34
+ if (!cacheKey || cacheKey.trim() === '') {
35
+ const commands = [];
36
+ commands.push('# Cache Pull - Skipped');
37
+ commands.push('echo "⏭️ Cache pull skipped: no cache_key configured"');
38
+ const script = this.createBashScriptFromCommands(commands, stepName);
39
+ return this.createScriptStep(script, stepName);
40
+ }
41
+ // Get cache paths - defaults to empty array (can be string or array)
42
+ const cachePathsInput = this.getInput(inputs, 'cache_paths', []);
43
+ // Normalize to array (handle single string input)
44
+ const cachePaths = Array.isArray(cachePathsInput)
45
+ ? cachePathsInput
46
+ : (typeof cachePathsInput === 'string' && cachePathsInput.trim() !== '')
47
+ ? [cachePathsInput]
48
+ : [];
49
+ // Get debug mode flag
50
+ const isDebugMode = this.getInput(inputs, 'is_debug_mode', false);
51
+ const commands = [];
52
+ commands.push('# Cache Pull');
53
+ commands.push(`echo "Cache key: ${this.escapeBash(cacheKey)}"`);
54
+ // Create cache directory if it doesn't exist
55
+ commands.push('');
56
+ commands.push('# Ensure cache directory exists');
57
+ commands.push(`CACHE_DIR="${this.escapeBash(config.paths.cacheDir)}"`);
58
+ commands.push('mkdir -p "$CACHE_DIR"');
59
+ // Generate cache file name based on cache key
60
+ commands.push('');
61
+ commands.push('# Generate cache file path');
62
+ commands.push(`CACHE_FILE="$CACHE_DIR/${this.escapeBash(cacheKey)}.tar.zst"`);
63
+ if (isDebugMode) {
64
+ commands.push('echo "Debug mode enabled"');
65
+ commands.push('echo "Cache file: $CACHE_FILE"');
66
+ }
67
+ // Check if cache file exists
68
+ commands.push('');
69
+ commands.push('# Check if cache exists');
70
+ commands.push('if [ -f "$CACHE_FILE" ]; then');
71
+ commands.push(' echo "Cache found, extracting..."');
72
+ if (isDebugMode) {
73
+ commands.push(' echo "Cache file size: $(du -h "$CACHE_FILE" | cut -f1)"');
74
+ }
75
+ // Extract cache
76
+ commands.push(' zstd -dc "$CACHE_FILE" | tar -xf - -C /');
77
+ commands.push(' echo "Cache restored successfully"');
78
+ // List restored paths if debug mode
79
+ if (isDebugMode && Array.isArray(cachePaths) && cachePaths.length > 0) {
80
+ commands.push(' echo "Restored paths:"');
81
+ for (const path of cachePaths) {
82
+ commands.push(` EXPANDED_PATH="${this.escapeBash(path)}"`);
83
+ commands.push(' EXPANDED_PATH="${EXPANDED_PATH/#~/$HOME}"');
84
+ commands.push(' if [ -e "$EXPANDED_PATH" ]; then');
85
+ commands.push(' echo " ✓ $EXPANDED_PATH"');
86
+ commands.push(' else');
87
+ commands.push(' echo " ✗ $EXPANDED_PATH (not found)"');
88
+ commands.push(' fi');
89
+ }
90
+ }
91
+ commands.push('else');
92
+ commands.push(` echo "No cache found for key: ${this.escapeBash(cacheKey)}"`);
93
+ commands.push(' echo "This is normal for the first build or after cache expiration"');
94
+ commands.push('fi');
95
+ const script = this.createBashScriptFromCommands(commands, stepName);
96
+ return this.createScriptStep(script, stepName);
97
+ }
98
+ async executeWithPreset(technology, inputs, config) {
99
+ const stepName = 'cache-pull';
100
+ const preset = CACHE_PRESETS[technology];
101
+ if (!preset) {
102
+ const supported = Object.keys(CACHE_PRESETS).join(', ');
103
+ throw new Error(`Unknown cache technology '${technology}'. Supported: ${supported}`);
104
+ }
105
+ const isDebugMode = this.getInput(inputs, 'is_debug_mode', false);
106
+ const commands = [];
107
+ commands.push(`# Cache Pull (${technology})`);
108
+ commands.push(`echo "Restoring ${technology} cache..."`);
109
+ commands.push('');
110
+ // Compute cache key from lockfile checksum at runtime
111
+ commands.push(`CACHE_DIR="${this.escapeBash(config.paths.cacheDir)}"`);
112
+ commands.push('mkdir -p "$CACHE_DIR"');
113
+ commands.push('');
114
+ commands.push(`LOCKFILE="${this.escapeBash(preset.lockfile)}"`);
115
+ commands.push('if [ -f "$LOCKFILE" ]; then');
116
+ commands.push(` CHECKSUM=$(shasum -a 256 "$LOCKFILE" | cut -d ' ' -f1 | head -c 16)`);
117
+ commands.push(` CACHE_KEY="${this.escapeBash(preset.keyPrefix)}-\${CHECKSUM}"`);
118
+ commands.push('else');
119
+ commands.push(` echo "Warning: $LOCKFILE not found, using fallback cache key"`);
120
+ commands.push(` CACHE_KEY="${this.escapeBash(preset.keyPrefix)}-no-lockfile"`);
121
+ commands.push('fi');
122
+ commands.push('');
123
+ if (isDebugMode) {
124
+ commands.push('echo "Lockfile: $LOCKFILE"');
125
+ commands.push('echo "Cache key: $CACHE_KEY"');
126
+ }
127
+ commands.push('CACHE_FILE="$CACHE_DIR/$CACHE_KEY.tar.zst"');
128
+ commands.push('');
129
+ commands.push('if [ -f "$CACHE_FILE" ]; then');
130
+ commands.push(' echo "Cache found, extracting..."');
131
+ if (isDebugMode) {
132
+ commands.push(' echo "Cache file size: $(du -h "$CACHE_FILE" | cut -f1)"');
133
+ }
134
+ commands.push(' zstd -dc "$CACHE_FILE" | tar -xf - -C /');
135
+ commands.push(' echo "Cache restored successfully"');
136
+ if (isDebugMode) {
137
+ commands.push(' echo "Restored paths:"');
138
+ for (const p of preset.paths) {
139
+ commands.push(` EXPANDED="${this.escapeBash(p)}"`);
140
+ commands.push(' EXPANDED="${EXPANDED/#~/$HOME}"');
141
+ commands.push(' if [ -e "$EXPANDED" ]; then');
142
+ commands.push(' echo " ✓ $EXPANDED"');
143
+ commands.push(' else');
144
+ commands.push(' echo " ✗ $EXPANDED (not found)"');
145
+ commands.push(' fi');
146
+ }
147
+ }
148
+ commands.push('else');
149
+ commands.push(' echo "No cache found for key: $CACHE_KEY"');
150
+ commands.push(' echo "This is normal for the first build or after cache expiration"');
151
+ commands.push('fi');
152
+ const script = this.createBashScriptFromCommands(commands, stepName);
153
+ return this.createScriptStep(script, stepName);
154
+ }
155
+ }
156
+ /**
157
+ * Cache push step executor
158
+ * Saves files to cache directory
159
+ */
160
+ export class CachePushStepExecutor extends BaseStepExecutor {
161
+ async execute(inputs, env, config) {
162
+ const stepName = 'cache-push';
163
+ if (config.local) {
164
+ const script = this.createBashScriptFromCommands(['echo "⏭️ Cache push skipped (local mode)"'], stepName);
165
+ return this.createScriptStep(script, stepName);
166
+ }
167
+ // Check for technology preset
168
+ const technology = this.getInput(inputs, 'technology', '').trim();
169
+ if (technology) {
170
+ return this.executeWithPreset(technology, inputs, config);
171
+ }
172
+ // Get cache key - optional (skip if not provided)
173
+ const cacheKey = this.getInput(inputs, 'cache_key', '');
174
+ // Skip if no cache key provided
175
+ if (!cacheKey || cacheKey.trim() === '') {
176
+ const commands = [];
177
+ commands.push('# Cache Push - Skipped');
178
+ commands.push('echo "⏭️ Cache push skipped: no cache_key configured"');
179
+ const script = this.createBashScriptFromCommands(commands, stepName);
180
+ return this.createScriptStep(script, stepName);
181
+ }
182
+ // Get cache paths - required (can be string or array)
183
+ const cachePathsInput = this.getInput(inputs, 'cache_paths', []);
184
+ // Normalize to array (handle single string input)
185
+ const cachePaths = Array.isArray(cachePathsInput)
186
+ ? cachePathsInput
187
+ : (typeof cachePathsInput === 'string' && cachePathsInput.trim() !== '')
188
+ ? [cachePathsInput]
189
+ : [];
190
+ if (cachePaths.length === 0) {
191
+ throw new Error(`Missing or empty 'cache_paths' for step '${stepName}'`);
192
+ }
193
+ // Get debug mode flag
194
+ const isDebugMode = this.getInput(inputs, 'is_debug_mode', false);
195
+ // Get ignore check flag
196
+ const ignoreCheckOnPaths = this.getInput(inputs, 'ignore_check_on_paths', false);
197
+ const commands = [];
198
+ commands.push('# Cache Push');
199
+ commands.push(`echo "Cache key: ${this.escapeBash(cacheKey)}"`);
200
+ // Create cache directory if it doesn't exist
201
+ commands.push('');
202
+ commands.push('# Ensure cache directory exists');
203
+ commands.push(`CACHE_DIR="${this.escapeBash(config.paths.cacheDir)}"`);
204
+ commands.push('mkdir -p "$CACHE_DIR"');
205
+ // Generate cache file name based on cache key
206
+ commands.push('');
207
+ commands.push('# Generate cache file path');
208
+ commands.push(`CACHE_FILE="$CACHE_DIR/${this.escapeBash(cacheKey)}.tar.zst"`);
209
+ if (isDebugMode) {
210
+ commands.push('echo "Debug mode enabled"');
211
+ commands.push('echo "Cache file: $CACHE_FILE"');
212
+ }
213
+ // Check which paths exist
214
+ commands.push('');
215
+ commands.push('# Check which paths exist');
216
+ commands.push('PATHS_TO_CACHE=()');
217
+ for (const path of cachePaths) {
218
+ // Resolve path identifiers (e.g., "derived_data:pattern" -> "~/Library/.../DerivedData/pattern")
219
+ let resolvedPath = path;
220
+ // Check if path uses identifier format (identifier:pattern)
221
+ if (path.includes(':')) {
222
+ const [identifier, pattern] = path.split(':', 2);
223
+ switch (identifier) {
224
+ case 'derived_data':
225
+ resolvedPath = `${config.paths.derivedDataDir}/${pattern}`;
226
+ break;
227
+ case 'builds':
228
+ resolvedPath = `${config.paths.buildsDir}/${pattern}`;
229
+ break;
230
+ default:
231
+ // Unknown identifier, use as-is
232
+ resolvedPath = path;
233
+ }
234
+ }
235
+ // Expand tilde by using parameter expansion
236
+ commands.push(`EXPANDED_PATH="${this.escapeBash(resolvedPath)}"`);
237
+ commands.push('EXPANDED_PATH="${EXPANDED_PATH/#~/$HOME}"');
238
+ commands.push('');
239
+ commands.push('# Expand glob patterns and check each match');
240
+ commands.push('FOUND_MATCH=false');
241
+ commands.push('shopt -s nullglob');
242
+ commands.push('for path_match in $EXPANDED_PATH; do');
243
+ commands.push(' if [ -e "$path_match" ]; then');
244
+ commands.push(' PATHS_TO_CACHE+=("$path_match")');
245
+ commands.push(' FOUND_MATCH=true');
246
+ if (isDebugMode) {
247
+ commands.push(' echo "Found: $path_match"');
248
+ }
249
+ commands.push(' fi');
250
+ commands.push('done');
251
+ commands.push('shopt -u nullglob');
252
+ commands.push('');
253
+ commands.push('if [ "$FOUND_MATCH" = false ]; then');
254
+ if (isDebugMode) {
255
+ commands.push(` echo "Not found: $EXPANDED_PATH"`);
256
+ }
257
+ if (!ignoreCheckOnPaths) {
258
+ commands.push(` echo "Warning: Path does not exist: $EXPANDED_PATH"`);
259
+ }
260
+ commands.push('fi');
261
+ }
262
+ // Create cache if we have paths
263
+ commands.push('');
264
+ commands.push('# Create cache archive');
265
+ commands.push('if [ ${#PATHS_TO_CACHE[@]} -gt 0 ]; then');
266
+ commands.push(' echo "Caching ${#PATHS_TO_CACHE[@]} path(s)..."');
267
+ if (isDebugMode) {
268
+ commands.push(' echo "Paths to cache:"');
269
+ commands.push(' printf " %s\\n" "${PATHS_TO_CACHE[@]}"');
270
+ }
271
+ commands.push(' tar -cf - "${PATHS_TO_CACHE[@]}" 2>/dev/null | zstd -3 > "$CACHE_FILE.tmp" && mv "$CACHE_FILE.tmp" "$CACHE_FILE" || true');
272
+ commands.push(' if [ -f "$CACHE_FILE" ]; then');
273
+ commands.push(' echo "Cache created successfully"');
274
+ if (isDebugMode) {
275
+ commands.push(' echo "Cache size: $(du -h "$CACHE_FILE" | cut -f1)"');
276
+ }
277
+ commands.push(' else');
278
+ commands.push(' echo "Warning: Failed to create cache file"');
279
+ commands.push(' fi');
280
+ commands.push('else');
281
+ commands.push(' echo "No paths to cache"');
282
+ commands.push('fi');
283
+ const script = this.createBashScriptFromCommands(commands, stepName);
284
+ return this.createScriptStep(script, stepName);
285
+ }
286
+ async executeWithPreset(technology, inputs, config) {
287
+ const stepName = 'cache-push';
288
+ const preset = CACHE_PRESETS[technology];
289
+ if (!preset) {
290
+ const supported = Object.keys(CACHE_PRESETS).join(', ');
291
+ throw new Error(`Unknown cache technology '${technology}'. Supported: ${supported}`);
292
+ }
293
+ const isDebugMode = this.getInput(inputs, 'is_debug_mode', false);
294
+ const commands = [];
295
+ commands.push(`# Cache Push (${technology})`);
296
+ commands.push(`echo "Saving ${technology} cache..."`);
297
+ commands.push('');
298
+ // Compute cache key from lockfile checksum at runtime
299
+ commands.push(`CACHE_DIR="${this.escapeBash(config.paths.cacheDir)}"`);
300
+ commands.push('mkdir -p "$CACHE_DIR"');
301
+ commands.push('');
302
+ commands.push(`LOCKFILE="${this.escapeBash(preset.lockfile)}"`);
303
+ commands.push('if [ -f "$LOCKFILE" ]; then');
304
+ commands.push(` CHECKSUM=$(shasum -a 256 "$LOCKFILE" | cut -d ' ' -f1 | head -c 16)`);
305
+ commands.push(` CACHE_KEY="${this.escapeBash(preset.keyPrefix)}-\${CHECKSUM}"`);
306
+ commands.push('else');
307
+ commands.push(` echo "Warning: $LOCKFILE not found, using fallback cache key"`);
308
+ commands.push(` CACHE_KEY="${this.escapeBash(preset.keyPrefix)}-no-lockfile"`);
309
+ commands.push('fi');
310
+ commands.push('');
311
+ if (isDebugMode) {
312
+ commands.push('echo "Lockfile: $LOCKFILE"');
313
+ commands.push('echo "Cache key: $CACHE_KEY"');
314
+ }
315
+ commands.push('CACHE_FILE="$CACHE_DIR/$CACHE_KEY.tar.zst"');
316
+ commands.push('');
317
+ // Collect paths to cache
318
+ commands.push('# Collect paths to cache');
319
+ commands.push('PATHS_TO_CACHE=()');
320
+ for (const p of preset.paths) {
321
+ commands.push(`EXPANDED="${this.escapeBash(p)}"`);
322
+ commands.push('EXPANDED="${EXPANDED/#~/$HOME}"');
323
+ commands.push('if [ -e "$EXPANDED" ]; then');
324
+ commands.push(' PATHS_TO_CACHE+=("$EXPANDED")');
325
+ if (isDebugMode) {
326
+ commands.push(' echo "Found: $EXPANDED"');
327
+ }
328
+ commands.push('else');
329
+ commands.push(` echo "Warning: Path does not exist: $EXPANDED"`);
330
+ commands.push('fi');
331
+ }
332
+ commands.push('');
333
+ // Create cache archive
334
+ commands.push('if [ ${#PATHS_TO_CACHE[@]} -gt 0 ]; then');
335
+ commands.push(' echo "Caching ${#PATHS_TO_CACHE[@]} path(s)..."');
336
+ commands.push(' tar -cf - "${PATHS_TO_CACHE[@]}" 2>/dev/null | zstd -3 > "$CACHE_FILE.tmp" && mv "$CACHE_FILE.tmp" "$CACHE_FILE" || true');
337
+ commands.push(' if [ -f "$CACHE_FILE" ]; then');
338
+ commands.push(' echo "Cache created successfully"');
339
+ if (isDebugMode) {
340
+ commands.push(' echo "Cache size: $(du -h "$CACHE_FILE" | cut -f1)"');
341
+ }
342
+ commands.push(' else');
343
+ commands.push(' echo "Warning: Failed to create cache file"');
344
+ commands.push(' fi');
345
+ commands.push('else');
346
+ commands.push(' echo "No paths to cache"');
347
+ commands.push('fi');
348
+ const script = this.createBashScriptFromCommands(commands, stepName);
349
+ return this.createScriptStep(script, stepName);
350
+ }
351
+ }
352
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Fastlane step: run a fastlane lane
3
+ */
4
+ import { BaseStepExecutor } from './base.js';
5
+ import type { StepDef, CIConfig } from '../../types.js';
6
+ import type { ValidationRequirement, StepOutput } from '../validation-types.js';
7
+ export interface FastlaneInputs {
8
+ /** Fastlane lane to run (required) */
9
+ lane?: string;
10
+ /** Working directory (parent of fastlane directory) */
11
+ work_dir?: string;
12
+ /** Update fastlane gem before run (true/false) */
13
+ update_fastlane?: string;
14
+ /** Enable verbose logging (yes/no) */
15
+ verbose_log?: string;
16
+ /** Enable collecting cache files (yes/no) */
17
+ enable_cache?: string;
18
+ }
19
+ /**
20
+ * Runs a fastlane lane with Gemfile detection and optional gem update.
21
+ */
22
+ export declare class FastlaneStepExecutor extends BaseStepExecutor {
23
+ getValidationRequirements(_inputs: FastlaneInputs, _env: Record<string, string>, _config: CIConfig): ValidationRequirement[];
24
+ getOutputs(): StepOutput[];
25
+ execute(inputs: FastlaneInputs, _env: Record<string, string>, _config: CIConfig): Promise<StepDef>;
26
+ }
27
+ //# sourceMappingURL=fastlane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastlane.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/fastlane.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEhF,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,gBAAgB;IACxD,yBAAyB,CACvB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAM1B,UAAU,IAAI,UAAU,EAAE;IAIpB,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;CAuEzG"}