@atomist/atomist-sdm
Version:
Atomist SDM to deliver our own projects
251 lines • 10.2 kB
JavaScript
;
/*
* 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