UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

276 lines 11.5 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.goalSetState = exports.storeGoalSet = exports.constructGoalSet = exports.descriptionFromState = exports.constructProvenance = exports.storeGoal = exports.constructSdmGoal = exports.constructSdmGoalImplementation = exports.goalCorrespondsToSdmGoal = exports.updateGoal = exports.environmentFromGoal = void 0; const GraphClient_1 = require("@atomist/automation-client/lib/spi/graph/GraphClient"); const _ = require("lodash"); const omitEmpty = require("omit-empty"); const sprintf_js_1 = require("sprintf-js"); const Goal_1 = require("../../api/goal/Goal"); const SdmGoalMessage_1 = require("../../api/goal/SdmGoalMessage"); const types_1 = require("../../typings/types"); function environmentFromGoal(goal) { return goal.definition.environment.replace(/\/$/, ""); // remove trailing slash at least } exports.environmentFromGoal = environmentFromGoal; async function updateGoal(ctx, before, params) { const description = params.description; const approval = params.approved ? constructProvenance(ctx) : !!before ? before.approval : undefined; const data = params.data ? params.data : !!before ? before.data : undefined; before.version = (before.version || 1) + 1; const sdmGoal = Object.assign(Object.assign({}, eventToMessage(before)), { state: params.state === "success" && !!before && before.approvalRequired ? types_1.SdmGoalState.waiting_for_approval : params.state, phase: params.phase, description, url: params.url ? params.url : before.url, externalUrls: params.externalUrls ? params.externalUrls : before.externalUrls, approval, ts: Date.now(), provenance: [constructProvenance(ctx)].concat(!!before ? before.provenance : []), error: _.get(params, "error.message"), data, push: cleanPush(before.push), version: before.version }); await storeGoal(ctx, sdmGoal); } exports.updateGoal = updateGoal; function eventToMessage(event) { return Object.assign(Object.assign({}, event), { repo: { name: event.repo.name, owner: event.repo.owner, providerId: event.repo.providerId, }, id: undefined }); } function goalCorrespondsToSdmGoal(goal, sdmGoal) { return goal.name === sdmGoal.name && environmentFromGoal(goal) === sdmGoal.environment; } exports.goalCorrespondsToSdmGoal = goalCorrespondsToSdmGoal; function constructSdmGoalImplementation(gi, registration) { return { method: SdmGoalMessage_1.SdmGoalFulfillmentMethod.Sdm, name: gi.implementationName, registration, }; } exports.constructSdmGoalImplementation = constructSdmGoalImplementation; function constructSdmGoal(ctx, parameters) { const { goalSet, goal, goalSetId, state, id, providerId, url } = parameters; const fulfillment = parameters.fulfillment || { method: SdmGoalMessage_1.SdmGoalFulfillmentMethod.Other, name: "unknown", registration: "unknown", }; if (!id.branch) { throw new Error(sprintf_js_1.sprintf("Please provide a branch in the RemoteRepoRef %j", parameters)); } if (!id.sha) { throw new Error(sprintf_js_1.sprintf("Please provide a sha in the RemoteRepoRef %j", parameters)); } const preConditions = []; const description = descriptionFromState(goal, state); const environment = environmentFromGoal(goal); if (Goal_1.hasPreconditions(goal)) { preConditions.push(...goal.dependsOn.map(d => ({ goalSet, name: d.name, uniqueName: d.uniqueName, environment: environmentFromGoal(d), }))); } const retryFeasible = goal.definition.retryFeasible ? goal.definition.retryFeasible : false; return { goalSet, registration: ctx.context.name, goalSetId, name: goal.name, uniqueName: goal.uniqueName, environment, fulfillment, sha: id.sha, branch: id.branch, repo: { name: id.repo, owner: id.owner, providerId, }, state, description, descriptions: { planned: goal.plannedDescription, requested: goal.requestedDescription, inProcess: goal.inProcessDescription, completed: goal.successDescription, failed: goal.failureDescription, canceled: goal.canceledDescription, stopped: goal.stoppedDescription, skipped: goal.skippedDescription, waitingForApproval: goal.waitingForApprovalDescription, waitingForPreApproval: goal.waitingForPreApprovalDescription, }, url, externalKey: goal.context, ts: Date.now(), approvalRequired: goal.definition.approvalRequired ? goal.definition.approvalRequired : false, preApprovalRequired: goal.definition.preApprovalRequired ? goal.definition.preApprovalRequired : false, retryFeasible, provenance: [constructProvenance(ctx)], preConditions, parameters: !!goal.definition.parameters ? JSON.stringify(goal.definition.parameters) : undefined, version: 1, }; } exports.constructSdmGoal = constructSdmGoal; async function storeGoal(ctx, sdmGoal) { const newGoal = omitEmpty(sdmGoal, { omitZero: false }); delete (newGoal).push; await ctx.graphClient.mutate({ name: "UpdateSdmGoal", variables: { goal: newGoal, }, options: GraphClient_1.MutationNoCacheOptions, }); return sdmGoal; } exports.storeGoal = storeGoal; function constructProvenance(ctx) { return { registration: ctx.context.name, version: ctx.context.version, name: ctx.context.operation, correlationId: ctx.correlationId, ts: Date.now(), }; } exports.constructProvenance = constructProvenance; function descriptionFromState(goal, state, goalEvent) { switch (state) { case types_1.SdmGoalState.planned: return _.get(goalEvent, "descriptions.planned", goal.plannedDescription); case types_1.SdmGoalState.requested: return _.get(goalEvent, "descriptions.requested", goal.requestedDescription); case types_1.SdmGoalState.in_process: return _.get(goalEvent, "descriptions.inProcess", goal.inProcessDescription); case types_1.SdmGoalState.waiting_for_approval: return _.get(goalEvent, "descriptions.waitingForApproval", goal.waitingForApprovalDescription); case types_1.SdmGoalState.waiting_for_pre_approval: return _.get(goalEvent, "descriptions.waitingForPreApproval", goal.waitingForPreApprovalDescription); case types_1.SdmGoalState.success: return _.get(goalEvent, "descriptions.completed", goal.successDescription); case types_1.SdmGoalState.failure: return _.get(goalEvent, "descriptions.failed", goal.failureDescription); case types_1.SdmGoalState.skipped: return _.get(goalEvent, "descriptions.skipped", goal.skippedDescription); case types_1.SdmGoalState.canceled: return _.get(goalEvent, "descriptions.canceled", goal.canceledDescription); case types_1.SdmGoalState.stopped: return _.get(goalEvent, "descriptions.stopped", goal.stoppedDescription); default: throw new Error("Unknown goal state " + state); } } exports.descriptionFromState = descriptionFromState; function constructGoalSet(ctx, goalSetId, goalSet, sdmGoals, tags, push) { let repo; if (!!push) { repo = { name: push.repo.name, owner: push.repo.owner, providerId: push.repo.org.provider.providerId, }; } else if (!!sdmGoals && sdmGoals.length > 0) { const goal = sdmGoals.find(g => !!g.repo); if (!!goal) { repo = { name: goal.repo.name, owner: goal.repo.owner, providerId: goal.repo.providerId, }; } } const sdmGoalSet = { sha: push.after.sha, branch: push.branch, goalSetId, goalSet, ts: Date.now(), repo, state: goalSetState(sdmGoals), goals: sdmGoals.map(g => ({ name: g.name, uniqueName: g.uniqueName, })), provenance: constructProvenance(ctx), tags, }; return sdmGoalSet; } exports.constructGoalSet = constructGoalSet; async function storeGoalSet(ctx, goalSet) { await ctx.graphClient.mutate({ name: "UpdateSdmGoalSet", variables: { goalSet: omitEmpty(goalSet, { omitZero: false }), }, options: GraphClient_1.MutationNoCacheOptions, }); } exports.storeGoalSet = storeGoalSet; function goalSetState(goals) { if (goals.some(g => g.state === types_1.SdmGoalState.failure)) { return types_1.SdmGoalState.failure; } else if (goals.some(g => g.state === types_1.SdmGoalState.canceled)) { return types_1.SdmGoalState.canceled; } else if (goals.some(g => g.state === types_1.SdmGoalState.stopped)) { return types_1.SdmGoalState.stopped; } else if (goals.some(g => g.state === types_1.SdmGoalState.in_process)) { return types_1.SdmGoalState.in_process; } else if (goals.some(g => g.state === types_1.SdmGoalState.waiting_for_pre_approval)) { return types_1.SdmGoalState.waiting_for_pre_approval; } else if (goals.some(g => g.state === types_1.SdmGoalState.waiting_for_approval)) { return types_1.SdmGoalState.waiting_for_approval; } else if (goals.some(g => g.state === types_1.SdmGoalState.pre_approved)) { return types_1.SdmGoalState.pre_approved; } else if (goals.some(g => g.state === types_1.SdmGoalState.approved)) { return types_1.SdmGoalState.approved; } else if (goals.some(g => g.state === types_1.SdmGoalState.requested)) { return types_1.SdmGoalState.requested; } else if (goals.some(g => g.state === types_1.SdmGoalState.planned)) { return types_1.SdmGoalState.planned; } else if (goals.some(g => g.state === types_1.SdmGoalState.skipped)) { return types_1.SdmGoalState.skipped; } else if (goals.every(g => g.state === types_1.SdmGoalState.success)) { return types_1.SdmGoalState.success; } else { const unknowns = goals.filter(g => g.state !== types_1.SdmGoalState.success).map(g => `${g.name}:${g.state}`); throw new Error("Unknown goal state(s): " + JSON.stringify(unknowns)); } } exports.goalSetState = goalSetState; function cleanPush(push) { const newPush = _.cloneDeep(push); if (!!newPush && !!newPush.goals) { delete newPush.goals; } return newPush; } //# sourceMappingURL=storeGoals.js.map