@atomist/sdm
Version:
Atomist Software Delivery Machine SDK
131 lines • 5.51 kB
JavaScript
;
/*
* Copyright © 2019 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.enrichGoalSetters = exports.goalContributors = exports.attachFacts = void 0;
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const _ = require("lodash");
const sha_1 = require("../../api-helper/misc/sha");
const Locking_1 = require("../goal/common/Locking");
const Goals_1 = require("../goal/Goals");
const GoalSetter_1 = require("../mapping/GoalSetter");
const Mapping_1 = require("../mapping/Mapping");
const GoalComponent_1 = require("./GoalComponent");
/**
* Enrich the invocation, attaching some facts.
* The returned object will be merged with any facts already on the invocation.
* @param {(f: (StatefulInvocation<FACT>)) => Promise<FACT>} compute additional facts.
* @return {GoalContribution<F>}
*/
function attachFacts(compute) {
return {
name: "attachFacts-" + sha_1.computeShaOf(compute.toString()),
mapping: async (f) => {
const withAdditionalFact = f;
if (!withAdditionalFact.facts) {
withAdditionalFact.facts = {};
}
const additionalState = await compute(withAdditionalFact);
_.merge(withAdditionalFact.facts, additionalState);
// The GoalContribution itself will be ignored
return undefined;
},
};
}
exports.attachFacts = attachFacts;
/**
* An additive goal setter assembles the goals contributed by all the contributors.
*/
class AdditiveGoalSetter {
constructor(name, contributors) {
this.name = name;
this.contributors = contributors;
}
get label() {
return this.contributors.filter(c => c.label)
.map(c => c.label).join(", ");
}
get structure() {
return {
components: this.contributors.map(vague => Mapping_1.mapMapping(vague, GoalComponent_1.toGoals)),
compositionStyle: GoalSetter_1.GoalSettingCompositionStyle.AllMatches,
};
}
async mapping(p) {
const names = [];
const contributorGoals = [];
for (const c of this.contributors) {
const mapping = await c.mapping(p);
if (mapping) {
const goals = GoalComponent_1.toGoals(mapping);
if (c.label) {
names.push(c.label);
}
else {
names.push(c.name);
}
contributorGoals.push(goals.goals.filter(g => g !== Locking_1.Locking));
// If we find the special locking goal, don't add any further goals
if (goals.goals.includes(Locking_1.Locking)) {
logger_1.logger.debug("Stopping goal contribution analysis, because %s has locked the goal set", c.name);
break;
}
}
}
const uniqueGoals = _.uniq(_.flatten(contributorGoals.filter(x => !!x)));
logger_1.logger.debug("%d contributors (%s): Contributor goal names=[%s]; Unique goal names=[%s]; correlationId=%s", this.contributors.length, this.contributors.map(c => c.name), contributorGoals.map(a => !!a ? a.map(b => b.name).join() : "undefined").join(": "), uniqueGoals.map(g => g.name), p.context.correlationId);
return uniqueGoals.length === 0 ?
undefined :
new Goals_1.Goals(names.join(", "), ...uniqueGoals);
}
}
/**
* Contribute goals based on a series of contribution rules.
*
* Instead of stopping at the first match, each push will get _all_ the goals it qualifies for.
*
* Duplicates will be removed.
*
* @param contributor first contributor
* @param {GoalContribution<F>} contributors
* @return a mapping to goals
*/
function goalContributors(contributor, ...contributors) {
if (contributors.length === 0) {
return Mapping_1.mapMapping(contributor, GoalComponent_1.toGoals);
}
return enrichGoalSetters(contributor, contributors[0], ...contributors.slice(1));
}
exports.goalContributors = goalContributors;
/**
* Enrich the given push mapping with our own contributions
* @param {Mapping<F extends SdmContext, Goals>} mapping
* @param {GoalContribution<F extends SdmContext>} contributor
* @param {GoalContribution<F extends SdmContext>} contributors
* @return {Mapping<F extends SdmContext, Goals>}
*/
function enrichGoalSetters(mapping, contributor, ...contributors) {
if (isAdditiveGoalSetter(mapping)) {
return new AdditiveGoalSetter(`${mapping.name}-enriched`, [...mapping.contributors, contributor, ...contributors]);
}
return new AdditiveGoalSetter(`${mapping.name}-enriched`, [mapping, contributor].concat(contributors));
}
exports.enrichGoalSetters = enrichGoalSetters;
function isAdditiveGoalSetter(a) {
const maybe = a;
return !!maybe && !!maybe.contributors && !!maybe.mapping;
}
//# sourceMappingURL=goalContribution.js.map