UNPKG

@atomist/sdm-pack-node

Version:

Extension pack for an Atomist SDM to work with Node.js projects

250 lines 10.6 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 sdm_core_1 = require("@atomist/sdm-core"); const sdm_pack_build_1 = require("@atomist/sdm-pack-build"); const base64url_1 = require("base64url"); const fs = require("fs-extra"); const hash = require("hasha"); const _ = require("lodash"); const nodePushTests_1 = require("../pushtest/nodePushTests"); const npmLogInterpreter_1 = require("./npmLogInterpreter"); /** * Options to use when running node commands like npm run compile that require dev dependencies to be installed */ exports.DevelopmentEnvOptions = { env: Object.assign({}, process.env, { NODE_ENV: "development" }), }; exports.Install = { command: "npm", args: ["ci"], options: exports.DevelopmentEnvOptions }; function nodeBuilder(...commands) { return sdm_pack_build_1.spawnBuilder(npmBuilderOptions(commands.map(cmd => ({ command: cmd.command, args: cmd.args, options: Object.assign({}, exports.DevelopmentEnvOptions, cmd.options), })))); } exports.nodeBuilder = nodeBuilder; function npmBuilderOptions(commands) { return { name: "NpmBuilder", commands, errorFinder: sdm_1.SuccessIsReturn0ErrorFinder, logInterpreter: npmLogInterpreter_1.NpmLogInterpreter, projectToAppInfo(p) { return __awaiter(this, void 0, void 0, function* () { const packageJson = yield p.findFile("package.json"); const content = yield packageJson.getContent(); const pkg = JSON.parse(content); return { id: p.id, name: pkg.name, version: pkg.version }; }); }, }; } function npmBuilderOptionsFromFile(commandFile) { return { name: "NpmBuilder", commandFile, errorFinder: (code, signal, l) => { return l.log.startsWith("[error]") || l.log.includes("ERR!"); }, logInterpreter: npmLogInterpreter_1.NpmLogInterpreter, projectToAppInfo(p) { return __awaiter(this, void 0, void 0, function* () { const packageJson = yield p.findFile("package.json"); const content = yield packageJson.getContent(); const pkg = JSON.parse(content); return { id: p.id, name: pkg.name, version: pkg.version }; }); }, }; } exports.npmBuilderOptionsFromFile = npmBuilderOptionsFromFile; exports.NpmPreparations = [npmInstallPreparation, npmVersionPreparation, npmCompilePreparation]; function npmInstallPreparation(p, goalInvocation) { return __awaiter(this, void 0, void 0, function* () { const hasPackageLock = p.fileExistsSync("package-lock.json"); return sdm_1.spawnLog("npm", [hasPackageLock ? "ci" : "install"], Object.assign({ cwd: p.baseDir }, exports.DevelopmentEnvOptions, { log: goalInvocation.progressLog })); }); } exports.npmInstallPreparation = npmInstallPreparation; function npmVersionPreparation(p, goalInvocation) { return __awaiter(this, void 0, void 0, function* () { const sdmGoal = goalInvocation.goalEvent; const version = yield sdm_core_1.readSdmVersion(sdmGoal.repo.owner, sdmGoal.repo.name, sdmGoal.repo.providerId, sdmGoal.sha, sdmGoal.branch, goalInvocation.context); return sdm_1.spawnLog("npm", ["--no-git-tag-version", "version", version], { cwd: p.baseDir, log: goalInvocation.progressLog, }); }); } exports.npmVersionPreparation = npmVersionPreparation; exports.NpmVersionProjectListener = { name: "npm version", pushTest: nodePushTests_1.IsNode, listener: (p, r, event) => __awaiter(this, void 0, void 0, function* () { if (sdm_1.GoalProjectListenerEvent.before === event) { return npmVersionPreparation(p, r); } }), }; function npmCompilePreparation(p, goalInvocation) { return __awaiter(this, void 0, void 0, function* () { if (yield hasCompileScriptInPackageJson(p)) { return sdm_1.spawnLog("npm", ["run", "compile"], Object.assign({ cwd: p.baseDir }, exports.DevelopmentEnvOptions, { log: goalInvocation.progressLog })); } else { return { code: 0 }; } }); } exports.npmCompilePreparation = npmCompilePreparation; function hasCompileScriptInPackageJson(p) { return __awaiter(this, void 0, void 0, function* () { const rawPj = yield p.getFile("package.json"); const pj = JSON.parse(yield rawPj.getContent()); return !!pj.scripts && !!pj.scripts.compile; }); } exports.NpmCompileProjectListener = { name: "npm compile", pushTest: nodePushTests_1.IsNode, listener: (p, r) => __awaiter(this, void 0, void 0, function* () { return npmCompilePreparation(p, r); }), events: [sdm_1.GoalProjectListenerEvent.before], }; exports.NodeModulesProjectListener = { name: "npm install", listener: (p, gi) => __awaiter(this, void 0, void 0, function* () { // Check if project has a package.json if (!(yield p.hasFile("package.json"))) { return; } return cacheNodeModules(p, gi, { scope: CacheScope.GoalSet }); }), events: [sdm_1.GoalProjectListenerEvent.before], pushTest: nodePushTests_1.IsNode, }; exports.NpmInstallProjectListener = exports.NodeModulesProjectListener; function npmInstallProjectListener(options = { scope: CacheScope.GoalSet }) { return { name: "npm install", listener: (p, gi) => __awaiter(this, void 0, void 0, function* () { // Check if project has a package.json if (!(yield p.hasFile("package.json"))) { return; } return cacheNodeModules(p, gi, options); }), events: [sdm_1.GoalProjectListenerEvent.before], pushTest: nodePushTests_1.IsNode, }; } exports.npmInstallProjectListener = npmInstallProjectListener; var CacheScope; (function (CacheScope) { CacheScope[CacheScope["GoalSet"] = 0] = "GoalSet"; CacheScope[CacheScope["Repository"] = 1] = "Repository"; })(CacheScope = exports.CacheScope || (exports.CacheScope = {})); function cacheNodeModules(p, gi, options) { return __awaiter(this, void 0, void 0, function* () { // If project already has a node_modules dir; there is nothing left to do if (yield p.hasDirectory("node_modules")) { return; } const hasPackageLock = yield p.hasFile("package-lock.json"); let requiresInstall = true; let installed = false; const { goalEvent } = gi; // Check cache for a previously cached node_modules cache archive let name; if (options.scope === CacheScope.GoalSet) { name = goalEvent.goalSetId; } else if (options.scope === CacheScope.Repository) { if (hasPackageLock) { name = base64url_1.default.fromBase64(hash(yield (yield p.getFile("package-lock.json")).getContent(), { algorithm: "md5", encoding: "base64", })); } else { name = base64url_1.default.fromBase64(hash(yield (yield p.getFile("package.json")).getContent(), { algorithm: "md5", encoding: "base64", })); } } const cacheFileName = `${_.get(gi, "configuration.sdm.cache.path", "/opt/data")}/${name}-node_modules.tar.gz`; if (_.get(gi, "configuration.sdm.cache.enabled") === true && (yield fs.pathExists(cacheFileName))) { const result = yield extract(cacheFileName, p, gi); requiresInstall = result.code !== 0; } if (requiresInstall) { let result; if (hasPackageLock) { result = yield runInstall("ci", p, gi); } else { result = yield runInstall("i", p, gi); } installed = result.code === 0; } // Cache the node_modules folder if (installed && _.get(gi, "configuration.sdm.cache.enabled") === true) { const tempCacheFileName = `${cacheFileName}.${automation_client_1.guid().slice(0, 7)}`; const result = yield compress(tempCacheFileName, p, gi); if (result.code === 0) { yield fs.move(tempCacheFileName, cacheFileName, { overwrite: true }); } } }); } function runInstall(cmd, p, gi) { return __awaiter(this, void 0, void 0, function* () { return sdm_1.spawnLog("npm", [cmd], { cwd: p.baseDir, env: Object.assign({}, process.env, { NODE_ENV: "development" }), log: gi.progressLog, }); }); } function compress(name, p, gi) { return __awaiter(this, void 0, void 0, function* () { return sdm_1.spawnLog("tar", ["-zcf", name, "node_modules"], { cwd: p.baseDir, log: gi.progressLog, }); }); } function extract(name, p, gi) { return __awaiter(this, void 0, void 0, function* () { return sdm_1.spawnLog("tar", ["-xf", name], { cwd: p.baseDir, log: gi.progressLog, }); }); } //# sourceMappingURL=npmBuilder.js.map