polyci 0.0.20 → 0.0.22
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/main.js +71 -64
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -5,15 +5,22 @@ import pino from "pino";
|
|
|
5
5
|
import pretty from "pino-pretty";
|
|
6
6
|
const log = pino(pretty());
|
|
7
7
|
const DEFAULT_TAG_TEMPLATE = "{module}-v{version}";
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
const DEFAULT_VERSION_TEMPLATE = "{version}";
|
|
9
|
+
const DEFAULT_BRANCH_VERSION_TEMPLATE = "{version}-{branch}-{increment}";
|
|
10
|
+
const DEFAULT_TAG_PATTERN = "^$MODULE_NAME-v(?<version>\\d+(\\.\\d+)*)-$CI_COMMIT_BRANCH-(?<increment>\\d+(\\.\\d+)*)$";
|
|
11
|
+
const ALLOWED_TAG_PLACEHOLDERS = new Set(["module", "version"]);
|
|
12
|
+
const ALLOWED_VERSION_PLACEHOLDERS = new Set(["branch", "version", "increment"]);
|
|
13
|
+
function applyVersionTemplate(template) {
|
|
11
14
|
return template
|
|
12
|
-
.replaceAll("{module}", moduleName)
|
|
13
15
|
.replaceAll("{branch}", "${CI_COMMIT_BRANCH}")
|
|
14
16
|
.replaceAll("{version}", "${NEXT_VERSION}")
|
|
15
17
|
.replaceAll("{increment}", "${NEXT_INCREMENT}");
|
|
16
18
|
}
|
|
19
|
+
function applyTagTemplate(template, moduleName, version) {
|
|
20
|
+
return template
|
|
21
|
+
.replaceAll("{module}", moduleName)
|
|
22
|
+
.replaceAll("{version}", version);
|
|
23
|
+
}
|
|
17
24
|
function getInvalidTagTemplatePlaceholders(template) {
|
|
18
25
|
const matches = template.matchAll(/\{([^}]+)\}/g);
|
|
19
26
|
const invalid = new Set();
|
|
@@ -25,6 +32,17 @@ function getInvalidTagTemplatePlaceholders(template) {
|
|
|
25
32
|
}
|
|
26
33
|
return [...invalid];
|
|
27
34
|
}
|
|
35
|
+
function getInvalidVersionTemplatePlaceholders(template) {
|
|
36
|
+
const matches = template.matchAll(/\{([^}]+)\}/g);
|
|
37
|
+
const invalid = new Set();
|
|
38
|
+
for (const match of matches) {
|
|
39
|
+
const placeholder = match[1];
|
|
40
|
+
if (!ALLOWED_VERSION_PLACEHOLDERS.has(placeholder)) {
|
|
41
|
+
invalid.add(placeholder);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return [...invalid];
|
|
45
|
+
}
|
|
28
46
|
function parseArgs() {
|
|
29
47
|
const program = new Command();
|
|
30
48
|
program
|
|
@@ -32,8 +50,10 @@ function parseArgs() {
|
|
|
32
50
|
.option("-o, --output <path>", "Output pipeline file path")
|
|
33
51
|
.option("--modules-root <path>", "Modules root directory", "./modules")
|
|
34
52
|
.option("--main-branch <name>", "Primary branch name for release tagging logic", "main")
|
|
35
|
-
.option("--
|
|
36
|
-
.option("--branch-
|
|
53
|
+
.option("--version-template <template>", "Template for primary branch module version; placeholders {version}, {branch}, {increment}", DEFAULT_VERSION_TEMPLATE)
|
|
54
|
+
.option("--branch-version-template <template>", "Template for non-primary branch module version; placeholders {version}, {branch}, {increment}", DEFAULT_BRANCH_VERSION_TEMPLATE)
|
|
55
|
+
.option("--tag-template <template>", "Template for non-primary branch tags; use placeholders {module}, {version}", DEFAULT_TAG_TEMPLATE)
|
|
56
|
+
.option("--tag-pattern <pattern>", "Tag pattern passed to semalease to find the latest tag and calculate the next version/increment", DEFAULT_TAG_PATTERN)
|
|
37
57
|
.option("--cwd <path>", "Working directory", process.cwd())
|
|
38
58
|
.parse();
|
|
39
59
|
const options = program.opts();
|
|
@@ -41,17 +61,25 @@ function parseArgs() {
|
|
|
41
61
|
const cwd = path.resolve(options.cwd);
|
|
42
62
|
const modulesRoot = path.resolve(cwd, options.modulesRoot);
|
|
43
63
|
const mainBranch = options.mainBranch;
|
|
64
|
+
const versionTemplate = options.versionTemplate;
|
|
65
|
+
const branchVersionTemplate = options.branchVersionTemplate;
|
|
44
66
|
const tagTemplate = options.tagTemplate;
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
program.error(`Invalid --
|
|
67
|
+
const tagPattern = options.tagPattern;
|
|
68
|
+
const invalidVersionTemplate = getInvalidVersionTemplatePlaceholders(versionTemplate);
|
|
69
|
+
if (invalidVersionTemplate.length > 0) {
|
|
70
|
+
program.error(`Invalid --version-template placeholders: ${invalidVersionTemplate
|
|
49
71
|
.map((x) => `{${x}}`)
|
|
50
|
-
.join(", ")}. Allowed: {
|
|
72
|
+
.join(", ")}. Allowed: {version}, {branch}, {increment}.`);
|
|
51
73
|
}
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
-
program.error(`Invalid --branch-
|
|
74
|
+
const invalidBranchVersionTemplate = getInvalidVersionTemplatePlaceholders(branchVersionTemplate);
|
|
75
|
+
if (invalidBranchVersionTemplate.length > 0) {
|
|
76
|
+
program.error(`Invalid --branch-version-template placeholders: ${invalidBranchVersionTemplate
|
|
77
|
+
.map((x) => `{${x}}`)
|
|
78
|
+
.join(", ")}. Allowed: {version}, {branch}, {increment}.`);
|
|
79
|
+
}
|
|
80
|
+
const invalidTagTemplate = getInvalidTagTemplatePlaceholders(tagTemplate);
|
|
81
|
+
if (invalidTagTemplate.length > 0) {
|
|
82
|
+
program.error(`Invalid --tag-template placeholders: ${invalidTagTemplate
|
|
55
83
|
.map((x) => `{${x}}`)
|
|
56
84
|
.join(", ")}. Allowed: {module}, {branch}, {version}, {increment}.`);
|
|
57
85
|
}
|
|
@@ -60,8 +88,10 @@ function parseArgs() {
|
|
|
60
88
|
output,
|
|
61
89
|
modulesRoot,
|
|
62
90
|
mainBranch,
|
|
91
|
+
versionTemplate,
|
|
92
|
+
branchVersionTemplate,
|
|
63
93
|
tagTemplate,
|
|
64
|
-
|
|
94
|
+
tagPattern,
|
|
65
95
|
};
|
|
66
96
|
}
|
|
67
97
|
function toPosixPath(p) {
|
|
@@ -190,7 +220,7 @@ function appendModuleTestJob(lines, module) {
|
|
|
190
220
|
lines.push(` - echo "test is tasty"`);
|
|
191
221
|
lines.push(``);
|
|
192
222
|
}
|
|
193
|
-
function appendModuleReleaseJob(lines, module) {
|
|
223
|
+
function appendModuleReleaseJob(lines, module, tagPattern) {
|
|
194
224
|
lines.push(`${module.jobId}_release:`);
|
|
195
225
|
lines.push(` stage: release`);
|
|
196
226
|
lines.push(` rules:`);
|
|
@@ -207,41 +237,16 @@ function appendModuleReleaseJob(lines, module) {
|
|
|
207
237
|
lines.push(` script:`);
|
|
208
238
|
lines.push(` - apk update`);
|
|
209
239
|
lines.push(` - apk add $GIT_PACKAGE`);
|
|
210
|
-
lines.push(` -
|
|
211
|
-
lines.push(` -
|
|
212
|
-
lines.push(` - npm ci`);
|
|
213
|
-
lines.push(` - git tag -l "^${module.moduleName}-v(?<version>\\d+(\\.\\d+)*)-$CI_COMMIT_BRANCH-(?<increment>\\d+(\\.\\d+)*)$"`);
|
|
214
|
-
lines.push(` - npx semalease --tag-pattern "^${module.moduleName}-v(?<version>\\d+(\\.\\d+)*)-$CI_COMMIT_BRANCH-(?<increment>\\d+(\\.\\d+)*)$" semalease.env`);
|
|
215
|
-
lines.push(` - source semalease.env`);
|
|
216
|
-
lines.push(` - |`);
|
|
217
|
-
lines.push(` if [ "$CI_COMMIT_BRANCH" = "main" ]; then`);
|
|
218
|
-
lines.push(` PACKAGE_VERSION="$NEXT_VERSION"`);
|
|
219
|
-
lines.push(` else`);
|
|
220
|
-
lines.push(` PACKAGE_VERSION="$NEXT_VERSION-$CI_COMMIT_BRANCH-$NEXT_INCREMENT"`);
|
|
221
|
-
lines.push(` fi`);
|
|
222
|
-
lines.push(` - |`);
|
|
223
|
-
lines.push(` if [ "$MODULE_TYPE" = "node-express" ]; then`);
|
|
224
|
-
lines.push(` node -e "const fs=require('fs'); const pkg=JSON.parse(fs.readFileSync('package.json','utf8')); pkg.version=process.argv[1]; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\\n');" "$PACKAGE_VERSION"`);
|
|
225
|
-
lines.push(` node ci/prepare-deploy-variables.js --instance-branch $CI_COMMIT_BRANCH`);
|
|
226
|
-
lines.push(` elif [ "$MODULE_TYPE" = "node-vite" ]; then`);
|
|
227
|
-
lines.push(` node ci/set-release-data.js -i $CI_COMMIT_BRANCH --version=$PACKAGE_VERSION -t`);
|
|
228
|
-
lines.push(` node -e "const fs=require('fs'); const pkg=JSON.parse(fs.readFileSync('package.json','utf8')); pkg.version=process.argv[1]; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\\n');" "$PACKAGE_VERSION"`);
|
|
229
|
-
lines.push(` node ci/prepare-deploy-variables.js --instance-branch $CI_COMMIT_BRANCH`);
|
|
230
|
-
lines.push(` else`);
|
|
231
|
-
lines.push(` echo "Invalid module type: $MODULE_TYPE"`);
|
|
232
|
-
lines.push(` exit 1`);
|
|
233
|
-
lines.push(` fi`);
|
|
240
|
+
lines.push(` - cd ${module.modulePath}`);
|
|
241
|
+
lines.push(` - npx semalease --tag-pattern "${tagPattern}" semalease.env`);
|
|
234
242
|
lines.push(` artifacts:`);
|
|
235
243
|
lines.push(` paths:`);
|
|
236
244
|
lines.push(` - $MODULE_PATH/dist`);
|
|
237
|
-
lines.push(` - $MODULE_PATH/package.json`);
|
|
238
|
-
lines.push(` - $MODULE_PATH/public/release.json`);
|
|
239
245
|
lines.push(` - $MODULE_PATH/semalease.env`);
|
|
240
|
-
lines.push(` - $MODULE_PATH/deploy.env`);
|
|
241
246
|
lines.push(` expire_in: 1 day`);
|
|
242
247
|
lines.push(``);
|
|
243
248
|
}
|
|
244
|
-
function appendGlobalReleaseJob(lines, modules, mainBranch,
|
|
249
|
+
function appendGlobalReleaseJob(lines, modules, mainBranch, versionTemplate, branchVersionTemplate, tagTemplate) {
|
|
245
250
|
lines.push(`release_and_tag:`);
|
|
246
251
|
lines.push(` stage: release`);
|
|
247
252
|
lines.push(` needs:`);
|
|
@@ -266,31 +271,31 @@ function appendGlobalReleaseJob(lines, modules, mainBranch, tagTemplate, branchT
|
|
|
266
271
|
lines.push(` - |`);
|
|
267
272
|
lines.push(` if [ -f "${module.modulePath}/semalease.env" ]; then`);
|
|
268
273
|
lines.push(` . "${module.modulePath}/semalease.env"`);
|
|
269
|
-
lines.push(`
|
|
274
|
+
lines.push(` MODULE_TAG=""`);
|
|
270
275
|
lines.push(` if [ "$CI_COMMIT_BRANCH" = "${mainBranch}" ]; then`);
|
|
271
276
|
lines.push(` if [ "\${NEXT_VERSION:-}" != "\${LATEST_VERSION:-}" ]; then`);
|
|
272
|
-
lines.push(`
|
|
277
|
+
lines.push(` MODULE_VERSION="${applyVersionTemplate(versionTemplate)}"`);
|
|
278
|
+
lines.push(` MODULE_TAG="${applyTagTemplate(tagTemplate, module.moduleName, applyVersionTemplate(versionTemplate))}"`);
|
|
273
279
|
lines.push(` else`);
|
|
274
|
-
lines.push(` echo "Version did not change for ${module.moduleName} on branch $CI_COMMIT_BRANCH, skipping
|
|
280
|
+
lines.push(` echo "Version did not change for ${module.moduleName} on branch $CI_COMMIT_BRANCH, skipping release."`);
|
|
275
281
|
lines.push(` fi`);
|
|
276
282
|
lines.push(` else`);
|
|
277
283
|
lines.push(` if [ "\${NEXT_VERSION:-}" != "\${LATEST_VERSION:-}" ] || [ "\${NEXT_INCREMENT:-}" != "\${LATEST_INCREMENT:-}" ]; then`);
|
|
278
|
-
lines.push(`
|
|
284
|
+
lines.push(` MODULE_VERSION="${applyVersionTemplate(branchVersionTemplate)}"`);
|
|
285
|
+
lines.push(` MODULE_TAG="${applyTagTemplate(tagTemplate, module.moduleName, applyVersionTemplate(branchVersionTemplate))}"`);
|
|
279
286
|
lines.push(` else`);
|
|
280
|
-
lines.push(` echo "Version/increment did not change for ${module.moduleName} on branch $CI_COMMIT_BRANCH, skipping
|
|
287
|
+
lines.push(` echo "Version/increment did not change for ${module.moduleName} on branch $CI_COMMIT_BRANCH, skipping release."`);
|
|
281
288
|
lines.push(` fi`);
|
|
282
289
|
lines.push(` fi`);
|
|
283
|
-
lines.push(` if [ "$
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
lines.push(` TAG_NAMES="\${TAG_NAMES} \${TAG_NAME}"`);
|
|
290
|
+
lines.push(` if [ "$MODULE_TAG" != "" ]; then`);
|
|
291
|
+
lines.push(` cp -r ci "${module.modulePath}/ci"`);
|
|
292
|
+
lines.push(` cd "${module.modulePath}"`);
|
|
293
|
+
lines.push(` source "ci/${module.moduleType}/release.sh"`);
|
|
294
|
+
lines.push(` cd - >/dev/null`);
|
|
295
|
+
lines.push(` TAG_NAMES="\${TAG_NAMES} \${MODULE_TAG}"`);
|
|
291
296
|
lines.push(` fi`);
|
|
292
297
|
lines.push(` else`);
|
|
293
|
-
lines.push(` echo "Missing ${module.modulePath}/semalease.env, skipping ${module.moduleName}"`);
|
|
298
|
+
lines.push(` echo "Missing ${module.modulePath}/semalease.env, skipping ${module.moduleName} release."`);
|
|
294
299
|
lines.push(` fi`);
|
|
295
300
|
}
|
|
296
301
|
lines.push(``);
|
|
@@ -356,6 +361,9 @@ function appendModuleDeployJob(lines, module) {
|
|
|
356
361
|
lines.push(` MODULE_TYPE: ${module.moduleType}`);
|
|
357
362
|
lines.push(` script:`);
|
|
358
363
|
lines.push(` - source $MODULE_PATH/deploy.env`);
|
|
364
|
+
lines.push(` - export INSTANCE_HOST`);
|
|
365
|
+
lines.push(` - export INSTANCE_CONTAINER `);
|
|
366
|
+
lines.push(` - export INSTANCE_VERSION`);
|
|
359
367
|
lines.push(` - apk add --update --no-cache openssh-client-default`);
|
|
360
368
|
lines.push(` - eval $(ssh-agent -s)`);
|
|
361
369
|
lines.push(` - echo "$DEPLOY_USER_KEY" | tr -d '\\r' | ssh-add -`);
|
|
@@ -365,7 +373,6 @@ function appendModuleDeployJob(lines, module) {
|
|
|
365
373
|
lines.push(` - chmod 644 ~/.ssh/known_hosts`);
|
|
366
374
|
lines.push(` - echo -n $CI_JOB_TOKEN | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY`);
|
|
367
375
|
lines.push(` - docker context create remote --docker "host=ssh://$DEPLOY_USER@$DEPLOY_ADDRESS:$DEPLOY_PORT"`);
|
|
368
|
-
// lines.push(` - docker context use remote`);
|
|
369
376
|
lines.push(` - cd ci`);
|
|
370
377
|
lines.push(` - export DOCKER_API_VERSION=1.41`);
|
|
371
378
|
lines.push(` - docker --context remote compose -p $INSTANCE_CONTAINER down --remove-orphans`);
|
|
@@ -374,15 +381,15 @@ function appendModuleDeployJob(lines, module) {
|
|
|
374
381
|
lines.push(` - rm -rf ~/.ssh`);
|
|
375
382
|
lines.push(``);
|
|
376
383
|
}
|
|
377
|
-
function buildPipeline(modules, mainBranch, tagTemplate,
|
|
384
|
+
function buildPipeline(modules, mainBranch, versionTemplate, branchVersionTemplate, tagTemplate, tagPattern) {
|
|
378
385
|
const lines = [];
|
|
379
386
|
appendGlobalVariables(lines);
|
|
380
387
|
for (const module of modules) {
|
|
381
388
|
appendModuleBuildJob(lines, module);
|
|
382
389
|
appendModuleTestJob(lines, module);
|
|
383
|
-
appendModuleReleaseJob(lines, module);
|
|
390
|
+
appendModuleReleaseJob(lines, module, tagPattern);
|
|
384
391
|
}
|
|
385
|
-
appendGlobalReleaseJob(lines, modules, mainBranch,
|
|
392
|
+
appendGlobalReleaseJob(lines, modules, mainBranch, versionTemplate, branchVersionTemplate, tagTemplate);
|
|
386
393
|
for (const module of modules) {
|
|
387
394
|
appendModulePublishJob(lines, module);
|
|
388
395
|
appendModuleDeployJob(lines, module);
|
|
@@ -390,7 +397,7 @@ function buildPipeline(modules, mainBranch, tagTemplate, branchTagTemplate) {
|
|
|
390
397
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
391
398
|
}
|
|
392
399
|
function main() {
|
|
393
|
-
const { cwd, output, modulesRoot, mainBranch,
|
|
400
|
+
const { cwd, output, modulesRoot, mainBranch, versionTemplate, branchVersionTemplate, tagTemplate, tagPattern } = parseArgs();
|
|
394
401
|
if (!output) {
|
|
395
402
|
log.error("Output path is required. Use [output] or --output <path>.");
|
|
396
403
|
process.exit(1);
|
|
@@ -400,7 +407,7 @@ function main() {
|
|
|
400
407
|
log.error({ cwd, modulesRoot }, "No supported modules were discovered under modules root");
|
|
401
408
|
process.exit(1);
|
|
402
409
|
}
|
|
403
|
-
const pipeline = buildPipeline(modules, mainBranch, tagTemplate,
|
|
410
|
+
const pipeline = buildPipeline(modules, mainBranch, versionTemplate, branchVersionTemplate, tagTemplate, tagPattern);
|
|
404
411
|
const outputPath = path.resolve(cwd, output);
|
|
405
412
|
fs.writeFileSync(outputPath, pipeline, "utf8");
|
|
406
413
|
log.info({ modules: modules.map((m) => m.modulePath), outputPath }, "Generated GitLab pipeline");
|