singularci
Version:
SingularCI is a DSL transpiler used to generate CI/CD configuration files for existing CI platforms
195 lines • 8.84 kB
JavaScript
"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.GitLabConfigGenerator = 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 GitLabConfigGenerator = class GitLabConfigGenerator {
constructor(parser) {
this.generateConfig = () => {
if (!this.shouldGenerate())
return;
this.pipeline = this.parser.parse();
this.buildSecrets();
this.buildTriggers();
this.buildStages();
this.buildJobs();
this.writeToFile();
};
this.writeToFile = () => {
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), ".gitlab-ci.yml"), yaml_1.default.stringify(this.configObject), "utf-8");
};
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 braces with empty spaces
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("${secrets.", "").replace("}", "") + "");
obj[key] = newValue;
}
}
}
}
}
}
return obj;
};
this.buildNeeds = (needs) => {
const needsArray = [];
for (let k = 0; k < needs.length; k++) {
const needsName = needs[k];
const neededStage = this.pipeline.getStages().find(stage => stage.getName() === needsName);
if (neededStage) {
const jobs = neededStage.getJobs();
const jobAmount = jobs.length;
for (let l = 0; l < jobAmount; l++) {
const jobName = `${neededStage.getName()}-${this.sanitizeJobName(jobs[l].getName())}`;
needsArray.push(jobName);
}
}
}
return needsArray;
};
this.buildBeforeScript = (tasks) => {
const beforeScriptArray = [];
for (const task of tasks) {
if (task.getType() === TaskEnum_1.TaskType.Checkout) {
beforeScriptArray.push(...(0, tasks_1.generateCheckoutTask)(task));
}
}
return beforeScriptArray;
};
this.buildTasks = (stageKey, jobObject, tasks) => {
const tasksArray = [];
for (const task of tasks) {
if (task.getType() === TaskEnum_1.TaskType.BuildDockerImage) {
jobObject[stageKey].image = "docker:latest";
jobObject[stageKey].services = (0, tasks_1.dockerSetup)();
tasksArray.push(...(0, tasks_1.generateBuildDockerImageTask)(task));
}
if (task.getType() === TaskEnum_1.TaskType.Run) {
tasksArray.push(...(0, tasks_1.generateRunTask)(task));
}
}
return tasksArray;
};
this.sanitizeJobName = (name) => {
return name.replaceAll(' ', '_');
};
this.parser = parser;
this.pipeline = this.parser.parse();
this.configObject = {};
}
shouldGenerate() {
return this.pipeline != undefined && this.pipeline.getPlatformTargets().getTargets().includes('GitLab');
}
buildStages() {
const stagesArray = [];
for (let i = 0; i < this.pipeline.getStages().length; i++) {
const stage = this.pipeline.getStages()[i];
stagesArray.push(stage.getName());
}
this.configObject.stages = stagesArray;
}
buildTriggers() {
const isPushSet = this.pipeline.getTrigger().getTypes().includes('push');
const isPullRequestSet = this.pipeline.getTrigger().getTypes().includes('pull_request');
const rulesObject = [];
const triggerObject = {
workflow: {
rules: rulesObject
}
};
if (isPushSet) {
triggerObject.workflow.rules.push({
if: '$CI_PIPELINE_SOURCE == "push"',
when: 'always'
});
}
if (isPullRequestSet) {
triggerObject.workflow.rules.push({
if: '$CI_PIPELINE_SOURCE == "merge_request_event"',
when: 'always'
});
}
Object.assign(this.configObject, triggerObject);
}
buildSecrets() {
this.pipeline = this.changeSecretsSyntax(this.pipeline);
}
buildJobs() {
const stages = this.pipeline.getStages();
for (let i = 0; i < stages.length; i++) {
const jobs = stages[i].getJobs();
for (let j = 0; j < jobs.length; j++) {
const tasks = jobs[j].getTasks();
const needs = stages[i].getNeeds();
const stage = stages[i];
const stageKey = `${stage.getName()}-${this.sanitizeJobName(jobs[j].getName())}`;
const tasksArray = [];
const needsArray = [];
const beforeScriptArray = [];
const jobObject = {
[stageKey]: {
image: this.getSelectedImage(this.pipeline.getStages()[i]),
stage: this.pipeline.getStages()[i].getName(),
needs: needsArray,
before_script: beforeScriptArray,
script: tasksArray,
}
};
beforeScriptArray.push(...this.buildBeforeScript(tasks));
tasksArray.push(...this.buildTasks(stageKey, jobObject, tasks));
needsArray.push(...this.buildNeeds(needs));
Object.assign(this.configObject, jobObject);
}
}
}
getSelectedImage(stage) {
const runsOn = stage.getRunsOn();
switch (runsOn) {
case "ubuntu-latest":
return "ubuntu:latest";
case "windows-latest":
return "mcr.microsoft.com/windows:20H2";
default:
return runsOn;
}
}
};
GitLabConfigGenerator = __decorate([
(0, typedi_1.Service)({ id: "GitLabConfigGenerator" }),
__param(0, (0, typedi_1.Inject)("dslparser")),
__metadata("design:paramtypes", [DSLParser_1.default])
], GitLabConfigGenerator);
exports.GitLabConfigGenerator = GitLabConfigGenerator;
//# sourceMappingURL=index.js.map