UNPKG

@atomist/sdm-core

Version:

Atomist Software Delivery Machine - Implementation

231 lines 9.94 kB
"use strict"; /* * 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. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const automation_client_1 = require("@atomist/automation-client"); const sdm_1 = require("@atomist/sdm"); const _ = require("lodash"); const array_1 = require("../../util/misc/array"); const CompressingGoalCache_1 = require("./CompressingGoalCache"); exports.CacheInputGoalDataKey = "@atomist/sdm/input"; exports.CacheOutputGoalDataKey = "@atomist/sdm/output"; const DefaultGoalCache = new CompressingGoalCache_1.CompressingGoalCache(); /** * Goal listener that performs caching after a goal has been run. * @param options The options for caching * @param classifier Whether only a specific classifier, as defined in the options, * needs to be cached. If omitted, all classifiers are cached. * @param classifiers Additional classifiers that need to be created. */ function cachePut(options, classifier, ...classifiers) { const allClassifiers = []; if (classifier) { allClassifiers.push(classifier, ...(classifiers || [])); } const entries = !!classifier ? options.entries.filter(pattern => allClassifiers.includes(pattern.classifier)) : options.entries; const listenerName = `caching outputs`; return { name: listenerName, listener: (p, gi) => __awaiter(this, void 0, void 0, function* () { if (!!isCacheEnabled(gi) && !process.env.ATOMIST_ISOLATED_GOAL_INIT) { const goalCache = cacheStore(gi); for (const entry of entries) { const files = []; if (isGlobFilePattern(entry.pattern)) { files.push(...(yield getFilePathsThroughPattern(p, entry.pattern.globPattern))); } else if (isDirectoryPattern(entry.pattern)) { files.push(entry.pattern.directory); } if (!_.isEmpty(files)) { yield goalCache.put(gi, p, files, entry.classifier); } } // Set outputs on the goal data const { goalEvent } = gi; const data = JSON.parse(goalEvent.data || "{}"); const newData = { [exports.CacheOutputGoalDataKey]: [ ...(data[exports.CacheOutputGoalDataKey] || []), ...entries, ], }; goalEvent.data = JSON.stringify(Object.assign(Object.assign({}, (JSON.parse(goalEvent.data || "{}"))), newData)); } }), pushTest: options.pushTest, events: [sdm_1.GoalProjectListenerEvent.after], }; } exports.cachePut = cachePut; function isGlobFilePattern(toBeDetermined) { return toBeDetermined.globPattern !== undefined; } function isDirectoryPattern(toBeDetermined) { return toBeDetermined.directory !== undefined; } function pushTestSucceeds(pushTest, gi, p) { return __awaiter(this, void 0, void 0, function* () { return (pushTest || sdm_1.AnyPush).mapping({ push: gi.goalEvent.push, project: p, id: gi.id, configuration: gi.configuration, addressChannels: gi.addressChannels, context: gi.context, preferences: gi.preferences, credentials: gi.credentials, }); }); } function invokeCacheMissListeners(optsToUse, p, gi, event) { return __awaiter(this, void 0, void 0, function* () { for (const cacheMissFallback of array_1.toArray(optsToUse.onCacheMiss)) { const allEvents = [sdm_1.GoalProjectListenerEvent.before, sdm_1.GoalProjectListenerEvent.after]; if ((cacheMissFallback.events || allEvents).filter(e => e === event).length > 0 && (yield pushTestSucceeds(cacheMissFallback.pushTest, gi, p))) { yield cacheMissFallback.listener(p, gi, event); } } }); } exports.NoOpGoalProjectListenerRegistration = { name: "NoOpListener", listener: () => __awaiter(void 0, void 0, void 0, function* () { }), pushTest: sdm_1.AnyPush, }; /** * Goal listener that performs cache restores before a goal has been run. * @param options The options for caching * @param classifier Whether only a specific classifier, as defined in the options, * needs to be restored. If omitted, all classifiers defined in the options are restored. * @param classifiers Additional classifiers that need to be restored. */ function cacheRestore(options, classifier, ...classifiers) { const allClassifiers = []; if (classifier) { allClassifiers.push(classifier, ...(classifiers || [])); } const optsToUse = Object.assign({ onCacheMiss: exports.NoOpGoalProjectListenerRegistration }, options); const classifiersToBeRestored = []; if (allClassifiers.length > 0) { classifiersToBeRestored.push(...allClassifiers); } else { classifiersToBeRestored.push(...optsToUse.entries.map(entry => entry.classifier)); } const listenerName = `restoring inputs`; return { name: listenerName, listener: (p, gi, event) => __awaiter(this, void 0, void 0, function* () { if (!!isCacheEnabled(gi)) { const goalCache = cacheStore(gi); for (const c of classifiersToBeRestored) { try { yield goalCache.retrieve(gi, p, c); } catch (e) { yield invokeCacheMissListeners(optsToUse, p, gi, event); } } } else { yield invokeCacheMissListeners(optsToUse, p, gi, event); } // Set inputs on the goal data const { goalEvent } = gi; const data = JSON.parse(goalEvent.data || "{}"); const newData = { [exports.CacheInputGoalDataKey]: [ ...(data[exports.CacheInputGoalDataKey] || []), ...classifiersToBeRestored.map(c => ({ classifier: c, })), ], }; goalEvent.data = JSON.stringify(Object.assign(Object.assign({}, (JSON.parse(goalEvent.data || "{}"))), newData)); }), pushTest: optsToUse.pushTest, events: [sdm_1.GoalProjectListenerEvent.before], }; } exports.cacheRestore = cacheRestore; /** * Goal listener that cleans up the cache restores after a goal has been run. * @param options The options for caching * @param classifier Whether only a specific classifier, as defined in the options, * needs to be removed. If omitted, all classifiers are removed. * @param classifiers Additional classifiers that need to be removed. */ function cacheRemove(options, classifier, ...classifiers) { const allClassifiers = []; if (classifier) { allClassifiers.push(...[classifier, ...classifiers]); } const classifiersToBeRemoved = []; if (allClassifiers.length > 0) { classifiersToBeRemoved.push(...allClassifiers); } else { classifiersToBeRemoved.push(...options.entries.map(entry => entry.classifier)); } const listenerName = `removing outputs`; return { name: listenerName, listener: (p, gi) => __awaiter(this, void 0, void 0, function* () { if (!!isCacheEnabled(gi)) { const goalCache = cacheStore(gi); for (const c of classifiersToBeRemoved) { yield goalCache.remove(gi, c); } } }), pushTest: options.pushTest, events: [sdm_1.GoalProjectListenerEvent.after], }; } exports.cacheRemove = cacheRemove; function getFilePathsThroughPattern(project, globPattern) { return __awaiter(this, void 0, void 0, function* () { const oldExcludes = automation_client_1.DefaultExcludes; automation_client_1.DefaultExcludes.splice(0, automation_client_1.DefaultExcludes.length); // necessary evil try { return yield automation_client_1.projectUtils.gatherFromFiles(project, globPattern, (f) => __awaiter(this, void 0, void 0, function* () { return f.path; })); } finally { automation_client_1.DefaultExcludes.push(...oldExcludes); } }); } function isCacheEnabled(gi) { return _.get(gi.configuration, "sdm.cache.enabled", false); } function cacheStore(gi) { return _.get(gi.configuration, "sdm.cache.store", DefaultGoalCache); } //# sourceMappingURL=goalCaching.js.map