UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

191 lines 8.35 kB
"use strict"; /* * Copyright © 2020 Atomist, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.RepositoryDrivenContainer = exports.repositoryDrivenContainer = exports.hasRepositoryGoals = void 0; const configuration_1 = require("@atomist/automation-client/lib/configuration"); const camelcaseKeys = require("camelcase-keys"); const yaml = require("js-yaml"); const _ = require("lodash"); const os = require("os"); const Goal_1 = require("../../../api/goal/Goal"); const GoalInvocation_1 = require("../../../api/goal/GoalInvocation"); const GoalNameGenerator_1 = require("../../../api/goal/GoalNameGenerator"); const GoalWithFulfillment_1 = require("../../../api/goal/GoalWithFulfillment"); const PushTest_1 = require("../../../api/mapping/PushTest"); const pushTestUtils_1 = require("../../../api/mapping/support/pushTestUtils"); const mapPushTests_1 = require("../../machine/yaml/mapPushTests"); const array_1 = require("../../util/misc/array"); const goalCaching_1 = require("../cache/goalCaching"); const container_1 = require("./container"); const docker_1 = require("./docker"); exports.hasRepositoryGoals = PushTest_1.pushTest("has SDM goals", async (pli) => { return (await pli.project.getFiles(".atomist/*goals.{yml,yaml}")).length > 0; }); function repositoryDrivenContainer(options = {}) { return new RepositoryDrivenContainer(options.tests || {}); } exports.repositoryDrivenContainer = repositoryDrivenContainer; class RepositoryDrivenContainer extends GoalWithFulfillment_1.FulfillableGoal { constructor(tests) { super({ uniqueName: "repository-driven-goal" }); this.tests = tests; this.addFulfillment({ progressReporter: container_1.ContainerProgressReporter, goalExecutor: async (gi) => { const registration = gi.parameters.registration; const c = new container_1.Container({ displayName: this.definition.displayName }); c.register = () => { }; c.addFulfillment = () => c; c.addFulfillmentCallback = () => c; c.withProjectListener = () => c; c.with(registration); return docker_1.executeDockerJob(c, registration)(gi); }, name: GoalNameGenerator_1.DefaultGoalNameGenerator.generateName(`container-docker-${this.definition.displayName}`), }); this.withProjectListener({ name: "cache-restore", events: [GoalInvocation_1.GoalProjectListenerEvent.before], listener: async (p, gi, e) => { const registration = gi.parameters.registration; if (registration.input && registration.input.length > 0) { await goalCaching_1.cacheRestore({ entries: registration.input }).listener(p, gi, e); } }, }).withProjectListener({ name: "cache-put", events: [GoalInvocation_1.GoalProjectListenerEvent.after], listener: async (p, gi, e) => { const registration = gi.parameters.registration; if (registration.output && registration.output.length > 0) { await goalCaching_1.cachePut({ entries: registration.output }).listener(p, gi, e); } }, }); } async plan(pli, goals) { const configYamls = (await pli.project.getFiles(".atomist/*goals.{yml,yaml}")) .sort((f1, f2) => f1.path.localeCompare(f2.path)); const plan = {}; for (const configYaml of configYamls) { const configs = yaml.safeLoadAll(await configYaml.getContent()); for (const config of configs) { for (const k in config) { if (config.hasOwnProperty(k)) { const value = config[k]; const v = camelcaseKeys(value, { deep: true }); const test = pushTestUtils_1.and(...array_1.toArray(await mapPushTests_1.mapTests(v.test, this.tests, {}))); if (await test.mapping(pli)) { const plannedGoals = array_1.toArray(mapGoals(v.goals, {})); plan[k] = { goals: plannedGoals, dependsOn: v.dependsOn, }; } } } } } await configuration_1.resolvePlaceholders(plan, value => resolvePlaceholder(value, pli)); return plan; } } exports.RepositoryDrivenContainer = RepositoryDrivenContainer; function mapGoals(goals, additionalGoals) { if (Array.isArray(goals)) { return array_1.toArray(goals).map(g => mapGoals(g, additionalGoals)); } else { if (!!goals.containers) { const name = _.get(goals, "containers.name") || _.get(goals, "containers[0].name"); return mapPlannedGoal(name, goals, array_1.toArray(goals.containers), array_1.toArray(goals.volumes)); } else if (!!goals.script) { const script = goals.script; return mapPlannedGoal(script.name, script, [{ name: script.name, image: script.image || "ubuntu:latest", command: script.command, args: script.args, }], []); } else { throw new Error(`Unable to construct goal from '${JSON.stringify(goals)}'`); } } } function mapPlannedGoal(name, details, containers, volumes) { const gd = new Goal_1.Goal({ uniqueName: name, displayName: name }); return { details: { displayName: gd.definition.displayName, descriptions: { planned: gd.plannedDescription, requested: gd.requestedDescription, inProcess: gd.inProcessDescription, completed: gd.successDescription, failed: gd.failureDescription, canceled: gd.canceledDescription, stopped: gd.stoppedDescription, waitingForApproval: gd.waitingForApprovalDescription, waitingForPreApproval: gd.waitingForPreApprovalDescription, }, retry: details.retry, preApproval: details.preApproval, approval: details.approval, }, parameters: { registration: { containers, volumes, input: details.input, output: details.output, }, }, }; } const PlaceholderExpression = /\$\{([.a-zA-Z_-]+)([.:0-9a-zA-Z-_ \" ]+)*\}/g; async function resolvePlaceholder(value, pli) { if (!PlaceholderExpression.test(value)) { return value; } PlaceholderExpression.lastIndex = 0; let currentValue = value; let result; // tslint:disable-next-line:no-conditional-assignment while (result = PlaceholderExpression.exec(currentValue)) { const fm = result[0]; let envValue = _.get(pli, result[1]); if (result[1] === "home") { envValue = os.userInfo().homedir; } const defaultValue = result[2] ? result[2].trim().slice(1) : undefined; if (envValue) { currentValue = currentValue.split(fm).join(envValue); } else if (defaultValue) { currentValue = currentValue.split(fm).join(defaultValue); } else { throw new Error(`Placeholder '${result[1]}' can't be resolved`); } PlaceholderExpression.lastIndex = 0; } return currentValue; } //# sourceMappingURL=repositoryDrivenContainer.js.map