@invarn/cibuild 2.6.4 → 2.6.6
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 +10 -10
- package/dist/src/commands/android-gms-guard.test.d.ts +9 -0
- package/dist/src/commands/android-gms-guard.test.d.ts.map +1 -0
- package/dist/src/commands/android-gms-guard.test.js +78 -0
- package/dist/src/commands/android-java-version.test.d.ts +12 -0
- package/dist/src/commands/android-java-version.test.d.ts.map +1 -0
- package/dist/src/commands/android-java-version.test.js +85 -0
- package/dist/src/commands/android-scanner.d.ts +68 -0
- package/dist/src/commands/android-scanner.d.ts.map +1 -1
- package/dist/src/commands/android-scanner.js +168 -7
- package/dist/src/commands/build.d.ts.map +1 -1
- package/dist/src/commands/build.js +5 -5
- package/dist/src/yaml/cache-key-missing-file.test.d.ts +12 -0
- package/dist/src/yaml/cache-key-missing-file.test.d.ts.map +1 -0
- package/dist/src/yaml/cache-key-missing-file.test.js +116 -0
- package/dist/src/yaml/converter.d.ts.map +1 -1
- package/dist/src/yaml/converter.js +32 -2
- package/dist/src/yaml/env-resolver.d.ts +13 -0
- package/dist/src/yaml/env-resolver.d.ts.map +1 -1
- package/dist/src/yaml/env-resolver.js +28 -8
- package/dist/src/yaml/preflight-validation.d.ts +12 -23
- package/dist/src/yaml/preflight-validation.d.ts.map +1 -1
- package/dist/src/yaml/preflight-validation.js +11 -142
- package/dist/src/yaml/steps/android.d.ts.map +1 -1
- package/dist/src/yaml/steps/android.js +17 -1
- package/dist/src/yaml/steps/git-clone.d.ts +8 -2
- package/dist/src/yaml/steps/git-clone.d.ts.map +1 -1
- package/dist/src/yaml/steps/git-clone.js +8 -2
- package/dist/src/yaml/steps/index.d.ts.map +1 -1
- package/dist/src/yaml/steps/index.js +9 -5
- package/dist/src/yaml/steps/steps.test.js +32 -0
- package/package.json +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A cache key that cannot be computed costs a cache, not a pipeline.
|
|
3
|
+
*
|
|
4
|
+
* `cache_key: pods-{{checksum "Podfile.lock"}}` in a repository with no
|
|
5
|
+
* Podfile.lock used to abort conversion, so the build died at `cache-pull`
|
|
6
|
+
* before compiling a single file — including in repositories that use Swift
|
|
7
|
+
* Package Manager and have no reason to own a CocoaPods lockfile at all.
|
|
8
|
+
* Every other step keeps the hard failure: a checksum in a real input is a
|
|
9
|
+
* value that step needs.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
|
12
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { convertYAMLToPipelineDef } from './converter.js';
|
|
16
|
+
import { clearRegistry, registerStep } from './steps/registry.js';
|
|
17
|
+
import { ScriptStepExecutor } from './steps/script.js';
|
|
18
|
+
import { CachePullStepExecutor, CachePushStepExecutor } from './steps/cache.js';
|
|
19
|
+
const mockConfig = {
|
|
20
|
+
artifactsDir: '/test/artifacts',
|
|
21
|
+
maxConcurrentJobs: 1,
|
|
22
|
+
paths: {
|
|
23
|
+
buildsDir: '/test/builds',
|
|
24
|
+
cacheDir: '/test/cache',
|
|
25
|
+
derivedDataDir: '/test/derived-data',
|
|
26
|
+
},
|
|
27
|
+
interpreters: {
|
|
28
|
+
bash: '/bin/bash',
|
|
29
|
+
python: 'python3',
|
|
30
|
+
ruby: 'ruby',
|
|
31
|
+
node: 'node',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
let workdir;
|
|
35
|
+
let previousCwd;
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
clearRegistry();
|
|
38
|
+
registerStep('script', new ScriptStepExecutor());
|
|
39
|
+
registerStep('cache-pull', new CachePullStepExecutor());
|
|
40
|
+
registerStep('cache-push', new CachePushStepExecutor());
|
|
41
|
+
previousCwd = process.cwd();
|
|
42
|
+
workdir = mkdtempSync(join(tmpdir(), 'cibuild-checksum-'));
|
|
43
|
+
process.chdir(workdir);
|
|
44
|
+
});
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
process.chdir(previousCwd);
|
|
47
|
+
rmSync(workdir, { recursive: true, force: true });
|
|
48
|
+
clearRegistry();
|
|
49
|
+
});
|
|
50
|
+
function pipelineWithPodsCache() {
|
|
51
|
+
return {
|
|
52
|
+
format_version: '1',
|
|
53
|
+
workflows: {
|
|
54
|
+
primary: {
|
|
55
|
+
steps: [
|
|
56
|
+
{
|
|
57
|
+
'cache-pull': {
|
|
58
|
+
inputs: {
|
|
59
|
+
cache_key: 'pods-{{checksum "Podfile.lock"}}',
|
|
60
|
+
cache_paths: ['Pods'],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
script: {
|
|
66
|
+
title: 'Build',
|
|
67
|
+
inputs: { content: 'echo building' },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
'cache-push': {
|
|
72
|
+
inputs: {
|
|
73
|
+
cache_key: 'pods-{{checksum "Podfile.lock"}}',
|
|
74
|
+
cache_paths: ['Pods'],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
describe('a cache key naming a file this repository does not have', () => {
|
|
84
|
+
test('skips the cache steps and keeps the build', async () => {
|
|
85
|
+
const result = await convertYAMLToPipelineDef(pipelineWithPodsCache(), mockConfig, 'primary');
|
|
86
|
+
expect(result.skippedSteps).toBe(2);
|
|
87
|
+
expect(Object.keys(result.pipeline.steps ?? {})).toHaveLength(1);
|
|
88
|
+
expect(result.warnings.join('\n')).toContain('Podfile.lock');
|
|
89
|
+
expect(result.warnings.join('\n')).toContain('uncached');
|
|
90
|
+
});
|
|
91
|
+
test('keeps the cache steps once the file is there', async () => {
|
|
92
|
+
writeFileSync(join(workdir, 'Podfile.lock'), 'PODFILE CHECKSUM: abc\n');
|
|
93
|
+
const result = await convertYAMLToPipelineDef(pipelineWithPodsCache(), mockConfig, 'primary');
|
|
94
|
+
expect(result.skippedSteps).toBe(0);
|
|
95
|
+
expect(Object.keys(result.pipeline.steps ?? {})).toHaveLength(3);
|
|
96
|
+
});
|
|
97
|
+
test('still fails a non-cache step whose checksum names a missing file', async () => {
|
|
98
|
+
const pipeline = {
|
|
99
|
+
format_version: '1',
|
|
100
|
+
workflows: {
|
|
101
|
+
primary: {
|
|
102
|
+
steps: [
|
|
103
|
+
{
|
|
104
|
+
script: {
|
|
105
|
+
title: 'Build',
|
|
106
|
+
inputs: { content: 'echo {{checksum "Podfile.lock"}}' },
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
await expect(convertYAMLToPipelineDef(pipeline, mockConfig, 'primary')).rejects.toThrow('Podfile.lock');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=cache-key-missing-file.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../../src/yaml/converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAC;AAMzE,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../../src/yaml/converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAC;AAMzE,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AA6CD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,QAAQ,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAgK3B;AAwGD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE,CAEtE"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { getInvarnMeta } from './meta-helpers.js';
|
|
6
6
|
import { detectPlatformInfo } from './platform-detector.js';
|
|
7
|
-
import { EnvResolver } from './env-resolver.js';
|
|
7
|
+
import { EnvResolver, ChecksumFileMissingError } from './env-resolver.js';
|
|
8
8
|
import { getStepExecutor, UnrecognizedStepError } from './steps/registry.js';
|
|
9
9
|
export class YAMLConversionError extends Error {
|
|
10
10
|
constructor(message) {
|
|
@@ -12,6 +12,15 @@ export class YAMLConversionError extends Error {
|
|
|
12
12
|
this.name = 'YAMLConversionError';
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* The steps whose whole job is to make a build faster. Nothing they do is
|
|
17
|
+
* required for the build to be correct, so an input they cannot resolve
|
|
18
|
+
* costs a cache, not a pipeline.
|
|
19
|
+
*/
|
|
20
|
+
const CACHE_STEPS = new Set(['cache-pull', 'cache-push']);
|
|
21
|
+
function isCacheStep(stepName) {
|
|
22
|
+
return CACHE_STEPS.has(stepName);
|
|
23
|
+
}
|
|
15
24
|
/**
|
|
16
25
|
* Mapping of common unsupported steps to CI Build alternatives
|
|
17
26
|
*/
|
|
@@ -123,7 +132,28 @@ export async function convertYAMLToPipelineDef(pipeline, config, workflowName, y
|
|
|
123
132
|
throw error;
|
|
124
133
|
}
|
|
125
134
|
// Interpolate step inputs
|
|
126
|
-
|
|
135
|
+
//
|
|
136
|
+
// A cache step whose key cannot be computed is not a broken pipeline. The
|
|
137
|
+
// key is usually `{{checksum "<lockfile>"}}`, and a repository without
|
|
138
|
+
// that lockfile has nothing to key a cache on — so there is no cache, and
|
|
139
|
+
// the build runs cold. Letting the error through instead killed five iOS
|
|
140
|
+
// builds in a thirty-repository study at `cache-pull`, before a single
|
|
141
|
+
// file compiled, on a CocoaPods lockfile that two of them had no reason
|
|
142
|
+
// to have. Every other step keeps the hard failure: a checksum in a real
|
|
143
|
+
// input is a value the step needs.
|
|
144
|
+
let interpolatedInputs;
|
|
145
|
+
try {
|
|
146
|
+
interpolatedInputs = envResolver.interpolateObject(parsedStep.inputs, parsedStep.title || parsedStep.name);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (error instanceof ChecksumFileMissingError && isCacheStep(resolvedStepName)) {
|
|
150
|
+
warnings.push(`⚠️ ${resolvedStepName}: no ${error.filePath} in this repository, so there is ` +
|
|
151
|
+
`nothing to key the cache on (skipping — the build runs uncached)`);
|
|
152
|
+
skippedSteps++;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
127
157
|
// Execute step to get script
|
|
128
158
|
const stepDef = await stepExecutor.execute(interpolatedInputs, envResolver.getAll(), config);
|
|
129
159
|
// Generate unique step ID
|
|
@@ -10,6 +10,19 @@ export declare class MissingEnvironmentVariableError extends Error {
|
|
|
10
10
|
readonly hint?: string | undefined;
|
|
11
11
|
constructor(variableName: string, stepName?: string | undefined, hint?: string | undefined);
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* A `{{checksum "path"}}` naming a file this checkout does not have.
|
|
15
|
+
*
|
|
16
|
+
* Distinct from a generic read failure because a caller can reasonably
|
|
17
|
+
* decide it does not matter. A cache key is the usual case: the file is
|
|
18
|
+
* absent, so there is nothing to key a cache on, so there is no cache — which
|
|
19
|
+
* is a slower build, not a broken one.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ChecksumFileMissingError extends Error {
|
|
22
|
+
readonly filePath: string;
|
|
23
|
+
readonly stepName?: string | undefined;
|
|
24
|
+
constructor(filePath: string, stepName?: string | undefined);
|
|
25
|
+
}
|
|
13
26
|
/**
|
|
14
27
|
* EnvResolver handles environment variable merging and interpolation
|
|
15
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-resolver.d.ts","sourceRoot":"","sources":["../../../src/yaml/env-resolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAc,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgEnF,qBAAa,+BAAgC,SAAQ,KAAK;aAEtC,YAAY,EAAE,MAAM;aACpB,QAAQ,CAAC,EAAE,MAAM;aACjB,IAAI,CAAC,EAAE,MAAM;gBAFb,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,IAAI,CAAC,EAAE,MAAM,YAAA;CAUhC;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,cAAc,CAAiB;gBAGrC,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM;IA0BvB;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKrC;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMtC;;;OAGG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQhC;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IA0BnD;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG;IAoBnD;;;OAGG;IACH,sBAAsB,IAAI,IAAI;IAQ9B;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAalB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"env-resolver.d.ts","sourceRoot":"","sources":["../../../src/yaml/env-resolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAc,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgEnF,qBAAa,+BAAgC,SAAQ,KAAK;aAEtC,YAAY,EAAE,MAAM;aACpB,QAAQ,CAAC,EAAE,MAAM;aACjB,IAAI,CAAC,EAAE,MAAM;gBAFb,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,IAAI,CAAC,EAAE,MAAM,YAAA;CAUhC;AAED;;;;;;;GAOG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;aAE/B,QAAQ,EAAE,MAAM;aAChB,QAAQ,CAAC,EAAE,MAAM;gBADjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,YAAA;CAKpC;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,cAAc,CAAiB;gBAGrC,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM;IA0BvB;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKrC;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMtC;;;OAGG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQhC;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IA0BnD;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG;IAoBnD;;;OAGG;IACH,sBAAsB,IAAI,IAAI;IAQ9B;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAalB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA0BvB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IA4FtB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAkBpB;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAuB9B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;CAS5B;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,WAAW,CAOb"}
|
|
@@ -76,6 +76,24 @@ export class MissingEnvironmentVariableError extends Error {
|
|
|
76
76
|
this.name = 'MissingEnvironmentVariableError';
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* A `{{checksum "path"}}` naming a file this checkout does not have.
|
|
81
|
+
*
|
|
82
|
+
* Distinct from a generic read failure because a caller can reasonably
|
|
83
|
+
* decide it does not matter. A cache key is the usual case: the file is
|
|
84
|
+
* absent, so there is nothing to key a cache on, so there is no cache — which
|
|
85
|
+
* is a slower build, not a broken one.
|
|
86
|
+
*/
|
|
87
|
+
export class ChecksumFileMissingError extends Error {
|
|
88
|
+
filePath;
|
|
89
|
+
stepName;
|
|
90
|
+
constructor(filePath, stepName) {
|
|
91
|
+
super(`Failed to compute checksum for "${filePath}": File not found: ${filePath}`);
|
|
92
|
+
this.filePath = filePath;
|
|
93
|
+
this.stepName = stepName;
|
|
94
|
+
this.name = 'ChecksumFileMissingError';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
79
97
|
/**
|
|
80
98
|
* EnvResolver handles environment variable merging and interpolation
|
|
81
99
|
*/
|
|
@@ -158,7 +176,7 @@ export class EnvResolver {
|
|
|
158
176
|
let result = str;
|
|
159
177
|
// Format 1: {{checksum "file"}}
|
|
160
178
|
result = result.replace(/\{\{checksum "([^"]+)"\}\}/g, (match, filePath) => {
|
|
161
|
-
return this.computeChecksum(filePath);
|
|
179
|
+
return this.computeChecksum(filePath, stepName);
|
|
162
180
|
});
|
|
163
181
|
// Format 2: {{getenv "VAR"}}
|
|
164
182
|
result = result.replace(/\{\{getenv "([^"]+)"\}\}/g, (match, varName) => {
|
|
@@ -230,14 +248,16 @@ export class EnvResolver {
|
|
|
230
248
|
* @returns MD5 hash of file contents
|
|
231
249
|
* @throws Error if file does not exist or cannot be read
|
|
232
250
|
*/
|
|
233
|
-
computeChecksum(filePath) {
|
|
251
|
+
computeChecksum(filePath, stepName) {
|
|
252
|
+
// Resolve relative path to absolute path
|
|
253
|
+
const absolutePath = path.resolve(process.cwd(), filePath);
|
|
254
|
+
// A file this checkout does not have gets its own error type, so a
|
|
255
|
+
// caller that can carry on without it — a cache key — can tell it apart
|
|
256
|
+
// from a file that exists and could not be read.
|
|
257
|
+
if (!fs.existsSync(absolutePath)) {
|
|
258
|
+
throw new ChecksumFileMissingError(filePath, stepName);
|
|
259
|
+
}
|
|
234
260
|
try {
|
|
235
|
-
// Resolve relative path to absolute path
|
|
236
|
-
const absolutePath = path.resolve(process.cwd(), filePath);
|
|
237
|
-
// Check if file exists
|
|
238
|
-
if (!fs.existsSync(absolutePath)) {
|
|
239
|
-
throw new Error(`File not found: ${filePath}`);
|
|
240
|
-
}
|
|
241
261
|
// Read file and compute MD5 hash
|
|
242
262
|
const fileBuffer = fs.readFileSync(absolutePath);
|
|
243
263
|
const hash = crypto.createHash('md5');
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pre-flight validation
|
|
3
|
-
*
|
|
2
|
+
* Pre-flight validation hook that runs before any workflow step executes.
|
|
3
|
+
*
|
|
4
|
+
* It no longer checks anything. The checks it used to carry — that
|
|
5
|
+
* CIBUILD_GIT_REPOSITORY_URL is set and reachable, and that activate-ssh-key
|
|
6
|
+
* precedes git-clone — assumed cibuild would clone the repository itself. It
|
|
7
|
+
* does not: the source is already on disk when a pipeline runs (a runner
|
|
8
|
+
* checks out the dispatched commit before cibuild starts; locally it is the
|
|
9
|
+
* working copy), so there is no remote to validate before execution. The
|
|
10
|
+
* class and its `validate()` signature are kept so the call site in
|
|
11
|
+
* pipeline-with-secrets.ts is unchanged.
|
|
4
12
|
*/
|
|
5
|
-
import { MissingEnvironmentVariableError } from './env-resolver.js';
|
|
13
|
+
import type { MissingEnvironmentVariableError } from './env-resolver.js';
|
|
6
14
|
import type { SecretsManager } from './secrets-manager.js';
|
|
7
15
|
import type { YAMLWorkflow } from './types.js';
|
|
8
16
|
/**
|
|
@@ -12,28 +20,9 @@ export interface PreFlightResult {
|
|
|
12
20
|
success: boolean;
|
|
13
21
|
error?: MissingEnvironmentVariableError;
|
|
14
22
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Validates that required environment variables exist and repository is accessible
|
|
17
|
-
* This runs before any workflow steps execute
|
|
18
|
-
*/
|
|
19
23
|
export declare class PreFlightValidator {
|
|
20
24
|
/**
|
|
21
|
-
*
|
|
22
|
-
* @param workflow The workflow to check
|
|
23
|
-
* @returns True if SSH key setup is in the workflow
|
|
24
|
-
*/
|
|
25
|
-
private hasSSHKeySetup;
|
|
26
|
-
/**
|
|
27
|
-
* Validates CIBUILD_GIT_REPOSITORY_URL exists and is accessible
|
|
28
|
-
* @param env Environment variables
|
|
29
|
-
* @param secretsManager Secrets manager to check for stored secrets
|
|
30
|
-
* @param workflow The workflow to check for SSH key setup
|
|
31
|
-
* @returns Validation result
|
|
32
|
-
*/
|
|
33
|
-
validateRepositoryAccess(env: Record<string, string>, secretsManager?: SecretsManager, workflow?: YAMLWorkflow): Promise<PreFlightResult>;
|
|
34
|
-
/**
|
|
35
|
-
* Run all pre-flight validations
|
|
36
|
-
* git-clone now uses the local checkout — no remote URL or connectivity check needed.
|
|
25
|
+
* Run all pre-flight validations. Always succeeds — see the file comment.
|
|
37
26
|
*/
|
|
38
27
|
validate(_env: Record<string, string>, _secretsManager?: SecretsManager, _workflow?: YAMLWorkflow): Promise<PreFlightResult>;
|
|
39
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preflight-validation.d.ts","sourceRoot":"","sources":["../../../src/yaml/preflight-validation.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"preflight-validation.d.ts","sourceRoot":"","sources":["../../../src/yaml/preflight-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,+BAA+B,CAAC;CACzC;AAED,qBAAa,kBAAkB;IAC7B;;OAEG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,eAAe,CAAC,EAAE,cAAc,EAChC,SAAS,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,eAAe,CAAC;CAG5B"}
|
|
@@ -1,149 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pre-flight validation
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
2
|
+
* Pre-flight validation hook that runs before any workflow step executes.
|
|
3
|
+
*
|
|
4
|
+
* It no longer checks anything. The checks it used to carry — that
|
|
5
|
+
* CIBUILD_GIT_REPOSITORY_URL is set and reachable, and that activate-ssh-key
|
|
6
|
+
* precedes git-clone — assumed cibuild would clone the repository itself. It
|
|
7
|
+
* does not: the source is already on disk when a pipeline runs (a runner
|
|
8
|
+
* checks out the dispatched commit before cibuild starts; locally it is the
|
|
9
|
+
* working copy), so there is no remote to validate before execution. The
|
|
10
|
+
* class and its `validate()` signature are kept so the call site in
|
|
11
|
+
* pipeline-with-secrets.ts is unchanged.
|
|
10
12
|
*/
|
|
11
13
|
export class PreFlightValidator {
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
14
|
-
* @param workflow The workflow to check
|
|
15
|
-
* @returns True if SSH key setup is in the workflow
|
|
16
|
-
*/
|
|
17
|
-
hasSSHKeySetup(workflow) {
|
|
18
|
-
if (!workflow.steps || workflow.steps.length === 0) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
let foundSSHKeyStep = false;
|
|
22
|
-
for (const step of workflow.steps) {
|
|
23
|
-
// Step can be an object with step name as key
|
|
24
|
-
const stepName = typeof step === 'string' ? step : Object.keys(step)[0];
|
|
25
|
-
// Check for git-clone step first - if we hit it before finding SSH key, return false
|
|
26
|
-
if (stepName.startsWith('git-clone')) {
|
|
27
|
-
return foundSSHKeyStep; // Return true only if we found SSH key before this
|
|
28
|
-
}
|
|
29
|
-
// Check for activate-ssh-key step
|
|
30
|
-
if (stepName.startsWith('activate-ssh-key')) {
|
|
31
|
-
foundSSHKeyStep = true;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
// If we got here, no git-clone step was found, so return if SSH key exists
|
|
35
|
-
return foundSSHKeyStep;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Validates CIBUILD_GIT_REPOSITORY_URL exists and is accessible
|
|
39
|
-
* @param env Environment variables
|
|
40
|
-
* @param secretsManager Secrets manager to check for stored secrets
|
|
41
|
-
* @param workflow The workflow to check for SSH key setup
|
|
42
|
-
* @returns Validation result
|
|
43
|
-
*/
|
|
44
|
-
async validateRepositoryAccess(env, secretsManager, workflow) {
|
|
45
|
-
// Check environment variables first, then secrets manager
|
|
46
|
-
let repoUrl = env.CIBUILD_GIT_REPOSITORY_URL || env.GIT_REPOSITORY_URL || '';
|
|
47
|
-
// If not in env, check secrets manager
|
|
48
|
-
if ((!repoUrl || repoUrl.trim() === '') && secretsManager) {
|
|
49
|
-
const secretId = secretsManager.getSecretIdByName('CIBUILD_GIT_REPOSITORY_URL');
|
|
50
|
-
if (secretId) {
|
|
51
|
-
repoUrl = secretsManager.getSecret(secretId) || '';
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Check if repository URL is provided
|
|
55
|
-
if (!repoUrl || repoUrl.trim() === '') {
|
|
56
|
-
return {
|
|
57
|
-
success: false,
|
|
58
|
-
error: new MissingEnvironmentVariableError('CIBUILD_GIT_REPOSITORY_URL', 'preflight-validation', 'Git repository URL for cloning source code in CI/CD builds.\n\n' +
|
|
59
|
-
'Expected format:\n' +
|
|
60
|
-
' ┌────────────────────────────────────────────────────────┐\n' +
|
|
61
|
-
' │ https://github.com/username/repository.git │\n' +
|
|
62
|
-
' │ git@github.com:username/repository.git │\n' +
|
|
63
|
-
' │ https://gitlab.com/username/repository.git │\n' +
|
|
64
|
-
' └────────────────────────────────────────────────────────┘\n\n' +
|
|
65
|
-
'How to set it:\n' +
|
|
66
|
-
' • Environment variable: GIT_REPOSITORY_URL=<your-repo-url>\n' +
|
|
67
|
-
' • In YAML inputs: repository: <your-repo-url>\n' +
|
|
68
|
-
' • CI platform automatically provides this in most cases'),
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
// If the workflow uses activate-ssh-key, skip connectivity test entirely.
|
|
72
|
-
// SSH authentication isn't available pre-execution, so any network test would fail
|
|
73
|
-
// for private repos regardless of whether the URL is SSH or HTTPS format.
|
|
74
|
-
const hasSSHKeyInWorkflow = workflow ? this.hasSSHKeySetup(workflow) : false;
|
|
75
|
-
if (hasSSHKeyInWorkflow) {
|
|
76
|
-
console.log('🔍 Pre-flight: Validating repository URL...');
|
|
77
|
-
console.log(` Repository: ${repoUrl}`);
|
|
78
|
-
console.log(' SSH authentication will be configured by activate-ssh-key step');
|
|
79
|
-
console.log('✅ Pre-flight: Repository URL validated (connectivity test skipped)\n');
|
|
80
|
-
return { success: true };
|
|
81
|
-
}
|
|
82
|
-
// Test repository connectivity using git ls-remote
|
|
83
|
-
try {
|
|
84
|
-
console.log('🔍 Pre-flight: Validating repository access...');
|
|
85
|
-
console.log(` Repository: ${repoUrl}`);
|
|
86
|
-
// Execute git ls-remote to check if repository is accessible
|
|
87
|
-
// This command lists remote references without cloning
|
|
88
|
-
// Timeout after 10 seconds to prevent hanging
|
|
89
|
-
execSync(`git ls-remote "${repoUrl}" HEAD`, {
|
|
90
|
-
stdio: 'pipe',
|
|
91
|
-
timeout: 10000,
|
|
92
|
-
encoding: 'utf-8',
|
|
93
|
-
});
|
|
94
|
-
console.log('✅ Pre-flight: Repository is accessible\n');
|
|
95
|
-
return { success: true };
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
// Repository is not accessible - analyze the error
|
|
99
|
-
const errorMessage = error.message || String(error);
|
|
100
|
-
console.log(`❌ Pre-flight: Repository access failed`);
|
|
101
|
-
console.log(` Error: ${errorMessage}\n`);
|
|
102
|
-
// Check if this is an SSH authentication error
|
|
103
|
-
const isSSHAuthError = errorMessage.includes('Permission denied') &&
|
|
104
|
-
errorMessage.includes('publickey');
|
|
105
|
-
const isSSHUrl = repoUrl.startsWith('git@') || repoUrl.includes('ssh://');
|
|
106
|
-
if (isSSHAuthError || (isSSHUrl && errorMessage.includes('Could not read from remote'))) {
|
|
107
|
-
// SSH authentication is the issue, not the repository URL
|
|
108
|
-
console.log('⚠️ Repository URL is valid, but SSH authentication is required.\n');
|
|
109
|
-
console.log('Please ensure:');
|
|
110
|
-
console.log(' 1. SSH key is configured in your workflow (activate-ssh-key step)');
|
|
111
|
-
console.log(' 2. SSH key has access to this repository');
|
|
112
|
-
console.log(' 3. SSH key is added to your GitHub/GitLab account\n');
|
|
113
|
-
throw new Error('Pre-flight validation failed: SSH authentication required.\n\n' +
|
|
114
|
-
`Repository: ${repoUrl}\n\n` +
|
|
115
|
-
'The repository URL is valid but requires SSH authentication.\n' +
|
|
116
|
-
'Make sure your workflow includes an "activate-ssh-key" step before "git-clone".\n\n' +
|
|
117
|
-
'Example workflow:\n' +
|
|
118
|
-
' steps:\n' +
|
|
119
|
-
' - activate-ssh-key@4: # Add SSH key first\n' +
|
|
120
|
-
' inputs:\n' +
|
|
121
|
-
' ssh_key_save_path: $HOME/.ssh/bitrise_rsa\n' +
|
|
122
|
-
' - git-clone@6: # Then clone\n\n' +
|
|
123
|
-
`Error details: ${errorMessage}`);
|
|
124
|
-
}
|
|
125
|
-
// For other errors (invalid URL, network issues, etc.), return error
|
|
126
|
-
return {
|
|
127
|
-
success: false,
|
|
128
|
-
error: new MissingEnvironmentVariableError('CIBUILD_GIT_REPOSITORY_URL', 'preflight-validation', 'Git repository URL validation failed. The repository is not accessible.\n\n' +
|
|
129
|
-
'Expected format:\n' +
|
|
130
|
-
' ┌────────────────────────────────────────────────────────┐\n' +
|
|
131
|
-
' │ https://github.com/username/repository.git │\n' +
|
|
132
|
-
' │ git@github.com:username/repository.git │\n' +
|
|
133
|
-
' │ https://gitlab.com/username/repository.git │\n' +
|
|
134
|
-
' └────────────────────────────────────────────────────────┘\n\n' +
|
|
135
|
-
'Common issues:\n' +
|
|
136
|
-
' • Invalid repository URL\n' +
|
|
137
|
-
' • Network connectivity issues\n' +
|
|
138
|
-
' • Repository does not exist or is private\n' +
|
|
139
|
-
' • Wrong URL format (check for typos)\n\n' +
|
|
140
|
-
`Error details: ${errorMessage}`),
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Run all pre-flight validations
|
|
146
|
-
* git-clone now uses the local checkout — no remote URL or connectivity check needed.
|
|
15
|
+
* Run all pre-flight validations. Always succeeds — see the file comment.
|
|
147
16
|
*/
|
|
148
17
|
async validate(_env, _secretsManager, _workflow) {
|
|
149
18
|
return { success: true };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/android.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,0BAA2B,SAAQ,gBAAgB;IAC9D,yBAAyB,CACvB,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;
|
|
1
|
+
{"version":3,"file":"android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/android.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,13 @@ export class SetJavaVersionStepExecutor extends BaseStepExecutor {
|
|
|
22
22
|
name: `java-${javaVersion}`,
|
|
23
23
|
description: `Java ${javaVersion} JDK`,
|
|
24
24
|
timing: 'pre-execution',
|
|
25
|
-
|
|
25
|
+
// The step this validates ends in `exit 1` when it cannot find the
|
|
26
|
+
// JDK, so a failed check is a build that is already lost. Reported as
|
|
27
|
+
// info, it printed "Java <n> not found", let the run proceed, and the
|
|
28
|
+
// pipeline died at the very next step — the same message, one VM
|
|
29
|
+
// later. The check now looks in every place the step looks, so the
|
|
30
|
+
// two can only disagree about a JDK that is genuinely absent.
|
|
31
|
+
severity: 'error',
|
|
26
32
|
hint: process.platform === 'darwin'
|
|
27
33
|
? `Install: brew install openjdk@${javaVersion}`
|
|
28
34
|
: `Install: sudo apt install openjdk-${javaVersion}-jdk`,
|
|
@@ -81,6 +87,16 @@ export class SetJavaVersionStepExecutor extends BaseStepExecutor {
|
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
}
|
|
90
|
+
// GitHub Actions publishes each preinstalled JDK as JAVA_HOME_<ver>_X64.
|
|
91
|
+
// The step reads it; without this the check could fail a build that the
|
|
92
|
+
// step itself would have run perfectly well.
|
|
93
|
+
const actionsHome = process.env[`JAVA_HOME_${version}_X64`];
|
|
94
|
+
if (actionsHome && existsSync(actionsHome)) {
|
|
95
|
+
return {
|
|
96
|
+
passed: true,
|
|
97
|
+
message: `Java ${version} found at: ${actionsHome} (GitHub Actions)`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
84
100
|
// Check Linux paths
|
|
85
101
|
const linuxPaths = [
|
|
86
102
|
`/usr/lib/jvm/java-${version}-openjdk-amd64`,
|
|
@@ -15,8 +15,14 @@ export interface GitCloneInputs {
|
|
|
15
15
|
clone_into_dir?: string;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* git-clone step executor.
|
|
19
|
+
*
|
|
20
|
+
* Does not clone. The source is already on disk when this runs — on a runner
|
|
21
|
+
* the dispatched commit was checked out before cibuild started (see
|
|
22
|
+
* cibuild-runner's GitCloneRunner); locally it is the developer's working copy.
|
|
23
|
+
* The step locates that checkout and republishes its commit metadata. Every
|
|
24
|
+
* input in GitCloneInputs is accepted so existing YAML keeps parsing, and none
|
|
25
|
+
* of them is read.
|
|
20
26
|
*/
|
|
21
27
|
export declare class GitCloneStepExecutor extends BaseStepExecutor {
|
|
22
28
|
getValidationRequirements(_inputs: GitCloneInputs, _env: Record<string, string>, _config: CIConfig): ValidationRequirement[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-clone.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/git-clone.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;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED
|
|
1
|
+
{"version":3,"file":"git-clone.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/git-clone.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;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;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;IAU1B,UAAU,IAAI,UAAU,EAAE;IAkDpB,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;CAqD1G"}
|
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { BaseStepExecutor } from './base.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* git-clone step executor.
|
|
7
|
+
*
|
|
8
|
+
* Does not clone. The source is already on disk when this runs — on a runner
|
|
9
|
+
* the dispatched commit was checked out before cibuild started (see
|
|
10
|
+
* cibuild-runner's GitCloneRunner); locally it is the developer's working copy.
|
|
11
|
+
* The step locates that checkout and republishes its commit metadata. Every
|
|
12
|
+
* input in GitCloneInputs is accepted so existing YAML keeps parsing, and none
|
|
13
|
+
* of them is read.
|
|
8
14
|
*/
|
|
9
15
|
export class GitCloneStepExecutor extends BaseStepExecutor {
|
|
10
16
|
getValidationRequirements(_inputs, _env, _config) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4CH;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4CH;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CA07C7C"}
|
|
@@ -32,28 +32,32 @@ import { UiFidelityRenderAndroidStepExecutor, DEFAULT_GRADLE_TASK, DEFAULT_PACKA
|
|
|
32
32
|
*/
|
|
33
33
|
export function initializeStepRegistry() {
|
|
34
34
|
// Git steps
|
|
35
|
+
// Does not clone. The source is already on disk when any step runs — on a
|
|
36
|
+
// runner the dispatched commit is checked out before cibuild starts; locally
|
|
37
|
+
// it is the developer's working copy. The inputs are kept so existing YAML
|
|
38
|
+
// keeps parsing; the executor never reads them.
|
|
35
39
|
registerStep('git-clone', new GitCloneStepExecutor(), {
|
|
36
40
|
name: 'git-clone',
|
|
37
|
-
description: '
|
|
41
|
+
description: 'Locate the source checkout already on disk and record its commit. Does not clone — on a runner the dispatched commit is checked out before any step runs; locally it is your working copy. Inputs are ignored.',
|
|
38
42
|
platform: 'all',
|
|
39
43
|
inputs: {
|
|
40
44
|
repository: {
|
|
41
|
-
description: '
|
|
45
|
+
description: 'Ignored — no clone is performed; the checkout already exists',
|
|
42
46
|
required: false,
|
|
43
47
|
default: '$CIBUILD_GIT_REPOSITORY_URL',
|
|
44
48
|
},
|
|
45
49
|
branch: {
|
|
46
|
-
description: '
|
|
50
|
+
description: 'Ignored — on a runner the dispatched ref is checked out, not this value',
|
|
47
51
|
required: false,
|
|
48
52
|
default: '$CIBUILD_GIT_BRANCH or main',
|
|
49
53
|
},
|
|
50
54
|
clone_depth: {
|
|
51
|
-
description: '
|
|
55
|
+
description: 'Ignored — no clone is performed; a runner checkout is always depth 1',
|
|
52
56
|
required: false,
|
|
53
57
|
default: 0,
|
|
54
58
|
},
|
|
55
59
|
clone_into_dir: {
|
|
56
|
-
description: '
|
|
60
|
+
description: 'Ignored — the checkout location is not chosen by this step',
|
|
57
61
|
required: false,
|
|
58
62
|
default: '.',
|
|
59
63
|
},
|