@catladder/cli 0.0.0-next-b3e567e8 → 0.0.0-next-dccc0a36
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/bundles/catenv/index.js +244 -67
- package/dist/bundles/cli/index.js +244 -67
- package/dist/bundles/skills/catladder-builds/SKILL.md +49 -2
- package/dist/bundles/skills/catladder-builds/references/build-types.md +2 -2
- package/dist/bundles/skills/catladder-pipelines/SKILL.md +13 -3
- package/dist/packages/pipeline/src/backends/github/GithubBackend.js +4 -4
- package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
- package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +4 -4
- package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
- package/dist/packages/pipeline/src/build/types.d.ts +6 -5
- package/dist/packages/pipeline/src/build/types.js.map +1 -1
- package/dist/packages/pipeline/src/customImages/hash.d.ts +9 -0
- package/dist/packages/pipeline/src/customImages/hash.js +41 -16
- package/dist/packages/pipeline/src/customImages/hash.js.map +1 -1
- package/dist/packages/pipeline/src/customImages/jobImagesPlan.d.ts +23 -5
- package/dist/packages/pipeline/src/customImages/jobImagesPlan.js +177 -43
- package/dist/packages/pipeline/src/customImages/jobImagesPlan.js.map +1 -1
- package/dist/packages/pipeline/src/customImages/projectImages.d.ts +67 -0
- package/dist/packages/pipeline/src/customImages/projectImages.js +9 -0
- package/dist/packages/pipeline/src/customImages/projectImages.js.map +1 -0
- package/dist/packages/pipeline/src/deploy/types/custom.d.ts +2 -2
- package/dist/packages/pipeline/src/deploy/types/index.d.ts +4 -4
- package/dist/packages/pipeline/src/deploy/types/pages.d.ts +2 -2
- package/dist/packages/pipeline/src/index.d.ts +2 -0
- package/dist/packages/pipeline/src/index.js +2 -0
- package/dist/packages/pipeline/src/index.js.map +1 -1
- package/dist/packages/pipeline/src/types/config.d.ts +8 -0
- package/dist/packages/pipeline/src/types/config.js.map +1 -1
- package/dist/packages/pipeline/src/types/jobs.d.ts +2 -1
- package/dist/packages/pipeline/src/types/jobs.js.map +1 -1
- package/dist/skills/catladder-builds/SKILL.md +49 -2
- package/dist/skills/catladder-builds/references/build-types.md +2 -2
- package/dist/skills/catladder-pipelines/SKILL.md +13 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -2321,7 +2321,7 @@ class GithubBackend {
|
|
|
2321
2321
|
await (0, promises_1.rm)(scriptFiles_1.GITHUB_SCRIPTS_FOLDER, { recursive: true, force: true });
|
|
2322
2322
|
}
|
|
2323
2323
|
async createFiles(config) {
|
|
2324
|
-
const images = this.createImagesPlan();
|
|
2324
|
+
const images = this.createImagesPlan(config);
|
|
2325
2325
|
const scripts = new scriptFiles_1.GithubScriptFiles();
|
|
2326
2326
|
const workflows = await this.createWorkflows(config, images, scripts);
|
|
2327
2327
|
return [
|
|
@@ -2336,13 +2336,13 @@ class GithubBackend {
|
|
|
2336
2336
|
...(0, shippedCatci_1.getCatciGeneratedFiles)(),
|
|
2337
2337
|
];
|
|
2338
2338
|
}
|
|
2339
|
-
createImagesPlan() {
|
|
2340
|
-
return new jobImagesPlan_1.JobImagesPlan(this.type);
|
|
2339
|
+
createImagesPlan(config) {
|
|
2340
|
+
return new jobImagesPlan_1.JobImagesPlan(this.type, config.images);
|
|
2341
2341
|
}
|
|
2342
2342
|
/**
|
|
2343
2343
|
* all workflows keyed by file name, mainly for testing purposes
|
|
2344
2344
|
*/
|
|
2345
|
-
async createWorkflows(config, images = this.createImagesPlan(), scripts = new scriptFiles_1.GithubScriptFiles()) {
|
|
2345
|
+
async createWorkflows(config, images = this.createImagesPlan(config), scripts = new scriptFiles_1.GithubScriptFiles()) {
|
|
2346
2346
|
var _a, _b, _c, _d;
|
|
2347
2347
|
const workflows = {};
|
|
2348
2348
|
// per-pipeline-type variables (pipelines.github.runnerVariables);
|
|
@@ -3311,7 +3311,7 @@ class GitlabBackend {
|
|
|
3311
3311
|
await (0, promises_1.rm)(this.generatedFolder, { force: true, recursive: true });
|
|
3312
3312
|
}
|
|
3313
3313
|
async createFiles(config) {
|
|
3314
|
-
const images = this.createImagesPlan();
|
|
3314
|
+
const images = this.createImagesPlan(config);
|
|
3315
3315
|
const includes = await this.createIncludes(config, images);
|
|
3316
3316
|
const mainFile = {
|
|
3317
3317
|
path: ".gitlab-ci.yml",
|
|
@@ -3328,15 +3328,15 @@ class GitlabBackend {
|
|
|
3328
3328
|
...(0, shippedCatci_1.getCatciGeneratedFiles)(),
|
|
3329
3329
|
];
|
|
3330
3330
|
}
|
|
3331
|
-
createImagesPlan() {
|
|
3332
|
-
return new jobImagesPlan_1.JobImagesPlan(this.type);
|
|
3331
|
+
createImagesPlan(config) {
|
|
3332
|
+
return new jobImagesPlan_1.JobImagesPlan(this.type, config.images);
|
|
3333
3333
|
}
|
|
3334
3334
|
/**
|
|
3335
3335
|
* the complete pipeline as one object (all includes merged into one),
|
|
3336
3336
|
* mainly for testing purposes
|
|
3337
3337
|
*/
|
|
3338
3338
|
async createCompletePipeline(config) {
|
|
3339
|
-
const includes = await this.createIncludes(config, this.createImagesPlan());
|
|
3339
|
+
const includes = await this.createIncludes(config, this.createImagesPlan(config));
|
|
3340
3340
|
return includes.reduce((acc, { content }) => {
|
|
3341
3341
|
return {
|
|
3342
3342
|
...acc,
|
|
@@ -6981,7 +6981,7 @@ exports.makeSecretEnvVarMapping = makeSecretEnvVarMapping;
|
|
|
6981
6981
|
"use strict";
|
|
6982
6982
|
|
|
6983
6983
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6984
|
-
exports.computeCustomImageHash = void 0;
|
|
6984
|
+
exports.computeInlineImageHash = exports.computeCustomImageHash = void 0;
|
|
6985
6985
|
const crypto_1 = __nccwpck_require__(76982);
|
|
6986
6986
|
const fs_1 = __nccwpck_require__(79896);
|
|
6987
6987
|
const path_1 = __nccwpck_require__(16928);
|
|
@@ -7002,6 +7002,29 @@ function listFilesRecursive(dir) {
|
|
|
7002
7002
|
})
|
|
7003
7003
|
.sort();
|
|
7004
7004
|
}
|
|
7005
|
+
/**
|
|
7006
|
+
* the parts every image definition hashes on top of its content:
|
|
7007
|
+
* files outside the definition, and the build args
|
|
7008
|
+
*/
|
|
7009
|
+
function hashExtras(hash, config) {
|
|
7010
|
+
const watchedPaths = [];
|
|
7011
|
+
// Hash extra paths (for files outside the dir)
|
|
7012
|
+
if (config.hashExtraPaths) {
|
|
7013
|
+
// Extra paths are literal file paths (not globs) for simplicity
|
|
7014
|
+
const extraFiles = [...config.hashExtraPaths].sort();
|
|
7015
|
+
for (const file of extraFiles) {
|
|
7016
|
+
hash.update(file);
|
|
7017
|
+
hash.update((0, fs_1.readFileSync)(file));
|
|
7018
|
+
}
|
|
7019
|
+
watchedPaths.push(...config.hashExtraPaths);
|
|
7020
|
+
}
|
|
7021
|
+
// Hash build args (sorted keys for determinism)
|
|
7022
|
+
if (config.buildArgs) {
|
|
7023
|
+
const sorted = Object.entries(config.buildArgs).sort(([a], [b]) => a.localeCompare(b));
|
|
7024
|
+
hash.update(JSON.stringify(sorted));
|
|
7025
|
+
}
|
|
7026
|
+
return watchedPaths;
|
|
7027
|
+
}
|
|
7005
7028
|
function computeCustomImageHash(config) {
|
|
7006
7029
|
var _a;
|
|
7007
7030
|
const hash = (0, crypto_1.createHash)("sha256");
|
|
@@ -7022,27 +7045,29 @@ function computeCustomImageHash(config) {
|
|
|
7022
7045
|
}
|
|
7023
7046
|
watchedPaths.push(`${extraDir}/**/*`);
|
|
7024
7047
|
}
|
|
7025
|
-
|
|
7026
|
-
if (config.hashExtraPaths) {
|
|
7027
|
-
// Extra paths are literal file paths (not globs) for simplicity
|
|
7028
|
-
const extraFiles = [...config.hashExtraPaths].sort();
|
|
7029
|
-
for (const file of extraFiles) {
|
|
7030
|
-
hash.update(file);
|
|
7031
|
-
hash.update((0, fs_1.readFileSync)(file));
|
|
7032
|
-
}
|
|
7033
|
-
watchedPaths.push(...config.hashExtraPaths);
|
|
7034
|
-
}
|
|
7035
|
-
// Hash build args (sorted keys for determinism)
|
|
7036
|
-
if (config.buildArgs) {
|
|
7037
|
-
const sorted = Object.entries(config.buildArgs).sort(([a], [b]) => a.localeCompare(b));
|
|
7038
|
-
hash.update(JSON.stringify(sorted));
|
|
7039
|
-
}
|
|
7048
|
+
watchedPaths.push(...hashExtras(hash, config));
|
|
7040
7049
|
return {
|
|
7041
7050
|
hash: hash.digest("hex").slice(0, 12),
|
|
7042
7051
|
watchedPaths,
|
|
7043
7052
|
};
|
|
7044
7053
|
}
|
|
7045
7054
|
exports.computeCustomImageHash = computeCustomImageHash;
|
|
7055
|
+
/**
|
|
7056
|
+
* the hash of an image defined by an inline Dockerfile: its content
|
|
7057
|
+
* stands in for the definition dir. The build context is deliberately
|
|
7058
|
+
* NOT hashed (it may be the whole repository) — `hashExtraPaths` is how
|
|
7059
|
+
* context files opt into the hash.
|
|
7060
|
+
*/
|
|
7061
|
+
function computeInlineImageHash(config) {
|
|
7062
|
+
const hash = (0, crypto_1.createHash)("sha256");
|
|
7063
|
+
hash.update(config.dockerfileContent);
|
|
7064
|
+
const watchedPaths = hashExtras(hash, config);
|
|
7065
|
+
return {
|
|
7066
|
+
hash: hash.digest("hex").slice(0, 12),
|
|
7067
|
+
watchedPaths,
|
|
7068
|
+
};
|
|
7069
|
+
}
|
|
7070
|
+
exports.computeInlineImageHash = computeInlineImageHash;
|
|
7046
7071
|
//# sourceMappingURL=hash.js.map
|
|
7047
7072
|
|
|
7048
7073
|
/***/ }),
|
|
@@ -7053,7 +7078,7 @@ exports.computeCustomImageHash = computeCustomImageHash;
|
|
|
7053
7078
|
"use strict";
|
|
7054
7079
|
|
|
7055
7080
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
7056
|
-
exports.JobImagesPlan = exports.GENERATED_IMAGES_FOLDER = void 0;
|
|
7081
|
+
exports.JobImagesPlan = exports.PROJECT_IMAGES_FOLDER = exports.GENERATED_IMAGES_FOLDER = void 0;
|
|
7057
7082
|
const fs_1 = __nccwpck_require__(79896);
|
|
7058
7083
|
const path_1 = __nccwpck_require__(16928);
|
|
7059
7084
|
const ciVariables_1 = __nccwpck_require__(72700);
|
|
@@ -7061,6 +7086,7 @@ const docker_1 = __nccwpck_require__(83777);
|
|
|
7061
7086
|
const runner_1 = __nccwpck_require__(71065);
|
|
7062
7087
|
const gitlab_1 = __nccwpck_require__(37393);
|
|
7063
7088
|
const hash_1 = __nccwpck_require__(34092);
|
|
7089
|
+
const projectImages_1 = __nccwpck_require__(55537);
|
|
7064
7090
|
const shippedImages_1 = __nccwpck_require__(28687);
|
|
7065
7091
|
exports.GENERATED_IMAGES_FOLDER = ".catladder-generated/images";
|
|
7066
7092
|
/**
|
|
@@ -7068,7 +7094,44 @@ exports.GENERATED_IMAGES_FOLDER = ".catladder-generated/images";
|
|
|
7068
7094
|
* catladder image, so building images never depends on one (bootstrap)
|
|
7069
7095
|
*/
|
|
7070
7096
|
const BUILDER_IMAGE = "docker.io/docker:29.5.1";
|
|
7071
|
-
|
|
7097
|
+
/**
|
|
7098
|
+
* every planned image is consumed the same way: its url, plus an
|
|
7099
|
+
* optional dependency on its build job
|
|
7100
|
+
*/
|
|
7101
|
+
const toResolvedJobImage = ({ imageRef, jobName, }) => ({
|
|
7102
|
+
image: imageRef,
|
|
7103
|
+
fromRepoRegistry: true,
|
|
7104
|
+
need: {
|
|
7105
|
+
job: jobName,
|
|
7106
|
+
artifacts: false,
|
|
7107
|
+
optional: true,
|
|
7108
|
+
global: true,
|
|
7109
|
+
},
|
|
7110
|
+
});
|
|
7111
|
+
/**
|
|
7112
|
+
* materializes an image definition directory into the generated files
|
|
7113
|
+
* (used for the definitions catladder ships)
|
|
7114
|
+
*/
|
|
7115
|
+
const materializeDir = (sourceDir, targetDir) => listFilesRecursive(sourceDir).map((file) => ({
|
|
7116
|
+
path: (0, path_1.join)(targetDir, file),
|
|
7117
|
+
content: (0, fs_1.readFileSync)((0, path_1.join)(sourceDir, file), "utf-8"),
|
|
7118
|
+
}));
|
|
7119
|
+
// built-in (catladder-shipped) images carry the catladder marker in
|
|
7120
|
+
// their job name; project-declared images get the short plain name
|
|
7121
|
+
const ensureJobName = (name) => `🐳 catladder image ${name}`;
|
|
7122
|
+
const projectEnsureJobName = (name) => `🐳 image ${name}`;
|
|
7123
|
+
/**
|
|
7124
|
+
* the config file whose content feeds the project image hashes
|
|
7125
|
+
* (`buildArgs`, `hashExtraPaths`): the gitlab change detection has to
|
|
7126
|
+
* watch it, because a config-only change alters the image tag without
|
|
7127
|
+
* touching the image dir
|
|
7128
|
+
*/
|
|
7129
|
+
const CONFIG_FILE = "catladder.ts";
|
|
7130
|
+
/**
|
|
7131
|
+
* where inline project Dockerfiles are materialized — a subfolder, so a
|
|
7132
|
+
* project image can carry the same name as a shipped one
|
|
7133
|
+
*/
|
|
7134
|
+
exports.PROJECT_IMAGES_FOLDER = `${exports.GENERATED_IMAGES_FOLDER}/project`;
|
|
7072
7135
|
/**
|
|
7073
7136
|
* plans the catladder job images of one backend run: resolves image
|
|
7074
7137
|
* references, collects the image build jobs, and the image definitions
|
|
@@ -7079,33 +7142,30 @@ const ensureJobName = (name) => `🐳 job image ${name}`;
|
|
|
7079
7142
|
* Reference-driven: only images actually used by a job are built.
|
|
7080
7143
|
*/
|
|
7081
7144
|
class JobImagesPlan {
|
|
7082
|
-
constructor(pipelineType) {
|
|
7145
|
+
constructor(pipelineType, projectImages = {}) {
|
|
7083
7146
|
this.pipelineType = pipelineType;
|
|
7147
|
+
this.projectImages = projectImages;
|
|
7084
7148
|
this.used = new Map();
|
|
7149
|
+
this.usedProject = new Map();
|
|
7085
7150
|
}
|
|
7086
7151
|
/**
|
|
7087
7152
|
* resolves a job image (marker or concrete) to a concrete image url
|
|
7088
7153
|
* plus the build job dependency
|
|
7089
7154
|
*/
|
|
7090
7155
|
resolve(image) {
|
|
7091
|
-
if (
|
|
7092
|
-
return
|
|
7156
|
+
if ((0, runner_1.isCatladderImageRef)(image)) {
|
|
7157
|
+
return this.resolveRef(image);
|
|
7158
|
+
}
|
|
7159
|
+
if ((0, projectImages_1.isProjectImageRef)(image)) {
|
|
7160
|
+
return this.resolveProjectRef(image);
|
|
7093
7161
|
}
|
|
7094
|
-
return
|
|
7162
|
+
return { image };
|
|
7095
7163
|
}
|
|
7096
7164
|
resolveRef(ref) {
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
fromRepoRegistry: true,
|
|
7102
|
-
need: {
|
|
7103
|
-
job: ensureJobName(name),
|
|
7104
|
-
artifacts: false,
|
|
7105
|
-
optional: true,
|
|
7106
|
-
global: true,
|
|
7107
|
-
},
|
|
7108
|
-
};
|
|
7165
|
+
return toResolvedJobImage(this.use(ref.catladderImage));
|
|
7166
|
+
}
|
|
7167
|
+
resolveProjectRef(ref) {
|
|
7168
|
+
return toResolvedJobImage(this.useProject(ref.image));
|
|
7109
7169
|
}
|
|
7110
7170
|
/**
|
|
7111
7171
|
* the registry image prefix. On github, container images can't use
|
|
@@ -7116,6 +7176,85 @@ class JobImagesPlan {
|
|
|
7116
7176
|
? "ghcr.io/${{ github.repository }}"
|
|
7117
7177
|
: `${(0, ciVariables_1.getCiVariable)({ pipelineType: this.pipelineType }, "registryImage")}`;
|
|
7118
7178
|
}
|
|
7179
|
+
useProject(name) {
|
|
7180
|
+
const existing = this.usedProject.get(name);
|
|
7181
|
+
if (existing) {
|
|
7182
|
+
return existing;
|
|
7183
|
+
}
|
|
7184
|
+
const imageConfig = this.projectImages[name];
|
|
7185
|
+
if (!imageConfig) {
|
|
7186
|
+
const declared = Object.keys(this.projectImages);
|
|
7187
|
+
throw new Error(`unknown job image "${name}" — ${declared.length > 0
|
|
7188
|
+
? `images declared in config.images: ${declared.join(", ")}`
|
|
7189
|
+
: "no images are declared in config.images"}`);
|
|
7190
|
+
}
|
|
7191
|
+
const source = this.planProjectSource(name, imageConfig);
|
|
7192
|
+
const planned = {
|
|
7193
|
+
...source,
|
|
7194
|
+
jobName: projectEnsureJobName(name),
|
|
7195
|
+
buildArgs: imageConfig.buildArgs,
|
|
7196
|
+
// `job-images/` keeps the project's job images apart from its
|
|
7197
|
+
// deployable component images (registry root) and build caches
|
|
7198
|
+
imageRef: `${this.registryImageRef()}/job-images/${name}:${source.hash}`,
|
|
7199
|
+
};
|
|
7200
|
+
this.usedProject.set(name, planned);
|
|
7201
|
+
return planned;
|
|
7202
|
+
}
|
|
7203
|
+
/**
|
|
7204
|
+
* the source-dependent half of a project image: an inline Dockerfile
|
|
7205
|
+
* is materialized into the generated files and hashed by its content,
|
|
7206
|
+
* a directory is hashed and watched in place
|
|
7207
|
+
*/
|
|
7208
|
+
planProjectSource(name, imageConfig) {
|
|
7209
|
+
var _a, _b;
|
|
7210
|
+
if (imageConfig.dockerfile !== undefined) {
|
|
7211
|
+
const content = toDockerfileContent(imageConfig.dockerfile);
|
|
7212
|
+
const dockerfilePath = `${exports.PROJECT_IMAGES_FOLDER}/${name}/Dockerfile`;
|
|
7213
|
+
const { hash, watchedPaths } = (0, hash_1.computeInlineImageHash)({
|
|
7214
|
+
dockerfileContent: content,
|
|
7215
|
+
hashExtraPaths: imageConfig.hashExtraPaths,
|
|
7216
|
+
buildArgs: imageConfig.buildArgs,
|
|
7217
|
+
});
|
|
7218
|
+
return {
|
|
7219
|
+
hash,
|
|
7220
|
+
dockerfilePath,
|
|
7221
|
+
// an inline definition carries no directory of its own — the
|
|
7222
|
+
// repository root is the sensible default context
|
|
7223
|
+
contextDir: (_a = imageConfig.context) !== null && _a !== void 0 ? _a : ".",
|
|
7224
|
+
watchedPaths: [
|
|
7225
|
+
`${exports.PROJECT_IMAGES_FOLDER}/${name}/**/*`,
|
|
7226
|
+
...watchedPaths,
|
|
7227
|
+
CONFIG_FILE,
|
|
7228
|
+
],
|
|
7229
|
+
files: [{ path: dockerfilePath, content }],
|
|
7230
|
+
};
|
|
7231
|
+
}
|
|
7232
|
+
const dir = imageConfig.dir;
|
|
7233
|
+
// fail at generation time with the offending image named: an
|
|
7234
|
+
// unreadable dir would otherwise surface as a bare fs ENOENT, and a
|
|
7235
|
+
// missing Dockerfile only as a docker build failure in CI
|
|
7236
|
+
if (!(0, fs_1.existsSync)(dir)) {
|
|
7237
|
+
throw new Error(`job image "${name}": the directory "${dir}" does not exist (config.images.${name}.dir, relative to the repository root)`);
|
|
7238
|
+
}
|
|
7239
|
+
if (!(0, fs_1.existsSync)((0, path_1.join)(dir, "Dockerfile"))) {
|
|
7240
|
+
throw new Error(`job image "${name}": no Dockerfile in "${dir}" (config.images.${name}.dir)`);
|
|
7241
|
+
}
|
|
7242
|
+
const { hash, watchedPaths } = (0, hash_1.computeCustomImageHash)({
|
|
7243
|
+
dir,
|
|
7244
|
+
hashExtraPaths: imageConfig.hashExtraPaths,
|
|
7245
|
+
buildArgs: imageConfig.buildArgs,
|
|
7246
|
+
});
|
|
7247
|
+
return {
|
|
7248
|
+
hash,
|
|
7249
|
+
dockerfilePath: `${dir}/Dockerfile`,
|
|
7250
|
+
contextDir: (_b = imageConfig.context) !== null && _b !== void 0 ? _b : dir,
|
|
7251
|
+
// the dir is committed in the project — watched in place, nothing
|
|
7252
|
+
// is materialized. The config file is watched too: buildArgs /
|
|
7253
|
+
// hashExtraPaths changes alter the tag without touching the dir
|
|
7254
|
+
watchedPaths: [...watchedPaths, CONFIG_FILE],
|
|
7255
|
+
files: [],
|
|
7256
|
+
};
|
|
7257
|
+
}
|
|
7119
7258
|
use(name) {
|
|
7120
7259
|
var _a;
|
|
7121
7260
|
const existing = this.used.get(name);
|
|
@@ -7130,27 +7269,43 @@ class JobImagesPlan {
|
|
|
7130
7269
|
dir: (0, shippedImages_1.getShippedImageDir)(name),
|
|
7131
7270
|
extraDirs: dependencies.map((dependency) => (0, shippedImages_1.getShippedImageDir)(dependency)),
|
|
7132
7271
|
});
|
|
7133
|
-
const
|
|
7134
|
-
|
|
7135
|
-
|
|
7272
|
+
const targetDir = `${exports.GENERATED_IMAGES_FOLDER}/${name}`;
|
|
7273
|
+
const planned = {
|
|
7274
|
+
hash,
|
|
7275
|
+
jobName: ensureJobName(name),
|
|
7276
|
+
imageRef: `${this.registryImageRef()}/catladder/${name}:${hash}`,
|
|
7277
|
+
dockerfilePath: `${targetDir}/Dockerfile`,
|
|
7278
|
+
// the jobs family INCLUDEs sibling images, so it builds from the
|
|
7279
|
+
// images root; the others from their own dir
|
|
7280
|
+
contextDir: shippedImages_1.RUNNER_IMAGE_BUILD_CONTEXT[name] === "root"
|
|
7281
|
+
? exports.GENERATED_IMAGES_FOLDER
|
|
7282
|
+
: targetDir,
|
|
7283
|
+
watchedPaths: [name, ...dependencies].map((dir) => `${exports.GENERATED_IMAGES_FOLDER}/${dir}/**/*`),
|
|
7284
|
+
// pipelines build from committed, reviewable files (and gitlab's
|
|
7285
|
+
// rules:changes can watch them)
|
|
7286
|
+
files: materializeDir((0, shippedImages_1.getShippedImageDir)(name), targetDir),
|
|
7287
|
+
};
|
|
7288
|
+
this.used.set(name, planned);
|
|
7289
|
+
return planned;
|
|
7136
7290
|
}
|
|
7137
7291
|
/**
|
|
7138
7292
|
* the image build jobs for all used images
|
|
7139
7293
|
*/
|
|
7140
7294
|
getEnsureJobs() {
|
|
7141
|
-
return [...this.used.
|
|
7295
|
+
return [...this.used.values(), ...this.usedProject.values()].map((planned) => this.createImageBuildJob(planned));
|
|
7142
7296
|
}
|
|
7143
|
-
|
|
7144
|
-
|
|
7297
|
+
createImageBuildJob({ jobName, imageRef, watchedPaths, dockerfilePath, contextDir, buildArgs, }) {
|
|
7298
|
+
const buildArgFlags = Object.entries(buildArgs !== null && buildArgs !== void 0 ? buildArgs : {})
|
|
7299
|
+
.map(([key, value]) => ` --build-arg '${key}=${value}'`)
|
|
7300
|
+
.join("");
|
|
7301
|
+
const buildCommand = `DOCKER_BUILDKIT=1 docker build -t ${imageRef}${buildArgFlags} -f ${dockerfilePath} ${contextDir}`;
|
|
7145
7302
|
const ctx = { pipelineType: this.pipelineType };
|
|
7146
7303
|
const registryUser = (0, ciVariables_1.getCiVariable)(ctx, "registryUser");
|
|
7147
7304
|
const jobToken = (0, ciVariables_1.getCiVariable)(ctx, "jobToken");
|
|
7148
7305
|
const registry = (0, ciVariables_1.getCiVariable)(ctx, "registry");
|
|
7149
|
-
const imageRef = `${this.registryImageRef()}/catladder/${name}:${hash}`;
|
|
7150
|
-
const watchedDirs = [name, ...((_a = shippedImages_1.RUNNER_IMAGE_DEPENDENCIES[name]) !== null && _a !== void 0 ? _a : [])];
|
|
7151
7306
|
const { services, runnerVariables } = (0, docker_1.getDockerJobBaseProps)();
|
|
7152
7307
|
return {
|
|
7153
|
-
name:
|
|
7308
|
+
name: jobName,
|
|
7154
7309
|
stage: "setup",
|
|
7155
7310
|
image: BUILDER_IMAGE,
|
|
7156
7311
|
services,
|
|
@@ -7160,7 +7315,9 @@ class JobImagesPlan {
|
|
|
7160
7315
|
// no equivalent and always runs (the existence check is fast)
|
|
7161
7316
|
rules: [
|
|
7162
7317
|
{
|
|
7163
|
-
|
|
7318
|
+
// a fresh array per job: the yaml serializer anchors repeated
|
|
7319
|
+
// objects, and a shared reference would reshuffle anchors
|
|
7320
|
+
changes: [...watchedPaths],
|
|
7164
7321
|
},
|
|
7165
7322
|
],
|
|
7166
7323
|
variables: {},
|
|
@@ -7174,31 +7331,33 @@ class JobImagesPlan {
|
|
|
7174
7331
|
` exit 0`,
|
|
7175
7332
|
`fi`,
|
|
7176
7333
|
]),
|
|
7177
|
-
...(0, gitlab_1.collapseableSection)("docker-build", "Building image")([
|
|
7178
|
-
`DOCKER_BUILDKIT=1 docker build -t ${imageRef} -f ${exports.GENERATED_IMAGES_FOLDER}/${name}/Dockerfile ${shippedImages_1.RUNNER_IMAGE_BUILD_CONTEXT[name] === "root"
|
|
7179
|
-
? exports.GENERATED_IMAGES_FOLDER
|
|
7180
|
-
: `${exports.GENERATED_IMAGES_FOLDER}/${name}`}`,
|
|
7181
|
-
]),
|
|
7334
|
+
...(0, gitlab_1.collapseableSection)("docker-build", "Building image")([buildCommand]),
|
|
7182
7335
|
...(0, gitlab_1.collapseableSection)("docker-push", "Pushing image")([`docker push ${imageRef}`]),
|
|
7183
7336
|
],
|
|
7184
7337
|
};
|
|
7185
7338
|
}
|
|
7186
7339
|
/**
|
|
7187
|
-
* the image definitions
|
|
7188
|
-
*
|
|
7189
|
-
*
|
|
7340
|
+
* the image definitions to materialize into the generated files (so
|
|
7341
|
+
* pipelines build from committed, reviewable files and gitlab's
|
|
7342
|
+
* rules:changes can watch them): the definitions catladder ships and
|
|
7343
|
+
* the project's inline Dockerfiles. A project image directory is
|
|
7344
|
+
* already committed and contributes nothing.
|
|
7190
7345
|
*/
|
|
7191
7346
|
getGeneratedFiles() {
|
|
7192
|
-
return [...this.used.
|
|
7193
|
-
const dir = (0, shippedImages_1.getShippedImageDir)(name);
|
|
7194
|
-
return listFilesRecursive(dir).map((file) => ({
|
|
7195
|
-
path: (0, path_1.join)(exports.GENERATED_IMAGES_FOLDER, name, file),
|
|
7196
|
-
content: (0, fs_1.readFileSync)((0, path_1.join)(dir, file), "utf-8"),
|
|
7197
|
-
}));
|
|
7198
|
-
});
|
|
7347
|
+
return [...this.used.values(), ...this.usedProject.values()].flatMap(({ files }) => files);
|
|
7199
7348
|
}
|
|
7200
7349
|
}
|
|
7201
7350
|
exports.JobImagesPlan = JobImagesPlan;
|
|
7351
|
+
/**
|
|
7352
|
+
* an inline Dockerfile is written as given — as one string, or as lines
|
|
7353
|
+
* joined with newlines (always newline-terminated)
|
|
7354
|
+
*/
|
|
7355
|
+
const toDockerfileContent = (dockerfile) => {
|
|
7356
|
+
const content = Array.isArray(dockerfile)
|
|
7357
|
+
? dockerfile.join("\n")
|
|
7358
|
+
: dockerfile;
|
|
7359
|
+
return content.endsWith("\n") ? content : `${content}\n`;
|
|
7360
|
+
};
|
|
7202
7361
|
const IGNORED_FILES = new Set([".DS_Store", "Thumbs.db"]);
|
|
7203
7362
|
const listFilesRecursive = (dir) => (0, fs_1.readdirSync)(dir, { recursive: true, encoding: "utf-8" })
|
|
7204
7363
|
.filter((entry) => {
|
|
@@ -7212,6 +7371,22 @@ const listFilesRecursive = (dir) => (0, fs_1.readdirSync)(dir, { recursive: true
|
|
|
7212
7371
|
|
|
7213
7372
|
/***/ }),
|
|
7214
7373
|
|
|
7374
|
+
/***/ 55537:
|
|
7375
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
7376
|
+
|
|
7377
|
+
"use strict";
|
|
7378
|
+
|
|
7379
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
7380
|
+
exports.isProjectImageRef = void 0;
|
|
7381
|
+
const isProjectImageRef = (value) => typeof value === "object" &&
|
|
7382
|
+
value !== null &&
|
|
7383
|
+
"image" in value &&
|
|
7384
|
+
typeof value.image === "string";
|
|
7385
|
+
exports.isProjectImageRef = isProjectImageRef;
|
|
7386
|
+
//# sourceMappingURL=projectImages.js.map
|
|
7387
|
+
|
|
7388
|
+
/***/ }),
|
|
7389
|
+
|
|
7215
7390
|
/***/ 28687:
|
|
7216
7391
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
7217
7392
|
|
|
@@ -9925,6 +10100,8 @@ __exportStar(__nccwpck_require__(68906), exports);
|
|
|
9925
10100
|
__exportStar(__nccwpck_require__(23040), exports);
|
|
9926
10101
|
__exportStar(__nccwpck_require__(35086), exports);
|
|
9927
10102
|
__exportStar(__nccwpck_require__(71065), exports);
|
|
10103
|
+
__exportStar(__nccwpck_require__(55537), exports);
|
|
10104
|
+
__exportStar(__nccwpck_require__(47864), exports);
|
|
9928
10105
|
__exportStar(__nccwpck_require__(80769), exports);
|
|
9929
10106
|
__exportStar(__nccwpck_require__(7732), exports);
|
|
9930
10107
|
__exportStar(__nccwpck_require__(66526), exports);
|