UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

269 lines 12.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.mergeOptions = exports.getGoalDefinitionFrom = exports.goal = exports.GoalWithFulfillment = exports.FulfillableGoalWithRegistrationsAndListeners = exports.FulfillableGoalWithRegistrations = exports.FulfillableGoal = exports.isSideEffect = exports.isImplementation = void 0; const configuration_1 = require("@atomist/automation-client/lib/configuration"); const _ = require("lodash"); const sdmGoal_1 = require("../../api-helper/goal/sdmGoal"); const logInterpreters_1 = require("../../api-helper/log/logInterpreters"); const Registerable_1 = require("../machine/Registerable"); const commonPushTests_1 = require("../mapping/support/commonPushTests"); const ServiceRegistration_1 = require("../registration/ServiceRegistration"); const createGoal_1 = require("./common/createGoal"); const Goal_1 = require("./Goal"); const GoalNameGenerator_1 = require("./GoalNameGenerator"); const environment_1 = require("./support/environment"); function isImplementation(f) { return !!f && !!f.goalExecutor && true; } exports.isImplementation = isImplementation; function isSideEffect(f) { return !isImplementation(f); } exports.isSideEffect = isSideEffect; /** * Goal that registers goal implementations, side effects and callbacks on the * current SDM. No additional registration with the SDM is needed. */ class FulfillableGoal extends Goal_1.GoalWithPrecondition { constructor(definitionOrGoal, ...dependsOn) { super(Goal_1.isGoalDefinition(definitionOrGoal) ? definitionOrGoal : definitionOrGoal.definition, ...dependsOn); this.definitionOrGoal = definitionOrGoal; this.fulfillments = []; this.callbacks = []; this.projectListeners = []; this.goalListeners = []; Registerable_1.registerRegistrable(this); } register(sdm) { this.sdm = sdm; this.fulfillments.forEach(f => this.registerFulfillment(f)); this.callbacks.forEach(cb => this.registerCallback(cb)); this.goalListeners.forEach(gl => sdm.addGoalExecutionListener(gl)); } withProjectListener(listener) { this.projectListeners.push(listener); return this; } withExecutionListener(listener) { const wrappedListener = async (gi) => { if (gi.goalEvent.uniqueName === this.uniqueName) { return listener(gi); } }; if (this.sdm) { this.sdm.addGoalExecutionListener(wrappedListener); } this.goalListeners.push(wrappedListener); return this; } withService(registration) { this.addFulfillmentCallback({ goal: this, callback: async (goalEvent, repoContext) => { const service = await registration.service(goalEvent, repoContext); if (!!service) { const data = sdmGoal_1.goalData(goalEvent); const servicesData = {}; _.set(servicesData, `${ServiceRegistration_1.ServiceRegistrationGoalDataKey}.${registration.name}`, service); goalEvent.data = JSON.stringify(_.merge(data, servicesData)); } return goalEvent; }, }); return this; } addFulfillmentCallback(cb) { if (this.sdm) { this.registerCallback(cb); } this.callbacks.push(cb); return this; } addFulfillment(fulfillment) { if (this.sdm) { this.registerFulfillment(fulfillment); } this.fulfillments.push(fulfillment); return this; } registerFulfillment(fulfillment) { if (isImplementation(fulfillment)) { let goalExecutor = fulfillment.goalExecutor; // Wrap the ExecuteGoal instance with WaitRules if provided if (Goal_1.isGoalDefinition(this.definitionOrGoal) && !!this.definitionOrGoal.preCondition) { goalExecutor = createGoal_1.createPredicatedGoalExecutor(this.definitionOrGoal.uniqueName, goalExecutor, this.definitionOrGoal.preCondition); } if (Goal_1.isGoalDefinition(this.definitionOrGoal) && !!this.definitionOrGoal.retryCondition) { goalExecutor = createGoal_1.createRetryingGoalExecutor(this.definitionOrGoal.uniqueName, goalExecutor, this.definitionOrGoal.retryCondition); } this.sdm.addGoalImplementation(fulfillment.name, this, goalExecutor, { pushTest: fulfillment.pushTest || commonPushTests_1.AnyPush, progressReporter: fulfillment.progressReporter, logInterpreter: fulfillment.logInterpreter, projectListeners: this.projectListeners, }); } else if (isSideEffect(fulfillment)) { this.sdm.addGoalSideEffect(this, fulfillment.name, fulfillment.registration, fulfillment.pushTest); } } async plan(pli, goals) { return undefined; } registerCallback(cb) { this.sdm.goalFulfillmentMapper.addFulfillmentCallback(cb); } } exports.FulfillableGoal = FulfillableGoal; /** * Goal that accepts registrations of R. */ class FulfillableGoalWithRegistrations extends FulfillableGoal { constructor(definitionOrGoal, ...dependsOn) { super(definitionOrGoal, ...dependsOn); this.definitionOrGoal = definitionOrGoal; this.registrations = []; } with(registration) { this.registrations.push(registration); return this; } } exports.FulfillableGoalWithRegistrations = FulfillableGoalWithRegistrations; /** * Goal that accepts registrations of R and listeners of L. */ class FulfillableGoalWithRegistrationsAndListeners extends FulfillableGoalWithRegistrations { constructor(definitionOrGoal, ...dependsOn) { super(definitionOrGoal, ...dependsOn); this.definitionOrGoal = definitionOrGoal; this.listeners = []; } withListener(listener) { this.listeners.push(listener); return this; } } exports.FulfillableGoalWithRegistrationsAndListeners = FulfillableGoalWithRegistrationsAndListeners; /** * Generic goal that can be used with a GoalDefinition. * Register goal implementations or side effects to this goal instance. */ class GoalWithFulfillment extends FulfillableGoal { withCallback(cb) { this.addFulfillmentCallback(cb); return this; } with(fulfillment) { this.addFulfillment(fulfillment); return this; } } exports.GoalWithFulfillment = GoalWithFulfillment; /** * Creates a new GoalWithFulfillment instance using conventions if overwrites aren't provided * * Call this from your machine.ts where you configure your sdm to create a custom goal. * * Caution: if you wrap this in another function, then you MUST provide details.uniqueName, * because the default is based on where in the code this `goal` function is called. * * @param details It is highly recommended that you supply at least uniqueName. * @param goalExecutor * @param options */ function goal(details = {}, goalExecutor, options) { const def = getGoalDefinitionFrom(details, GoalNameGenerator_1.DefaultGoalNameGenerator.generateName(details.displayName || "goal")); const g = new GoalWithFulfillment(def); if (!!goalExecutor) { const optsToUse = Object.assign({ pushTest: commonPushTests_1.AnyPush, logInterpreter: logInterpreters_1.LogSuppressor }, (!!options ? options : {})); g.with(Object.assign({ name: def.uniqueName, goalExecutor }, optsToUse)); if (!!optsToUse.plan) { g.plan = optsToUse.plan; } } return g; } exports.goal = goal; /** * Construct a PredicatedGoalDefinition from the provided goalDetails * @param goalDetails * @param uniqueName * @param definition */ // tslint:disable:cyclomatic-complexity function getGoalDefinitionFrom(goalDetails, uniqueName, definition) { if (typeof goalDetails === "string") { return Object.assign(Object.assign({}, (definition || {})), { uniqueName: goalDetails || uniqueName }); } else { const defaultDefinition = Object.assign({}, (definition || {})); const goalDetailsToUse = goalDetails || {}; if (!!goalDetailsToUse.descriptions) { defaultDefinition.canceledDescription = goalDetailsToUse.descriptions.canceled || defaultDefinition.canceledDescription; defaultDefinition.completedDescription = goalDetailsToUse.descriptions.completed || defaultDefinition.completedDescription; defaultDefinition.failedDescription = goalDetailsToUse.descriptions.failed || defaultDefinition.failedDescription; defaultDefinition.plannedDescription = goalDetailsToUse.descriptions.planned || defaultDefinition.plannedDescription; defaultDefinition.requestedDescription = goalDetailsToUse.descriptions.requested || defaultDefinition.requestedDescription; defaultDefinition.stoppedDescription = goalDetailsToUse.descriptions.stopped || defaultDefinition.stoppedDescription; defaultDefinition.waitingForApprovalDescription = goalDetailsToUse.descriptions.waitingForApproval || defaultDefinition.waitingForApprovalDescription; defaultDefinition.waitingForPreApprovalDescription = goalDetailsToUse.descriptions.waitingForPreApproval || defaultDefinition.waitingForPreApprovalDescription; defaultDefinition.workingDescription = goalDetailsToUse.descriptions.inProcess || defaultDefinition.workingDescription; } return Object.assign(Object.assign({}, defaultDefinition), { displayName: goalDetailsToUse.displayName || defaultDefinition.displayName, uniqueName: goalDetailsToUse.uniqueName || uniqueName, environment: getEnvironment(goalDetailsToUse), approvalRequired: goalDetailsToUse.approval || defaultDefinition.approvalRequired, preApprovalRequired: goalDetailsToUse.preApproval || defaultDefinition.preApprovalRequired, retryFeasible: goalDetailsToUse.retry || defaultDefinition.retryFeasible, isolated: goalDetailsToUse.isolate || defaultDefinition.isolated, preCondition: goalDetailsToUse.preCondition }); } } exports.getGoalDefinitionFrom = getGoalDefinitionFrom; /** * Merge Goal configuration options into a final options object. * Starts off by merging the explicitly provided options over the provided defaults; finally merges the configuration * values at the given configuration path (prefixed with sdm.) over the previous merge. * @param defaults * @param explicit * @param configurationPath */ function mergeOptions(defaults, explicit, configurationPath) { const options = _.merge(_.cloneDeep(defaults), explicit || {}); if (!!configurationPath) { const configurationOptions = configuration_1.configurationValue(`sdm.${configurationPath}`, {}); return _.merge(options, configurationOptions); } return options; } exports.mergeOptions = mergeOptions; function getEnvironment(details) { if (details && details.environment && typeof details.environment === "string") { switch (details.environment) { case "testing": return environment_1.StagingEnvironment; case "production": return environment_1.ProductionEnvironment; default: return environment_1.IndependentOfEnvironment; } } else if (details && typeof details.environment !== "string") { return details.environment; } else { return environment_1.IndependentOfEnvironment; } } //# sourceMappingURL=GoalWithFulfillment.js.map