@catladder/cli 0.0.0-next-8b9ad5ca → 0.0.0-next-6a4450e0
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 +773 -95
- package/dist/bundles/cli/index.js +847 -121
- package/dist/cli/src/apps/cli/commands/project/commandConfigSecrets.js +22 -4
- package/dist/cli/src/apps/cli/commands/project/commandConfigSecrets.js.map +1 -1
- package/dist/cli/src/commands/project/commandSecretsSyncGithub.d.ts +11 -2
- package/dist/cli/src/commands/project/commandSecretsSyncGithub.js +37 -14
- package/dist/cli/src/commands/project/commandSecretsSyncGithub.js.map +1 -1
- package/dist/cli/src/utils/github.d.ts +6 -1
- package/dist/cli/src/utils/github.js +16 -9
- package/dist/cli/src/utils/github.js.map +1 -1
- package/dist/pipeline/src/backends/github/GithubBackend.d.ts +4 -1
- package/dist/pipeline/src/backends/github/GithubBackend.js +70 -12
- package/dist/pipeline/src/backends/github/GithubBackend.js.map +1 -1
- package/dist/pipeline/src/backends/github/ciVariables.js +3 -1
- package/dist/pipeline/src/backends/github/ciVariables.js.map +1 -1
- package/dist/pipeline/src/backends/github/createGithubJobs.d.ts +13 -3
- package/dist/pipeline/src/backends/github/createGithubJobs.js +80 -14
- package/dist/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
- package/dist/pipeline/src/backends/github/githubReleaseJobs.d.ts +2 -1
- package/dist/pipeline/src/backends/github/githubReleaseJobs.js +46 -33
- package/dist/pipeline/src/backends/github/githubReleaseJobs.js.map +1 -1
- package/dist/pipeline/src/backends/github/index.d.ts +2 -1
- package/dist/pipeline/src/backends/github/index.js +2 -1
- package/dist/pipeline/src/backends/github/index.js.map +1 -1
- package/dist/pipeline/src/backends/github/scriptFiles.d.ts +25 -0
- package/dist/pipeline/src/backends/github/scriptFiles.js +50 -0
- package/dist/pipeline/src/backends/github/scriptFiles.js.map +1 -0
- package/dist/pipeline/src/backends/gitlab/GitlabBackend.d.ts +1 -0
- package/dist/pipeline/src/backends/gitlab/GitlabBackend.js +18 -8
- package/dist/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
- package/dist/pipeline/src/backends/gitlab/ciVariables.js +2 -1
- package/dist/pipeline/src/backends/gitlab/ciVariables.js.map +1 -1
- package/dist/pipeline/src/backends/gitlab/createGitlabJobs.d.ts +3 -2
- package/dist/pipeline/src/backends/gitlab/createGitlabJobs.js +84 -10
- package/dist/pipeline/src/backends/gitlab/createGitlabJobs.js.map +1 -1
- package/dist/pipeline/src/backends/gitlab/createGitlabPipeline.js +1 -1
- package/dist/pipeline/src/backends/gitlab/createGitlabPipeline.js.map +1 -1
- package/dist/pipeline/src/backends/gitlab/gitlabReleaseJobs.js +2 -2
- package/dist/pipeline/src/backends/gitlab/gitlabReleaseJobs.js.map +1 -1
- package/dist/pipeline/src/backends/types.d.ts +2 -1
- package/dist/pipeline/src/bash/ciVariables.d.ts +1 -1
- package/dist/pipeline/src/bash/ciVariables.js.map +1 -1
- package/dist/pipeline/src/build/node/yarn.js +4 -1
- package/dist/pipeline/src/build/node/yarn.js.map +1 -1
- package/dist/pipeline/src/build/types.d.ts +1 -1
- package/dist/pipeline/src/constants.js +1 -1
- package/dist/pipeline/src/context/getEnvironmentVariables.d.ts +8 -0
- package/dist/pipeline/src/context/getEnvironmentVariables.js +3 -3
- package/dist/pipeline/src/context/getEnvironmentVariables.js.map +1 -1
- package/dist/pipeline/src/context/transformJobOnlyVars.js +2 -2
- package/dist/pipeline/src/context/transformJobOnlyVars.js.map +1 -1
- package/dist/pipeline/src/context/utils/envVars.d.ts +7 -0
- package/dist/pipeline/src/context/utils/envVars.js +22 -1
- package/dist/pipeline/src/context/utils/envVars.js.map +1 -1
- package/dist/pipeline/src/customImages/hash.d.ts +15 -0
- package/dist/pipeline/src/customImages/hash.js +71 -0
- package/dist/pipeline/src/customImages/hash.js.map +1 -0
- package/dist/pipeline/src/customImages/jobImagesPlan.d.ts +59 -0
- package/dist/pipeline/src/customImages/jobImagesPlan.js +172 -0
- package/dist/pipeline/src/customImages/jobImagesPlan.js.map +1 -0
- package/dist/pipeline/src/customImages/shippedImages.d.ts +28 -0
- package/dist/pipeline/src/customImages/shippedImages.js +60 -0
- package/dist/pipeline/src/customImages/shippedImages.js.map +1 -0
- package/dist/pipeline/src/deploy/cloudRun/index.js +4 -1
- package/dist/pipeline/src/deploy/cloudRun/index.js.map +1 -1
- package/dist/pipeline/src/deploy/cloudRun/utils/database.js +4 -1
- package/dist/pipeline/src/deploy/cloudRun/utils/database.js.map +1 -1
- package/dist/pipeline/src/pipeline/generatePipelineFiles.js +16 -1
- package/dist/pipeline/src/pipeline/generatePipelineFiles.js.map +1 -1
- package/dist/pipeline/src/runner/index.d.ts +20 -1
- package/dist/pipeline/src/runner/index.js +16 -3
- package/dist/pipeline/src/runner/index.js.map +1 -1
- package/dist/pipeline/src/types/config.d.ts +26 -2
- package/dist/pipeline/src/types/github-types.d.ts +5 -0
- package/dist/pipeline/src/types/jobs.d.ts +10 -2
- package/dist/pipeline/src/types/jobs.js.map +1 -1
- package/dist/pipeline/src/utils/gitlab.d.ts +5 -0
- package/dist/pipeline/src/utils/gitlab.js +6 -0
- package/dist/pipeline/src/utils/gitlab.js.map +1 -1
- package/dist/pipeline/src/utils/writeFiles.d.ts +6 -0
- package/dist/pipeline/src/utils/writeFiles.js +8 -0
- package/dist/pipeline/src/utils/writeFiles.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/apps/cli/commands/project/commandConfigSecrets.ts +25 -5
- package/src/commands/project/commandSecretsSyncGithub.ts +34 -11
- package/src/utils/github.ts +24 -7
|
@@ -1522,7 +1522,11 @@ const createAllJobs_1 = __nccwpck_require__(3671);
|
|
|
1522
1522
|
const config_1 = __nccwpck_require__(6925);
|
|
1523
1523
|
const ciVariables_1 = __nccwpck_require__(3093);
|
|
1524
1524
|
const createGithubJobs_1 = __nccwpck_require__(4016);
|
|
1525
|
+
const jobImagesPlan_1 = __nccwpck_require__(1585);
|
|
1526
|
+
const scriptFunctions_1 = __nccwpck_require__(5759);
|
|
1527
|
+
const utils_1 = __nccwpck_require__(595);
|
|
1525
1528
|
const githubReleaseJobs_1 = __nccwpck_require__(5611);
|
|
1529
|
+
const scriptFiles_1 = __nccwpck_require__(9189);
|
|
1526
1530
|
const WORKFLOWS_FOLDER = ".github/workflows";
|
|
1527
1531
|
/**
|
|
1528
1532
|
* generated workflow files are prefixed so that cleanup never touches
|
|
@@ -1567,18 +1571,29 @@ class GithubBackend {
|
|
|
1567
1571
|
async cleanup() {
|
|
1568
1572
|
const entries = await (0, promises_1.readdir)(WORKFLOWS_FOLDER).catch(() => []);
|
|
1569
1573
|
await Promise.all(entries.filter(file => file.startsWith(GENERATED_FILE_PREFIX)).map(file => (0, promises_1.unlink)((0, path_1.join)(WORKFLOWS_FOLDER, file))));
|
|
1574
|
+
await (0, promises_1.rm)(scriptFiles_1.GITHUB_SCRIPTS_FOLDER, {
|
|
1575
|
+
recursive: true,
|
|
1576
|
+
force: true
|
|
1577
|
+
});
|
|
1570
1578
|
}
|
|
1571
1579
|
async createFiles(config) {
|
|
1572
|
-
const
|
|
1573
|
-
|
|
1580
|
+
const images = this.createImagesPlan(config);
|
|
1581
|
+
const scripts = new scriptFiles_1.GithubScriptFiles();
|
|
1582
|
+
const workflows = await this.createWorkflows(config, images, scripts);
|
|
1583
|
+
return [...Object.entries(workflows).map(([fileName, workflow]) => ({
|
|
1574
1584
|
path: (0, path_1.join)(WORKFLOWS_FOLDER, fileName),
|
|
1575
1585
|
content: workflow
|
|
1576
|
-
}))
|
|
1586
|
+
})),
|
|
1587
|
+
// materialized job scripts and image definitions (repo mode)
|
|
1588
|
+
...scripts.getGeneratedFiles(), ...images.getGeneratedFiles()];
|
|
1589
|
+
}
|
|
1590
|
+
createImagesPlan(config) {
|
|
1591
|
+
return new jobImagesPlan_1.JobImagesPlan((0, jobImagesPlan_1.getJobImagesMode)(config, this.type), this.type);
|
|
1577
1592
|
}
|
|
1578
1593
|
/**
|
|
1579
1594
|
* all workflows keyed by file name, mainly for testing purposes
|
|
1580
1595
|
*/
|
|
1581
|
-
async createWorkflows(config) {
|
|
1596
|
+
async createWorkflows(config, images = this.createImagesPlan(config), scripts = new scriptFiles_1.GithubScriptFiles()) {
|
|
1582
1597
|
const workflows = {};
|
|
1583
1598
|
const reviewStopJobs = {};
|
|
1584
1599
|
const manualJobs = {};
|
|
@@ -1589,13 +1604,14 @@ class GithubBackend {
|
|
|
1589
1604
|
pipelineType: this.type
|
|
1590
1605
|
});
|
|
1591
1606
|
const uploadProviderIds = (0, createGithubJobs_1.getUploadProviderIds)(allJobs);
|
|
1607
|
+
const secretKinds = (0, createGithubJobs_1.collectSecretKinds)(allJobs);
|
|
1592
1608
|
const jobs = {};
|
|
1593
1609
|
// NOTE: agent jobs are gitlab-only and skipped on github
|
|
1594
1610
|
[...allJobs.workspaces, ...allJobs.components].forEach(({
|
|
1595
1611
|
context,
|
|
1596
1612
|
jobs: contextJobs
|
|
1597
1613
|
}) => contextJobs.forEach(job => {
|
|
1598
|
-
const [id, githubJob] = (0, createGithubJobs_1.makeGithubJob)(context, job, allJobs, uploadProviderIds);
|
|
1614
|
+
const [id, githubJob] = (0, createGithubJobs_1.makeGithubJob)(context, job, allJobs, uploadProviderIds, images, scripts, secretKinds);
|
|
1599
1615
|
if (isReviewStopJob(context, job)) {
|
|
1600
1616
|
reviewStopJobs[id] = githubJob;
|
|
1601
1617
|
} else if (isManualTaskJob(job)) {
|
|
@@ -1605,15 +1621,19 @@ class GithubBackend {
|
|
|
1605
1621
|
}
|
|
1606
1622
|
}));
|
|
1607
1623
|
if (trigger === "mainBranch") {
|
|
1608
|
-
const releaseJobs = (0, githubReleaseJobs_1.getGithubReleaseJobs)(config, Object.keys(jobs));
|
|
1624
|
+
const releaseJobs = (0, githubReleaseJobs_1.getGithubReleaseJobs)(config, Object.keys(jobs), images);
|
|
1609
1625
|
Object.assign(jobs, releaseJobs.main);
|
|
1610
1626
|
Object.assign(manualJobs, releaseJobs.manual);
|
|
1611
1627
|
}
|
|
1612
1628
|
if (Object.keys(jobs).length > 0) {
|
|
1613
1629
|
workflows[`${GENERATED_FILE_PREFIX}${workflowFileName(trigger)}`] = {
|
|
1614
1630
|
...TRIGGER_WORKFLOWS[trigger],
|
|
1631
|
+
...workflowPermissions(images),
|
|
1615
1632
|
env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
|
|
1616
|
-
jobs
|
|
1633
|
+
jobs: {
|
|
1634
|
+
...makeEnsureImageGithubJobs(images),
|
|
1635
|
+
...jobs
|
|
1636
|
+
}
|
|
1617
1637
|
};
|
|
1618
1638
|
}
|
|
1619
1639
|
}
|
|
@@ -1625,8 +1645,12 @@ class GithubBackend {
|
|
|
1625
1645
|
types: ["closed"]
|
|
1626
1646
|
}
|
|
1627
1647
|
},
|
|
1648
|
+
...workflowPermissions(images),
|
|
1628
1649
|
env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
|
|
1629
|
-
jobs:
|
|
1650
|
+
jobs: {
|
|
1651
|
+
...makeEnsureImageGithubJobs(images),
|
|
1652
|
+
...reviewStopJobs
|
|
1653
|
+
}
|
|
1630
1654
|
};
|
|
1631
1655
|
}
|
|
1632
1656
|
if (Object.keys(manualJobs).length > 0) {
|
|
@@ -1644,17 +1668,51 @@ class GithubBackend {
|
|
|
1644
1668
|
}
|
|
1645
1669
|
}
|
|
1646
1670
|
},
|
|
1671
|
+
...workflowPermissions(images),
|
|
1647
1672
|
env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
|
|
1648
|
-
jobs:
|
|
1649
|
-
...
|
|
1650
|
-
|
|
1651
|
-
|
|
1673
|
+
jobs: {
|
|
1674
|
+
...makeEnsureImageGithubJobs(images),
|
|
1675
|
+
...Object.fromEntries(Object.entries(manualJobs).map(([id, job]) => [id, {
|
|
1676
|
+
...job,
|
|
1677
|
+
if: `\${{ inputs.job == '${id}' }}`
|
|
1678
|
+
}]))
|
|
1679
|
+
}
|
|
1652
1680
|
};
|
|
1653
1681
|
}
|
|
1654
1682
|
return workflows;
|
|
1655
1683
|
}
|
|
1656
1684
|
}
|
|
1657
1685
|
exports.GithubBackend = GithubBackend;
|
|
1686
|
+
/**
|
|
1687
|
+
* repo mode needs packages:write for pushing job images to ghcr
|
|
1688
|
+
*/
|
|
1689
|
+
const workflowPermissions = images => images.mode === "repo" ? {
|
|
1690
|
+
permissions: {
|
|
1691
|
+
contents: "read",
|
|
1692
|
+
packages: "write"
|
|
1693
|
+
}
|
|
1694
|
+
} : {};
|
|
1695
|
+
/**
|
|
1696
|
+
* the image build jobs: always run (github has no server-side
|
|
1697
|
+
* changes-filter), the existence check makes unchanged runs fast.
|
|
1698
|
+
* Docker is native on github runners — no container, no dind.
|
|
1699
|
+
*/
|
|
1700
|
+
const makeEnsureImageGithubJobs = images => Object.fromEntries(images.getEnsureJobs().map(job => {
|
|
1701
|
+
var _a, _b;
|
|
1702
|
+
return [(0, createGithubJobs_1.githubGlobalJobId)(job.name), {
|
|
1703
|
+
name: job.name,
|
|
1704
|
+
"runs-on": "ubuntu-latest",
|
|
1705
|
+
steps: [{
|
|
1706
|
+
name: "Checkout",
|
|
1707
|
+
uses: "actions/checkout@v4"
|
|
1708
|
+
}, {
|
|
1709
|
+
name: job.name,
|
|
1710
|
+
id: "main",
|
|
1711
|
+
run: [...(0, scriptFunctions_1.getGithubScriptFunctionDefinitions)(), ...((_b = (_a = job.script) === null || _a === void 0 ? void 0 : _a.filter(utils_1.notNil)) !== null && _b !== void 0 ? _b : [])].join("\n"),
|
|
1712
|
+
shell: "bash"
|
|
1713
|
+
}]
|
|
1714
|
+
}];
|
|
1715
|
+
}));
|
|
1658
1716
|
const workflowFileName = trigger => {
|
|
1659
1717
|
switch (trigger) {
|
|
1660
1718
|
case "mr":
|
|
@@ -1705,7 +1763,8 @@ exports.GITHUB_CI_VARIABLES = {
|
|
|
1705
1763
|
jobToken: "CL_JOB_TOKEN",
|
|
1706
1764
|
jobImage: "CL_JOB_IMAGE",
|
|
1707
1765
|
registry: "CL_REGISTRY",
|
|
1708
|
-
registryImage: "CL_REGISTRY_IMAGE"
|
|
1766
|
+
registryImage: "CL_REGISTRY_IMAGE",
|
|
1767
|
+
registryUser: "CL_REGISTRY_USER"
|
|
1709
1768
|
};
|
|
1710
1769
|
/**
|
|
1711
1770
|
* the workflow-level env the backend injects to provide the CL_*
|
|
@@ -1715,6 +1774,7 @@ exports.GITHUB_INJECTED_WORKFLOW_ENV = {
|
|
|
1715
1774
|
CL_JOB_TOKEN: "${{ github.token }}",
|
|
1716
1775
|
CL_REGISTRY: "ghcr.io",
|
|
1717
1776
|
CL_REGISTRY_IMAGE: "ghcr.io/${{ github.repository }}",
|
|
1777
|
+
CL_REGISTRY_USER: "${{ github.actor }}",
|
|
1718
1778
|
// empty outside of pull request events
|
|
1719
1779
|
CL_PR_NUMBER: "${{ github.event.number }}"
|
|
1720
1780
|
};
|
|
@@ -1730,7 +1790,7 @@ exports.GITHUB_INJECTED_WORKFLOW_ENV = {
|
|
|
1730
1790
|
Object.defineProperty(exports, "__esModule", ({
|
|
1731
1791
|
value: true
|
|
1732
1792
|
}));
|
|
1733
|
-
exports.getUploadProviderIds = exports.makeGithubJob = exports.resolveGithubNeeds = exports.githubJobId = void 0;
|
|
1793
|
+
exports.getUploadProviderIds = exports.makeGithubJob = exports.collectSecretKinds = exports.resolveGithubNeeds = exports.githubGlobalJobId = exports.githubJobId = void 0;
|
|
1734
1794
|
const lodash_es_1 = __nccwpck_require__(4284);
|
|
1735
1795
|
const getInjectVarsScript_1 = __nccwpck_require__(436);
|
|
1736
1796
|
const createJobCache_1 = __nccwpck_require__(5644);
|
|
@@ -1738,6 +1798,7 @@ const getEnvironmentVariables_1 = __nccwpck_require__(5855);
|
|
|
1738
1798
|
const utils_1 = __nccwpck_require__(595);
|
|
1739
1799
|
const gitlab_1 = __nccwpck_require__(3468);
|
|
1740
1800
|
const scriptFunctions_1 = __nccwpck_require__(5759);
|
|
1801
|
+
const ciVariables_1 = __nccwpck_require__(3093);
|
|
1741
1802
|
/**
|
|
1742
1803
|
* runner variables that only make sense on gitlab runners and must not
|
|
1743
1804
|
* leak into github jobs (docker-in-docker daemon config, kubernetes
|
|
@@ -1756,6 +1817,9 @@ const slug = value => {
|
|
|
1756
1817
|
};
|
|
1757
1818
|
const githubJobId = (context, jobName) => slug(`${context.type === "workspace" ? "ws-" : ""}${context.name}-${jobName}-${context.env}`);
|
|
1758
1819
|
exports.githubJobId = githubJobId;
|
|
1820
|
+
/** id of a job without component/workspace context (e.g. image builds) */
|
|
1821
|
+
const githubGlobalJobId = jobName => slug(jobName);
|
|
1822
|
+
exports.githubGlobalJobId = githubGlobalJobId;
|
|
1759
1823
|
const githubJobName = (context, jobName) => `${context.name} ${jobName} | ${context.env}`;
|
|
1760
1824
|
const resolveNeed = (context, need, allJobs) => {
|
|
1761
1825
|
var _a;
|
|
@@ -1777,6 +1841,12 @@ const resolveNeed = (context, need, allJobs) => {
|
|
|
1777
1841
|
return (0, exports.githubJobId)(provider.context, jobName);
|
|
1778
1842
|
};
|
|
1779
1843
|
if ((0, lodash_es_1.isObject)(need)) {
|
|
1844
|
+
if ("global" in need && need.global) {
|
|
1845
|
+
return {
|
|
1846
|
+
id: (0, exports.githubGlobalJobId)(need.job),
|
|
1847
|
+
artifacts: need.artifacts
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1780
1850
|
if ("workspaceName" in need && need.workspaceName) {
|
|
1781
1851
|
return {
|
|
1782
1852
|
id: findWorkspaceJob(need.workspaceName, need.job),
|
|
@@ -1794,9 +1864,9 @@ const resolveNeed = (context, need, allJobs) => {
|
|
|
1794
1864
|
artifacts: true
|
|
1795
1865
|
};
|
|
1796
1866
|
};
|
|
1797
|
-
const resolveGithubNeeds = (context, job, allJobs) => {
|
|
1867
|
+
const resolveGithubNeeds = (context, job, allJobs, extraNeeds = []) => {
|
|
1798
1868
|
var _a;
|
|
1799
|
-
const resolved = ((_a = job.needs) !== null && _a !== void 0 ? _a : []).map(need => resolveNeed(context, need, allJobs));
|
|
1869
|
+
const resolved = [...extraNeeds, ...((_a = job.needs) !== null && _a !== void 0 ? _a : [])].map(need => resolveNeed(context, need, allJobs));
|
|
1800
1870
|
// deduplicate by provider id, explicit entries win (they come last)
|
|
1801
1871
|
return [...new Map(resolved.map(n => [n.id, n])).values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
1802
1872
|
};
|
|
@@ -1837,29 +1907,73 @@ const createCacheSteps = (context, job) => {
|
|
|
1837
1907
|
};
|
|
1838
1908
|
});
|
|
1839
1909
|
};
|
|
1840
|
-
|
|
1910
|
+
/**
|
|
1911
|
+
* how a vault-stored value reaches the job env: masked github secret,
|
|
1912
|
+
* or plain (unmasked) github variable for non-sensitive values — those
|
|
1913
|
+
* stay readable in logs and usable in environment urls
|
|
1914
|
+
*/
|
|
1915
|
+
const vaultValueExpression = (name, kinds) => kinds.get(name) === "variable" ? `\${{ vars.${name} }}` : `\${{ secrets.${name} }}`;
|
|
1916
|
+
/**
|
|
1917
|
+
* the kind of every vault-stored var of all components, keyed by its
|
|
1918
|
+
* CL_* name — the lookup for cross-component references
|
|
1919
|
+
*/
|
|
1920
|
+
const collectSecretKinds = allJobs => {
|
|
1921
|
+
const kinds = new Map();
|
|
1922
|
+
allJobs.components.forEach(({
|
|
1923
|
+
context
|
|
1924
|
+
}) => {
|
|
1925
|
+
var _a, _b;
|
|
1926
|
+
const entries = [...context.environment.secretEnvVarKeys, ...((_a = context.environment.jobOnlyVars.build.secretEnvVarKeys) !== null && _a !== void 0 ? _a : []), ...((_b = context.environment.jobOnlyVars.deploy.secretEnvVarKeys) !== null && _b !== void 0 ? _b : [])];
|
|
1927
|
+
entries.forEach(({
|
|
1928
|
+
key,
|
|
1929
|
+
kind
|
|
1930
|
+
}) => kinds.set((0, getEnvironmentVariables_1.getSecretVarName)(context.env, context.name, key), kind !== null && kind !== void 0 ? kind : "secret"));
|
|
1931
|
+
});
|
|
1932
|
+
return kinds;
|
|
1933
|
+
};
|
|
1934
|
+
exports.collectSecretKinds = collectSecretKinds;
|
|
1935
|
+
const getSecretsEnv = (context, kinds) => {
|
|
1841
1936
|
var _a, _b;
|
|
1842
1937
|
const keys = [...context.environment.secretEnvVarKeys, ...((_a = context.environment.jobOnlyVars.build.secretEnvVarKeys) !== null && _a !== void 0 ? _a : []), ...((_b = context.environment.jobOnlyVars.deploy.secretEnvVarKeys) !== null && _b !== void 0 ? _b : [])];
|
|
1843
1938
|
return Object.fromEntries(keys.map(({
|
|
1844
1939
|
key
|
|
1845
1940
|
}) => {
|
|
1846
1941
|
const name = (0, getEnvironmentVariables_1.getSecretVarName)(context.env, context.name, key);
|
|
1847
|
-
return [name,
|
|
1942
|
+
return [name, vaultValueExpression(name, kinds)];
|
|
1848
1943
|
}));
|
|
1849
1944
|
};
|
|
1850
|
-
|
|
1945
|
+
/**
|
|
1946
|
+
* every CL_* variable the job script reads must exist in the job env.
|
|
1947
|
+
* On gitlab all project variables are implicitly available in every
|
|
1948
|
+
* job — cross-component references (`${other-component:KEY}`) rely on
|
|
1949
|
+
* that. Github jobs only see what is injected explicitly, so the
|
|
1950
|
+
* script is scanned for the names it actually references.
|
|
1951
|
+
*/
|
|
1952
|
+
const getReferencedSecretsEnv = (script, kinds) => Object.fromEntries([...script.matchAll(/\$\{?(CL_[A-Za-z0-9_]+)\}?/g)].map(match => match[1]).filter(name => !(name in ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV)).map(name => [name, vaultValueExpression(name, kinds)]));
|
|
1953
|
+
const makeGithubJob = (context, job, allJobs, uploadProviderIds, images, scripts, secretKinds = new Map()) => {
|
|
1851
1954
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1852
1955
|
const id = (0, exports.githubJobId)(context, job.name);
|
|
1853
1956
|
const isComponent = context.type === "component";
|
|
1854
1957
|
const createsJobEnv = !!job.environment && isComponent && (!job.environment.action || job.environment.action === "start");
|
|
1855
1958
|
const skipCheckout = ((_a = job.runnerVariables) === null || _a === void 0 ? void 0 : _a.GIT_STRATEGY) === "none";
|
|
1856
|
-
const
|
|
1857
|
-
const
|
|
1959
|
+
const resolved = images.resolve(job.image);
|
|
1960
|
+
const needs = (0, exports.resolveGithubNeeds)(context, job, allJobs, resolved.need ? [resolved.need] : []);
|
|
1961
|
+
const image = typeof resolved.image === "string" ? resolved.image : Array.isArray(resolved.image) ? resolved.image[0] : (_b = resolved.image) === null || _b === void 0 ? void 0 : _b.name;
|
|
1858
1962
|
const runScript = [...(0, scriptFunctions_1.getGithubScriptFunctionDefinitions)(), ...(0, gitlab_1.collapseableSection)("injectvars", "Injecting variables")((0, getInjectVarsScript_1.getInjectVarsScript)((_c = job.variables) !== null && _c !== void 0 ? _c : {})), ...((_e = (_d = job.script) === null || _d === void 0 ? void 0 : _d.filter(utils_1.notNil)) !== null && _e !== void 0 ? _e : []), ...(createsJobEnv ? [`echo "url=$ROOT_URL" >> "$GITHUB_OUTPUT"`] : [])].join("\n");
|
|
1963
|
+
// scripts live in committed files to keep workflows under github's
|
|
1964
|
+
// 512 KB limit. Two classes of jobs must keep their script inline:
|
|
1965
|
+
// jobs without a checkout have no repo files, and `${{ }}` expressions
|
|
1966
|
+
// are only interpolated inside the workflow file itself.
|
|
1967
|
+
const run = skipCheckout || runScript.includes("${{") ? runScript : scripts.add(id, runScript);
|
|
1859
1968
|
const artifactPaths = (_g = (_f = job.artifacts) === null || _f === void 0 ? void 0 : _f.paths) !== null && _g !== void 0 ? _g : [];
|
|
1860
|
-
const
|
|
1969
|
+
const declaredServices = ((_h = job.services) !== null && _h !== void 0 ? _h : []).map(service => typeof service === "string" ? {
|
|
1861
1970
|
name: service
|
|
1862
|
-
} : service)
|
|
1971
|
+
} : service);
|
|
1972
|
+
// docker runs natively on github runners, so gitlab's docker-in-docker
|
|
1973
|
+
// services are dropped. The job container stays: the runner mounts the
|
|
1974
|
+
// host's docker socket into it, and images like docker-build carry the
|
|
1975
|
+
// helper scripts (ensure*Dockerfile etc.) the job scripts rely on.
|
|
1976
|
+
const services = Object.fromEntries(declaredServices.filter(service => !isDindService(service.name)).map(service => [slug("alias" in service && service.alias ? service.alias : service.name), {
|
|
1863
1977
|
image: service.name,
|
|
1864
1978
|
...("variables" in service && service.variables ? {
|
|
1865
1979
|
env: service.variables
|
|
@@ -1867,7 +1981,8 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds) => {
|
|
|
1867
1981
|
}]));
|
|
1868
1982
|
const env = {
|
|
1869
1983
|
...Object.fromEntries(Object.entries((_j = job.runnerVariables) !== null && _j !== void 0 ? _j : {}).filter(([key]) => !GITLAB_ONLY_RUNNER_VARIABLES.has(key))),
|
|
1870
|
-
...(isComponent ? getSecretsEnv(context) : {}),
|
|
1984
|
+
...(isComponent ? getSecretsEnv(context, secretKinds) : {}),
|
|
1985
|
+
...getReferencedSecretsEnv(runScript, secretKinds),
|
|
1871
1986
|
CL_JOB_IMAGE: image !== null && image !== void 0 ? image : "runner"
|
|
1872
1987
|
};
|
|
1873
1988
|
const githubJob = {
|
|
@@ -1878,7 +1993,14 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds) => {
|
|
|
1878
1993
|
} : {}),
|
|
1879
1994
|
...(image ? {
|
|
1880
1995
|
container: {
|
|
1881
|
-
image
|
|
1996
|
+
image,
|
|
1997
|
+
// private images in the repo's registry need credentials
|
|
1998
|
+
...(resolved.fromRepoRegistry ? {
|
|
1999
|
+
credentials: {
|
|
2000
|
+
username: "${{ github.actor }}",
|
|
2001
|
+
password: "${{ github.token }}"
|
|
2002
|
+
}
|
|
2003
|
+
} : {})
|
|
1882
2004
|
}
|
|
1883
2005
|
} : {}),
|
|
1884
2006
|
...(Object.keys(services).length > 0 ? {
|
|
@@ -1905,7 +2027,7 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds) => {
|
|
|
1905
2027
|
})), {
|
|
1906
2028
|
name: job.name,
|
|
1907
2029
|
id: "main",
|
|
1908
|
-
run
|
|
2030
|
+
run,
|
|
1909
2031
|
shell: "bash"
|
|
1910
2032
|
}, ...(uploadProviderIds.has(id) || artifactPaths.length > 0 ? artifactPaths.length > 0 ? [{
|
|
1911
2033
|
name: "Upload artifacts",
|
|
@@ -1913,7 +2035,11 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds) => {
|
|
|
1913
2035
|
with: {
|
|
1914
2036
|
name: id,
|
|
1915
2037
|
path: artifactPaths.join("\n"),
|
|
1916
|
-
"if-no-files-found": "warn"
|
|
2038
|
+
"if-no-files-found": "warn",
|
|
2039
|
+
// gitlab artifacts include everything; upload-artifact
|
|
2040
|
+
// silently drops hidden files by default — which is
|
|
2041
|
+
// exactly where next.js builds live (.next)
|
|
2042
|
+
"include-hidden-files": true
|
|
1917
2043
|
}
|
|
1918
2044
|
}] : [] : [])]
|
|
1919
2045
|
};
|
|
@@ -1946,36 +2072,49 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
1946
2072
|
value: true
|
|
1947
2073
|
}));
|
|
1948
2074
|
exports.getGithubReleaseJobs = void 0;
|
|
1949
|
-
const
|
|
1950
|
-
const createReleaseJob = needs =>
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
permissions: {
|
|
1958
|
-
contents: "write"
|
|
1959
|
-
},
|
|
1960
|
-
...(needs && needs.length > 0 ? {
|
|
1961
|
-
needs
|
|
1962
|
-
} : {}),
|
|
1963
|
-
env: {
|
|
1964
|
-
GITHUB_TOKEN: "${{ github.token }}"
|
|
1965
|
-
},
|
|
1966
|
-
steps: [{
|
|
1967
|
-
name: "Checkout",
|
|
1968
|
-
uses: "actions/checkout@v4",
|
|
1969
|
-
// semantic-release needs the full history to determine the version
|
|
1970
|
-
with: {
|
|
1971
|
-
"fetch-depth": 0
|
|
1972
|
-
}
|
|
1973
|
-
}, {
|
|
2075
|
+
const createGithubJobs_1 = __nccwpck_require__(4016);
|
|
2076
|
+
const createReleaseJob = (images, needs) => {
|
|
2077
|
+
const resolved = images.resolveRef({
|
|
2078
|
+
catladderImage: "semantic-release"
|
|
2079
|
+
});
|
|
2080
|
+
const imageNeeds = resolved.need && typeof resolved.need === "object" ? [(0, createGithubJobs_1.githubGlobalJobId)(resolved.need.job)] : [];
|
|
2081
|
+
const allNeeds = [...imageNeeds, ...(needs !== null && needs !== void 0 ? needs : [])];
|
|
2082
|
+
return {
|
|
1974
2083
|
name: "create release",
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2084
|
+
"runs-on": "ubuntu-latest",
|
|
2085
|
+
container: {
|
|
2086
|
+
image: resolved.image,
|
|
2087
|
+
...(resolved.fromRepoRegistry ? {
|
|
2088
|
+
credentials: {
|
|
2089
|
+
username: "${{ github.actor }}",
|
|
2090
|
+
password: "${{ github.token }}"
|
|
2091
|
+
}
|
|
2092
|
+
} : {})
|
|
2093
|
+
},
|
|
2094
|
+
// semantic-release pushes the version tag and release commit
|
|
2095
|
+
permissions: {
|
|
2096
|
+
contents: "write"
|
|
2097
|
+
},
|
|
2098
|
+
...(allNeeds.length > 0 ? {
|
|
2099
|
+
needs: allNeeds
|
|
2100
|
+
} : {}),
|
|
2101
|
+
env: {
|
|
2102
|
+
GITHUB_TOKEN: "${{ github.token }}"
|
|
2103
|
+
},
|
|
2104
|
+
steps: [{
|
|
2105
|
+
name: "Checkout",
|
|
2106
|
+
uses: "actions/checkout@v4",
|
|
2107
|
+
// semantic-release needs the full history to determine the version
|
|
2108
|
+
with: {
|
|
2109
|
+
"fetch-depth": 0
|
|
2110
|
+
}
|
|
2111
|
+
}, {
|
|
2112
|
+
name: "create release",
|
|
2113
|
+
run: "semanticRelease",
|
|
2114
|
+
shell: "bash"
|
|
2115
|
+
}]
|
|
2116
|
+
};
|
|
2117
|
+
};
|
|
1979
2118
|
/**
|
|
1980
2119
|
* the release jobs for the github backend (the counterpart of the
|
|
1981
2120
|
* gitlab release jobs):
|
|
@@ -1985,22 +2124,22 @@ const createReleaseJob = needs => ({
|
|
|
1985
2124
|
* - otherwise (manual, the default): the release job goes to the
|
|
1986
2125
|
* manual tasks workflow
|
|
1987
2126
|
*/
|
|
1988
|
-
const getGithubReleaseJobs = (config, mainWorkflowJobIds) => {
|
|
2127
|
+
const getGithubReleaseJobs = (config, mainWorkflowJobIds, images) => {
|
|
1989
2128
|
var _a;
|
|
1990
2129
|
if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
|
|
1991
2130
|
return {
|
|
1992
2131
|
main: {
|
|
1993
|
-
"create-release": createReleaseJob(mainWorkflowJobIds)
|
|
2132
|
+
"create-release": createReleaseJob(images, mainWorkflowJobIds)
|
|
1994
2133
|
},
|
|
1995
2134
|
manual: {
|
|
1996
|
-
"force-create-release": createReleaseJob()
|
|
2135
|
+
"force-create-release": createReleaseJob(images)
|
|
1997
2136
|
}
|
|
1998
2137
|
};
|
|
1999
2138
|
}
|
|
2000
2139
|
return {
|
|
2001
2140
|
main: {},
|
|
2002
2141
|
manual: {
|
|
2003
|
-
"create-release": createReleaseJob()
|
|
2142
|
+
"create-release": createReleaseJob(images)
|
|
2004
2143
|
}
|
|
2005
2144
|
};
|
|
2006
2145
|
};
|
|
@@ -2038,6 +2177,64 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
2038
2177
|
}));
|
|
2039
2178
|
__exportStar(__nccwpck_require__(4038), exports);
|
|
2040
2179
|
__exportStar(__nccwpck_require__(3093), exports);
|
|
2180
|
+
__exportStar(__nccwpck_require__(9189), exports);
|
|
2181
|
+
|
|
2182
|
+
/***/ }),
|
|
2183
|
+
|
|
2184
|
+
/***/ 9189:
|
|
2185
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
2186
|
+
|
|
2187
|
+
"use strict";
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
2191
|
+
value: true
|
|
2192
|
+
}));
|
|
2193
|
+
exports.GithubScriptFiles = exports.GITHUB_SCRIPTS_FOLDER = void 0;
|
|
2194
|
+
const path_1 = __nccwpck_require__(6928);
|
|
2195
|
+
/**
|
|
2196
|
+
* folder for job scripts materialized into the repository (committed,
|
|
2197
|
+
* like the image definitions). Owned entirely by the github backend.
|
|
2198
|
+
*/
|
|
2199
|
+
exports.GITHUB_SCRIPTS_FOLDER = ".catladder-generated/github/scripts";
|
|
2200
|
+
/**
|
|
2201
|
+
* github silently ignores workflow files larger than 512 KB — no run,
|
|
2202
|
+
* no check suite, no error. Inlining every job's bash script blows past
|
|
2203
|
+
* that limit on bigger projects, so job scripts are materialized into
|
|
2204
|
+
* committed files and the workflow step only invokes them.
|
|
2205
|
+
*
|
|
2206
|
+
* Scripts containing `${{ ... }}` expressions must stay inline: the
|
|
2207
|
+
* runner only interpolates expressions in the workflow file itself,
|
|
2208
|
+
* never in files read at runtime.
|
|
2209
|
+
*/
|
|
2210
|
+
class GithubScriptFiles {
|
|
2211
|
+
constructor() {
|
|
2212
|
+
this.files = new Map();
|
|
2213
|
+
}
|
|
2214
|
+
/**
|
|
2215
|
+
* materializes a job script into a committed file and returns the
|
|
2216
|
+
* step command invoking it
|
|
2217
|
+
*/
|
|
2218
|
+
add(jobId, script) {
|
|
2219
|
+
const path = (0, path_1.join)(exports.GITHUB_SCRIPTS_FOLDER, `${jobId}.sh`);
|
|
2220
|
+
// `shell: bash` steps run with `bash -eo pipefail`; the script file
|
|
2221
|
+
// must fail exactly like the inline version did
|
|
2222
|
+
const content = `#!/usr/bin/env bash\nset -eo pipefail\n\n${script}\n`;
|
|
2223
|
+
const existing = this.files.get(path);
|
|
2224
|
+
if (existing !== undefined && existing !== content) {
|
|
2225
|
+
throw new Error(`conflicting scripts for job id '${jobId}'`);
|
|
2226
|
+
}
|
|
2227
|
+
this.files.set(path, content);
|
|
2228
|
+
return `bash ${path}`;
|
|
2229
|
+
}
|
|
2230
|
+
getGeneratedFiles() {
|
|
2231
|
+
return [...this.files.entries()].map(([path, content]) => ({
|
|
2232
|
+
path,
|
|
2233
|
+
content
|
|
2234
|
+
}));
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
exports.GithubScriptFiles = GithubScriptFiles;
|
|
2041
2238
|
|
|
2042
2239
|
/***/ }),
|
|
2043
2240
|
|
|
@@ -2092,6 +2289,7 @@ const promises_1 = __nccwpck_require__(1943);
|
|
|
2092
2289
|
const rules_1 = __nccwpck_require__(4565);
|
|
2093
2290
|
const config_1 = __nccwpck_require__(6925);
|
|
2094
2291
|
const createAllJobs_1 = __nccwpck_require__(3671);
|
|
2292
|
+
const jobImagesPlan_1 = __nccwpck_require__(1585);
|
|
2095
2293
|
const createGitlabJobs_1 = __nccwpck_require__(512);
|
|
2096
2294
|
const createGitlabPipeline_1 = __nccwpck_require__(1862);
|
|
2097
2295
|
const gitlabReleaseJobs_1 = __nccwpck_require__(5531);
|
|
@@ -2111,31 +2309,38 @@ class GitlabBackend {
|
|
|
2111
2309
|
});
|
|
2112
2310
|
}
|
|
2113
2311
|
async createFiles(config) {
|
|
2114
|
-
const
|
|
2312
|
+
const images = this.createImagesPlan(config);
|
|
2313
|
+
const includes = await this.createIncludes(config, images);
|
|
2115
2314
|
const mainFile = {
|
|
2116
2315
|
path: ".gitlab-ci.yml",
|
|
2117
2316
|
content: {
|
|
2118
2317
|
include: includes.map(i => i.path)
|
|
2119
2318
|
}
|
|
2120
2319
|
};
|
|
2121
|
-
return [mainFile, ...includes
|
|
2320
|
+
return [mainFile, ...includes,
|
|
2321
|
+
// materialized image definitions (repo mode)
|
|
2322
|
+
...images.getGeneratedFiles()];
|
|
2323
|
+
}
|
|
2324
|
+
createImagesPlan(config) {
|
|
2325
|
+
return new jobImagesPlan_1.JobImagesPlan((0, jobImagesPlan_1.getJobImagesMode)(config, this.type), this.type);
|
|
2122
2326
|
}
|
|
2123
2327
|
/**
|
|
2124
2328
|
* the complete pipeline as one object (all includes merged into one),
|
|
2125
2329
|
* mainly for testing purposes
|
|
2126
2330
|
*/
|
|
2127
2331
|
async createCompletePipeline(config) {
|
|
2128
|
-
const includes = await this.createIncludes(config);
|
|
2332
|
+
const includes = await this.createIncludes(config, this.createImagesPlan(config));
|
|
2129
2333
|
return includes.reduce((acc, {
|
|
2130
2334
|
content
|
|
2131
2335
|
}) => {
|
|
2132
2336
|
return {
|
|
2133
2337
|
...acc,
|
|
2338
|
+
// includes are always yaml objects
|
|
2134
2339
|
...content // merge all includes into one object
|
|
2135
2340
|
};
|
|
2136
2341
|
}, {});
|
|
2137
2342
|
}
|
|
2138
|
-
async createIncludes(config) {
|
|
2343
|
+
async createIncludes(config, images) {
|
|
2139
2344
|
const {
|
|
2140
2345
|
jobs,
|
|
2141
2346
|
image,
|
|
@@ -2143,7 +2348,7 @@ class GitlabBackend {
|
|
|
2143
2348
|
variables,
|
|
2144
2349
|
workflow,
|
|
2145
2350
|
...pipelineRest
|
|
2146
|
-
} = await this.createPipeline(config);
|
|
2351
|
+
} = await this.createPipeline(config, images);
|
|
2147
2352
|
// we will create 1 include per component or workspace
|
|
2148
2353
|
// this is for better readability in git diffs and to avoid problems with yaml files beeing too large
|
|
2149
2354
|
// group by context
|
|
@@ -2176,14 +2381,14 @@ class GitlabBackend {
|
|
|
2176
2381
|
};
|
|
2177
2382
|
return [mainInclude, ...componentIncludes];
|
|
2178
2383
|
}
|
|
2179
|
-
async createPipeline(config) {
|
|
2384
|
+
async createPipeline(config, images) {
|
|
2180
2385
|
const stages = (0, getPipelineStages_1.getPipelineStages)(config);
|
|
2181
2386
|
// for all triggers create jobs and add base rules
|
|
2182
2387
|
const allJobsPerTrigger = await Promise.all(config_1.ALL_PIPELINE_TRIGGERS.map(async trigger => await (0, createGitlabJobs_1.createGitlabJobs)(await (0, createAllJobs_1.createAllJobs)({
|
|
2183
2388
|
config,
|
|
2184
2389
|
trigger,
|
|
2185
2390
|
pipelineType: this.type
|
|
2186
|
-
}), getGitlabRulesForTrigger(trigger)))).then(j => j.flat());
|
|
2391
|
+
}), images, getGitlabRulesForTrigger(trigger)))).then(j => j.flat());
|
|
2187
2392
|
const allWorkspaceJobs = allJobsPerTrigger.filter(j => {
|
|
2188
2393
|
var _a;
|
|
2189
2394
|
return ((_a = j.context) === null || _a === void 0 ? void 0 : _a.type) === "workspace";
|
|
@@ -2212,7 +2417,9 @@ class GitlabBackend {
|
|
|
2212
2417
|
var _a;
|
|
2213
2418
|
return ((_a = j.context) === null || _a === void 0 ? void 0 : _a.type) === "agent";
|
|
2214
2419
|
});
|
|
2215
|
-
|
|
2420
|
+
// context-less jobs (image build jobs)
|
|
2421
|
+
const allContextlessJobs = allJobsPerTrigger.filter(j => j.context === null);
|
|
2422
|
+
const allJobs = [...allContextlessJobs, ...allWorkspaceJobs, ...allComponentJobs, ...allGlobalJobs].reduce((acc, {
|
|
2216
2423
|
gitlabJob,
|
|
2217
2424
|
name,
|
|
2218
2425
|
context
|
|
@@ -2326,7 +2533,8 @@ exports.GITLAB_CI_VARIABLES = {
|
|
|
2326
2533
|
jobToken: "CI_JOB_TOKEN",
|
|
2327
2534
|
jobImage: "CI_JOB_IMAGE",
|
|
2328
2535
|
registry: "CI_REGISTRY",
|
|
2329
|
-
registryImage: "CI_REGISTRY_IMAGE"
|
|
2536
|
+
registryImage: "CI_REGISTRY_IMAGE",
|
|
2537
|
+
registryUser: "CI_REGISTRY_USER"
|
|
2330
2538
|
};
|
|
2331
2539
|
|
|
2332
2540
|
/***/ }),
|
|
@@ -2395,7 +2603,7 @@ const getFullReferencedJobNameFromWorkspace = (referencedJobName, workspaceName,
|
|
|
2395
2603
|
});
|
|
2396
2604
|
};
|
|
2397
2605
|
const getJobName = need => (0, lodash_es_1.isObject)(need) ? need.job : need;
|
|
2398
|
-
const makeGitlabJob = (context, job, allJobs, baseRules) => {
|
|
2606
|
+
const makeGitlabJob = (context, job, allJobs, images, baseRules) => {
|
|
2399
2607
|
var _a, _b;
|
|
2400
2608
|
const {
|
|
2401
2609
|
environment,
|
|
@@ -2413,8 +2621,14 @@ const makeGitlabJob = (context, job, allJobs, baseRules) => {
|
|
|
2413
2621
|
allow_failure: jobAllowFailure,
|
|
2414
2622
|
cache: jobCache,
|
|
2415
2623
|
caches,
|
|
2624
|
+
image: jobImage,
|
|
2416
2625
|
...rest
|
|
2417
2626
|
} = job;
|
|
2627
|
+
// catladder image references resolve according to the jobImages mode;
|
|
2628
|
+
// in repo mode the job additionally depends on the image build job
|
|
2629
|
+
const resolvedImage = images.resolve(jobImage);
|
|
2630
|
+
const image = resolvedImage.image;
|
|
2631
|
+
const imageNeeds = resolvedImage.need ? [resolvedImage.need] : [];
|
|
2418
2632
|
// the neutral `gate` translates to gitlab's when/allow_failure;
|
|
2419
2633
|
// explicitly set gitlab fields take precedence
|
|
2420
2634
|
const when = jobWhen !== null && jobWhen !== void 0 ? jobWhen : gate ? gate === "manual" ? "manual" : "on_success" : undefined;
|
|
@@ -2423,7 +2637,7 @@ const makeGitlabJob = (context, job, allJobs, baseRules) => {
|
|
|
2423
2637
|
// an explicitly set gitlab `cache` takes precedence
|
|
2424
2638
|
const cache = jobCache !== null && jobCache !== void 0 ? jobCache : caches && context.type !== "agent" ? (0, createJobCache_1.createJobCacheFromCacheConfigs)(context, caches) : undefined;
|
|
2425
2639
|
const stage = envMode === "stagePerEnv" && context.type !== "agent" ? `${job.stage} ${context.env}` : job.stage;
|
|
2426
|
-
const deduplicatedGitlabNeeds = getGitlabNeeds(context, job, allJobs);
|
|
2640
|
+
const deduplicatedGitlabNeeds = getGitlabNeeds(context, job, allJobs, imageNeeds);
|
|
2427
2641
|
const fullJobName = getFullJobName({
|
|
2428
2642
|
type: context.type,
|
|
2429
2643
|
name,
|
|
@@ -2452,6 +2666,7 @@ const makeGitlabJob = (context, job, allJobs, baseRules) => {
|
|
|
2452
2666
|
retry: defaults_1.BASE_RETRY,
|
|
2453
2667
|
interruptible: true,
|
|
2454
2668
|
...rest,
|
|
2669
|
+
image,
|
|
2455
2670
|
allow_failure,
|
|
2456
2671
|
cache: cache ? (0, cache_1.addCacheFallback)(cache, context) : undefined,
|
|
2457
2672
|
rules: rules.length > 0 ? rules : undefined,
|
|
@@ -2527,13 +2742,13 @@ const addGitlabEnvironment = (context, catladderJobEnvironment, job, allJobs) =>
|
|
|
2527
2742
|
script: [...((_b = job.script) !== null && _b !== void 0 ? _b : []), ...(createsJobEnv ? scriptToAdd : [])]
|
|
2528
2743
|
};
|
|
2529
2744
|
};
|
|
2530
|
-
const createGitlabJobs = async (allJobs, baseRules) => {
|
|
2531
|
-
|
|
2745
|
+
const createGitlabJobs = async (allJobs, images, baseRules) => {
|
|
2746
|
+
const contextualJobs = [...allJobs.workspaces, ...allJobs.components, ...allJobs.agents].flatMap(({
|
|
2532
2747
|
context,
|
|
2533
2748
|
jobs
|
|
2534
2749
|
}) => {
|
|
2535
2750
|
return jobs.map(job => {
|
|
2536
|
-
const [fullJobName, gitlabJob] = (0, exports.makeGitlabJob)(context, job, allJobs, baseRules);
|
|
2751
|
+
const [fullJobName, gitlabJob] = (0, exports.makeGitlabJob)(context, job, allJobs, images, baseRules);
|
|
2537
2752
|
return {
|
|
2538
2753
|
name: fullJobName,
|
|
2539
2754
|
gitlabJob,
|
|
@@ -2541,13 +2756,66 @@ const createGitlabJobs = async (allJobs, baseRules) => {
|
|
|
2541
2756
|
};
|
|
2542
2757
|
});
|
|
2543
2758
|
});
|
|
2759
|
+
// image build jobs (repo mode): no context, plain names, their
|
|
2760
|
+
// rules:changes combined with the trigger rules
|
|
2761
|
+
const imageJobs = images.getEnsureJobs().map(job => ({
|
|
2762
|
+
name: job.name,
|
|
2763
|
+
gitlabJob: makeEnsureImageGitlabJob(job, baseRules),
|
|
2764
|
+
context: null
|
|
2765
|
+
}));
|
|
2766
|
+
return [...imageJobs, ...contextualJobs];
|
|
2544
2767
|
};
|
|
2545
2768
|
exports.createGitlabJobs = createGitlabJobs;
|
|
2546
|
-
|
|
2769
|
+
/**
|
|
2770
|
+
* lowers an image build job: only runs when the (generated) image
|
|
2771
|
+
* definition changed, within the trigger's base rules
|
|
2772
|
+
*/
|
|
2773
|
+
const makeEnsureImageGitlabJob = (job, baseRules) => {
|
|
2774
|
+
var _a, _b, _c, _d;
|
|
2775
|
+
const changes = (_b = (_a = job.rules) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.changes;
|
|
2776
|
+
const rules = (baseRules !== null && baseRules !== void 0 ? baseRules : []).map(baseRule => baseRule.when === "never" ? baseRule : {
|
|
2777
|
+
...baseRule,
|
|
2778
|
+
changes
|
|
2779
|
+
});
|
|
2780
|
+
return (0, removeUndefined_1.removeUndefined)({
|
|
2781
|
+
retry: defaults_1.BASE_RETRY,
|
|
2782
|
+
interruptible: true,
|
|
2783
|
+
image: job.image,
|
|
2784
|
+
services: job.services,
|
|
2785
|
+
rules: rules.length > 0 ? rules : [{
|
|
2786
|
+
changes
|
|
2787
|
+
}],
|
|
2788
|
+
variables: job.runnerVariables,
|
|
2789
|
+
script: (_d = (_c = job.script) === null || _c === void 0 ? void 0 : _c.filter(utils_1.notNil)) !== null && _d !== void 0 ? _d : [],
|
|
2790
|
+
stage: job.stage,
|
|
2791
|
+
needs: []
|
|
2792
|
+
});
|
|
2793
|
+
};
|
|
2794
|
+
function getGitlabNeeds(context, job, allJobs, extraNeeds = []) {
|
|
2547
2795
|
var _a;
|
|
2548
|
-
const
|
|
2796
|
+
const jobWithExtraNeeds = extraNeeds.length > 0 ? {
|
|
2797
|
+
...job,
|
|
2798
|
+
needs: [...extraNeeds, ...((_a = job.needs) !== null && _a !== void 0 ? _a : [])]
|
|
2799
|
+
} : job;
|
|
2800
|
+
const needs = context.type === "workspace" ? getGitlabNeedsForWorkspaceJob(context, jobWithExtraNeeds, allJobs) : context.type === "agent" ? mapAgentNeeds(jobWithExtraNeeds.needs) : getGitlabNeedsForComponentJob(context, jobWithExtraNeeds, allJobs);
|
|
2549
2801
|
return needs ? deduplicateNeeds(needs) : undefined;
|
|
2550
2802
|
}
|
|
2803
|
+
/**
|
|
2804
|
+
* agent jobs use their needs as-is; global needs (image build jobs)
|
|
2805
|
+
* keep their plain name and optional flag
|
|
2806
|
+
*/
|
|
2807
|
+
function mapAgentNeeds(needs) {
|
|
2808
|
+
if (!needs) {
|
|
2809
|
+
return null;
|
|
2810
|
+
}
|
|
2811
|
+
return needs.map(n => (0, lodash_es_1.isObject)(n) && "global" in n && n.global ? {
|
|
2812
|
+
job: n.job,
|
|
2813
|
+
artifacts: n.artifacts,
|
|
2814
|
+
...(n.optional ? {
|
|
2815
|
+
optional: true
|
|
2816
|
+
} : {})
|
|
2817
|
+
} : n);
|
|
2818
|
+
}
|
|
2551
2819
|
function deduplicateNeeds(needs) {
|
|
2552
2820
|
return needs ? [...new Map(needs.map(n => [(0, lodash_es_1.isObject)(n) ? n.job : n, n])).values()] : undefined;
|
|
2553
2821
|
}
|
|
@@ -2556,11 +2824,19 @@ function getGitlabNeedsForComponentJob(context, {
|
|
|
2556
2824
|
}, allJobs) {
|
|
2557
2825
|
return (needs !== null && needs !== void 0 ? needs : []).map(n => {
|
|
2558
2826
|
var _a;
|
|
2559
|
-
return (0, lodash_es_1.isObject)(n) ? "
|
|
2827
|
+
return (0, lodash_es_1.isObject)(n) ? "global" in n && n.global ?
|
|
2828
|
+
// global jobs (e.g. image builds) keep their plain name
|
|
2829
|
+
{
|
|
2830
|
+
job: n.job,
|
|
2831
|
+
artifacts: n.artifacts,
|
|
2832
|
+
...(n.optional ? {
|
|
2833
|
+
optional: true
|
|
2834
|
+
} : {})
|
|
2835
|
+
} : "workspaceName" in n && n.workspaceName ? {
|
|
2560
2836
|
job: getFullReferencedJobNameFromWorkspace(n.job, n.workspaceName, context.env, allJobs),
|
|
2561
2837
|
artifacts: n.artifacts
|
|
2562
2838
|
} : {
|
|
2563
|
-
job: getFullReferencedJobNameFromComponent(n.job, (_a = n.componentName) !== null && _a !== void 0 ? _a : context.name, context.env, allJobs),
|
|
2839
|
+
job: getFullReferencedJobNameFromComponent(n.job, "componentName" in n ? (_a = n.componentName) !== null && _a !== void 0 ? _a : context.name : context.name, context.env, allJobs),
|
|
2564
2840
|
artifacts: n.artifacts
|
|
2565
2841
|
} : getFullReferencedJobNameFromComponent(n, context.name, context.env, allJobs);
|
|
2566
2842
|
}) // sort in a predictable manner for snapshot tests
|
|
@@ -2573,7 +2849,13 @@ function getGitlabNeedsForComponentJob(context, {
|
|
|
2573
2849
|
function getGitlabNeedsForWorkspaceJob(context, {
|
|
2574
2850
|
needs
|
|
2575
2851
|
}, allJobs) {
|
|
2576
|
-
return (needs !== null && needs !== void 0 ? needs : []).map(n => (0, lodash_es_1.isObject)(n) ? {
|
|
2852
|
+
return (needs !== null && needs !== void 0 ? needs : []).map(n => (0, lodash_es_1.isObject)(n) ? "global" in n && n.global ? {
|
|
2853
|
+
job: n.job,
|
|
2854
|
+
artifacts: n.artifacts,
|
|
2855
|
+
...(n.optional ? {
|
|
2856
|
+
optional: true
|
|
2857
|
+
} : {})
|
|
2858
|
+
} : {
|
|
2577
2859
|
job: getFullReferencedJobNameFromWorkspace(n.job, "workspaceName" in n && n.workspaceName ? n.workspaceName : context.name, context.env, allJobs),
|
|
2578
2860
|
artifacts: n.artifacts
|
|
2579
2861
|
} : getFullReferencedJobNameFromWorkspace(n, context.name, context.env, allJobs)) // sort in a predictable manner for snapshot tests
|
|
@@ -2602,7 +2884,7 @@ const createGitlabPipelineWithDefaults = ({
|
|
|
2602
2884
|
...config
|
|
2603
2885
|
}) => {
|
|
2604
2886
|
return {
|
|
2605
|
-
image: image !== null && image !== void 0 ? image : (0, runner_1.
|
|
2887
|
+
image: image !== null && image !== void 0 ? image : (0, runner_1.getCentralRunnerImageUrl)("jobs-default"),
|
|
2606
2888
|
// default image
|
|
2607
2889
|
variables: {
|
|
2608
2890
|
FF_USE_FASTZIP: "true",
|
|
@@ -2705,7 +2987,7 @@ const getGitlabReleaseJobs = config => {
|
|
|
2705
2987
|
return {
|
|
2706
2988
|
["create release"]: {
|
|
2707
2989
|
stage: "release",
|
|
2708
|
-
image: (0, runner_1.
|
|
2990
|
+
image: (0, runner_1.getCentralRunnerImageUrl)("semantic-release"),
|
|
2709
2991
|
script: ["semanticRelease"],
|
|
2710
2992
|
after_script: [EXPIRED_TOKEN_HELP],
|
|
2711
2993
|
rules: [...baseReleaseRules, {
|
|
@@ -2718,7 +3000,7 @@ const getGitlabReleaseJobs = config => {
|
|
|
2718
3000
|
},
|
|
2719
3001
|
["⚠️ force create release"]: {
|
|
2720
3002
|
stage: "release",
|
|
2721
|
-
image: (0, runner_1.
|
|
3003
|
+
image: (0, runner_1.getCentralRunnerImageUrl)("semantic-release"),
|
|
2722
3004
|
script: ["semanticRelease"],
|
|
2723
3005
|
after_script: [EXPIRED_TOKEN_HELP],
|
|
2724
3006
|
needs: [],
|
|
@@ -4461,7 +4743,10 @@ const getYarnInstallCommand = async context => {
|
|
|
4461
4743
|
// inline builds make debugging easier as it prints it out in the logs, instead of writing it in temp files
|
|
4462
4744
|
return `yarn install --immutable --inline-builds`;
|
|
4463
4745
|
};
|
|
4464
|
-
const ensureNodeVersion = context => (0, gitlab_1.collapseableSection)("nodeinstall", "Ensure node version")([
|
|
4746
|
+
const ensureNodeVersion = context => (0, gitlab_1.collapseableSection)("nodeinstall", "Ensure node version")([
|
|
4747
|
+
// github actions overrides HOME in container jobs, so also look
|
|
4748
|
+
// for nvm where the catladder images install it (/root/.nvm)
|
|
4749
|
+
'if [ -f "$HOME/.nvm/nvm.sh" ]; then source "$HOME/.nvm/nvm.sh"; elif [ -f /root/.nvm/nvm.sh ]; then export NVM_DIR=/root/.nvm; source /root/.nvm/nvm.sh; fi', "if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi"]);
|
|
4465
4750
|
exports.ensureNodeVersion = ensureNodeVersion;
|
|
4466
4751
|
const getYarnInstall = async (context, options) => {
|
|
4467
4752
|
const postInstall = context.type !== "workspace" && context.build.type !== "disabled" && "postInstall" in context.build.config ? context.build.config.postInstall : null;
|
|
@@ -4840,7 +5125,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
4840
5125
|
value: true
|
|
4841
5126
|
}));
|
|
4842
5127
|
exports.DOCKER_REGISTRY = exports.PIPELINE_IMAGE_TAG = void 0;
|
|
4843
|
-
exports.PIPELINE_IMAGE_TAG = "next-
|
|
5128
|
+
exports.PIPELINE_IMAGE_TAG = "next-6a4450e0" || 0;
|
|
4844
5129
|
exports.DOCKER_REGISTRY = "git.panter.ch:5001/catladder/catladder" || 0;
|
|
4845
5130
|
|
|
4846
5131
|
/***/ }),
|
|
@@ -5252,7 +5537,7 @@ const getBasePredefinedVariables = ctx => {
|
|
|
5252
5537
|
};
|
|
5253
5538
|
};
|
|
5254
5539
|
const getEnvironmentVariables = async (ctx, options = {}) => {
|
|
5255
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
5540
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
5256
5541
|
const environmentContext = (0, getEnvironmentContext_1.getEnvironmentContext)(ctx);
|
|
5257
5542
|
const {
|
|
5258
5543
|
config,
|
|
@@ -5309,13 +5594,13 @@ const getEnvironmentVariables = async (ctx, options = {}) => {
|
|
|
5309
5594
|
}
|
|
5310
5595
|
const publicEnvVarsRaw = (_e = (_d = envConfigRaw.vars) === null || _d === void 0 ? void 0 : _d.public) !== null && _e !== void 0 ? _e : {};
|
|
5311
5596
|
const additionalSecretKeys = deployConfigRaw ? deploy_1.DEPLOY_TYPES[deployConfigRaw.type].additionalSecretKeys(environmentContext) : [];
|
|
5312
|
-
const secretEnvVarKeys = [...(0, envVars_1.
|
|
5597
|
+
const secretEnvVarKeys = [...(0, envVars_1.normalizeSecretVarsConfig)((_f = envConfigRaw.vars) === null || _f === void 0 ? void 0 : _f.secret), ...additionalSecretKeys];
|
|
5313
5598
|
const secretEnvVars = (0, envVars_1.makeSecretEnvVarMapping)(env, componentName, secretEnvVarKeys);
|
|
5314
5599
|
const publicEnvVarsRawSanitized = (0, envVars_1.stringifyValues)(publicEnvVarsRaw);
|
|
5315
5600
|
const publicEnvVarsUnresolved = Object.fromEntries(Object.entries(publicEnvVarsRawSanitized).map(([key, value]) => [key, (0, VariableValueContainingReferences_1.createVariableValueContainingReferencesFromString)(value, {
|
|
5316
5601
|
componentName: ctx.componentName
|
|
5317
5602
|
})]));
|
|
5318
|
-
const publicEnvVars = ((
|
|
5603
|
+
const publicEnvVars = ((_g = options.shouldResolveReferences) !== null && _g !== void 0 ? _g : true) ? await (0, resolveAllReferences_1.resolveAllReferences)(publicEnvVarsUnresolved, async otherComponentName => {
|
|
5319
5604
|
const {
|
|
5320
5605
|
envVars: otherEnvVars
|
|
5321
5606
|
} = await (0, exports.getEnvironmentVariables)({
|
|
@@ -5475,7 +5760,7 @@ const envVars_1 = __nccwpck_require__(4946);
|
|
|
5475
5760
|
* @returns
|
|
5476
5761
|
*/
|
|
5477
5762
|
const transformJobOnlyVars = async (env, componentName, vars) => {
|
|
5478
|
-
var _a
|
|
5763
|
+
var _a;
|
|
5479
5764
|
if (!vars) {
|
|
5480
5765
|
return {
|
|
5481
5766
|
envVars: {},
|
|
@@ -5483,7 +5768,7 @@ const transformJobOnlyVars = async (env, componentName, vars) => {
|
|
|
5483
5768
|
};
|
|
5484
5769
|
}
|
|
5485
5770
|
const publicVars = (0, envVars_1.stringifyValues)((_a = vars === null || vars === void 0 ? void 0 : vars.public) !== null && _a !== void 0 ? _a : {});
|
|
5486
|
-
const secretEnvVarKeys = (0, envVars_1.
|
|
5771
|
+
const secretEnvVarKeys = (0, envVars_1.normalizeSecretVarsConfig)(vars === null || vars === void 0 ? void 0 : vars.secret);
|
|
5487
5772
|
const deployJobOnlySecretEnvVars = (vars === null || vars === void 0 ? void 0 : vars.secret) ? (0, envVars_1.makeSecretEnvVarMapping)(env, componentName, secretEnvVarKeys) : {};
|
|
5488
5773
|
const envVars = {
|
|
5489
5774
|
...deployJobOnlySecretEnvVars,
|
|
@@ -5507,7 +5792,7 @@ exports.transformJobOnlyVars = transformJobOnlyVars;
|
|
|
5507
5792
|
Object.defineProperty(exports, "__esModule", ({
|
|
5508
5793
|
value: true
|
|
5509
5794
|
}));
|
|
5510
|
-
exports.makeSecretEnvVarMapping = exports.stringListToSecreteEnvVarList = exports.stringifyValues = void 0;
|
|
5795
|
+
exports.makeSecretEnvVarMapping = exports.normalizeSecretVarsConfig = exports.stringListToSecreteEnvVarList = exports.stringifyValues = void 0;
|
|
5511
5796
|
const lodash_es_1 = __nccwpck_require__(4284);
|
|
5512
5797
|
const getEnvironmentVariables_1 = __nccwpck_require__(5855);
|
|
5513
5798
|
const BashExpression_1 = __nccwpck_require__(5354);
|
|
@@ -5517,6 +5802,27 @@ const stringListToSecreteEnvVarList = keys => keys.map(key => ({
|
|
|
5517
5802
|
key
|
|
5518
5803
|
}));
|
|
5519
5804
|
exports.stringListToSecreteEnvVarList = stringListToSecreteEnvVarList;
|
|
5805
|
+
/**
|
|
5806
|
+
* normalizes both config forms of vault-stored env vars: the deprecated
|
|
5807
|
+
* plain string[] (all keys secret) and the record form carrying a kind
|
|
5808
|
+
* (or config object) per key
|
|
5809
|
+
*/
|
|
5810
|
+
const normalizeSecretVarsConfig = secret => {
|
|
5811
|
+
if (!secret) {
|
|
5812
|
+
return [];
|
|
5813
|
+
}
|
|
5814
|
+
if (Array.isArray(secret)) {
|
|
5815
|
+
return (0, exports.stringListToSecreteEnvVarList)(secret);
|
|
5816
|
+
}
|
|
5817
|
+
return Object.entries(secret).map(([key, config]) => typeof config === "string" ? {
|
|
5818
|
+
key,
|
|
5819
|
+
kind: config
|
|
5820
|
+
} : {
|
|
5821
|
+
key,
|
|
5822
|
+
...config
|
|
5823
|
+
});
|
|
5824
|
+
};
|
|
5825
|
+
exports.normalizeSecretVarsConfig = normalizeSecretVarsConfig;
|
|
5520
5826
|
const makeSecretEnvVarMapping = (env, componentName, secretEnvVars) => {
|
|
5521
5827
|
return Object.fromEntries(secretEnvVars.map(({
|
|
5522
5828
|
key
|
|
@@ -5526,6 +5832,330 @@ exports.makeSecretEnvVarMapping = makeSecretEnvVarMapping;
|
|
|
5526
5832
|
|
|
5527
5833
|
/***/ }),
|
|
5528
5834
|
|
|
5835
|
+
/***/ 3231:
|
|
5836
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5837
|
+
|
|
5838
|
+
"use strict";
|
|
5839
|
+
|
|
5840
|
+
|
|
5841
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
5842
|
+
value: true
|
|
5843
|
+
}));
|
|
5844
|
+
exports.computeCustomImageHash = void 0;
|
|
5845
|
+
const crypto_1 = __nccwpck_require__(6982);
|
|
5846
|
+
const fs_1 = __nccwpck_require__(9896);
|
|
5847
|
+
const path_1 = __nccwpck_require__(6928);
|
|
5848
|
+
const IGNORED_FILES = new Set([".DS_Store", "Thumbs.db"]);
|
|
5849
|
+
const isIgnoredFile = path => {
|
|
5850
|
+
var _a;
|
|
5851
|
+
return IGNORED_FILES.has((_a = path.split("/").pop()) !== null && _a !== void 0 ? _a : "");
|
|
5852
|
+
};
|
|
5853
|
+
function listFilesRecursive(dir) {
|
|
5854
|
+
const resolved = (0, path_1.resolve)(dir);
|
|
5855
|
+
const entries = (0, fs_1.readdirSync)(resolved, {
|
|
5856
|
+
recursive: true,
|
|
5857
|
+
encoding: "utf-8"
|
|
5858
|
+
});
|
|
5859
|
+
return entries.filter(entry => {
|
|
5860
|
+
if (isIgnoredFile(entry)) {
|
|
5861
|
+
// OS junk files exist locally but not in CI checkouts — they
|
|
5862
|
+
// must never influence the content hash
|
|
5863
|
+
return false;
|
|
5864
|
+
}
|
|
5865
|
+
const fullPath = (0, path_1.join)(resolved, entry);
|
|
5866
|
+
return (0, fs_1.statSync)(fullPath).isFile();
|
|
5867
|
+
}).sort();
|
|
5868
|
+
}
|
|
5869
|
+
function computeCustomImageHash(config) {
|
|
5870
|
+
var _a;
|
|
5871
|
+
const hash = (0, crypto_1.createHash)("sha256");
|
|
5872
|
+
const watchedPaths = [];
|
|
5873
|
+
// Hash all files in the dir (includes the Dockerfile and any context files)
|
|
5874
|
+
const dirFiles = listFilesRecursive(config.dir);
|
|
5875
|
+
for (const file of dirFiles) {
|
|
5876
|
+
const fullPath = (0, path_1.join)((0, path_1.resolve)(config.dir), file);
|
|
5877
|
+
hash.update(file); // include relative path for disambiguation
|
|
5878
|
+
hash.update((0, fs_1.readFileSync)(fullPath));
|
|
5879
|
+
}
|
|
5880
|
+
watchedPaths.push(`${config.dir}/**/*`);
|
|
5881
|
+
// extra dirs (e.g. included base image definitions)
|
|
5882
|
+
for (const extraDir of (_a = config.extraDirs) !== null && _a !== void 0 ? _a : []) {
|
|
5883
|
+
for (const file of listFilesRecursive(extraDir)) {
|
|
5884
|
+
hash.update(file);
|
|
5885
|
+
hash.update((0, fs_1.readFileSync)((0, path_1.join)((0, path_1.resolve)(extraDir), file)));
|
|
5886
|
+
}
|
|
5887
|
+
watchedPaths.push(`${extraDir}/**/*`);
|
|
5888
|
+
}
|
|
5889
|
+
// Hash extra paths (for files outside the dir)
|
|
5890
|
+
if (config.hashExtraPaths) {
|
|
5891
|
+
// Extra paths are literal file paths (not globs) for simplicity
|
|
5892
|
+
const extraFiles = [...config.hashExtraPaths].sort();
|
|
5893
|
+
for (const file of extraFiles) {
|
|
5894
|
+
hash.update(file);
|
|
5895
|
+
hash.update((0, fs_1.readFileSync)(file));
|
|
5896
|
+
}
|
|
5897
|
+
watchedPaths.push(...config.hashExtraPaths);
|
|
5898
|
+
}
|
|
5899
|
+
// Hash build args (sorted keys for determinism)
|
|
5900
|
+
if (config.buildArgs) {
|
|
5901
|
+
const sorted = Object.entries(config.buildArgs).sort(([a], [b]) => a.localeCompare(b));
|
|
5902
|
+
hash.update(JSON.stringify(sorted));
|
|
5903
|
+
}
|
|
5904
|
+
return {
|
|
5905
|
+
hash: hash.digest("hex").slice(0, 12),
|
|
5906
|
+
watchedPaths
|
|
5907
|
+
};
|
|
5908
|
+
}
|
|
5909
|
+
exports.computeCustomImageHash = computeCustomImageHash;
|
|
5910
|
+
|
|
5911
|
+
/***/ }),
|
|
5912
|
+
|
|
5913
|
+
/***/ 1585:
|
|
5914
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5915
|
+
|
|
5916
|
+
"use strict";
|
|
5917
|
+
|
|
5918
|
+
|
|
5919
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
5920
|
+
value: true
|
|
5921
|
+
}));
|
|
5922
|
+
exports.JobImagesPlan = exports.getJobImagesMode = exports.GENERATED_IMAGES_FOLDER = void 0;
|
|
5923
|
+
const fs_1 = __nccwpck_require__(9896);
|
|
5924
|
+
const path_1 = __nccwpck_require__(6928);
|
|
5925
|
+
const ciVariables_1 = __nccwpck_require__(4489);
|
|
5926
|
+
const docker_1 = __nccwpck_require__(2764);
|
|
5927
|
+
const constants_1 = __nccwpck_require__(3480);
|
|
5928
|
+
const runner_1 = __nccwpck_require__(2348);
|
|
5929
|
+
const gitlab_1 = __nccwpck_require__(3468);
|
|
5930
|
+
const hash_1 = __nccwpck_require__(3231);
|
|
5931
|
+
const shippedImages_1 = __nccwpck_require__(7734);
|
|
5932
|
+
exports.GENERATED_IMAGES_FOLDER = ".catladder-generated/images";
|
|
5933
|
+
/**
|
|
5934
|
+
* the official docker cli image used to build the job images — NOT a
|
|
5935
|
+
* catladder image, so building images never depends on one (bootstrap)
|
|
5936
|
+
*/
|
|
5937
|
+
const BUILDER_IMAGE = "docker.io/docker:29.5.1";
|
|
5938
|
+
const getJobImagesMode = (config, pipelineType) => {
|
|
5939
|
+
var _a;
|
|
5940
|
+
// the central registry is not reachable from github runners
|
|
5941
|
+
if (pipelineType === "github" && config.jobImages === "central") {
|
|
5942
|
+
throw new Error(`jobImages: "central" is not supported on github: catladder's central registry (${constants_1.DOCKER_REGISTRY}) is unreachable from github runners. Use "repo" (the default) instead.`);
|
|
5943
|
+
}
|
|
5944
|
+
return (_a = config.jobImages) !== null && _a !== void 0 ? _a : pipelineType === "github" ? "repo" : "central";
|
|
5945
|
+
};
|
|
5946
|
+
exports.getJobImagesMode = getJobImagesMode;
|
|
5947
|
+
const ensureJobName = name => `🐳 job image ${name}`;
|
|
5948
|
+
/**
|
|
5949
|
+
* plans the catladder job images of one backend run: resolves image
|
|
5950
|
+
* references, and (in repo mode) collects the image build jobs and the
|
|
5951
|
+
* image definitions to materialize into the generated files.
|
|
5952
|
+
*
|
|
5953
|
+
* Reference-driven: only images actually used by a job are built.
|
|
5954
|
+
*/
|
|
5955
|
+
class JobImagesPlan {
|
|
5956
|
+
constructor(mode, pipelineType) {
|
|
5957
|
+
this.mode = mode;
|
|
5958
|
+
this.pipelineType = pipelineType;
|
|
5959
|
+
this.used = new Map();
|
|
5960
|
+
}
|
|
5961
|
+
/**
|
|
5962
|
+
* resolves a job image (marker or concrete) to a concrete image url
|
|
5963
|
+
* plus the build job dependency in repo mode
|
|
5964
|
+
*/
|
|
5965
|
+
resolve(image) {
|
|
5966
|
+
if (!(0, runner_1.isCatladderImageRef)(image)) {
|
|
5967
|
+
return {
|
|
5968
|
+
image
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
return this.resolveRef(image);
|
|
5972
|
+
}
|
|
5973
|
+
resolveRef(ref) {
|
|
5974
|
+
const name = ref.catladderImage;
|
|
5975
|
+
if (this.mode === "central" || shippedImages_1.CENTRAL_ONLY_IMAGES.has(name)) {
|
|
5976
|
+
return {
|
|
5977
|
+
image: (0, runner_1.getCentralRunnerImageUrl)(name)
|
|
5978
|
+
};
|
|
5979
|
+
}
|
|
5980
|
+
const {
|
|
5981
|
+
hash
|
|
5982
|
+
} = this.use(name);
|
|
5983
|
+
return {
|
|
5984
|
+
image: `${this.registryImageRef()}/catladder/${name}:${hash}`,
|
|
5985
|
+
fromRepoRegistry: true,
|
|
5986
|
+
need: {
|
|
5987
|
+
job: ensureJobName(name),
|
|
5988
|
+
artifacts: false,
|
|
5989
|
+
optional: true,
|
|
5990
|
+
global: true
|
|
5991
|
+
}
|
|
5992
|
+
};
|
|
5993
|
+
}
|
|
5994
|
+
/**
|
|
5995
|
+
* the registry image prefix. On github, container images can't use
|
|
5996
|
+
* runtime env vars — the expression form is required.
|
|
5997
|
+
*/
|
|
5998
|
+
registryImageRef() {
|
|
5999
|
+
return this.pipelineType === "github" ? "ghcr.io/${{ github.repository }}" : `${(0, ciVariables_1.getCiVariable)({
|
|
6000
|
+
pipelineType: this.pipelineType
|
|
6001
|
+
}, "registryImage")}`;
|
|
6002
|
+
}
|
|
6003
|
+
use(name) {
|
|
6004
|
+
var _a;
|
|
6005
|
+
const existing = this.used.get(name);
|
|
6006
|
+
if (existing) {
|
|
6007
|
+
return existing;
|
|
6008
|
+
}
|
|
6009
|
+
const dependencies = (_a = shippedImages_1.RUNNER_IMAGE_DEPENDENCIES[name]) !== null && _a !== void 0 ? _a : [];
|
|
6010
|
+
// dependencies are materialized (and hashed) as part of this image,
|
|
6011
|
+
// but also usable standalone
|
|
6012
|
+
dependencies.forEach(dependency => this.use(dependency));
|
|
6013
|
+
const {
|
|
6014
|
+
hash
|
|
6015
|
+
} = (0, hash_1.computeCustomImageHash)({
|
|
6016
|
+
dir: (0, shippedImages_1.getShippedImageDir)(name),
|
|
6017
|
+
extraDirs: dependencies.map(dependency => (0, shippedImages_1.getShippedImageDir)(dependency))
|
|
6018
|
+
});
|
|
6019
|
+
const entry = {
|
|
6020
|
+
hash
|
|
6021
|
+
};
|
|
6022
|
+
this.used.set(name, entry);
|
|
6023
|
+
return entry;
|
|
6024
|
+
}
|
|
6025
|
+
/**
|
|
6026
|
+
* the image build jobs for all used images (repo mode; empty in
|
|
6027
|
+
* central mode)
|
|
6028
|
+
*/
|
|
6029
|
+
getEnsureJobs() {
|
|
6030
|
+
return [...this.used.entries()].map(([name, {
|
|
6031
|
+
hash
|
|
6032
|
+
}]) => this.createEnsureJob(name, hash));
|
|
6033
|
+
}
|
|
6034
|
+
createEnsureJob(name, hash) {
|
|
6035
|
+
var _a;
|
|
6036
|
+
const ctx = {
|
|
6037
|
+
pipelineType: this.pipelineType
|
|
6038
|
+
};
|
|
6039
|
+
const registryUser = (0, ciVariables_1.getCiVariable)(ctx, "registryUser");
|
|
6040
|
+
const jobToken = (0, ciVariables_1.getCiVariable)(ctx, "jobToken");
|
|
6041
|
+
const registry = (0, ciVariables_1.getCiVariable)(ctx, "registry");
|
|
6042
|
+
const imageRef = `${this.registryImageRef()}/catladder/${name}:${hash}`;
|
|
6043
|
+
const watchedDirs = [name, ...((_a = shippedImages_1.RUNNER_IMAGE_DEPENDENCIES[name]) !== null && _a !== void 0 ? _a : [])];
|
|
6044
|
+
const {
|
|
6045
|
+
services,
|
|
6046
|
+
runnerVariables
|
|
6047
|
+
} = (0, docker_1.getDockerJobBaseProps)();
|
|
6048
|
+
return {
|
|
6049
|
+
name: ensureJobName(name),
|
|
6050
|
+
stage: "setup",
|
|
6051
|
+
image: BUILDER_IMAGE,
|
|
6052
|
+
services,
|
|
6053
|
+
runnerVariables,
|
|
6054
|
+
needs: [],
|
|
6055
|
+
// gitlab: only run when the image definition changed; github has
|
|
6056
|
+
// no equivalent and always runs (the existence check is fast)
|
|
6057
|
+
rules: [{
|
|
6058
|
+
changes: watchedDirs.map(dir => `${exports.GENERATED_IMAGES_FOLDER}/${dir}/**/*`)
|
|
6059
|
+
}],
|
|
6060
|
+
variables: {},
|
|
6061
|
+
script: [...(0, gitlab_1.collapseableSection)("docker-login", "Docker Login")([`docker login --username ${registryUser} --password ${jobToken} ${registry}`]), ...(0, gitlab_1.collapseableSection)("check-image", "Checking if image exists")([`if docker manifest inspect ${imageRef} > /dev/null 2>&1; then`, ` echo "Image ${imageRef} already exists, skipping build"`, ` exit 0`, `fi`]), ...(0, gitlab_1.collapseableSection)("docker-build", "Building image")([`DOCKER_BUILDKIT=1 docker build -t ${imageRef} -f ${exports.GENERATED_IMAGES_FOLDER}/${name}/Dockerfile ${shippedImages_1.RUNNER_IMAGE_BUILD_CONTEXT[name] === "root" ? exports.GENERATED_IMAGES_FOLDER : `${exports.GENERATED_IMAGES_FOLDER}/${name}`}`]), ...(0, gitlab_1.collapseableSection)("docker-push", "Pushing image")([`docker push ${imageRef}`])]
|
|
6062
|
+
};
|
|
6063
|
+
}
|
|
6064
|
+
/**
|
|
6065
|
+
* the image definitions of all used images, materialized into the
|
|
6066
|
+
* generated files (so pipelines build from committed, reviewable
|
|
6067
|
+
* files and gitlab's rules:changes can watch them)
|
|
6068
|
+
*/
|
|
6069
|
+
getGeneratedFiles() {
|
|
6070
|
+
return [...this.used.keys()].flatMap(name => {
|
|
6071
|
+
const dir = (0, shippedImages_1.getShippedImageDir)(name);
|
|
6072
|
+
return listFilesRecursive(dir).map(file => ({
|
|
6073
|
+
path: (0, path_1.join)(exports.GENERATED_IMAGES_FOLDER, name, file),
|
|
6074
|
+
content: (0, fs_1.readFileSync)((0, path_1.join)(dir, file), "utf-8")
|
|
6075
|
+
}));
|
|
6076
|
+
});
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
exports.JobImagesPlan = JobImagesPlan;
|
|
6080
|
+
const IGNORED_FILES = new Set([".DS_Store", "Thumbs.db"]);
|
|
6081
|
+
const listFilesRecursive = dir => (0, fs_1.readdirSync)(dir, {
|
|
6082
|
+
recursive: true,
|
|
6083
|
+
encoding: "utf-8"
|
|
6084
|
+
}).filter(entry => {
|
|
6085
|
+
var _a;
|
|
6086
|
+
// OS junk files exist locally but not in CI checkouts
|
|
6087
|
+
return !IGNORED_FILES.has((_a = entry.split("/").pop()) !== null && _a !== void 0 ? _a : "") && (0, fs_1.statSync)((0, path_1.join)(dir, entry)).isFile();
|
|
6088
|
+
}).sort();
|
|
6089
|
+
|
|
6090
|
+
/***/ }),
|
|
6091
|
+
|
|
6092
|
+
/***/ 7734:
|
|
6093
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6094
|
+
|
|
6095
|
+
"use strict";
|
|
6096
|
+
|
|
6097
|
+
|
|
6098
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6099
|
+
value: true
|
|
6100
|
+
}));
|
|
6101
|
+
exports.getShippedImageDir = exports.getShippedImagesDir = exports.RUNNER_IMAGE_BUILD_CONTEXT = exports.CENTRAL_ONLY_IMAGES = exports.RUNNER_IMAGE_DEPENDENCIES = void 0;
|
|
6102
|
+
const fs_1 = __nccwpck_require__(9896);
|
|
6103
|
+
const path_1 = __nccwpck_require__(6928);
|
|
6104
|
+
/**
|
|
6105
|
+
* images whose Dockerfile INCLUDEs another image's Dockerfile
|
|
6106
|
+
* (dockerfile-x/dockerfile-plus, resolved against the images root as
|
|
6107
|
+
* build context)
|
|
6108
|
+
*/
|
|
6109
|
+
exports.RUNNER_IMAGE_DEPENDENCIES = {
|
|
6110
|
+
"jobs-meteor": ["jobs-default"],
|
|
6111
|
+
"jobs-testing-chrome": ["jobs-default"]
|
|
6112
|
+
};
|
|
6113
|
+
/**
|
|
6114
|
+
* the docker build context of each image, mirroring the central image
|
|
6115
|
+
* builds: the jobs family builds from the images root (their
|
|
6116
|
+
* Dockerfiles INCLUDE sibling images), the others from their own dir
|
|
6117
|
+
* (their COPY paths are relative to it)
|
|
6118
|
+
*/
|
|
6119
|
+
/**
|
|
6120
|
+
* images that cannot be built from the shipped definitions and always
|
|
6121
|
+
* come from the central registry: semantic-release bakes catladder's
|
|
6122
|
+
* own cli sources into the image (repo-root build context).
|
|
6123
|
+
* TODO: make the semantic-release image self-contained.
|
|
6124
|
+
*/
|
|
6125
|
+
exports.CENTRAL_ONLY_IMAGES = new Set(["semantic-release"]);
|
|
6126
|
+
exports.RUNNER_IMAGE_BUILD_CONTEXT = {
|
|
6127
|
+
"jobs-default": "root",
|
|
6128
|
+
"jobs-meteor": "root",
|
|
6129
|
+
"jobs-testing-chrome": "root",
|
|
6130
|
+
kubernetes: "self",
|
|
6131
|
+
"docker-build": "self",
|
|
6132
|
+
gcloud: "self",
|
|
6133
|
+
"semantic-release": "self",
|
|
6134
|
+
"agent-claude": "self"
|
|
6135
|
+
};
|
|
6136
|
+
/**
|
|
6137
|
+
* the directory containing the image definitions shipped with the
|
|
6138
|
+
* package (copied into dist at build time; the repository layout is
|
|
6139
|
+
* the fallback for development and tests)
|
|
6140
|
+
*/
|
|
6141
|
+
const getShippedImagesDir = () => {
|
|
6142
|
+
const candidates = [
|
|
6143
|
+
// built package: dist/customImages -> dist/runner-images
|
|
6144
|
+
(0, path_1.join)(__dirname, "..", "runner-images"),
|
|
6145
|
+
// repository: pipeline/src/customImages -> <root>/runner-images
|
|
6146
|
+
(0, path_1.join)(__dirname, "..", "..", "..", "runner-images")];
|
|
6147
|
+
const found = candidates.find(candidate => (0, fs_1.existsSync)(candidate));
|
|
6148
|
+
if (!found) {
|
|
6149
|
+
throw new Error("shipped job image definitions not found");
|
|
6150
|
+
}
|
|
6151
|
+
return found;
|
|
6152
|
+
};
|
|
6153
|
+
exports.getShippedImagesDir = getShippedImagesDir;
|
|
6154
|
+
const getShippedImageDir = name => (0, path_1.join)((0, exports.getShippedImagesDir)(), name);
|
|
6155
|
+
exports.getShippedImageDir = getShippedImageDir;
|
|
6156
|
+
|
|
6157
|
+
/***/ }),
|
|
6158
|
+
|
|
5529
6159
|
/***/ 4628:
|
|
5530
6160
|
/***/ ((__unused_webpack_module, exports) => {
|
|
5531
6161
|
|
|
@@ -6752,7 +7382,10 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
6752
7382
|
hidden: true
|
|
6753
7383
|
}, {
|
|
6754
7384
|
key: exports.GCLOUD_RUN_CANONICAL_HOST_SUFFIX,
|
|
6755
|
-
hidden: true
|
|
7385
|
+
hidden: true,
|
|
7386
|
+
// a public url fragment, not sensitive: masking it would
|
|
7387
|
+
// suppress environment urls on github and break log links
|
|
7388
|
+
kind: "variable"
|
|
6756
7389
|
}] : []), ...(ctx.deployConfigRaw && ctx.deployConfigRaw.cloudSql ? [{
|
|
6757
7390
|
key: "DB_PASSWORD"
|
|
6758
7391
|
}] : [])],
|
|
@@ -6868,7 +7501,10 @@ const getDatabaseDeleteScript = (context, deployConfig) => {
|
|
|
6868
7501
|
// unfortunatly the database cannot be deleted right after the service has stopped, as it might still have connections
|
|
6869
7502
|
// we have to repeate this process
|
|
6870
7503
|
return [`echo "deleting database ${DB_NAME}..."`, `echo "👆 this can take multiple attemps (3-5min), because google cloud run may still have a connection to the database after the cloud run service is shut down"`, (0, gitlab_1.repeatOnFailure)(`gcloud sql databases delete ${DB_NAME} --instance=${instanceId} --project ${projectId}`, {
|
|
6871
|
-
pauseInSeconds: 10
|
|
7504
|
+
pauseInSeconds: 10,
|
|
7505
|
+
// connections normally clear within 3-5min; anything beyond is
|
|
7506
|
+
// a permanent error (missing permission, wrong instance, ...)
|
|
7507
|
+
maxAttempts: 30
|
|
6872
7508
|
})];
|
|
6873
7509
|
};
|
|
6874
7510
|
exports.getDatabaseDeleteScript = getDatabaseDeleteScript;
|
|
@@ -8592,6 +9228,7 @@ const promises_1 = __nccwpck_require__(1943);
|
|
|
8592
9228
|
const path_1 = __nccwpck_require__(6928);
|
|
8593
9229
|
const backends_1 = __nccwpck_require__(3243);
|
|
8594
9230
|
const gitlab_1 = __nccwpck_require__(8475);
|
|
9231
|
+
const jobImagesPlan_1 = __nccwpck_require__(1585);
|
|
8595
9232
|
/**
|
|
8596
9233
|
* generates the pipeline files of all pipeline types enabled in the
|
|
8597
9234
|
* config (see `pipelines`). Pass an explicit `pipelineType` to generate
|
|
@@ -8599,6 +9236,16 @@ const gitlab_1 = __nccwpck_require__(8475);
|
|
|
8599
9236
|
*/
|
|
8600
9237
|
async function generatePipelineFiles(context, pipelineType) {
|
|
8601
9238
|
const pipelineTypes = pipelineType ? [pipelineType] : (0, backends_1.getEnabledPipelineTypes)(context.config);
|
|
9239
|
+
if (!pipelineType) {
|
|
9240
|
+
// the materialized image definitions are a union across all enabled
|
|
9241
|
+
// backends and no single backend may wipe them — cleaned once per
|
|
9242
|
+
// full generation, so images that fell out of use don't linger (and
|
|
9243
|
+
// keep triggering gitlab's rules:changes)
|
|
9244
|
+
await (0, promises_1.rm)(jobImagesPlan_1.GENERATED_IMAGES_FOLDER, {
|
|
9245
|
+
recursive: true,
|
|
9246
|
+
force: true
|
|
9247
|
+
});
|
|
9248
|
+
}
|
|
8602
9249
|
for (const type of pipelineTypes) {
|
|
8603
9250
|
await generatePipelineFilesForBackend(context, (0, backends_1.getPipelineBackend)(type));
|
|
8604
9251
|
}
|
|
@@ -8616,7 +9263,11 @@ async function generatePipelineFilesForBackend(context, backend) {
|
|
|
8616
9263
|
await (0, promises_1.mkdir)((0, path_1.dirname)(path), {
|
|
8617
9264
|
recursive: true
|
|
8618
9265
|
});
|
|
8619
|
-
|
|
9266
|
+
if (typeof content === "string") {
|
|
9267
|
+
await context.fileWriter.writeGeneratedFileRaw(path, content);
|
|
9268
|
+
} else {
|
|
9269
|
+
await context.fileWriter.writeYamlfile(path, content);
|
|
9270
|
+
}
|
|
8620
9271
|
}));
|
|
8621
9272
|
}
|
|
8622
9273
|
/**
|
|
@@ -8972,10 +9623,23 @@ exports.RULE_CONDITION_HOTFIX_BRANCH = "$CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x)
|
|
|
8972
9623
|
Object.defineProperty(exports, "__esModule", ({
|
|
8973
9624
|
value: true
|
|
8974
9625
|
}));
|
|
8975
|
-
exports.getRunnerImage = void 0;
|
|
9626
|
+
exports.getCentralRunnerImageUrl = exports.getRunnerImage = exports.isCatladderImageRef = void 0;
|
|
8976
9627
|
const constants_1 = __nccwpck_require__(3480);
|
|
8977
|
-
const
|
|
9628
|
+
const isCatladderImageRef = value => typeof value === "object" && value !== null && "catladderImage" in value && typeof value.catladderImage === "string";
|
|
9629
|
+
exports.isCatladderImageRef = isCatladderImageRef;
|
|
9630
|
+
/**
|
|
9631
|
+
* job creators use this to reference a catladder-provided job image;
|
|
9632
|
+
* the backends resolve it to a concrete image url
|
|
9633
|
+
*/
|
|
9634
|
+
const getRunnerImage = imageName => ({
|
|
9635
|
+
catladderImage: imageName
|
|
9636
|
+
});
|
|
8978
9637
|
exports.getRunnerImage = getRunnerImage;
|
|
9638
|
+
/**
|
|
9639
|
+
* the image url in catladder's central registry (the classic behavior)
|
|
9640
|
+
*/
|
|
9641
|
+
const getCentralRunnerImageUrl = imageName => constants_1.DOCKER_REGISTRY + "/" + imageName + ":" + constants_1.PIPELINE_IMAGE_TAG;
|
|
9642
|
+
exports.getCentralRunnerImageUrl = getCentralRunnerImageUrl;
|
|
8979
9643
|
|
|
8980
9644
|
/***/ }),
|
|
8981
9645
|
|
|
@@ -9190,8 +9854,14 @@ const sanitizeForBashVariable = name => name.replace(/-/g, "_");
|
|
|
9190
9854
|
exports.sanitizeForBashVariable = sanitizeForBashVariable;
|
|
9191
9855
|
const repeatOnFailure = (command, options) => {
|
|
9192
9856
|
return `
|
|
9857
|
+
_attempt=0
|
|
9193
9858
|
until ${command}
|
|
9194
9859
|
do
|
|
9860
|
+
_attempt=$((_attempt+1))
|
|
9861
|
+
if [ "$_attempt" -ge ${options.maxAttempts} ]; then
|
|
9862
|
+
echo "giving up after ${options.maxAttempts} attempts"
|
|
9863
|
+
exit 1
|
|
9864
|
+
fi
|
|
9195
9865
|
echo "Trying again."
|
|
9196
9866
|
sleep ${options.pauseInSeconds}
|
|
9197
9867
|
done
|
|
@@ -9379,6 +10049,14 @@ class FileWriter {
|
|
|
9379
10049
|
extension: (_b = path.split(".").pop()) !== null && _b !== void 0 ? _b : ""
|
|
9380
10050
|
};
|
|
9381
10051
|
}
|
|
10052
|
+
/**
|
|
10053
|
+
* writes content verbatim (no auto-generated header) — e.g. for
|
|
10054
|
+
* materialized dockerfiles, where a leading comment would break
|
|
10055
|
+
* parser directives like `# syntax = ...`
|
|
10056
|
+
*/
|
|
10057
|
+
async writeGeneratedFileRaw(path, content) {
|
|
10058
|
+
await this.writeTheFile(path, content);
|
|
10059
|
+
}
|
|
9382
10060
|
async writeGeneratedFile(path, content, options) {
|
|
9383
10061
|
await this.writeTheFile(path, [this.getAutoGeneratedHeader(options.commentChar), content].join("\n"));
|
|
9384
10062
|
}
|