UNPKG

@atomist/sdm-pack-aspect

Version:

an Atomist SDM Extension Pack for visualizing drift across an organization

188 lines (172 loc) 7.89 kB
/* * 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. */ import { GitHubRepoRef, logger, MappedParameters, QueryNoCacheOptions, } from "@atomist/automation-client"; import { CommandHandlerRegistration, DeclarationType, execPromise, isLazyProjectLoader, ProviderType, PushImpactListenerInvocation, SoftwareDeliveryMachine, } from "@atomist/sdm"; import { Aspect, fingerprintRunner, } from "@atomist/sdm-pack-fingerprint"; import { sendFingerprintsToAtomist } from "@atomist/sdm-pack-fingerprint/lib/adhoc/fingerprints"; import { createFingerprintComputer } from "@atomist/sdm-pack-fingerprint/lib/machine/runner"; import * as _ from "lodash"; import { GitHubAppInstallationByOwner, IngestScmCommit, ScmCommitInput, ScmProviderById, } from "../typings/types"; // tslint:disable-next-line:interface-over-type-literal export type CalculateFingerprintTaskParameters = { providerId: string, repoId: string, owner: string, name: string, branch: string, }; export function calculateFingerprintTask(sdm: SoftwareDeliveryMachine, aspects: Aspect[]) : CommandHandlerRegistration<CalculateFingerprintTaskParameters> { // Also register the provided aspects in the registration metadata sdm.configuration.metadata = { ...sdm.configuration.metadata, "atomist.aspects": JSON.stringify(aspects.map(a => ({ name: a.name, displayName: a.displayName }))), }; return { name: "CalculateFingerprintTask", description: "Trigger calculation of fingerprints on the provided repository", parameters: { providerId: { description: "Id of the SCMProvider" }, repoId: { description: "Id of the Repo" }, owner: { uri: MappedParameters.GitHubOwner, declarationType: DeclarationType.Mapped }, name: { uri: MappedParameters.GitHubRepository, declarationType: DeclarationType.Mapped }, branch: { description: "Name of the branch" }, }, listener: async ci => { try { const provider = _.get(await ci.context.graphClient.query<ScmProviderById.Query, ScmProviderById.Variables>({ name: "ScmProviderById", variables: { providerId: ci.parameters.providerId, }, options: QueryNoCacheOptions, }), "SCMProvider[0]"); const app = _.get(await ci.context.graphClient.query<GitHubAppInstallationByOwner.Query, GitHubAppInstallationByOwner.Variables>({ name: "GitHubAppInstallationByOwner", variables: { name: ci.parameters.owner, }, options: QueryNoCacheOptions, }), "GitHubAppInstallation[0]"); const token = _.get(provider, "credential.secret") || _.get(app, "token.secret"); const id = GitHubRepoRef.from({ owner: ci.parameters.owner, repo: ci.parameters.name, branch: ci.parameters.branch, rawApiBase: provider.apiUrl, }); const credentials = !!token ? { token } : undefined; await ci.configuration.sdm.projectLoader.doWithProject({ ...ci, id, credentials }, async p => { if (isLazyProjectLoader(ci.configuration.sdm.projectLoader)) { await p.materialize(); } // git rev-parse HEAD = sha const sha = (await execPromise("git", ["rev-parse", "HEAD"], { cwd: p.baseDir })).stdout.trim(); // const author = (await execPromise("git", ["show", "-s", "--format=%an"], { cwd: p.baseDir })).stdout.trim(); const email = (await execPromise("git", ["show", "-s", "--format=%ae"], { cwd: p.baseDir })).stdout.trim(); const ts = (await execPromise("git", ["show", "-s", "--format=%at"], { cwd: p.baseDir })).stdout.trim(); const message = (await execPromise("git", ["show", "-s", "--format=%B"], { cwd: p.baseDir })).stdout.trim(); // Ingest initial commit const commit: ScmCommitInput = { repoId: ci.parameters.repoId, branchName: ci.parameters.branch, timestamp: new Date(+ts * 1000).toISOString(), email: { address: email, }, sha, message, }; await ci.context.graphClient.mutate<IngestScmCommit.Mutation, IngestScmCommit.Variables>({ name: "IngestScmCommit", variables: { providerId: provider.id, commit, }, }); // Run the fingerprint code const pi: PushImpactListenerInvocation = { context: ci.context, configuration: ci.configuration, project: p, addressChannels: ci.addressChannels, preferences: ci.preferences, credentials: ci.credentials, id, impactedSubProject: p, filesChanged: undefined, commit: { sha, message, }, push: { repo: { defaultBranch: ci.parameters.branch, channels: [], name: ci.parameters.name, owner: ci.parameters.owner, org: { owner: ci.parameters.owner, provider: { apiUrl: provider.apiUrl, providerId: ci.parameters.providerId, providerType: ProviderType.github_com, }, }, }, after: { sha, message, }, commits: [{ sha, message, }], branch: ci.parameters.branch, timestamp: ts, }, }; const fingerprintComputer = createFingerprintComputer(aspects); await fingerprintRunner(aspects, [], fingerprintComputer, sendFingerprintsToAtomist)(pi); }); } catch (e) { logger.error(`Fingerprinting task failed to execute: ${e.message}`); } }, }; }