@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.
- package/dist/cli.cjs +1 -1
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +987 -0
- package/dist/src/commands/android-scanner.d.ts +32 -0
- package/dist/src/commands/android-scanner.d.ts.map +1 -0
- package/dist/src/commands/android-scanner.js +667 -0
- package/dist/src/commands/build.d.ts +5 -0
- package/dist/src/commands/build.d.ts.map +1 -0
- package/dist/src/commands/build.js +1096 -0
- package/dist/src/commands/edit.d.ts +3 -0
- package/dist/src/commands/edit.d.ts.map +1 -0
- package/dist/src/commands/edit.js +651 -0
- package/dist/src/commands/file-secret-collector.d.ts +37 -0
- package/dist/src/commands/file-secret-collector.d.ts.map +1 -0
- package/dist/src/commands/file-secret-collector.js +199 -0
- package/dist/src/commands/github-workflow.d.ts +5 -0
- package/dist/src/commands/github-workflow.d.ts.map +1 -0
- package/dist/src/commands/github-workflow.js +45 -0
- package/dist/src/commands/ios-scanner.d.ts +27 -0
- package/dist/src/commands/ios-scanner.d.ts.map +1 -0
- package/dist/src/commands/ios-scanner.js +337 -0
- package/dist/src/commands/reset.d.ts +7 -0
- package/dist/src/commands/reset.d.ts.map +1 -0
- package/dist/src/commands/reset.js +81 -0
- package/dist/src/commands/secrets-sync-workflow.d.ts +15 -0
- package/dist/src/commands/secrets-sync-workflow.d.ts.map +1 -0
- package/dist/src/commands/secrets-sync-workflow.js +255 -0
- package/dist/src/commands/secrets-upload.d.ts +21 -0
- package/dist/src/commands/secrets-upload.d.ts.map +1 -0
- package/dist/src/commands/secrets-upload.js +177 -0
- package/dist/src/commands/secrets-upload.test.d.ts +5 -0
- package/dist/src/commands/secrets-upload.test.d.ts.map +1 -0
- package/dist/src/commands/secrets-upload.test.js +60 -0
- package/dist/src/config.d.ts +3 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +47 -0
- package/dist/src/envman/cli.d.ts +21 -0
- package/dist/src/envman/cli.d.ts.map +1 -0
- package/dist/src/envman/cli.js +240 -0
- package/dist/src/envman/envman.d.ts +83 -0
- package/dist/src/envman/envman.d.ts.map +1 -0
- package/dist/src/envman/envman.js +361 -0
- package/dist/src/envman/envman.test.d.ts +5 -0
- package/dist/src/envman/envman.test.d.ts.map +1 -0
- package/dist/src/envman/envman.test.js +236 -0
- package/dist/src/envman/index.d.ts +23 -0
- package/dist/src/envman/index.d.ts.map +1 -0
- package/dist/src/envman/index.js +23 -0
- package/dist/src/envman/types.d.ts +55 -0
- package/dist/src/envman/types.d.ts.map +1 -0
- package/dist/src/envman/types.js +12 -0
- package/dist/src/lib.d.ts +27 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +32 -0
- package/dist/src/pipeline.d.ts +3 -0
- package/dist/src/pipeline.d.ts.map +1 -0
- package/dist/src/pipeline.js +57 -0
- package/dist/src/runner.d.ts +17 -0
- package/dist/src/runner.d.ts.map +1 -0
- package/dist/src/runner.js +234 -0
- package/dist/src/types.d.ts +58 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/yaml/bitrise-compat.d.ts +65 -0
- package/dist/src/yaml/bitrise-compat.d.ts.map +1 -0
- package/dist/src/yaml/bitrise-compat.js +206 -0
- package/dist/src/yaml/bitrise-compat.test.d.ts +5 -0
- package/dist/src/yaml/bitrise-compat.test.d.ts.map +1 -0
- package/dist/src/yaml/bitrise-compat.test.js +347 -0
- package/dist/src/yaml/converter.d.ts +33 -0
- package/dist/src/yaml/converter.d.ts.map +1 -0
- package/dist/src/yaml/converter.js +222 -0
- package/dist/src/yaml/converter.test.d.ts +5 -0
- package/dist/src/yaml/converter.test.d.ts.map +1 -0
- package/dist/src/yaml/converter.test.js +348 -0
- package/dist/src/yaml/e2e.test.d.ts +6 -0
- package/dist/src/yaml/e2e.test.d.ts.map +1 -0
- package/dist/src/yaml/e2e.test.js +446 -0
- package/dist/src/yaml/env-resolver.d.ts +120 -0
- package/dist/src/yaml/env-resolver.d.ts.map +1 -0
- package/dist/src/yaml/env-resolver.js +405 -0
- package/dist/src/yaml/env-resolver.test.d.ts +5 -0
- package/dist/src/yaml/env-resolver.test.d.ts.map +1 -0
- package/dist/src/yaml/env-resolver.test.js +502 -0
- package/dist/src/yaml/interactive-prompts.d.ts +71 -0
- package/dist/src/yaml/interactive-prompts.d.ts.map +1 -0
- package/dist/src/yaml/interactive-prompts.js +258 -0
- package/dist/src/yaml/missing-env-handler.d.ts +45 -0
- package/dist/src/yaml/missing-env-handler.d.ts.map +1 -0
- package/dist/src/yaml/missing-env-handler.js +64 -0
- package/dist/src/yaml/parser.d.ts +33 -0
- package/dist/src/yaml/parser.d.ts.map +1 -0
- package/dist/src/yaml/parser.js +145 -0
- package/dist/src/yaml/pipeline-with-secrets.d.ts +25 -0
- package/dist/src/yaml/pipeline-with-secrets.d.ts.map +1 -0
- package/dist/src/yaml/pipeline-with-secrets.js +76 -0
- package/dist/src/yaml/platform-detector.d.ts +83 -0
- package/dist/src/yaml/platform-detector.d.ts.map +1 -0
- package/dist/src/yaml/platform-detector.js +188 -0
- package/dist/src/yaml/platform-detector.test.d.ts +5 -0
- package/dist/src/yaml/platform-detector.test.d.ts.map +1 -0
- package/dist/src/yaml/platform-detector.test.js +414 -0
- package/dist/src/yaml/preflight-validation.d.ts +40 -0
- package/dist/src/yaml/preflight-validation.d.ts.map +1 -0
- package/dist/src/yaml/preflight-validation.js +152 -0
- package/dist/src/yaml/secrets-manager.d.ts +77 -0
- package/dist/src/yaml/secrets-manager.d.ts.map +1 -0
- package/dist/src/yaml/secrets-manager.js +219 -0
- package/dist/src/yaml/step-validator.d.ts +54 -0
- package/dist/src/yaml/step-validator.d.ts.map +1 -0
- package/dist/src/yaml/step-validator.js +403 -0
- package/dist/src/yaml/steps/android-sign.d.ts +35 -0
- package/dist/src/yaml/steps/android-sign.d.ts.map +1 -0
- package/dist/src/yaml/steps/android-sign.js +147 -0
- package/dist/src/yaml/steps/android-version.d.ts +26 -0
- package/dist/src/yaml/steps/android-version.d.ts.map +1 -0
- package/dist/src/yaml/steps/android-version.js +128 -0
- package/dist/src/yaml/steps/android-version.test.d.ts +5 -0
- package/dist/src/yaml/steps/android-version.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/android-version.test.js +196 -0
- package/dist/src/yaml/steps/android.d.ts +95 -0
- package/dist/src/yaml/steps/android.d.ts.map +1 -0
- package/dist/src/yaml/steps/android.js +916 -0
- package/dist/src/yaml/steps/app-store-deploy.d.ts +48 -0
- package/dist/src/yaml/steps/app-store-deploy.d.ts.map +1 -0
- package/dist/src/yaml/steps/app-store-deploy.js +162 -0
- package/dist/src/yaml/steps/base.d.ts +238 -0
- package/dist/src/yaml/steps/base.d.ts.map +1 -0
- package/dist/src/yaml/steps/base.js +345 -0
- package/dist/src/yaml/steps/bitrise-android-tools.d.ts +26 -0
- package/dist/src/yaml/steps/bitrise-android-tools.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-android-tools.js +198 -0
- package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-android-tools.test.js +280 -0
- package/dist/src/yaml/steps/bitrise-apk-info.d.ts +22 -0
- package/dist/src/yaml/steps/bitrise-apk-info.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-apk-info.js +144 -0
- package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-apk-info.test.js +331 -0
- package/dist/src/yaml/steps/bitrise-slack.d.ts +49 -0
- package/dist/src/yaml/steps/bitrise-slack.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-slack.js +280 -0
- package/dist/src/yaml/steps/bitrise-slack.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-slack.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-slack.test.js +484 -0
- package/dist/src/yaml/steps/bitrise-ssh.d.ts +27 -0
- package/dist/src/yaml/steps/bitrise-ssh.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-ssh.js +134 -0
- package/dist/src/yaml/steps/bitrise-ssh.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-ssh.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-ssh.test.js +205 -0
- package/dist/src/yaml/steps/cache.d.ts +52 -0
- package/dist/src/yaml/steps/cache.d.ts.map +1 -0
- package/dist/src/yaml/steps/cache.js +352 -0
- package/dist/src/yaml/steps/fastlane.d.ts +27 -0
- package/dist/src/yaml/steps/fastlane.d.ts.map +1 -0
- package/dist/src/yaml/steps/fastlane.js +79 -0
- package/dist/src/yaml/steps/file.d.ts +27 -0
- package/dist/src/yaml/steps/file.d.ts.map +1 -0
- package/dist/src/yaml/steps/file.js +35 -0
- package/dist/src/yaml/steps/flutter.d.ts +63 -0
- package/dist/src/yaml/steps/flutter.d.ts.map +1 -0
- package/dist/src/yaml/steps/flutter.js +215 -0
- package/dist/src/yaml/steps/git-clone.d.ts +26 -0
- package/dist/src/yaml/steps/git-clone.d.ts.map +1 -0
- package/dist/src/yaml/steps/git-clone.js +111 -0
- package/dist/src/yaml/steps/google-play-deploy.d.ts +37 -0
- package/dist/src/yaml/steps/google-play-deploy.d.ts.map +1 -0
- package/dist/src/yaml/steps/google-play-deploy.js +193 -0
- package/dist/src/yaml/steps/google-play-deploy.test.d.ts +5 -0
- package/dist/src/yaml/steps/google-play-deploy.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/google-play-deploy.test.js +310 -0
- package/dist/src/yaml/steps/index.d.ts +10 -0
- package/dist/src/yaml/steps/index.d.ts.map +1 -0
- package/dist/src/yaml/steps/index.js +1361 -0
- package/dist/src/yaml/steps/ios-deps.d.ts +43 -0
- package/dist/src/yaml/steps/ios-deps.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-deps.js +141 -0
- package/dist/src/yaml/steps/ios-deps.test.d.ts +5 -0
- package/dist/src/yaml/steps/ios-deps.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-deps.test.js +90 -0
- package/dist/src/yaml/steps/ios-signing.d.ts +31 -0
- package/dist/src/yaml/steps/ios-signing.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-signing.js +144 -0
- package/dist/src/yaml/steps/ios-version.d.ts +47 -0
- package/dist/src/yaml/steps/ios-version.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-version.js +151 -0
- package/dist/src/yaml/steps/linting.d.ts +47 -0
- package/dist/src/yaml/steps/linting.d.ts.map +1 -0
- package/dist/src/yaml/steps/linting.js +148 -0
- package/dist/src/yaml/steps/phase2.test.d.ts +6 -0
- package/dist/src/yaml/steps/phase2.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase2.test.js +197 -0
- package/dist/src/yaml/steps/phase3.test.d.ts +5 -0
- package/dist/src/yaml/steps/phase3.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase3.test.js +144 -0
- package/dist/src/yaml/steps/phase4.test.d.ts +5 -0
- package/dist/src/yaml/steps/phase4.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase4.test.js +166 -0
- package/dist/src/yaml/steps/phase5.test.d.ts +6 -0
- package/dist/src/yaml/steps/phase5.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase5.test.js +263 -0
- package/dist/src/yaml/steps/registry.d.ts +88 -0
- package/dist/src/yaml/steps/registry.d.ts.map +1 -0
- package/dist/src/yaml/steps/registry.js +125 -0
- package/dist/src/yaml/steps/registry.test.d.ts +5 -0
- package/dist/src/yaml/steps/registry.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/registry.test.js +235 -0
- package/dist/src/yaml/steps/release.d.ts +50 -0
- package/dist/src/yaml/steps/release.d.ts.map +1 -0
- package/dist/src/yaml/steps/release.js +154 -0
- package/dist/src/yaml/steps/script.d.ts +23 -0
- package/dist/src/yaml/steps/script.d.ts.map +1 -0
- package/dist/src/yaml/steps/script.js +63 -0
- package/dist/src/yaml/steps/spec-validation.test.d.ts +6 -0
- package/dist/src/yaml/steps/spec-validation.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/spec-validation.test.js +130 -0
- package/dist/src/yaml/steps/steps.test.d.ts +6 -0
- package/dist/src/yaml/steps/steps.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/steps.test.js +505 -0
- package/dist/src/yaml/steps/test-config.d.ts +3 -0
- package/dist/src/yaml/steps/test-config.d.ts.map +1 -0
- package/dist/src/yaml/steps/test-config.js +17 -0
- package/dist/src/yaml/steps/xcode-new.test.d.ts +5 -0
- package/dist/src/yaml/steps/xcode-new.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/xcode-new.test.js +211 -0
- package/dist/src/yaml/steps/xcode.d.ts +222 -0
- package/dist/src/yaml/steps/xcode.d.ts.map +1 -0
- package/dist/src/yaml/steps/xcode.js +999 -0
- package/dist/src/yaml/types.d.ts +68 -0
- package/dist/src/yaml/types.d.ts.map +1 -0
- package/dist/src/yaml/types.js +5 -0
- package/dist/src/yaml/validation-types.d.ts +96 -0
- package/dist/src/yaml/validation-types.d.ts.map +1 -0
- package/dist/src/yaml/validation-types.js +8 -0
- package/dist/src/yaml/yaml-updater.d.ts +24 -0
- package/dist/src/yaml/yaml-updater.d.ts.map +1 -0
- package/dist/src/yaml/yaml-updater.js +128 -0
- 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"}
|