UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

245 lines 10.3 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.configureYaml = exports.Target = void 0; const configuration_1 = require("@atomist/automation-client/lib/configuration"); const changeCase = require("change-case"); const fg = require("fast-glob"); const fs = require("fs-extra"); const yaml = require("js-yaml"); const stringify = require("json-stringify-safe"); const _ = require("lodash"); const path = require("path"); const trace = require("stack-trace"); const github_1 = require("../../../pack/github-goal-status/github"); const goalState_1 = require("../../../pack/goal-state/goalState"); const array_1 = require("../../util/misc/array"); const configure_1 = require("../configure"); const mapCommand_1 = require("./mapCommand"); const mapGoals_1 = require("./mapGoals"); const mapRules_1 = require("./mapRules"); const util_1 = require("./util"); var Target; (function (Target) { Target["SDM"] = "sdm"; Target["Skill"] = "skill"; })(Target = exports.Target || (exports.Target = {})); async function createExtensions(cwd, options, cfg, sdm) { var _a, _b, _c, _d, _e, _f; const commandCallback = async (c, k) => { let registration; try { const makerResult = await c(sdm); registration = Object.assign({ name: k }, makerResult); } catch (e) { e.message = `Failed to make command using CommandMaker ${k}: ${e.message}`; throw e; } try { sdm.addCommand(registration); } catch (e) { e.message = `Failed to add command ${k} '${stringify(registration)}': ${e.message}`; throw e; } }; if (!((_a = options === null || options === void 0 ? void 0 : options.makers) === null || _a === void 0 ? void 0 : _a.commands)) { await awaitIterable(await requireCommands(cwd, (_b = options === null || options === void 0 ? void 0 : options.patterns) === null || _b === void 0 ? void 0 : _b.commands), commandCallback); } else { await awaitIterable(options.makers.commands, commandCallback); } const eventCallback = async (e, k) => { let registration; try { const makerResult = await e(sdm); registration = Object.assign({ name: k }, makerResult); } catch (e) { e.message = `Failed to make event using EventMaker ${k}: ${e.message}`; throw e; } try { sdm.addEvent(registration); } catch (e) { e.message = `Failed to add event ${k} '${stringify(registration)}': ${e.message}`; throw e; } }; if (!((_c = options.makers) === null || _c === void 0 ? void 0 : _c.events)) { await awaitIterable(await requireEvents(cwd, (_d = options === null || options === void 0 ? void 0 : options.patterns) === null || _d === void 0 ? void 0 : _d.events), eventCallback); } else { await awaitIterable(options.makers.events, eventCallback); } await requireIngesters(cwd, (_e = options === null || options === void 0 ? void 0 : options.patterns) === null || _e === void 0 ? void 0 : _e.ingesters); sdm.addExtensionPacks(...(((_f = sdm.configuration.sdm) === null || _f === void 0 ? void 0 : _f.extensionPacks) || [ goalState_1.goalStateSupport({ cancellation: { enabled: true, }, }), github_1.githubGoalStatusSupport(), ])); } /** * Load one or more yaml files to create goal sets * * When providing more than one yaml file, files are being loaded * in provided order with later files overwriting earlier ones. */ async function configureYaml(patterns, options = {}) { // Get the caller of this function to determine the cwd for resolving glob patterns const callerCallSite = trace .get() .filter(t => t.getFileName() !== __filename) .filter(t => !!t.getFileName())[0]; const cwd = options.cwd || path.dirname(callerCallSite.getFileName()); const cfg = await createConfiguration(cwd, options); return configure_1.configure(async (sdm) => { let sdmToUse = sdm; if (options.target === Target.Skill) { sdmToUse = mapCommand_1.decorateSoftwareDeliveryMachine(sdm); } await createExtensions(cwd, options, cfg, sdmToUse); return createGoalData(patterns, cwd, options, cfg, sdmToUse); }, options.options || {}); } exports.configureYaml = configureYaml; async function createConfiguration(cwd, options) { var _a, _b; const cfg = {}; if (!((_a = options === null || options === void 0 ? void 0 : options.makers) === null || _a === void 0 ? void 0 : _a.configurations)) { await awaitIterable(await requireConfiguration(cwd, (_b = options === null || options === void 0 ? void 0 : options.patterns) === null || _b === void 0 ? void 0 : _b.configurations), async (v) => { const c = await v(cfg); configuration_1.deepMergeConfigs(cfg, c); }); } else { await awaitIterable(options.makers.configurations, async (v) => { const c = await v(cfg); configuration_1.deepMergeConfigs(cfg, c); }); } _.update(options, "options.preProcessors", old => (!!old ? old : [])); options.options.preProcessors = [ async (c) => configuration_1.deepMergeConfigs(c, cfg), ...array_1.toArray(options.options.preProcessors), ]; return cfg; } // tslint:disable-next-line:cyclomatic-complexity async function createGoalData(patterns, cwd, options, cfg, sdm) { var _a, _b; const additionalGoals = options.goals ? await sdm.createGoals(options.goals, options.configurers) : {}; const goalMakers = !!((_a = options.makers) === null || _a === void 0 ? void 0 : _a.goals) ? options.makers.goals : await requireGoals(cwd, _.get(cfg, "extensions.goals")); const testMakers = !!((_b = options.makers) === null || _b === void 0 ? void 0 : _b.tests) ? options.makers.tests : await requireTests(cwd, _.get(cfg, "extensions.tests")); const files = await resolvePaths(cwd, patterns, true); const goalData = {}; for (const file of files) { const configs = yaml.safeLoadAll(await fs.readFile(path.join(cwd, file), { encoding: "UTF-8" })); for (const config of configs) { if (!!config.configuration) { _.merge(sdm.configuration, util_1.camelCase(config.configuration)); } if (!!config.skill) { _.merge(sdm.configuration, util_1.camelCase(config.skill)); sdm.configuration.name = config.skill.name; sdm.name = config.skill.title || config.skill.name; } for (const k in config) { if (config.hasOwnProperty(k)) { const value = config[k]; // Ignore two special keys used to set up the SDM if (k === "name" || k === "configuration" || k === "skill") { continue; } // Just create goals and register with SDM if (k === "goals") { await mapGoals_1.mapGoals(sdm, util_1.camelCase(value), additionalGoals, goalMakers, options.tests || {}, testMakers); } if (k === "rules") { await mapRules_1.mapRules(value, goalData, sdm, options, additionalGoals, goalMakers, testMakers); } } } } } return goalData; } async function requireExtensions(cwd, pattern, cb = () => { }) { if (pattern.length === 0) { return {}; } const extensions = {}; const files = await resolvePaths(cwd, pattern); for (const file of files) { const testJs = require(`${cwd}/${file}`); _.forEach(testJs, (v, k) => { if (!!cb) { cb(v, k, extensions); } extensions[k] = v; }); } return extensions; } async function requireTests(cwd, pattern = ["tests/**.js", "lib/tests/**.js"]) { return requireExtensions(cwd, pattern, (v, k, e) => (e[changeCase.snake(k)] = v)); } async function requireGoals(cwd, pattern = ["goals/**.js", "lib/goals/**.js"]) { return requireExtensions(cwd, pattern, (v, k, e) => (e[changeCase.snake(k)] = v)); } async function requireCommands(cwd, pattern = ["commands/**.js", "lib/commands/**.js"]) { return requireExtensions(cwd, pattern); } async function requireEvents(cwd, pattern = ["events/**.js", "lib/events/**.js"]) { return requireExtensions(cwd, pattern); } async function requireConfiguration(cwd, pattern = ["config.js", "lib/config.js"]) { return requireExtensions(cwd, pattern); } async function requireIngesters(cwd, pattern = ["ingesters/**.graphql", "lib/graphql/ingester/**.graphql"]) { const ingesters = []; const files = await resolvePaths(cwd, pattern); for (const file of files) { ingesters.push((await fs.readFile(file)).toString()); } return ingesters; } async function awaitIterable(elems, cb) { for (const k in elems) { if (elems.hasOwnProperty(k)) { const v = elems[k]; await cb(v, k); } } } async function resolvePaths(cwd, patterns, watch = false) { const paths = await fg(array_1.toArray(patterns), { ignore: [`**/{.git,node_modules}/**`], cwd }); if (watch) { util_1.watchPaths(paths); } return paths; } //# sourceMappingURL=configureYaml.js.map