UNPKG

@atomist/sdm-pack-fingerprints

Version:

an Atomist SDM Extension Pack for fingerprinting code

298 lines (294 loc) 13.9 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) { 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) : new P(function (resolve) { resolve(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 slack_messages_1 = require("@atomist/slack-messages"); const fingerprints_1 = require("../../adhoc/fingerprints"); const preferences_1 = require("../../adhoc/preferences"); const Aspects_1 = require("../../machine/Aspects"); const messages_1 = require("../../support/messages"); /** * Call relevant apply functions from Registrations for a Fingerprint * This happens in the context of an an editable Project */ function pushFingerprint(p, aspects, fp) { return __awaiter(this, void 0, void 0, function* () { const aspect = Aspects_1.aspectOf(fp, aspects); if (!!aspect && !!aspect.apply) { const result = yield aspect.apply(p, fp); if (result) { automation_client_1.logger.info(`Successfully applied policy ${fp.name}`); } return result; } return false; }); } /** * Create a CodeTransform that can be used to apply a Fingerprint to a Project * This CodeTransform is takes one target Fingerprint in it's set of parameters. */ function runAllFingerprintAppliers(aspects) { return (p, cli) => __awaiter(this, void 0, void 0, function* () { const { type, name } = preferences_1.fromName(cli.parameters.targetfingerprint); const aspect = Aspects_1.aspectOf({ type }, aspects); let details; if (!!aspect && !!aspect.toDisplayableFingerprintName) { details = `${slack_messages_1.italic(aspect.displayName)} ${slack_messages_1.codeLine(aspect.toDisplayableFingerprintName(name))}`; } else { details = slack_messages_1.codeLine(cli.parameters.targetfingerprint); } const message = sdm_1.slackInfoMessage("Apply Policy", `Applying policy to ${slack_messages_1.bold(`${p.id.owner}/${p.id.repo}/${p.id.branch}:`)} ${details}`); yield cli.addressChannels(message, { id: cli.parameters.msgId }); const fingerprint = yield preferences_1.queryPreferences(cli.context.graphClient, type, name); const result = yield pushFingerprint(p, aspects, fingerprint); if (!cli.parameters.title) { cli.parameters.title = messages_1.applyFingerprintTitle(fingerprint, aspects); } if (!cli.parameters.body) { cli.parameters.body = messages_1.prBodyFromFingerprint(fingerprint, aspects); } if (result) { return p; } else { return { edited: false, success: true, target: p }; } }); } exports.runAllFingerprintAppliers = runAllFingerprintAppliers; function runFingerprintAppliersBySha(aspects) { return (p, cli) => __awaiter(this, void 0, void 0, function* () { const { type, name } = preferences_1.fromName(cli.parameters.targetfingerprint); const aspect = Aspects_1.aspectOf({ type }, aspects); let details; if (!!aspect && !!aspect.toDisplayableFingerprintName) { details = `${slack_messages_1.italic(aspect.displayName)} ${slack_messages_1.codeLine(aspect.toDisplayableFingerprintName(name))}`; } else { details = slack_messages_1.codeLine(cli.parameters.targetfingerprint); } const message = sdm_1.slackInfoMessage("Apply Policy", `Applying policy to ${slack_messages_1.bold(`${p.id.owner}/${p.id.repo}/${p.id.branch}:`)} ${details}`); yield cli.addressChannels(message, { id: cli.parameters.msgId }); const fp = yield cli.context.graphClient.query({ name: "GetFpBySha", variables: { type, name, sha: cli.parameters.sha, }, options: automation_client_1.QueryNoCacheOptions, }); const fingerprint = { type, name, data: JSON.parse(fp.SourceFingerprint.data), sha: fp.SourceFingerprint.sha, }; const result = yield pushFingerprint(p, aspects, fingerprint); if (!cli.parameters.title) { cli.parameters.title = messages_1.applyFingerprintTitle(fingerprint, aspects); } if (!cli.parameters.body) { cli.parameters.body = messages_1.prBodyFromFingerprint(fingerprint, aspects); } if (result) { return p; } else { return { edited: false, success: true, target: p }; } }); } exports.runFingerprintAppliersBySha = runFingerprintAppliersBySha; /** * Create a CodeTransform that can be used to apply a Fingerprint to a Project * This CodeTransform takes a set of Fingerprints in it's set of parameters */ function runEveryFingerprintApplication(aspects) { return (p, cli) => __awaiter(this, void 0, void 0, function* () { const fingerprints = cli.parameters.fingerprints.split(",").map(fp => fp.trim()); const details = fingerprints.map(f => { const { type, name } = preferences_1.fromName(f); const aspect = Aspects_1.aspectOf({ type }, aspects); let detail; if (!!aspect && !!aspect.toDisplayableFingerprintName) { detail = `${slack_messages_1.italic(aspect.displayName)} ${slack_messages_1.codeLine(aspect.toDisplayableFingerprintName(name))}`; } else { detail = slack_messages_1.codeLine(f); } return detail; }); const message = sdm_1.slackInfoMessage("Apply Policies", `Applying policies to ${slack_messages_1.bold(`${p.id.owner}/${p.id.repo}/${p.id.branch}`)}: ${details.join("\n")}`); yield cli.addressChannels(message, { id: cli.parameters.msgId }); for (const fpName of fingerprints) { const { type, name } = preferences_1.fromName(fpName.trim()); const result = yield pushFingerprint(p, aspects, yield preferences_1.queryPreferences(cli.context.graphClient, type, name)); if (!result) { return { edited: false, success: true, target: p }; } } return p; }); } exports.ApplyTargetFingerprintName = "ApplyTargetFingerprint"; function applyTarget(sdm, aspects, presentation) { return { name: exports.ApplyTargetFingerprintName, intent: [ `apply fingerprint target ${sdm.configuration.name.replace("@", "")}`, `applyFingerprint ${sdm.configuration.name.replace("@", "")}`, ], description: "choose to raise a PR on the current project to apply a target fingerprint", parameters: { msgId: { required: false, displayable: false }, targetfingerprint: { required: true }, body: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, title: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, branch: { required: false, displayable: false }, }, transformPresentation: presentation, transform: runAllFingerprintAppliers(aspects), autoSubmit: true, }; } exports.applyTarget = applyTarget; exports.ApplyTargetFingerprintByShaName = "ApplyTargetFingerprintBySha"; function applyTargetBySha(sdm, aspects, presentation) { return { name: exports.ApplyTargetFingerprintByShaName, intent: [ `apply fingerprint target by sha ${sdm.configuration.name.replace("@", "")}`, ], description: "Apply a fingerprint target identified by the fingerprint's sha and type", parameters: { msgId: { required: false, displayable: false }, targetfingerprint: { required: true }, sha: { required: true }, body: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, title: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, branch: { required: false, displayable: false }, }, transformPresentation: presentation, transform: runFingerprintAppliersBySha(aspects), autoSubmit: true, }; } exports.applyTargetBySha = applyTargetBySha; // use where ApplyTargetFingerprints was used exports.ApplyAllFingerprintsName = "ApplyAllFingerprints"; function applyTargets(sdm, registrations, presentation) { return { name: exports.ApplyAllFingerprintsName, description: "apply a bunch of fingerprints", transform: runEveryFingerprintApplication(registrations), transformPresentation: presentation, parameters: { msgId: { required: false, displayable: false }, fingerprints: { required: true }, body: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, title: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, branch: { required: false, displayable: false }, }, autoSubmit: true, }; } exports.applyTargets = applyTargets; exports.BroadcastFingerprintMandateName = "BroadcastFingerprintMandate"; function broadcastFingerprintMandate(sdm, aspects) { return { name: exports.BroadcastFingerprintMandateName, description: "create a PR in many Repos", listener: (i) => __awaiter(this, void 0, void 0, function* () { const refs = []; const { type, name } = preferences_1.fromName(i.parameters.fingerprint); const fp = yield preferences_1.queryPreferences(i.context.graphClient, type, name); const data = yield (fingerprints_1.findTaggedRepos(i.context.graphClient))(fp.type, fp.name); // TODO does the analysis only have the matching tagged repos or all of them? if (!!data.headCommitsWithFingerprint) { refs.push(...data.headCommitsWithFingerprint .filter(head => !!head.branch && !!head.branch.name && head.branch.name === "master") .filter(head => head.analysis.some(x => { return x.type === fp.type && x.name === fp.name && x.sha !== fp.sha; })) .map(x => { return { owner: x.repo.owner, repo: x.repo.name, url: "url", branch: "master", }; })); } const aspect = Aspects_1.aspectOf({ type }, aspects); let details; if (!!aspect && !!aspect.toDisplayableFingerprintName) { details = `${slack_messages_1.italic(aspect.displayName)} ${slack_messages_1.codeLine(aspect.toDisplayableFingerprintName(name))}`; } else { details = slack_messages_1.codeLine(i.parameters.fingerprint); } yield sdm_1.createJob({ command: exports.ApplyTargetFingerprintName, description: `Applying policy: ${details}`, name: `ApplyPolicy/${i.parameters.fingerprint}`, parameters: refs.map(r => ({ title: i.parameters.title, body: i.parameters.body, branch: r.branch, targetfingerprint: i.parameters.fingerprint, targets: { owner: r.owner, repo: r.repo, branch: r.branch, }, })), }, i.context); const message = sdm_1.slackSuccessMessage("Boardcast Policy Update", `Successfully scheduled job to apply target for fingerprint ${slack_messages_1.codeLine(i.parameters.fingerprint)} to $ refs.length} ${refs.length > 1 ? "repositories" : "repository"}`); // replace the previous message where we chose this action yield i.addressChannels(message, { id: i.parameters.msgId }); }), parameters: { msgId: { required: false, displayable: false }, fingerprint: { required: true }, body: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, title: { required: false, displayable: true, control: "textarea", pattern: /[\S\s]*/ }, branch: { required: false, displayable: false }, }, autoSubmit: true, }; } exports.broadcastFingerprintMandate = broadcastFingerprintMandate; //# sourceMappingURL=applyFingerprint.js.map