UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

179 lines 9.72 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. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.computeStartingPoint = exports.isSeedDrivenGeneratorParameters = exports.toGeneratorParametersMaker = exports.generatorCommand = void 0; const HandlerResult_1 = require("@atomist/automation-client/lib/HandlerResult"); const onCommand_1 = require("@atomist/automation-client/lib/onCommand"); const RepoId_1 = require("@atomist/automation-client/lib/operations/common/RepoId"); const generatorUtils_1 = require("@atomist/automation-client/lib/operations/generate/generatorUtils"); const Project_1 = require("@atomist/automation-client/lib/project/Project"); const MessageClient_1 = require("@atomist/automation-client/lib/spi/message/MessageClient"); const constructionUtils_1 = require("@atomist/automation-client/lib/util/constructionUtils"); const slack_messages_1 = require("@atomist/slack-messages"); const storeGoals_1 = require("../../goal/storeGoals"); const handlerRegistrations_1 = require("../../machine/handlerRegistrations"); const projectLoaderRepoLoader_1 = require("../../machine/projectLoaderRepoLoader"); const toMachineOptions_1 = require("../../machine/toMachineOptions"); const messages_1 = require("../../misc/slack/messages"); const CachingProjectLoader_1 = require("../../project/CachingProjectLoader"); /** * Create a command handler for project generation * @param sdm this machine or its options * @param {EditorFactory<P extends SeedDrivenGeneratorParameters>} editorFactory to create editorCommand to perform transformation * @param {Maker<P extends SeedDrivenGeneratorParameters>} paramsMaker * @param {string} name * @param {Partial<GeneratorCommandDetails<P extends SeedDrivenGeneratorParameters>>} details * @return {HandleCommand} */ function generatorCommand(sdm, editorFactory, name, paramsMaker, fallbackTarget, startingPoint, details = {}, cr) { const detailsToUse = Object.assign(Object.assign({}, defaultDetails(toMachineOptions_1.toMachineOptions(sdm), name)), details); return onCommand_1.commandHandlerFrom(handleGenerate(editorFactory, detailsToUse, startingPoint, cr, toMachineOptions_1.toMachineOptions(sdm)), toGeneratorParametersMaker(paramsMaker, constructionUtils_1.toFactory(fallbackTarget)()), name, detailsToUse.description, detailsToUse.intent, detailsToUse.tags); } exports.generatorCommand = generatorCommand; /** * Return a parameters maker that is targeting aware * @param {Maker<PARAMS>} paramsMaker * @return {Maker<EditorOrReviewerParameters & PARAMS>} */ function toGeneratorParametersMaker(paramsMaker, target) { const sampleParams = constructionUtils_1.toFactory(paramsMaker)(); return isSeedDrivenGeneratorParameters(sampleParams) ? paramsMaker : () => { // This way we won't bother with source, but rely on startingPoint const rawParms = constructionUtils_1.toFactory(paramsMaker)(); const allParms = rawParms; allParms.target = target; return allParms; }; } exports.toGeneratorParametersMaker = toGeneratorParametersMaker; function isSeedDrivenGeneratorParameters(p) { const maybe = p; return !!maybe && !!maybe.target; } exports.isSeedDrivenGeneratorParameters = isSeedDrivenGeneratorParameters; function handleGenerate(editorFactory, details, startingPoint, cr, sdmo) { return (ctx, parameters) => { return handle(ctx, editorFactory, parameters, details, startingPoint, cr, sdmo); }; } async function handle(ctx, editorFactory, params, details, startingPoint, cr, sdmo) { try { const pi = Object.assign(Object.assign({}, handlerRegistrations_1.toCommandListenerInvocation(cr, ctx, params, sdmo)), params); pi.credentials = await handlerRegistrations_1.resolveCredentialsPromise(pi.credentials); const r = await generatorUtils_1.generate(computeStartingPoint(params, ctx, details.repoLoader(params), details, startingPoint, cr, sdmo), ctx, pi.credentials, editorFactory(params, ctx), details.projectPersister, params.target.repoRef, params, undefined); if (!!cr.afterAction && r.success === true) { const afterActions = Array.isArray(cr.afterAction) ? cr.afterAction : [cr.afterAction]; for (const afterAction of afterActions) { await afterAction(r.target, pi); } } // TODO cd support other providers which needs to start upstream from this if (params.target.repoRef.providerType === RepoId_1.ProviderType.github_com && r.success === true) { const repoProvenance = { repo: { name: params.target.repoRef.repo, owner: params.target.repoRef.owner, providerId: "zjlmxjzwhurspem", }, provenance: storeGoals_1.constructProvenance(ctx), }; await ctx.messageClient.send(repoProvenance, MessageClient_1.addressEvent("SdmRepoProvenance")); } await ctx.messageClient.respond(messages_1.slackSuccessMessage(`Create Project`, `Successfully created new project ${slack_messages_1.bold(`${params.target.repoRef.owner}/${params.target.repoRef.repo}`)} at ${slack_messages_1.url(params.target.repoRef.url)}`)); return { code: 0, // Redirect to local project page redirect: details.redirecter(params.target.repoRef), // local SDM uses this to print instructions generatedRepositoryUrl: params.target.repoRef.url, }; } catch (err) { if (err instanceof handlerRegistrations_1.CommandListenerExecutionInterruptError) { // We're continuing return HandlerResult_1.Success; } await ctx.messageClient.respond(messages_1.slackErrorMessage(`Create Project`, `Project creation for ${slack_messages_1.bold(`${params.target.repoRef.owner}/${params.target.repoRef.repo}`)} failed: ${slack_messages_1.codeBlock(err.message)}`, ctx)); } return undefined; } /** * Retrieve a seed. Set the seed location on the parameters if possible and necessary. */ async function computeStartingPoint(params, ctx, repoLoader, details, startingPoint, cr, sdmo) { if (!startingPoint) { if (!params.source || !params.source.repoRef) { throw new Error("If startingPoint is not provided in GeneratorRegistration, parameters.source must specify seed project location: " + `Offending registration had intent ${details.intent}`); } await infoMessage(`Cloning seed project from parameters ${slack_messages_1.url(params.source.repoRef.url)}`, ctx); return repoLoader(params.source.repoRef); } if (Project_1.isProject(startingPoint)) { await infoMessage(`Using starting point project specified in registration`, ctx); return startingPoint; } else if (RepoId_1.isRemoteRepoRef(startingPoint)) { const source = startingPoint; await infoMessage(`Cloning seed project from starting point ${slack_messages_1.bold(`${source.owner}/${source.repo}`)} at ${slack_messages_1.url(source.url)}`, ctx); const repoRef = startingPoint; params.source = { repoRef }; return repoLoader(repoRef); } else { // Combine this for backward compatibility const pi = Object.assign(Object.assign({}, handlerRegistrations_1.toCommandListenerInvocation(cr, ctx, params, sdmo)), params); pi.credentials = await handlerRegistrations_1.resolveCredentialsPromise(pi.credentials); // It's a function that takes the parameters and returns either a project or a RemoteRepoRef const rr = startingPoint(pi); if (isProjectPromise(rr)) { const p = await rr; await infoMessage(`Using dynamically chosen starting point project ${slack_messages_1.bold(`${p.id.owner}:${p.id.repo}`)}`, ctx); return p; } if (Project_1.isProject(rr)) { await infoMessage(`Using dynamically chosen starting point project ${slack_messages_1.bold(`${rr.id.owner}:${rr.id.repo}`)}`, ctx); // params.source will remain undefined in this case return rr; } else { await infoMessage(`Cloning dynamically chosen starting point from ${slack_messages_1.url(rr.url)}`, ctx); params.source = { repoRef: rr }; return repoLoader(rr); } } } exports.computeStartingPoint = computeStartingPoint; function isProjectPromise(a) { return !!a.then; } function defaultDetails(opts, name) { return { description: name, repoFinder: opts.repoFinder, repoLoader: (p) => projectLoaderRepoLoader_1.projectLoaderRepoLoader(opts.projectLoader || new CachingProjectLoader_1.CachingProjectLoader(), p.target.credentials, true), projectPersister: opts.projectPersister, redirecter: () => undefined, }; } async function infoMessage(text, ctx) { return ctx.messageClient.respond(messages_1.slackInfoMessage("Create Project", text)); } //# sourceMappingURL=generatorCommand.js.map