dryrun-ci
Version:
DryRun CI - Local GitLab CI/CD pipeline testing tool with Docker execution, performance monitoring, and security sandboxing
125 lines (124 loc) • 5.57 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseGitLabYaml = void 0;
const yaml = __importStar(require("js-yaml"));
function parseGitLabYaml(yamlContent) {
try {
const parsed = yaml.load(yamlContent);
if (!parsed || typeof parsed !== 'object') {
throw new Error('Invalid YAML: Root must be an object');
}
// Extract stages
const stages = parsed.stages || ['build', 'test', 'deploy'];
if (!Array.isArray(stages)) {
throw new Error('Invalid YAML: stages must be an array');
}
// Extract global configuration
const globalConfig = {
image: parsed.image,
variables: parsed.variables || {},
before_script: parsed.before_script,
after_script: parsed.after_script,
};
// Extract jobs
const jobs = {};
const reservedKeys = ['stages', 'variables', 'image', 'before_script', 'after_script', 'cache'];
Object.entries(parsed).forEach(([key, value]) => {
if (reservedKeys.includes(key) || key.startsWith('.')) {
return; // Skip reserved keys and hidden jobs
}
if (typeof value !== 'object' || value === null) {
throw new Error(`Invalid job configuration for "${key}": must be an object`);
}
const jobConfig = value;
// Validate job type - GitLab supports different job types
const hasScript = jobConfig.script && Array.isArray(jobConfig.script);
const hasTrigger = jobConfig.trigger;
const hasExtends = jobConfig.extends;
const hasInclude = jobConfig.include;
// At least one of these should be present for a valid job, or it could be a configuration-only job
if (!hasScript && !hasTrigger && !hasExtends && !hasInclude) {
// This might be a configuration-only job (variables, etc.) or inherit from extends
// We'll allow it but ensure it has some meaningful configuration
if (!jobConfig.variables && !jobConfig.before_script && !jobConfig.after_script && !jobConfig.cache && !jobConfig.artifacts) {
console.warn(`Warning: Job "${key}" appears to have minimal configuration`);
}
}
// Validate script if present
if (jobConfig.script && !Array.isArray(jobConfig.script)) {
throw new Error(`Job "${key}": script must be an array`);
}
// Determine stage
let stage = jobConfig.stage;
if (!stage) {
// If no stage specified, use the first stage
stage = stages[0];
}
if (!stages.includes(stage)) {
throw new Error(`Job "${key}": stage "${stage}" is not defined in stages`);
}
// Build job object
const job = {
name: key,
stage,
script: jobConfig.script,
trigger: jobConfig.trigger,
extends: jobConfig.extends,
image: jobConfig.image || globalConfig.image,
before_script: jobConfig.before_script || globalConfig.before_script,
after_script: jobConfig.after_script || globalConfig.after_script,
variables: { ...globalConfig.variables, ...(jobConfig.variables || {}) },
only: jobConfig.only,
except: jobConfig.except,
when: jobConfig.when || 'on_success',
allow_failure: jobConfig.allow_failure || false,
dependencies: jobConfig.dependencies,
needs: jobConfig.needs,
artifacts: jobConfig.artifacts,
cache: jobConfig.cache,
};
jobs[key] = job;
});
if (Object.keys(jobs).length === 0) {
throw new Error('No jobs found in pipeline configuration');
}
return {
stages,
jobs,
variables: globalConfig.variables,
image: globalConfig.image,
before_script: globalConfig.before_script,
after_script: globalConfig.after_script,
};
}
catch (error) {
if (error instanceof yaml.YAMLException) {
throw new Error(`YAML parsing error: ${error.message}`);
}
throw error;
}
}
exports.parseGitLabYaml = parseGitLabYaml;