gitlab-ci-local
Version:
Tired of pushing to test your .gitlab-ci.yml?
136 lines • 28.3 kB
JavaScript
import fs from "fs-extra";
import * as yaml from "js-yaml";
import chalk from "chalk";
import assert from "assert";
import { Utils } from "./utils.js";
import dotenv from "dotenv";
export class VariablesFromFiles {
static async init(argv, writeStreams, gitData) {
const cwd = argv.cwd;
const stateDir = argv.stateDir;
const homeDir = argv.home;
const remoteVariables = argv.remoteVariables;
const autoCompleting = argv.autoCompleting;
const homeVariablesFile = `${homeDir}/${stateDir}/variables.yml`;
const variables = {};
let remoteFileData = {};
let homeFileData = {};
if (remoteVariables && !autoCompleting) {
const match = /(?<url>git@.*?)=(?<file>.*?)=(?<ref>.*)/.exec(remoteVariables);
assert(match != null, "--remote-variables is malformed use 'git@gitlab.com:firecow/example.git=gitlab-variables.yml=master' syntax");
const url = match.groups?.url;
const file = match.groups?.file;
const ref = match.groups?.ref;
const res = await Utils.bash(`set -eou pipefail; git archive --remote=${url} ${ref} ${file} | tar -xO ${file}`, cwd);
remoteFileData = yaml.load(`${res.stdout}`);
}
if (await fs.pathExists(homeVariablesFile)) {
homeFileData = yaml.load(await fs.readFile(homeVariablesFile, "utf8"), { schema: yaml.FAILSAFE_SCHEMA });
}
const unpack = (v) => {
if (typeof v === "string") {
const catchAll = { values: {}, type: null };
catchAll.values = {};
catchAll.values["*"] = v;
return catchAll;
}
else {
v.type = v.type ?? "variable";
}
return v;
};
const addToVariables = async (key, val, scopePriority, isDotEnv = false) => {
const { type, values } = unpack(val);
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");
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");
variables[key] = variables[key] ?? { type: "file", environments: [] };
if (fs.existsSync(fileSource)) {
variables[key].environments.push({ content, regexp, regexpPriority: matcher.length, scopePriority, fileSource });
}
else {
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");
variables[key] = variables[key] ?? { type: "file", environments: [] };
variables[key].environments.push({ content, regexp, regexpPriority: matcher.length, scopePriority });
}
else {
assert(false, `${key} was not handled properly`);
}
}
};
const addVariableFileToVariables = async (fileData, filePriority) => {
for (const [globalKey, globalEntry] of Object.entries(fileData?.global ?? {})) {
await addToVariables(globalKey, globalEntry, 1 + filePriority);
}
const groupUrl = `${gitData.remote.host}/${gitData.remote.group}/`;
for (const [groupKey, groupEntries] of Object.entries(fileData?.group ?? {})) {
if (!groupUrl.includes(this.normalizeProjectKey(groupKey, writeStreams)))
continue;
assert(groupEntries != null, "groupEntries cannot be null/undefined");
assert(Utils.isObject(groupEntries), "group entries in variable files must be an object");
for (const [k, v] of Object.entries(groupEntries)) {
await addToVariables(k, v, 2 + filePriority);
}
}
const projectUrl = `${gitData.remote.host}/${gitData.remote.group}/${gitData.remote.project}.git`;
for (const [projectKey, projectEntries] of Object.entries(fileData?.project ?? [])) {
if (!projectUrl.includes(this.normalizeProjectKey(projectKey, writeStreams)))
continue;
assert(projectEntries != null, "projectEntries cannot be null/undefined");
assert(Utils.isObject(projectEntries), "project entries in variable files must be an object");
for (const [k, v] of Object.entries(projectEntries)) {
await addToVariables(k, v, 3 + filePriority);
}
}
};
await addVariableFileToVariables(remoteFileData, 0);
await addVariableFileToVariables(homeFileData, 10);
const projectVariablesFile = `${argv.cwd}/${argv.variablesFile}`;
if (fs.existsSync(projectVariablesFile)) {
let isDotEnvFormat = false;
const projectVariablesFileRawContent = await fs.readFile(projectVariablesFile, "utf8");
let projectVariablesFileData;
try {
projectVariablesFileData = yaml.load(projectVariablesFileRawContent, { schema: yaml.FAILSAFE_SCHEMA }) ?? {};
if (typeof (projectVariablesFileData) === "string") {
isDotEnvFormat = true;
projectVariablesFileData = dotenv.parse(projectVariablesFileRawContent);
}
}
catch (e) {
if (e instanceof yaml.YAMLException) {
isDotEnvFormat = true;
projectVariablesFileData = dotenv.parse(projectVariablesFileRawContent);
}
}
assert(projectVariablesFileData != null, "projectEntries cannot be null/undefined");
assert(Utils.isObject(projectVariablesFileData), `${argv.cwd}/.gitlab-ci-local-variables.yml must contain an object`);
for (const [k, v] of Object.entries(projectVariablesFileData)) {
await addToVariables(k, v, 24, isDotEnvFormat);
}
}
for (const varObj of Object.values(variables)) {
varObj.environments.sort((a, b) => b.scopePriority - a.scopePriority);
varObj.environments.sort((a, b) => b.regexpPriority - a.regexpPriority);
}
return variables;
}
static normalizeProjectKey(key, writeStreams) {
if (!key.includes(":"))
return key;
writeStreams.stderr(chalk `{yellow WARNING: Interpreting '${key}' as '${key.replace(":", "/")}'}\n`);
return key.replace(":", "/");
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFyaWFibGVzLWZyb20tZmlsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ2YXJpYWJsZXMtZnJvbS1maWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDMUIsT0FBTyxLQUFLLElBQUksTUFBTSxTQUFTLENBQUM7QUFDaEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBRTFCLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ2pDLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQWE1QixNQUFNLE9BQU8sa0JBQWtCO0lBRTNCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFFLElBQVUsRUFBRSxZQUEwQixFQUFFLE9BQWdCO1FBQ3ZFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDckIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUMvQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQzFCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDN0MsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUMzQyxNQUFNLGlCQUFpQixHQUFHLEdBQUcsT0FBTyxJQUFJLFFBQVEsZ0JBQWdCLENBQUM7UUFDakUsTUFBTSxTQUFTLEdBQW1DLEVBQUUsQ0FBQztRQUNyRCxJQUFJLGNBQWMsR0FBUSxFQUFFLENBQUM7UUFDN0IsSUFBSSxZQUFZLEdBQVEsRUFBRSxDQUFDO1FBRTNCLElBQUksZUFBZSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDckMsTUFBTSxLQUFLLEdBQUcseUNBQXlDLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQzlFLE1BQU0sQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFLDZH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LENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7V3JpdGVTdHJlYW1zfSBmcm9tIFwiLi93cml0ZS1zdHJlYW1zLmpzXCI7XG5pbXBvcnQge0dpdERhdGF9IGZyb20gXCIuL2dpdC1kYXRhLmpzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzLWV4dHJhXCI7XG5pbXBvcnQgKiBhcyB5YW1sIGZyb20gXCJqcy15YW1sXCI7XG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQge0FyZ3Z9IGZyb20gXCIuL2FyZ3YuanNcIjtcbmltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHtVdGlsc30gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCBkb3RlbnYgZnJvbSBcImRvdGVudlwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIENJQ0RWYXJpYWJsZSB7XG4gICAgdHlwZTogXCJmaWxlXCIgfCBcInZhcmlhYmxlXCI7XG4gICAgZW52aXJvbm1lbnRzOiB7XG4gICAgICAgIGNvbnRlbnQ6IHN0cmluZztcbiAgICAgICAgcmVnZXhwOiBSZWdFeHA7XG4gICAgICAgIHJlZ2V4cFByaW9yaXR5OiBudW1iZXI7XG4gICAgICAgIHNjb3BlUHJpb3JpdHk6IG51bWJlcjtcbiAgICAgICAgZmlsZVNvdXJjZT86IHN0cmluZztcbiAgICB9W107XG59XG5cbmV4cG9ydCBjbGFzcyBWYXJpYWJsZXNGcm9tRmlsZXMge1xuXG4gICAgc3RhdGljIGFzeW5jIGluaXQgKGFyZ3Y6IEFyZ3YsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBnaXREYXRhOiBHaXREYXRhKTogUHJvbWlzZTx7W25hbWU6IHN0cmluZ106IENJQ0RWYXJpYWJsZX0+IHtcbiAgICAgICAgY29uc3QgY3dkID0gYXJndi5jd2Q7XG4gICAgICAgIGNvbnN0IHN0YXRlRGlyID0gYXJndi5zdGF0ZURpcjtcbiAgICAgICAgY29uc3QgaG9tZURpciA9IGFyZ3YuaG9tZTtcbiAgICAgICAgY29uc3QgcmVtb3RlVmFyaWFibGVzID0gYXJndi5yZW1vdGVWYXJpYWJsZXM7XG4gICAgICAgIGNvbnN0IGF1dG9Db21wbGV0aW5nID0gYXJndi5hdXRvQ29tcGxldGluZztcbiAgICAgICAgY29uc3QgaG9tZVZhcmlhYmxlc0ZpbGUgPSBgJHtob21lRGlyfS8ke3N0YXRlRGlyfS92YXJpYWJsZXMueW1sYDtcbiAgICAgICAgY29uc3QgdmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IENJQ0RWYXJpYWJsZX0gPSB7fTtcbiAgICAgICAgbGV0IHJlbW90ZUZpbGVEYXRhOiBhbnkgPSB7fTtcbiAgICAgICAgbGV0IGhvbWVGaWxlRGF0YTogYW55ID0ge307XG5cbiAgICAgICAgaWYgKHJlbW90ZVZhcmlhYmxlcyAmJiAhYXV0b0NvbXBsZXRpbmcpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gLyg/PHVybD5naXRALio/KT0oPzxmaWxlPi4qPyk9KD88cmVmPi4qKS8uZXhlYyhyZW1vdGVWYXJpYWJsZXMpO1xuICAgICAgICAgICAgYXNzZXJ0KG1hdGNoICE9IG51bGwsIFwiLS1yZW1vdGUtdmFyaWFibGVzIGlzIG1hbGZvcm1lZCB1c2UgJ2dpdEBnaXRsYWIuY29tOmZpcmVjb3cvZXhhbXBsZS5naXQ9Z2l0bGFiLXZhcmlhYmxlcy55bWw9bWFzdGVyJyBzeW50YXhcIik7XG4gICAgICAgICAgICBjb25zdCB1cmwgPSBtYXRjaC5ncm91cHM/LnVybDtcbiAgICAgICAgICAgIGNvbnN0IGZpbGUgPSBtYXRjaC5ncm91cHM/LmZpbGU7XG4gICAgICAgICAgICBjb25zdCByZWYgPSBtYXRjaC5ncm91cHM/LnJlZjtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IFV0aWxzLmJhc2goYHNldCAtZW91IHBpcGVmYWlsOyBnaXQgYXJjaGl2ZSAtLXJlbW90ZT0ke3VybH0gJHtyZWZ9ICR7ZmlsZX0gfCB0YXIgLXhPICR7ZmlsZX1gLCBjd2QpO1xuICAgICAgICAgICAgcmVtb3RlRmlsZURhdGEgPSB5YW1sLmxvYWQoYCR7cmVzLnN0ZG91dH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKGhvbWVWYXJpYWJsZXNGaWxlKSkge1xuICAgICAgICAgICAgaG9tZUZpbGVEYXRhID0geWFtbC5sb2FkKGF3YWl0IGZzLnJlYWRGaWxlKGhvbWVWYXJpYWJsZXNGaWxlLCBcInV0ZjhcIiksIHtzY2hlbWE6IHlhbWwuRkFJTFNBRkVfU0NIRU1BfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1bnBhY2sgPSAodjogYW55KToge3ZhbHVlczogYW55OyB0eXBlOiBcImZpbGVcIiB8IFwidmFyaWFibGVcIiB8IG51bGx9ID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhdGNoQWxsOiB7dmFsdWVzOiBhbnk7IHR5cGU6IFwiZmlsZVwiIHwgXCJ2YXJpYWJsZVwiIHwgbnVsbH0gPSB7dmFsdWVzOiB7fSwgdHlwZTogbnVsbH07XG4gICAgICAgICAgICAgICAgY2F0Y2hBbGwudmFsdWVzID0ge307XG4gICAgICAgICAgICAgICAgY2F0Y2hBbGwudmFsdWVzW1wiKlwiXSA9IHY7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhdGNoQWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2LnR5cGUgPSB2LnR5cGUgPz8gXCJ2YXJpYWJsZVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGFkZFRvVmFyaWFibGVzID0gYXN5bmMgKGtleTogc3RyaW5nLCB2YWw6IGFueSwgc2NvcGVQcmlvcml0eTogbnVtYmVyLCBpc0RvdEVudiA9IGZhbHNlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7dHlwZSwgdmFsdWVzfSA9IHVucGFjayh2YWwpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBbbWF0Y2hlciwgY29udGVudF0gb2YgT2JqZWN0LmVudHJpZXModmFsdWVzKSkge1xuICAgICAgICAgICAgICAgIGFzc2VydCh0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiLCBgJHtrZXl9LiR7bWF0Y2hlcn0gY29udGVudCBtdXN0IGJlIHRleHQgb3IgbXVsdGlsaW5lIHRleHRgKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNEb3RFbnYgfHwgdHlwZSA9PT0gXCJ2YXJpYWJsZVwiIHx8ICh0eXBlID09PSBudWxsICYmICEvXlsvfl0vLmV4ZWMoY29udGVudCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2V4cCA9IG1hdGNoZXIgPT09IFwiKlwiID8gLy4qL2cgOiBuZXcgUmVnRXhwKGBeJHttYXRjaGVyLnJlcGxhY2UoL1xcKi9nLCBcIi4qXCIpfSRgLCBcImdcIik7XG4gICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlc1trZXldID0gdmFyaWFibGVzW2tleV0gPz8ge3R5cGU6IFwidmFyaWFibGVcIiwgZW52aXJvbm1lbnRzOiBbXX07XG4gICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlc1trZXldLmVudmlyb25tZW50cy5wdXNoKHtjb250ZW50LCByZWdleHAsIHJlZ2V4cFByaW9yaXR5OiBtYXRjaGVyLmxlbmd0aCwgc2NvcGVQcmlvcml0eX0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gbnVsbCAmJiAvXlsvfl0vLmV4ZWMoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsZVNvdXJjZSA9IGNvbnRlbnQucmVwbGFjZSgvXn5cXC8oLiopLywgYCR7aG9tZURpcn0vJDFgKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVnZXhwID0gbWF0Y2hlciA9PT0gXCIqXCIgPyAvLiovZyA6IG5ldyBSZWdFeHAoYF4ke21hdGNoZXIucmVwbGFjZSgvXFwqL2csIFwiLipcIil9JGAsIFwiZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzW2tleV0gPSB2YXJpYWJsZXNba2V5XSA/PyB7dHlwZTogXCJmaWxlXCIsIGVudmlyb25tZW50czogW119O1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhmaWxlU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzW2tleV0uZW52aXJvbm1lbnRzLnB1c2goe2NvbnRlbnQsIHJlZ2V4cCwgcmVnZXhwUHJpb3JpdHk6IG1hdGNoZXIubGVuZ3RoLCBzY29wZVByaW9yaXR5LCBmaWxlU291cmNlfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZXNba2V5XS5lbnZpcm9ubWVudHMucHVzaCh7Y29udGVudDogYHdhcm46ICR7a2V5fSBpcyBwb2ludGluZyB0byBpbnZhbGlkIHBhdGhcXG5gLCByZWdleHAsIHJlZ2V4cFByaW9yaXR5OiBtYXRjaGVyLmxlbmd0aCwgc2NvcGVQcmlvcml0eX0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcImZpbGVcIikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWdleHAgPSBtYXRjaGVyID09PSBcIipcIiA/IC8uKi9nIDogbmV3IFJlZ0V4cChgXiR7bWF0Y2hlci5yZXBsYWNlKC9cXCovZywgXCIuKlwiKX0kYCwgXCJnXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZXNba2V5XSA9IHZhcmlhYmxlc1trZXldID8/IHt0eXBlOiBcImZpbGVcIiwgZW52aXJvbm1lbnRzOiBbXX07XG4gICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlc1trZXldLmVudmlyb25tZW50cy5wdXNoKHtjb250ZW50LCByZWdleHAsIHJlZ2V4cFByaW9yaXR5OiBtYXRjaGVyLmxlbmd0aCwgc2NvcGVQcmlvcml0eX0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChmYWxzZSwgYCR7a2V5fSB3YXMgbm90IGhhbmRsZWQgcHJvcGVybHlgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgYWRkVmFyaWFibGVGaWxlVG9WYXJpYWJsZXMgPSBhc3luYyAoZmlsZURhdGE6IGFueSwgZmlsZVByaW9yaXR5OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW2dsb2JhbEtleSwgZ2xvYmFsRW50cnldIG9mIE9iamVjdC5lbnRyaWVzKGZpbGVEYXRhPy5nbG9iYWwgPz8ge30pKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgYWRkVG9WYXJpYWJsZXMoZ2xvYmFsS2V5LCBnbG9iYWxFbnRyeSwgMSArIGZpbGVQcmlvcml0eSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGdyb3VwVXJsID0gYCR7Z2l0RGF0YS5yZW1vdGUuaG9zdH0vJHtnaXREYXRhLnJlbW90ZS5ncm91cH0vYDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW2dyb3VwS2V5LCBncm91cEVudHJpZXNdIG9mIE9iamVjdC5lbnRyaWVzKGZpbGVEYXRhPy5ncm91cCA/PyB7fSkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWdyb3VwVXJsLmluY2x1ZGVzKHRoaXMubm9ybWFsaXplUHJvamVjdEtleShncm91cEtleSwgd3JpdGVTdHJlYW1zKSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGFzc2VydChncm91cEVudHJpZXMgIT0gbnVsbCwgXCJncm91cEVudHJpZXMgY2Fubm90IGJlIG51bGwvdW5kZWZpbmVkXCIpO1xuICAgICAgICAgICAgICAgIGFzc2VydChVdGlscy5pc09iamVjdChncm91cEVudHJpZXMpLCBcImdyb3VwIGVudHJpZXMgaW4gdmFyaWFibGUgZmlsZXMgbXVzdCBiZSBhbiBvYmplY3RcIik7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMoZ3JvdXBFbnRyaWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBhZGRUb1ZhcmlhYmxlcyhrLCB2LCAyICsgZmlsZVByaW9yaXR5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHByb2plY3RVcmwgPSBgJHtnaXREYXRhLnJlbW90ZS5ob3N0fS8ke2dpdERhdGEucmVtb3RlLmdyb3VwfS8ke2dpdERhdGEucmVtb3RlLnByb2plY3R9LmdpdGA7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtwcm9qZWN0S2V5LCBwcm9qZWN0RW50cmllc10gb2YgT2JqZWN0LmVudHJpZXMoZmlsZURhdGE/LnByb2plY3QgPz8gW10pKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFwcm9qZWN0VXJsLmluY2x1ZGVzKHRoaXMubm9ybWFsaXplUHJvamVjdEtleShwcm9qZWN0S2V5LCB3cml0ZVN0cmVhbXMpKSkgY29udGludWU7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KHByb2plY3RFbnRyaWVzICE9IG51bGwsIFwicHJvamVjdEVudHJpZXMgY2Fubm90IGJlIG51bGwvdW5kZWZpbmVkXCIpO1xuICAgICAgICAgICAgICAgIGFzc2VydChVdGlscy5pc09iamVjdChwcm9qZWN0RW50cmllcyksIFwicHJvamVjdCBlbnRyaWVzIGluIHZhcmlhYmxlIGZpbGVzIG11c3QgYmUgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHByb2plY3RFbnRyaWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBhZGRUb1ZhcmlhYmxlcyhrLCB2LCAzICsgZmlsZVByaW9yaXR5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgYWRkVmFyaWFibGVGaWxlVG9WYXJpYWJsZXMocmVtb3RlRmlsZURhdGEsIDApO1xuICAgICAgICBhd2FpdCBhZGRWYXJpYWJsZUZpbGVUb1ZhcmlhYmxlcyhob21lRmlsZURhdGEsIDEwKTtcblxuICAgICAgICBjb25zdCBwcm9qZWN0VmFyaWFibGVzRmlsZSA9IGAke2FyZ3YuY3dkfS8ke2FyZ3YudmFyaWFibGVzRmlsZX1gO1xuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhwcm9qZWN0VmFyaWFibGVzRmlsZSkpIHtcbiAgICAgICAgICAgIGxldCBpc0RvdEVudkZvcm1hdCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgcHJvamVjdFZhcmlhYmxlc0ZpbGVSYXdDb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUocHJvamVjdFZhcmlhYmxlc0ZpbGUsIFwidXRmOFwiKTtcbiAgICAgICAgICAgIGxldCBwcm9qZWN0VmFyaWFibGVzRmlsZURhdGE7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHByb2plY3RWYXJpYWJsZXNGaWxlRGF0YSA9IHlhbWwubG9hZChwcm9qZWN0VmFyaWFibGVzRmlsZVJhd0NvbnRlbnQsIHtzY2hlbWE6IHlhbWwuRkFJTFNBRkVfU0NIRU1BfSkgPz8ge307XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mKHByb2plY3RWYXJpYWJsZXNGaWxlRGF0YSkgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNEb3RFbnZGb3JtYXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBwcm9qZWN0VmFyaWFibGVzRmlsZURhdGEgPSBkb3RlbnYucGFyc2UocHJvamVjdFZhcmlhYmxlc0ZpbGVSYXdDb250ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiB5YW1sLllBTUxFeGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgaXNEb3RFbnZGb3JtYXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBwcm9qZWN0VmFyaWFibGVzRmlsZURhdGEgPSBkb3RlbnYucGFyc2UocHJvamVjdFZhcmlhYmxlc0ZpbGVSYXdDb250ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhc3NlcnQocHJvamVjdFZhcmlhYmxlc0ZpbGVEYXRhICE9IG51bGwsIFwicHJvamVjdEVudHJpZXMgY2Fubm90IGJlIG51bGwvdW5kZWZpbmVkXCIpO1xuICAgICAgICAgICAgYXNzZXJ0KFV0aWxzLmlzT2JqZWN0KHByb2plY3RWYXJpYWJsZXNGaWxlRGF0YSksIGAke2FyZ3YuY3dkfS8uZ2l0bGFiLWNpLWxvY2FsLXZhcmlhYmxlcy55bWwgbXVzdCBjb250YWluIGFuIG9iamVjdGApO1xuICAgICAgICAgICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMocHJvamVjdFZhcmlhYmxlc0ZpbGVEYXRhKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGFkZFRvVmFyaWFibGVzKGssIHYsIDI0LCBpc0RvdEVudkZvcm1hdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IHZhck9iaiBvZiBPYmplY3QudmFsdWVzKHZhcmlhYmxlcykpIHtcbiAgICAgICAgICAgIHZhck9iai5lbnZpcm9ubWVudHMuc29ydCgoYSwgYikgPT4gYi5zY29wZVByaW9yaXR5IC0gYS5zY29wZVByaW9yaXR5KTtcbiAgICAgICAgICAgIHZhck9iai5lbnZpcm9ubWVudHMuc29ydCgoYSwgYikgPT4gYi5yZWdleHBQcmlvcml0eSAtIGEucmVnZXhwUHJpb3JpdHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHZhcmlhYmxlcztcbiAgICB9XG5cbiAgICBzdGF0aWMgbm9ybWFsaXplUHJvamVjdEtleSAoa2V5OiBzdHJpbmcsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCFrZXkuaW5jbHVkZXMoXCI6XCIpKSByZXR1cm4ga2V5O1xuICAgICAgICB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYHt5ZWxsb3cgV0FSTklORzogSW50ZXJwcmV0aW5nICcke2tleX0nIGFzICcke2tleS5yZXBsYWNlKFwiOlwiLCBcIi9cIil9J31cXG5gKTtcbiAgICAgICAgcmV0dXJuIGtleS5yZXBsYWNlKFwiOlwiLCBcIi9cIik7XG4gICAgfVxufVxuIl19