mirror of
https://github.com/firecow/gitlab-ci-local.git
synced 2026-06-01 18:37:36 +02:00
Fix remaining SonarCloud findings (#1823)
This commit is contained in:
+4
-4
@@ -2,14 +2,14 @@ import eslint from "@eslint/js";
|
||||
import tseslint from "typescript-eslint";
|
||||
import stylistic from "@stylistic/eslint-plugin";
|
||||
|
||||
export default tseslint.config(
|
||||
export default [
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
{
|
||||
ignores: [
|
||||
"**/*.js",
|
||||
"**/*.cjs",
|
||||
".gitlab-ci-local",
|
||||
"**/.gitlab-ci-local/**",
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -50,4 +50,4 @@ export default tseslint.config(
|
||||
"key-spacing": "error",
|
||||
},
|
||||
},
|
||||
);
|
||||
];
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
import fs from "fs-extra";
|
||||
import * as dotenv from "dotenv";
|
||||
import * as path from "path";
|
||||
import * as path from "node:path";
|
||||
import camelCase from "camelcase";
|
||||
import {Utils} from "./utils.js";
|
||||
import {WriteStreams} from "./write-streams.js";
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import {WriteStreams} from "./write-streams.js";
|
||||
import {Executor} from "./executor.js";
|
||||
import fs from "fs-extra";
|
||||
import {Argv} from "./argv.js";
|
||||
import {AssertionError} from "assert";
|
||||
import {AssertionError} from "node:assert";
|
||||
|
||||
export class Commander {
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import chalk from "chalk-template";
|
||||
import deepExtend from "deep-extend";
|
||||
import assert, {AssertionError} from "assert";
|
||||
import assert, {AssertionError} from "node:assert";
|
||||
import {Job, Need} from "./job.js";
|
||||
import {traverse} from "object-traversal";
|
||||
import {Utils} from "./utils.js";
|
||||
@@ -150,7 +150,7 @@ export function cacheEach (jobName: string, gitlabData: any) {
|
||||
|
||||
jobData.cache = Array.isArray(cache) ? cache : [cache];
|
||||
for (const [i, c] of Object.entries<any>(jobData.cache)) {
|
||||
if (c.key?.files instanceof Array) {
|
||||
if (Array.isArray(c.key?.files)) {
|
||||
assert(c.key.files.length === 1 || c.key.files.length === 2, `cache:key:files should be an array of one or two file paths. Got ${c.key.files.length}`);
|
||||
}
|
||||
jobData.cache[i] = cacheComplex(c);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import chalk from "chalk-template";
|
||||
import {Job} from "./job.js";
|
||||
import assert, {AssertionError} from "assert";
|
||||
import assert, {AssertionError} from "node:assert";
|
||||
import {Argv} from "./argv.js";
|
||||
import pMap from "p-map";
|
||||
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
import {Utils} from "./utils.js";
|
||||
import assert, {AssertionError} from "assert";
|
||||
import assert, {AssertionError} from "node:assert";
|
||||
import {WriteStreams} from "./write-streams.js";
|
||||
import chalk from "chalk-template";
|
||||
|
||||
@@ -35,12 +35,12 @@ export class GitData {
|
||||
|
||||
static async init (cwd: string, writeStreams: WriteStreams): Promise<GitData> {
|
||||
const gitData = new GitData();
|
||||
const promises = [];
|
||||
promises.push(gitData.initCommitData(cwd, writeStreams));
|
||||
promises.push(gitData.initRemoteData(cwd, writeStreams));
|
||||
promises.push(gitData.initUserData(cwd, writeStreams));
|
||||
promises.push(gitData.initBranchData(cwd, writeStreams));
|
||||
await Promise.all(promises);
|
||||
await Promise.all([
|
||||
gitData.initCommitData(cwd, writeStreams),
|
||||
gitData.initRemoteData(cwd, writeStreams),
|
||||
gitData.initUserData(cwd, writeStreams),
|
||||
gitData.initBranchData(cwd, writeStreams),
|
||||
]);
|
||||
return gitData;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import * as yaml from "js-yaml";
|
||||
import chalk from "chalk-template";
|
||||
import path from "path";
|
||||
import path from "node:path";
|
||||
import fs from "fs-extra";
|
||||
import yargs from "yargs";
|
||||
import {Commander} from "./commander.js";
|
||||
@@ -11,7 +11,7 @@ import {WriteStreams} from "./write-streams.js";
|
||||
import {cleanupJobResources, Job} from "./job.js";
|
||||
import {Utils} from "./utils.js";
|
||||
import {Argv} from "./argv.js";
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
|
||||
const generateGitIgnore = (cwd: string, stateDir: string) => {
|
||||
const gitIgnoreFilePath = `${cwd}/${stateDir}/.gitignore`;
|
||||
|
||||
+28
-23
@@ -6,7 +6,7 @@ import split2 from "split2";
|
||||
import {Utils} from "./utils.js";
|
||||
import {WriteStreams} from "./write-streams.js";
|
||||
import {GitData} from "./git-data.js";
|
||||
import assert, {AssertionError} from "assert";
|
||||
import assert, {AssertionError} from "node:assert";
|
||||
import {Mutex} from "./mutex.js";
|
||||
import {Argv} from "./argv.js";
|
||||
import execa from "execa";
|
||||
@@ -418,10 +418,10 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
}
|
||||
break;
|
||||
case "object":
|
||||
if (! Array.isArray(allowFailure.exit_codes)) {
|
||||
allowedExitCodes = [allowFailure.exit_codes];
|
||||
} else {
|
||||
if (Array.isArray(allowFailure.exit_codes)) {
|
||||
allowedExitCodes = allowFailure.exit_codes;
|
||||
} else {
|
||||
allowedExitCodes = [allowFailure.exit_codes];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -685,12 +685,11 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
const tmpVolumeName = this.tmpVolumeName;
|
||||
const fileVariablesDir = this.fileVariablesDir;
|
||||
|
||||
const volumePromises = [];
|
||||
volumePromises.push(Utils.spawn([this.argv.containerExecutable, "volume", "create", `${buildVolumeName}`], argv.cwd));
|
||||
volumePromises.push(Utils.spawn([this.argv.containerExecutable, "volume", "create", `${tmpVolumeName}`], argv.cwd));
|
||||
this._containerVolumeNames.push(buildVolumeName);
|
||||
this._containerVolumeNames.push(tmpVolumeName);
|
||||
await Promise.all(volumePromises);
|
||||
this._containerVolumeNames.push(buildVolumeName, tmpVolumeName);
|
||||
await Promise.all([
|
||||
Utils.spawn([this.argv.containerExecutable, "volume", "create", `${buildVolumeName}`], argv.cwd),
|
||||
Utils.spawn([this.argv.containerExecutable, "volume", "create", `${tmpVolumeName}`], argv.cwd),
|
||||
]);
|
||||
|
||||
const time = process.hrtime();
|
||||
this.refreshLongRunningSilentTimeout(writeStreams);
|
||||
@@ -762,7 +761,7 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
}
|
||||
|
||||
await this.execPreScripts(expanded);
|
||||
if (this._prescriptsExitCode == null) throw Error("this._prescriptsExitCode must be defined!");
|
||||
if (this._prescriptsExitCode == null) throw new Error("this._prescriptsExitCode must be defined!");
|
||||
|
||||
await this.execAfterScripts(expanded);
|
||||
|
||||
@@ -844,7 +843,7 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
scripts.forEach((script) => {
|
||||
const split = script.split(/\r?\n/);
|
||||
const multilineText = split.length > 1 ? " # collapsed multi-line command" : "";
|
||||
const text = split[0]?.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/[$]/g, "\\$");
|
||||
const text = split[0]?.replaceAll("\\", String.raw`\\`).replaceAll("\"", String.raw`\"`).replaceAll("$", String.raw`\$`);
|
||||
if (this.interactive) {
|
||||
cmd += chalk`echo "{green $ ${text}${multilineText}}"\n`;
|
||||
} else {
|
||||
@@ -1035,7 +1034,8 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
|
||||
for (const [key, val] of Object.entries(expanded)) {
|
||||
// Replacing `'` with `'\''` to correctly handle single quotes(if `val` contains `'`) in shell commands
|
||||
dockerCmd += ` -e '${key}=${val.toString().replaceAll("'", String.raw`'\''`)}' \\\n`;
|
||||
const escaped = val.toString().replaceAll("'", String.raw`'\''`);
|
||||
dockerCmd += ` -e '${key}=${escaped}' \\\n`;
|
||||
}
|
||||
|
||||
if (this.imageEntrypoint) {
|
||||
@@ -1594,7 +1594,8 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
|
||||
for (const [key, val] of Object.entries(expanded)) {
|
||||
// Replacing `'` with `'\''` to correctly handle single quotes(if `val` contains `'`) in shell commands
|
||||
dockerCmd += ` -e '${key}=${val.toString().replaceAll("'", String.raw`'\''`)}' \\\n`;
|
||||
const escaped = val.toString().replaceAll("'", String.raw`'\''`);
|
||||
dockerCmd += ` -e '${key}=${escaped}' \\\n`;
|
||||
}
|
||||
|
||||
const serviceEntrypoint = service.entrypoint;
|
||||
@@ -1621,7 +1622,10 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
dockerCmd += `${Utils.safeBashString(e)} `;
|
||||
});
|
||||
}
|
||||
(service.command ?? []).forEach((e) => dockerCmd += `"${e.replace(/\$/g, "\\$")}" `);
|
||||
for (const e of service.command ?? []) {
|
||||
const escaped = e.replaceAll("$", String.raw`\$`);
|
||||
dockerCmd += `"${escaped}" `;
|
||||
}
|
||||
|
||||
const time = process.hrtime();
|
||||
|
||||
@@ -1656,14 +1660,15 @@ If you know what you're doing and would like to suppress this warning, use one o
|
||||
const time = process.hrtime();
|
||||
try {
|
||||
// Iterate over each port defined in the image, and try to connect to the alias
|
||||
await Promise.any(Object.keys(imageInspect[0].Config.ExposedPorts).map((port) => {
|
||||
if (!port.endsWith("/tcp")) return;
|
||||
const portNum = parseInt(port.replace("/tcp", ""));
|
||||
const containerName = `gcl-wait-for-it-${this.jobId}-${serviceIndex}-${portNum}`;
|
||||
const spawnCmd = [this.argv.containerExecutable, "run", "--rm", `--name=${containerName}`, "--network", `${this._serviceNetworkId}`, `${waitImageName}`, `${serviceAlias}:${portNum}`, "-t", `${waitForServicesTimeout}`];
|
||||
this._containersToClean.push(containerName);
|
||||
return Utils.spawn(spawnCmd);
|
||||
}));
|
||||
await Promise.any(Object.keys(imageInspect[0].Config.ExposedPorts)
|
||||
.filter((port) => port.endsWith("/tcp"))
|
||||
.map((port) => {
|
||||
const portNum = Number.parseInt(port.replace("/tcp", ""));
|
||||
const containerName = `gcl-wait-for-it-${this.jobId}-${serviceIndex}-${portNum}`;
|
||||
const spawnCmd = [this.argv.containerExecutable, "run", "--rm", `--name=${containerName}`, "--network", `${this._serviceNetworkId}`, `${waitImageName}`, `${serviceAlias}:${portNum}`, "-t", `${waitForServicesTimeout}`];
|
||||
this._containersToClean.push(containerName);
|
||||
return Utils.spawn(spawnCmd);
|
||||
}));
|
||||
const endTime = process.hrtime(time);
|
||||
writeStreams.stdout(chalk`${this.formattedJobName} {greenBright service image: ${serviceName} healthcheck passed in {green ${prettyHrtime(endTime)}}}\n`);
|
||||
} catch (e: any) {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
import deepExtend from "deep-extend";
|
||||
|
||||
export function isPlainParallel (jobData: any) {
|
||||
|
||||
@@ -3,11 +3,11 @@ import {Utils} from "./utils.js";
|
||||
import fs from "fs-extra";
|
||||
import {WriteStreams} from "./write-streams.js";
|
||||
import {GitData} from "./git-data.js";
|
||||
import assert, {AssertionError} from "assert";
|
||||
import assert, {AssertionError} from "node:assert";
|
||||
import chalk from "chalk-template";
|
||||
import {Parser} from "./parser.js";
|
||||
import axios from "axios";
|
||||
import path from "path";
|
||||
import path from "node:path";
|
||||
import prettyHrtime from "pretty-hrtime";
|
||||
import semver from "semver";
|
||||
import {RE2JS} from "re2js";
|
||||
@@ -433,11 +433,11 @@ export async function resolveIncludeLocal (pattern: string, cwd: string) {
|
||||
|
||||
// `**` matches anything
|
||||
const anything = ".*?";
|
||||
pattern = pattern.replaceAll(/\\\*\\\*/g, anything);
|
||||
pattern = pattern.replaceAll(String.raw`\*\*`, anything);
|
||||
|
||||
// `*` matches anything except for `/`
|
||||
const anything_but_not_slash = "([^/])*?";
|
||||
pattern = pattern.replaceAll(/\\\*/g, anything_but_not_slash);
|
||||
pattern = pattern.replaceAll(String.raw`\*`, anything_but_not_slash);
|
||||
|
||||
const re2js = RE2JS.compile(`^${pattern}`);
|
||||
return repoFiles.filter((f: any) => re2js.matches(f));
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
import chalk from "chalk-template";
|
||||
import path from "path";
|
||||
import path from "node:path";
|
||||
import deepExtend from "deep-extend";
|
||||
import fs from "fs-extra";
|
||||
import * as yaml from "js-yaml";
|
||||
@@ -7,7 +7,7 @@ import prettyHrtime from "pretty-hrtime";
|
||||
import {Job} from "./job.js";
|
||||
import * as DataExpander from "./data-expander.js";
|
||||
import {Utils} from "./utils.js";
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
import {Validator} from "./validator.js";
|
||||
import * as parallel from "./parallel.js";
|
||||
import {GitData} from "./git-data.js";
|
||||
@@ -199,7 +199,7 @@ export class Parser {
|
||||
if (this.argv.maxJobNamePadding !== null && this.argv.maxJobNamePadding <= 0) {
|
||||
this._jobNamePad = 0;
|
||||
} else {
|
||||
const jobs = this.argv.job.length !== 0 ? this.argv.job : this.jobs;
|
||||
const jobs = this.argv.job.length === 0 ? this.jobs : this.argv.job;
|
||||
jobs.forEach((job) => {
|
||||
let jobNeedsLength: number[] = [];
|
||||
|
||||
@@ -304,7 +304,7 @@ export class Parser {
|
||||
const uninterpolatedConfigurations: any = fileData[1];
|
||||
|
||||
const interpolatedConfigurations = JSON.stringify(uninterpolatedConfigurations)
|
||||
.replace(
|
||||
.replaceAll(
|
||||
/(?<firstChar>.)?(?<secondChar>.)?\$\[\[\s*inputs.(?<interpolationKey>[\w-]+)\s*\|?\s*(?<interpolationFunctions>.*?)\s*\]\](?<lastChar>[^$])?/g // https://regexr.com/81c16
|
||||
, (_: string, firstChar: string, secondChar: string, interpolationKey: string, interpolationFunctions: string, lastChar: string) => {
|
||||
const configFilePath = path.relative(process.cwd(), filePath);
|
||||
|
||||
@@ -38,7 +38,7 @@ export function init ({gitData, argv, envMatchedVariables}: PredefinedVariablesO
|
||||
CI_PROJECT_NAME: gitData.remote.project,
|
||||
CI_PROJECT_TITLE: `${camelCase(gitData.remote.project)}`,
|
||||
CI_PROJECT_PATH: `${gitData.remote.group}/${gitData.remote.project}`,
|
||||
CI_PROJECT_PATH_SLUG: `${gitData.remote.group.replace(/\//g, "-")}-${gitData.remote.project}`.toLowerCase(),
|
||||
CI_PROJECT_PATH_SLUG: `${gitData.remote.group.replaceAll("/", "-")}-${gitData.remote.project}`.toLowerCase(),
|
||||
CI_PROJECT_ROOT_NAMESPACE: CI_PROJECT_ROOT_NAMESPACE,
|
||||
CI_PROJECT_NAMESPACE: CI_PROJECT_NAMESPACE,
|
||||
CI_PROJECT_VISIBILITY: "internal",
|
||||
@@ -46,7 +46,7 @@ export function init ({gitData, argv, envMatchedVariables}: PredefinedVariablesO
|
||||
CI_COMMIT_REF_PROTECTED: "false",
|
||||
CI_COMMIT_BRANCH: gitData.commit.REF_NAME, // Not available in merge request or tag pipelines
|
||||
CI_COMMIT_REF_NAME: gitData.commit.REF_NAME, // Tag or branch name
|
||||
CI_COMMIT_REF_SLUG: gitData.commit.REF_NAME.replace(/[^a-z\d]+/ig, "-").replace(/^-/, "").slice(0, 63).replace(/-$/, "").toLowerCase(),
|
||||
CI_COMMIT_REF_SLUG: gitData.commit.REF_NAME.replaceAll(/[^a-z\d]+/ig, "-").replace(/^-/, "").slice(0, 63).replace(/-$/, "").toLowerCase(),
|
||||
CI_COMMIT_TIMESTAMP: gitData.commit.TIMESTAMP,
|
||||
CI_PIPELINE_CREATED_AT: new Date().toISOString().split(".")[0] + "Z",
|
||||
CI_COMMIT_TITLE: "Commit Title", // First line of commit message.
|
||||
|
||||
+7
-8
@@ -7,7 +7,7 @@ import fs from "fs-extra";
|
||||
import checksum from "checksum";
|
||||
import base64url from "base64url";
|
||||
import execa, {ExecaError} from "execa";
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
import {CICDVariable} from "./variables-from-files.js";
|
||||
import {GitData} from "./git-data.js";
|
||||
import {globbySync} from "globby";
|
||||
@@ -92,7 +92,7 @@ export class Utils {
|
||||
const matches = Array.from(content.matchAllRE2JS(regex));
|
||||
if (matches.length === 0) return "0";
|
||||
|
||||
const lastMatch = matches[matches.length - 1];
|
||||
const lastMatch = matches.at(-1)!;
|
||||
const digits = /\d+(?:\.\d+)?/.exec(lastMatch[1] ?? lastMatch[0] ?? "");
|
||||
if (!digits) return "0";
|
||||
return digits[0] ?? "0";
|
||||
@@ -111,16 +111,15 @@ export class Utils {
|
||||
return text;
|
||||
}
|
||||
|
||||
return text.replace(
|
||||
return text.replaceAll(
|
||||
/(\$\$)|\$\{([a-zA-Z_]\w*)}|\$([a-zA-Z_]\w*)/g, // https://regexr.com/7s4ka
|
||||
(_match, escape, var1, var2) => {
|
||||
if (typeof escape !== "undefined") {
|
||||
if (escape !== undefined) {
|
||||
return expandWith.unescape;
|
||||
} else {
|
||||
const name = var1 || var2;
|
||||
assert(name, "unexpected unset capture group");
|
||||
return `${expandWith.variable(name)}`;
|
||||
}
|
||||
const name = var1 || var2;
|
||||
assert(name, "unexpected unset capture group");
|
||||
return `${expandWith.variable(name)}`;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import Ajv from "ajv";
|
||||
import {Job} from "./job.js";
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
import chalk from "chalk-template";
|
||||
import schema from "./schema.js";
|
||||
import {betterAjvErrors} from "./schema-error.js";
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as yaml from "js-yaml";
|
||||
import chalk from "chalk-template";
|
||||
import prettyHrtime from "pretty-hrtime";
|
||||
import {Argv} from "./argv.js";
|
||||
import assert from "assert";
|
||||
import assert from "node:assert";
|
||||
import {Utils} from "./utils.js";
|
||||
import dotenv from "dotenv";
|
||||
import deepExtend from "deep-extend";
|
||||
@@ -72,12 +72,12 @@ export class VariablesFromFiles {
|
||||
for (const [matcher, content] of Object.entries(values)) {
|
||||
assert(typeof content == "string", `${key}.${matcher} content must be text or multiline text`);
|
||||
if (isDotEnv || type === "variable" || (type === null && !/^[/~]/.exec(content))) {
|
||||
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replace(/\*/g, ".*")}$`, "g");
|
||||
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replaceAll("*", ".*")}$`, "g");
|
||||
variables[key] = variables[key] ?? {type: "variable", environments: []};
|
||||
variables[key].environments.push({content, regexp, regexpPriority: matcher.length, scopePriority});
|
||||
} else if (type === null && /^[/~]/.exec(content)) {
|
||||
const fileSource = content.replace(/^~\/(.*)/, `${homeDir}/$1`);
|
||||
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replace(/\*/g, ".*")}$`, "g");
|
||||
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replaceAll("*", ".*")}$`, "g");
|
||||
variables[key] = variables[key] ?? {type: "file", environments: []};
|
||||
if (fs.existsSync(fileSource)) {
|
||||
variables[key].environments.push({content, regexp, regexpPriority: matcher.length, scopePriority, fileSource});
|
||||
@@ -85,7 +85,7 @@ export class VariablesFromFiles {
|
||||
variables[key].environments.push({content: `warn: ${key} is pointing to invalid path\n`, regexp, regexpPriority: matcher.length, scopePriority});
|
||||
}
|
||||
} else if (type === "file") {
|
||||
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replace(/\*/g, ".*")}$`, "g");
|
||||
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replaceAll("*", ".*")}$`, "g");
|
||||
variables[key] = variables[key] ?? {type: "file", environments: []};
|
||||
variables[key].environments.push({content, regexp, regexpPriority: matcher.length, scopePriority});
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user