UNPKG

@atomist/atomist-sdm

Version:

Atomist SDM to deliver our own projects

251 lines 10.2 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 sdm_1 = require("@atomist/sdm"); const fs = require("fs-extra"); const path = require("path"); const semver = require("semver"); const goals_1 = require("./goals"); const release_1 = require("./release"); /** * Push test for Go projects built with make. */ exports.IsGoMake = sdm_1.allSatisfied(sdm_1.hasFile("main.go"), sdm_1.hasFile("Makefile")); /** * Push test for Go projects built with make with Dockerfile. */ exports.IsGoMakeDocker = sdm_1.allSatisfied(exports.IsGoMake, sdm_1.hasFile("docker/Dockerfile")); /** * Add Go support and implementations of SDM goals. * * @param sdm Software Delivery machine to modify * @return modified software delivery machine */ function addGoSupport(sdm) { goals_1.version.with({ name: "go-versioner", logInterpreter: sdm_1.LogSuppressor, pushTest: exports.IsGoMake, versioner: GoVersioner, }); goals_1.build.with({ name: "go-make-build", builder: GoBuilder, pushTest: exports.IsGoMake, }) .withProjectListener(exports.GoPathHack); goals_1.publish.with({ name: "go-publish", goalExecutor: goals_1.noOpGoalExecutor, pushTest: exports.IsGoMake, }); goals_1.dockerBuild.with({ name: "go-docker-build", options: Object.assign({}, sdm.configuration.sdm.docker.hub, { push: true, builder: "docker", builderPath: "docker", dockerfileFinder: () => __awaiter(this, void 0, void 0, function* () { return "docker/Dockerfile"; }) }), logInterpreter: sdm_1.LogSuppressor, pushTest: exports.IsGoMakeDocker, }) .withProjectListener(GoDockerBuild); goals_1.release.with({ name: "go-release", goalExecutor: goals_1.noOpGoalExecutor, pushTest: exports.IsGoMake, }); goals_1.releaseVersion.with({ name: "go-release-version", goalExecutor: release_1.executeReleaseVersion(exports.goProjectIdentifier, goIncrementPatch), logInterpreter: sdm_1.LogSuppressor, pushTest: exports.IsGoMake, }); goals_1.releaseDocs.with({ name: "go-release", goalExecutor: goals_1.noOpGoalExecutor, pushTest: exports.IsGoMake, }); return sdm; } exports.addGoSupport = addGoSupport; const goExtractVersionRegExp = /^[\S\s]*\bversion\s*=\s*"(\d+\.\d+\.\d+)"[\S\s]*$/; const goSetVersionRegExp = /^(\s*version\s*=\s*)"(\d+\.\d+\.\d+)"\s*$/m; const GoVersioner = (e, p, l) => __awaiter(this, void 0, void 0, function* () { const baseVersion = (yield exports.goProjectIdentifier(p)).version; l.write(`Using base version '${baseVersion}'`); const prereleaseVersion = release_1.addBranchPreRelease(baseVersion, e); l.write(`Calculated pre-release version '${prereleaseVersion}'`); return prereleaseVersion; }); /** * Extract project information from Go project. */ exports.goProjectIdentifier = (p) => __awaiter(this, void 0, void 0, function* () { let v; const versionFile = yield p.getFile("cmd/version.go"); if (versionFile) { v = (yield versionFile.getContent()).replace(goExtractVersionRegExp, "$1"); } else { v = "0.0.0"; } return { id: p.id, name: p.name, version: v, }; }); function projectGoPath(project) { const goPath = path.join(project.baseDir, ".gosdm"); const goProjectDir = path.join(goPath, "src", "github.com", "atomist", project.name); return { goPath, goProjectDir }; } /** * Hack a GOPATH to work with the way the SDM checks projects out. */ function goPathHack(project, goalInvocation) { return __awaiter(this, void 0, void 0, function* () { const log = goalInvocation.progressLog; const pgp = projectGoPath(project); if (fs.existsSync(pgp.goProjectDir)) { const msg = `Go project directory already exists: ${pgp.goProjectDir}`; log.write(msg); return { code: 0, message: msg }; } try { const projectCopyPath = project.baseDir + ".gosdm.tmp"; yield fs.ensureDir(projectCopyPath); yield fs.copy(project.baseDir, projectCopyPath); yield fs.ensureDir(pgp.goProjectDir); yield fs.move(projectCopyPath, pgp.goProjectDir, { overwrite: true }); } catch (e) { const msg = `Failed to create GOPATH directory tree for ${project.name}: ${e.message}`; log.write(msg); return { code: 1, message: msg }; } const message = `Created GOPATH tree for ${project.name}: ${pgp.goProjectDir}`; log.write(message); return { code: 0, message }; }); } exports.goPathHack = goPathHack; exports.GoPathHack = { name: "go path hack", events: [sdm_1.GoalProjectListenerEvent.before], listener: goPathHack, pushTest: exports.IsGoMake, }; /** * Generic make executor for Go projects. GoPathHack should be * executed before this. */ function goMake(p, log, args = []) { return __awaiter(this, void 0, void 0, function* () { const pgp = projectGoPath(p); const makeOptions = { cwd: pgp.goProjectDir, env: Object.assign({}, process.env, { GOPATH: pgp.goPath }), log, }; log.write(`Running 'make' for ${p.name} in '${makeOptions.cwd}' with GOPATH='${makeOptions.env.GOPATH}'`); const makeResult = yield sdm_1.spawnLog("make", args, makeOptions); if (makeResult.code) { if (makeResult.error) { log.write(`Make errored for ${p.name}: ${makeResult.error.message}`); } else { log.write(`Make failed for ${p.name}: ${makeResult.code}`); } } else { log.write(`Successful 'make' invocation for ${p.name} in '${pgp.goProjectDir}' with GOPATH='${pgp.goPath}'`); } return makeResult; }); } /** * Builder for Go projects that use make. GoPathHack should be * executed before this. */ const GoBuilder = (goalInvocation, buildNo) => { const { configuration, credentials, id, progressLog } = goalInvocation; return configuration.sdm.projectLoader.doWithProject({ credentials, id, readOnly: true, cloneOptions: { detachHead: true } }, (p) => __awaiter(this, void 0, void 0, function* () { const appInfo = yield exports.goProjectIdentifier(p); const buildResult = yield goMake(p, progressLog); return { appInfo, buildResult, deploymentUnitFile: undefined }; })); }; /** * Build amd64/linux binary for Docker. */ const GoDockerBuild = { name: "go-make-docker", events: [sdm_1.GoalProjectListenerEvent.before], listener: (p, gi) => sdm_1.spawnLog("make", ["docker-target"], { cwd: p.baseDir, log: gi.progressLog }), pushTest: exports.IsGoMakeDocker, }; /** * Command for incrementing the version patch value in * `cmd/version.go` and `Makefile`. */ function goIncrementPatch(p, log) { return __awaiter(this, void 0, void 0, function* () { const vPath = "cmd/version.go"; const vFile = yield p.getFile(vPath); if (!vFile) { const msg = `Project does not have '${vPath}' file`; log.write(msg); return { code: 1, message: msg }; } const vContent = yield vFile.getContent(); const currentVersion = vContent.replace(goExtractVersionRegExp, "$1"); if (!currentVersion) { const msg = `Failed to extract version from '${vPath}' file`; log.write(msg); return { code: 1, message: msg }; } const newVersion = semver.inc(currentVersion, "patch"); if (!newVersion || newVersion === currentVersion) { const msg = `Failed to increment patch in version '${currentVersion}' from '${vPath}' file`; log.write(msg); return { code: 1, message: msg }; } log.write(`Incremented version: ${currentVersion} => ${newVersion}`); yield vFile.setContent(vContent.replace(goSetVersionRegExp, `$1"${newVersion}"`)); log.write(`Incremented patch level in '${vPath}' file`); const makefilePath = "Makefile"; const makefileFile = yield p.getFile(makefilePath); if (!makefileFile) { const msg = `Project does not have '${makefilePath}' file`; log.write(msg); return { code: 1, message: msg }; } yield makefileFile.setContent((yield makefileFile.getContent()).replace(/^DOCKER_VERSION\s*=.*/m, `DOCKER_VERSION = ${newVersion}`)); log.write(`Incremented patch level in '${makefilePath}' file`); const message = `Incremented patch level: ${currentVersion} => ${newVersion}`; log.write(message); return { code: 0, message }; }); } exports.goIncrementPatch = goIncrementPatch; //# sourceMappingURL=goSupport.js.map