@topgroup/diginext
Version:
A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.
221 lines (220 loc) • 9.51 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.requestBuild = void 0;
const chalk_1 = __importDefault(require("chalk"));
const log_1 = require("diginext-utils/dist/xconsole/log");
const socket_io_client_1 = require("socket.io-client");
const config_1 = require("../../config/config");
const fetchApi_1 = require("../../modules/api/fetchApi");
const plugins_1 = require("../../plugins");
const ask_project_and_app_1 = require("../apps/ask-project-and-app");
const update_git_config_1 = require("../apps/update-git-config");
const create_build_slug_1 = require("../deploy/create-build-slug");
const git_utils_1 = require("../git/git-utils");
const ask_for_registry_1 = require("../registry/ask-for-registry");
const generate_build_tag_1 = require("./generate-build-tag");
/**
* Request the build server to start building & deploying
*/
async function requestBuild(options) {
var _a;
if (process.env.CLI_MODE === "server") {
(0, log_1.logError)(`This command is only available at CLIENT MODE.`);
return;
}
const { DB } = await Promise.resolve().then(() => __importStar(require("../../modules/api/DB")));
if (!options.targetDirectory)
options.targetDirectory = process.cwd();
// ask for project & app information
let project, app;
if (!options.appSlug) {
let { project: _project, app: _app } = await (0, ask_project_and_app_1.askForProjectAndApp)(options.targetDirectory, options);
project = _project;
app = _app;
if (options.isDebugging)
console.log("askForDeployEnvironmentInfo > app :>> ", app);
if (options.isDebugging)
console.log("askForDeployEnvironmentInfo > project :>> ", project);
options.appSlug = app.slug;
options.projectSlug = app.projectSlug;
}
// verify if this app's directory has any git remote integrated
const gitInfo = await (0, plugins_1.getCurrentGitRepoData)(options.targetDirectory);
if (options.isDebugging)
console.log("askForDeployEnvironmentInfo > gitInfo :>> ", gitInfo);
if (!gitInfo) {
(0, log_1.logError)(`This app's directory doesn't have any git remote integrated.`);
return;
}
const gitBranch = gitInfo.branch;
if (!app.git || !app.git.provider || !app.git.repoSSH || !app.git.repoURL) {
const updateGitInfo = { provider: gitInfo.provider, repoSSH: gitInfo.repoSSH, repoURL: gitInfo.repoURL };
if (options.isDebugging)
console.log("askForDeployEnvironmentInfo > updateGitInfo :>> ", updateGitInfo);
app = await (0, update_git_config_1.updateAppGitInfo)(app, updateGitInfo);
if (options.isDebugging)
console.log("askForDeployEnvironmentInfo > app :>> ", app);
}
// container registry
let registry;
if (typeof options.registry === "boolean" || typeof options.registry === "undefined") {
registry = await (0, ask_for_registry_1.askForRegistry)();
options.registry = registry.slug;
}
else {
registry = await DB.findOne("registry", { slug: options.registry }, { subpath: "/all" });
}
if (!registry) {
(0, log_1.logError)(`Container Registry "${options.registry}" not found.`);
return;
}
//
const { buildServerUrl } = (0, config_1.getCliConfig)();
const { env, targetDirectory } = options;
const START_BUILD_API_PATH = `${buildServerUrl}/api/v1/build/start`;
// check Dockerfile -> no dockerfile, no build -> failed
let dockerFile = (0, plugins_1.resolveDockerfilePath)({ targetDirectory, env });
if (!dockerFile)
return;
/**
* Generate build number & build image as docker image tag
*/
const imageURL = `${registry.imageBaseURL}/${app.projectSlug}-${app.slug}`;
const tagInfo = await (0, generate_build_tag_1.generateBuildTagBySourceDir)(options.targetDirectory, { branch: options.gitBranch });
if (options.isDebugging)
console.log("tagInfo :>> ", tagInfo);
options.buildTag = tagInfo.tag;
options.buildImage = `${imageURL}:${options.buildTag}`;
if (options.isDebugging)
console.log("options.buildTag :>> ", options.buildTag);
const SOCKET_ROOM = (0, create_build_slug_1.createBuildSlug)({ projectSlug: project.slug, appSlug: app.slug, buildTag: options.buildTag });
/**
* Stage, commit & push configuration files (dx.json) to GIT repository:
*/
try {
await (0, git_utils_1.stageCommitAndPushAll)({
directory: options.targetDirectory,
message: `build(${env}): ${options.buildImage}`,
});
}
catch (e) {
// Stop the process if this throws any errors
(0, log_1.logError)(`Can't commit files for building this app: ${e}`);
return;
}
/**
* [5] Notify the commander & call API to request server build:
*/
(0, log_1.log)(`Requesting Diginext Server to build this app: "${app.projectSlug}/${app.slug}" (branch: "${gitBranch}")`);
// const deployOptions = JSON.stringify(options);
const requestBuildData = {
gitBranch: gitBranch,
buildTag: options.buildTag,
buildNumber: tagInfo.number,
registrySlug: registry.slug,
appSlug: app.slug,
};
if (options.isDebugging) {
console.log("Request build data :>> ");
console.dir(requestBuildData, { depth: 10 });
}
try {
const requestResult = await (0, fetchApi_1.fetchApi)({
url: START_BUILD_API_PATH,
method: "POST",
data: requestBuildData,
});
if (options.isDebugging) {
console.log("Request build result :>> ");
console.dir(requestResult, { depth: 10 });
}
if (!requestResult.status)
(0, log_1.logError)(requestResult.messages[0] || `Unable to process Request Build API.`);
(0, log_1.log)(`-> Check build status here: ${(_a = requestResult.data) === null || _a === void 0 ? void 0 : _a.logURL} `);
}
catch (e) {
(0, log_1.logError)(`Unable to call Build Deploy API:`, e);
return;
}
// update the project so it can be sorted on top
try {
await DB.updateOne("project", { slug: app.projectSlug }, { lastUpdatedBy: options.username });
}
catch (e) {
(0, log_1.logWarn)(e);
}
// friendly reminder
if (env == "prod")
(0, log_1.log)(chalk_1.default.red(`⚠️⚠️⚠️ REMEMBER TO CREATE PULL REQUEST TO "master" (or "main") BRANCH ⚠️⚠️⚠️`));
if (options.isTail) {
let socketURL = buildServerUrl.replace(/https/gi, "wss");
socketURL = buildServerUrl.replace(/http/gi, "ws");
const socket = (0, socket_io_client_1.io)(socketURL, { transports: ["websocket"], timeout: 60000 });
socket.on("error", (e) => (0, log_1.logError)(e));
socket.on("connect_error", (e) => (0, log_1.logError)(e));
socket.on("disconnect", () => {
// log("[CLI Server] Disconnected");
socket.emit("leave", { room: SOCKET_ROOM });
});
socket.on("connect", () => {
// log("[CLI Server] Connected");
socket.emit("join", { room: SOCKET_ROOM });
});
return new Promise((resolve, reject) => {
socket.on("message", ({ action, message, type }) => {
if (message) {
const errorWordIndex = message.toLowerCase().indexOf("error");
if (errorWordIndex > -1) {
(0, log_1.logWarn)(message);
}
else {
(0, log_1.log)(message);
}
}
if (action == "end") {
socket.disconnect();
if (type === "error") {
// process.exit(1);
reject(message);
}
else {
// process.exit(0);
resolve(true);
}
}
});
// Max build duration: 30 mins
setTimeout(() => reject(`Request timeout (30 minutes)`), 30 * 60 * 1000);
});
}
else {
return true;
}
}
exports.requestBuild = requestBuild;