UNPKG

singularci

Version:

SingularCI is a DSL transpiler used to generate CI/CD configuration files for existing CI platforms

187 lines 9.01 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GitHubConfigGenerator = void 0; const yaml_1 = __importDefault(require("yaml")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const tasks_1 = require("./tasks"); const typedi_1 = require("typedi"); const DSLParser_1 = __importDefault(require("./../../Parser/DSLParser")); const TaskEnum_1 = require("../../SemanticModel/Tasks/TaskEnum"); let GitHubConfigGenerator = class GitHubConfigGenerator { constructor(parser) { this.generateConfig = () => { if (!this.shouldGenerate()) return; this.pipeline = this.parser.parse(); // Generate Folders and files this.createFolderStructure(); this.buildSecrets(); this.buildTriggers(); this.buildStages(); this.writeToFile(); }; this.writeToFile = () => { fs_1.default.writeFileSync(path_1.default.join(process.cwd(), ".github/workflows/workflow.yml"), yaml_1.default.stringify(this.configObject), "utf-8"); }; this.createFolderStructure = () => { if (fs_1.default.existsSync(path_1.default.join(process.cwd(), ".github"))) { fs_1.default.rmSync(path_1.default.join(process.cwd(), ".github"), { recursive: true }); } fs_1.default.mkdirSync(path_1.default.join(process.cwd(), ".github")); fs_1.default.mkdirSync(path_1.default.join(process.cwd(), ".github/workflows")); fs_1.default.writeFileSync(path_1.default.join(process.cwd(), ".github/workflows/workflow.yml"), "", "utf-8"); }; this.buildTriggers = () => { const isPushSet = this.pipeline.getTrigger().getTypes().includes('push'); const isPullRequestSet = this.pipeline.getTrigger().getTypes().includes('pull_request'); const onObject = {}; const triggerObject = { on: onObject }; if (isPushSet) { const pushObject = { branches: [...this.pipeline.getTrigger().getBranches()] }; triggerObject.on.push = pushObject; } if (isPullRequestSet) { const pullRequestObject = { branches: [...this.pipeline.getTrigger().getBranches()] }; triggerObject.on.pull_request = pullRequestObject; } Object.assign(this.configObject, triggerObject); }; this.buildSecrets = () => { this.pipeline = this.changeSecretsSyntax(this.pipeline); }; this.changeSecretsSyntax = (obj) => { if (typeof obj === 'object') { // iterating over the object using for..in for (const key in obj) { //checking if the current value is an object itself if (typeof obj[key] === 'object') { // if so then again calling the same function this.changeSecretsSyntax(obj[key]); } else { // else getting the value and replacing single { with {{ and so on if (obj[key] !== undefined && isNaN(obj[key])) { const secrets = obj[key].match(/\$\{(secrets\.)[a-zA-Z][^{}]+\}/gm); if (secrets) { for (let i = 0; i < secrets.length; i++) { const newValue = obj[key].replace(secrets[i], "${{ " + secrets[i].replace("${", "").replace("}", "") + " }}"); obj[key] = newValue; } } } } } } return obj; }; this.buildStages = () => { const StagesArray = {}; const stagesObject = { jobs: StagesArray }; for (const stage of this.pipeline.getStages()) { const builtStage = this.buildStage(stage); const stageId = this.generateStageId(this.sanitizeJobName(stage.getName())); stagesObject.jobs[stageId] = builtStage; } Object.assign(this.configObject, stagesObject); }; this.generateStageId = (name) => { const str = "" + name; return str.replace(' ', '_').toLowerCase(); }; this.buildStage = (stage) => { const stageObject = { steps: this.buildJobs(stage.getJobs()) }; Object.assign(stageObject, this.setRuntimeContainer(stage)); if (stage.getNeeds().length > 0) { stageObject.needs = stage.getNeeds(); } return stageObject; }; this.buildJobs = (jobs) => { const resultArr = []; for (const job of jobs) { const tasks = job.getTasks(); const checkoutTasks = tasks.filter((task) => task.getType() === TaskEnum_1.TaskType.Checkout); let checkoutRepoName = ""; if (checkoutTasks.length > 1) { throw new Error("Only one checkout is allowed per job"); } if (checkoutTasks.length === 1) { checkoutRepoName = checkoutTasks[0].getRepositoryName(); } for (const task of tasks) { const tempTasks = []; if (task.getType() === TaskEnum_1.TaskType.BuildDockerImage) { tempTasks.push(...(0, tasks_1.generateBuildDockerImageTask)(task)); } if (task.getType() === TaskEnum_1.TaskType.Checkout) { tempTasks.push((0, tasks_1.generateCheckoutTask)(task)); } if (task.getType() === TaskEnum_1.TaskType.Run) { const tempObj = (0, tasks_1.generateRunTask)(task); if (checkoutRepoName) { // @ts-ignore tempObj["working-directory"] = checkoutRepoName; } tempTasks.push(tempObj); } if (task.getType() === TaskEnum_1.TaskType.Checkout) { resultArr.unshift(...tempTasks); } else { resultArr.push(...tempTasks); } } } return resultArr; }; this.setRuntimeContainer = (stage) => { const runsOn = stage.getRunsOn(); if (runsOn != "ubuntu-latest" && runsOn != "windows-latest") { return { 'runs-on': "ubuntu-latest", 'container': runsOn }; } return { 'runs-on': runsOn }; }; this.sanitizeJobName = (name) => { return name.replaceAll(' ', '_'); }; this.parser = parser; this.pipeline = parser.parse(); this.configObject = {}; } shouldGenerate() { return this.pipeline != undefined && this.pipeline.getPlatformTargets().getTargets().includes('GitHub'); } }; GitHubConfigGenerator = __decorate([ (0, typedi_1.Service)({ id: "GitHubConfigGenerator" }), __param(0, (0, typedi_1.Inject)('dslparser')), __metadata("design:paramtypes", [DSLParser_1.default]) ], GitHubConfigGenerator); exports.GitHubConfigGenerator = GitHubConfigGenerator; //# sourceMappingURL=index.js.map