UNPKG

@topgroup/diginext

Version:

A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.

181 lines (180 loc) 10.9 kB
"use strict"; 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.WebhookService = void 0; const humanize_duration_1 = __importDefault(require("humanize-duration")); const app_config_1 = require("../app.config"); const Webhook_1 = require("../entities/Webhook"); const create_build_slug_1 = require("../modules/deploy/create-build-slug"); const mongodb_1 = require("../plugins/mongodb"); const BaseService_1 = __importDefault(require("./BaseService")); const NotificationService_1 = require("./NotificationService"); class WebhookService extends BaseService_1.default { constructor(ownership) { super(Webhook_1.webhookSchema, ownership); this.notiSvc = new NotificationService_1.NotificationService(ownership); } async create(data, options) { if (!data.events) throw new Error(`Webhook "events" (Array) is required.`); if (!data.channels) data.channels = ["email"]; if (!data.consumers) data.consumers = []; data.consumers.forEach((userId) => { if (!mongodb_1.MongoDB.isValidObjectId(userId)) throw new Error(`Invalid "consumers" array, should be a valid list of user ID.`); }); data.events.forEach((event) => { switch (event) { case "build_status": if (!data.build) throw new Error(`Missing a referenced "build" associated with the webhook event "${event}".`); break; case "deploy_status": if (!data.release) throw new Error(`Missing a referenced "release" associated with the webhook event "${event}".`); break; default: break; } }); return super.create(data, options); } /** * Trigger a webhook & send the notification * @param id - Webhook ID * @param status - Webhook event status */ async trigger(id, status, options) { // validate if (!id) throw new Error(`Webhook "id" is required.`); if (!status) throw new Error(`Webhook "status" is required.`); const webhook = await this.updateOne({ _id: id }, { status }, options); if (!webhook) throw new Error(`Webhook not found.`); // process const { DB } = await Promise.resolve().then(() => __importStar(require("../modules/api/DB"))); this.notiSvc.ownership = this.ownership; return Promise.all(webhook.events.map((event) => { switch (event) { case "build_status": if (webhook.status === "failed" || webhook.status === "success") { return DB.findOne("build", { _id: webhook.build }, { populate: ["workspace", "owner", "project", "app"] }) .then((build) => { if (!build) throw new Error(`Build not found.`); const { projectSlug, appSlug, tag: buildTag } = build; const SOCKET_ROOM = (0, create_build_slug_1.createBuildSlug)({ projectSlug, appSlug, buildTag }); const logURL = `${app_config_1.Config.BASE_URL}/build/logs?build_slug=${SOCKET_ROOM}`; const duration = (0, humanize_duration_1.default)(build.duration); const owner = build.owner; return this.notiSvc .webhookSend(webhook, { references: { build: mongodb_1.MongoDB.toString(build._id) }, url: logURL, from: mongodb_1.MongoDB.toString(webhook.owner), to: webhook.consumers.map((recipientId) => mongodb_1.MongoDB.toString(recipientId)), title: webhook.status === "failed" ? `Build failed: ${build === null || build === void 0 ? void 0 : build.name}` : `Build success: ${build === null || build === void 0 ? void 0 : build.name}`, message: `- Workspace: ${this.ownership.workspace.name}<br/>- Project: ${(build === null || build === void 0 ? void 0 : build.project).name}<br/>- App: ${(build === null || build === void 0 ? void 0 : build.app).name}<br/>- User: ${owner.name} (${owner.slug})<br/>- Duration: ${duration}<br/>- View logs: <a href="${logURL}">CLICK HERE</a><br/>- Container image: ${build === null || build === void 0 ? void 0 : build.image}`, }) .catch((e) => { console.error(`Unable to trigger webhook:`, e); }); }) .catch((e) => { console.error(`Build not found:`, e); }); } break; case "deploy_status": if (webhook.status === "failed" || webhook.status === "success") { return DB.findOne("release", { _id: webhook.release }, { populate: ["workspace", "owner", "project", "app", "build"] }) .then((release) => { if (!release) throw new Error(`Release not found.`); const { build } = release; const { projectSlug, appSlug, tag: buildTag, duration: buildDuration } = build; const SOCKET_ROOM = (0, create_build_slug_1.createBuildSlug)({ projectSlug, appSlug, buildTag }); const buildListPageUrl = `${app_config_1.Config.BASE_URL}/build`; const logURL = `${app_config_1.Config.BASE_URL}/build/logs?build_slug=${SOCKET_ROOM}`; const duration = (0, humanize_duration_1.default)(buildDuration); const owner = release.owner; return this.notiSvc .webhookSend(webhook, { references: { release: mongodb_1.MongoDB.toString(release._id) }, url: logURL, from: mongodb_1.MongoDB.toString(webhook.owner), to: webhook.consumers.map((recipientId) => mongodb_1.MongoDB.toString(recipientId)), title: webhook.status === "failed" ? `Deploy failed: ${release === null || release === void 0 ? void 0 : release.name}` : `Deploy success: ${release === null || release === void 0 ? void 0 : release.name}`, message: (webhook.status === "failed" ? `Failed to deploy "${release === null || release === void 0 ? void 0 : release.appSlug}" app of "${release === null || release === void 0 ? void 0 : release.projectSlug}" project to "${release === null || release === void 0 ? void 0 : release.env.toUpperCase()}" environment.<br/>- View build logs: <a href="${logURL}">CLICK HERE</a><br/>- Duration: ${duration}` : `<strong>App has been deployed to "${release === null || release === void 0 ? void 0 : release.env.toUpperCase()}" environment successfully.</strong><br/><br/>- Workspace: ${(release === null || release === void 0 ? void 0 : release.workspace).name}<br/>- User: ${owner.name} (${owner.slug})<br/>- App: ${release === null || release === void 0 ? void 0 : release.appSlug}<br/>- Project: ${release === null || release === void 0 ? void 0 : release.projectSlug}<br/>- URL: <a href="https://${(release === null || release === void 0 ? void 0 : release.env) === "production" ? release === null || release === void 0 ? void 0 : release.prereleaseUrl : release === null || release === void 0 ? void 0 : release.productionUrl}">CLICK TO VIEW</a><br/>- View build logs: <a href="${logURL}">CLICK HERE</a><br/>- Duration: ${duration}<br/>- Container Image: ${release === null || release === void 0 ? void 0 : release.image}`) + `<br/><br/>Go to <a href="${buildListPageUrl}">DXUP Dashboard</a>.<br/><br/>Best regards, <a href="https://dxup.dev">DXUP</a> Team.`, }) .catch((e) => { console.error(`Unable to trigger webhook:`, e); }); }) .catch((e) => { console.error(`Release not found:`, e); }); } break; default: throw new Error(`Invalid webhook event: "${event}".`); break; } })); } /** * Subscribe a consumer to a webhook * @param id - Webhook ID * @param data - Subscription data */ async subscribe(id, consumers, options) { // validate if (!id) throw new Error(`Webhook ID is required.`); if (!consumers) throw new Error(`Webhook "consumers" (Array of UserID) is required.`); const webhook = await this.updateOne({ id }, // add consumers to existing webhook if it's not exists { $addToSet: { consumers: { $each: consumers }, }, }, { raw: true }); if (!webhook) throw new Error(`Webhook not found.`); return webhook; } } exports.WebhookService = WebhookService;