fix: actions in slack notification

This commit is contained in:
vincent-tarrit
2026-03-23 18:44:14 +01:00
parent 6fb4a13a18
commit a322ac374c
2 changed files with 772 additions and 776 deletions
@@ -5,408 +5,406 @@ import { renderAsync } from "@react-email/components";
import { format } from "date-fns"; import { format } from "date-fns";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { import {
sendCustomNotification, sendCustomNotification,
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification, sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendPushoverNotification, sendPushoverNotification,
sendResendNotification, sendResendNotification,
sendSlackNotification, sendSlackNotification,
sendTeamsNotification, sendTeamsNotification,
sendTelegramNotification, sendTelegramNotification,
} from "./utils"; } from "./utils";
interface Props { interface Props {
projectName: string; projectName: string;
applicationName: string; applicationName: string;
applicationType: string; applicationType: string;
errorMessage: string; errorMessage: string;
buildLink: string; buildLink: string;
organizationId: string; organizationId: string;
} }
export const sendBuildErrorNotifications = async ({ export const sendBuildErrorNotifications = async ({
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
errorMessage, errorMessage,
buildLink, buildLink,
organizationId, organizationId,
}: Props) => { }: Props) => {
const date = new Date(); const date = new Date();
const unixDate = ~~(Number(date) / 1000); const unixDate = ~~(Number(date) / 1000);
const notificationList = await db.query.notifications.findMany({ const notificationList = await db.query.notifications.findMany({
where: and( where: and(
eq(notifications.appBuildError, true), eq(notifications.appBuildError, true),
eq(notifications.organizationId, organizationId), eq(notifications.organizationId, organizationId),
), ),
with: { with: {
email: true, email: true,
discord: true, discord: true,
telegram: true, telegram: true,
slack: true, slack: true,
resend: true, resend: true,
gotify: true, gotify: true,
ntfy: true, ntfy: true,
custom: true, custom: true,
lark: true, lark: true,
pushover: true, pushover: true,
teams: true, teams: true,
}, },
}); });
for (const notification of notificationList) { for (const notification of notificationList) {
const { const {
email, email,
resend, resend,
discord, discord,
telegram, telegram,
slack, slack,
gotify, gotify,
ntfy, ntfy,
custom, custom,
lark, lark,
pushover, pushover,
teams, teams,
} = notification; } = notification;
try { try {
if (email || resend) { if (email || resend) {
const template = await renderAsync( const template = await renderAsync(
BuildFailedEmail({ BuildFailedEmail({
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
errorMessage: errorMessage, errorMessage: errorMessage,
buildLink, buildLink,
date: date.toLocaleString(), date: date.toLocaleString(),
}), }),
).catch(); ).catch();
if (email) { if (email) {
await sendEmailNotification( await sendEmailNotification(
email, email,
"Build failed for dokploy", "Build failed for dokploy",
template, template,
); );
} }
if (resend) { if (resend) {
await sendResendNotification( await sendResendNotification(
resend, resend,
"Build failed for dokploy", "Build failed for dokploy",
template, template,
); );
} }
} }
if (discord) { if (discord) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${discord.decoration ? decoration : ""} ${text}`.trim(); `${discord.decoration ? decoration : ""} ${text}`.trim();
const limitCharacter = 800; const limitCharacter = 800;
const truncatedErrorMessage = errorMessage.substring(0, limitCharacter); const truncatedErrorMessage = errorMessage.substring(0, limitCharacter);
await sendDiscordNotification(discord, { await sendDiscordNotification(discord, {
title: decorate(">", "`⚠️` Build Failed"), title: decorate(">", "`⚠️` Build Failed"),
color: 0xed4245, color: 0xed4245,
fields: [ fields: [
{ {
name: decorate("`🛠️`", "Project"), name: decorate("`🛠️`", "Project"),
value: projectName, value: projectName,
inline: true, inline: true,
}, },
{ {
name: decorate("`⚙️`", "Application"), name: decorate("`⚙️`", "Application"),
value: applicationName, value: applicationName,
inline: true, inline: true,
}, },
{ {
name: decorate("`❔`", "Type"), name: decorate("`❔`", "Type"),
value: applicationType, value: applicationType,
inline: true, inline: true,
}, },
{ {
name: decorate("`📅`", "Date"), name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`, value: `<t:${unixDate}:D>`,
inline: true, inline: true,
}, },
{ {
name: decorate("`⌚`", "Time"), name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`, value: `<t:${unixDate}:t>`,
inline: true, inline: true,
}, },
{ {
name: decorate("`❓`", "Type"), name: decorate("`❓`", "Type"),
value: "Failed", value: "Failed",
inline: true, inline: true,
}, },
{ {
name: decorate("`⚠️`", "Error Message"), name: decorate("`⚠️`", "Error Message"),
value: `\`\`\`${truncatedErrorMessage}\`\`\``, value: `\`\`\`${truncatedErrorMessage}\`\`\``,
}, },
{ {
name: decorate("`🧷`", "Build Link"), name: decorate("`🧷`", "Build Link"),
value: `[Click here to access build link](${buildLink})`, value: `[Click here to access build link](${buildLink})`,
}, },
], ],
timestamp: date.toISOString(), timestamp: date.toISOString(),
footer: { footer: {
text: "Dokploy Build Notification", text: "Dokploy Build Notification",
}, },
}); });
} }
if (gotify) { if (gotify) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${gotify.decoration ? decoration : ""} ${text}\n`; `${gotify.decoration ? decoration : ""} ${text}\n`;
await sendGotifyNotification( await sendGotifyNotification(
gotify, gotify,
decorate("⚠️", "Build Failed"), decorate("⚠️", "Build Failed"),
`${decorate("🛠️", `Project: ${projectName}`)}` + `${decorate("🛠️", `Project: ${projectName}`)}` +
`${decorate("⚙️", `Application: ${applicationName}`)}` + `${decorate("⚙️", `Application: ${applicationName}`)}` +
`${decorate("❔", `Type: ${applicationType}`)}` + `${decorate("❔", `Type: ${applicationType}`)}` +
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` +
`${decorate("⚠️", `Error:\n${errorMessage}`)}` + `${decorate("⚠️", `Error:\n${errorMessage}`)}` +
`${decorate("🔗", `Build details:\n${buildLink}`)}`, `${decorate("🔗", `Build details:\n${buildLink}`)}`,
); );
} }
if (ntfy) { if (ntfy) {
await sendNtfyNotification( await sendNtfyNotification(
ntfy, ntfy,
"Build Failed", "Build Failed",
"warning", "warning",
`view, Build details, ${buildLink}, clear=true;`, `view, Build details, ${buildLink}, clear=true;`,
`🛠️Project: ${projectName}\n` + `🛠️Project: ${projectName}\n` +
`⚙️Application: ${applicationName}\n` + `⚙️Application: ${applicationName}\n` +
`❔Type: ${applicationType}\n` + `❔Type: ${applicationType}\n` +
`🕒Date: ${date.toLocaleString()}\n` + `🕒Date: ${date.toLocaleString()}\n` +
`⚠️Error:\n${errorMessage}`, `⚠️Error:\n${errorMessage}`,
); );
} }
if (telegram) { if (telegram) {
const inlineButton = [ const inlineButton = [
[ [
{ {
text: "Deployment Logs", text: "Deployment Logs",
url: buildLink, url: buildLink,
}, },
], ],
]; ];
await sendTelegramNotification( await sendTelegramNotification(
telegram, telegram,
`<b>⚠️ Build Failed</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`, `<b>⚠️ Build Failed</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`,
inlineButton, inlineButton,
); );
} }
if (slack) { if (slack) {
const { channel } = slack; const { channel } = slack;
await sendSlackNotification(slack, { await sendSlackNotification(slack, {
channel: channel, channel: channel,
attachments: [ attachments: [
{ {
color: "#FF0000", color: "#FF0000",
pretext: ":warning: *Build Failed*", pretext: ":warning: *Build Failed*",
fields: [ fields: [
{ {
title: "Project", title: "Project",
value: projectName, value: projectName,
short: true, short: true,
}, },
{ {
title: "Application", title: "Application",
value: applicationName, value: applicationName,
short: true, short: true,
}, },
{ {
title: "Type", title: "Type",
value: applicationType, value: applicationType,
short: true, short: true,
}, },
{ {
title: "Time", title: "Time",
value: date.toLocaleString(), value: date.toLocaleString(),
short: true, short: true,
}, },
{ {
title: "Error", title: "Error",
value: `\`\`\`${errorMessage}\`\`\``, value: `\`\`\`${errorMessage}\`\`\``,
short: false, short: false,
}, },
], {
actions: [ title: "Details",
{ value: `<${buildLink}|View Build Details>`,
type: "button", short: false,
text: "View Build Details", },
url: buildLink, ],
}, },
], ],
}, });
], }
});
}
if (custom) { if (custom) {
await sendCustomNotification(custom, { await sendCustomNotification(custom, {
title: "Build Error", title: "Build Error",
message: "Build failed with errors", message: "Build failed with errors",
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
errorMessage, errorMessage,
buildLink, buildLink,
timestamp: date.toISOString(), timestamp: date.toISOString(),
date: date.toLocaleString(), date: date.toLocaleString(),
status: "error", status: "error",
type: "build", type: "build",
}); });
} }
if (lark) { if (lark) {
const limitCharacter = 800; const limitCharacter = 800;
const truncatedErrorMessage = errorMessage.substring(0, limitCharacter); const truncatedErrorMessage = errorMessage.substring(0, limitCharacter);
await sendLarkNotification(lark, { await sendLarkNotification(lark, {
msg_type: "interactive", msg_type: "interactive",
card: { card: {
schema: "2.0", schema: "2.0",
config: { config: {
update_multi: true, update_multi: true,
style: { style: {
text_size: { text_size: {
normal_v2: { normal_v2: {
default: "normal", default: "normal",
pc: "normal", pc: "normal",
mobile: "heading", mobile: "heading",
}, },
}, },
}, },
}, },
header: { header: {
title: { title: {
tag: "plain_text", tag: "plain_text",
content: "⚠️ Build Failed", content: "⚠️ Build Failed",
}, },
subtitle: { subtitle: {
tag: "plain_text", tag: "plain_text",
content: "", content: "",
}, },
template: "red", template: "red",
padding: "12px 12px 12px 12px", padding: "12px 12px 12px 12px",
}, },
body: { body: {
direction: "vertical", direction: "vertical",
padding: "12px 12px 12px 12px", padding: "12px 12px 12px 12px",
elements: [ elements: [
{ {
tag: "column_set", tag: "column_set",
columns: [ columns: [
{ {
tag: "column", tag: "column",
width: "weighted", width: "weighted",
elements: [ elements: [
{ {
tag: "markdown", tag: "markdown",
content: `**Project:**\n${projectName}`, content: `**Project:**\n${projectName}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
{ {
tag: "markdown", tag: "markdown",
content: `**Type:**\n${applicationType}`, content: `**Type:**\n${applicationType}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
{ {
tag: "markdown", tag: "markdown",
content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``, content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
], ],
vertical_align: "top", vertical_align: "top",
weight: 1, weight: 1,
}, },
{ {
tag: "column", tag: "column",
width: "weighted", width: "weighted",
elements: [ elements: [
{ {
tag: "markdown", tag: "markdown",
content: `**Application:**\n${applicationName}`, content: `**Application:**\n${applicationName}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
{ {
tag: "markdown", tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`, content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
], ],
vertical_align: "top", vertical_align: "top",
weight: 1, weight: 1,
}, },
], ],
}, },
{ {
tag: "button", tag: "button",
text: { text: {
tag: "plain_text", tag: "plain_text",
content: "View Build Details", content: "View Build Details",
}, },
type: "danger", type: "danger",
width: "default", width: "default",
size: "medium", size: "medium",
behaviors: [ behaviors: [
{ {
type: "open_url", type: "open_url",
default_url: buildLink, default_url: buildLink,
pc_url: "", pc_url: "",
ios_url: "", ios_url: "",
android_url: "", android_url: "",
}, },
], ],
margin: "0px 0px 0px 0px", margin: "0px 0px 0px 0px",
}, },
], ],
}, },
}, },
}); });
} }
if (pushover) { if (pushover) {
await sendPushoverNotification( await sendPushoverNotification(
pushover, pushover,
"Build Failed", "Build Failed",
`Project: ${projectName}\nApplication: ${applicationName}\nType: ${applicationType}\nDate: ${date.toLocaleString()}\nError: ${errorMessage}`, `Project: ${projectName}\nApplication: ${applicationName}\nType: ${applicationType}\nDate: ${date.toLocaleString()}\nError: ${errorMessage}`,
); );
} }
if (teams) { if (teams) {
const limitCharacter = 800; const limitCharacter = 800;
const truncatedErrorMessage = errorMessage.substring(0, limitCharacter); const truncatedErrorMessage = errorMessage.substring(0, limitCharacter);
await sendTeamsNotification(teams, { await sendTeamsNotification(teams, {
title: "⚠️ Build Failed", title: "⚠️ Build Failed",
facts: [ facts: [
{ name: "Project", value: projectName }, { name: "Project", value: projectName },
{ name: "Application", value: applicationName }, { name: "Application", value: applicationName },
{ name: "Type", value: applicationType }, { name: "Type", value: applicationType },
{ name: "Date", value: format(date, "PP pp") }, { name: "Date", value: format(date, "PP pp") },
{ name: "Error Message", value: truncatedErrorMessage }, { name: "Error Message", value: truncatedErrorMessage },
], ],
potentialAction: { potentialAction: {
type: "Action.OpenUrl", type: "Action.OpenUrl",
title: "View Build Details", title: "View Build Details",
url: buildLink, url: buildLink,
}, },
}); });
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
} }
}; };
@@ -6,419 +6,417 @@ import { renderAsync } from "@react-email/components";
import { format } from "date-fns"; import { format } from "date-fns";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { import {
sendCustomNotification, sendCustomNotification,
sendDiscordNotification, sendDiscordNotification,
sendEmailNotification, sendEmailNotification,
sendGotifyNotification, sendGotifyNotification,
sendLarkNotification, sendLarkNotification,
sendNtfyNotification, sendNtfyNotification,
sendPushoverNotification, sendPushoverNotification,
sendResendNotification, sendResendNotification,
sendSlackNotification, sendSlackNotification,
sendTeamsNotification, sendTeamsNotification,
sendTelegramNotification, sendTelegramNotification,
} from "./utils"; } from "./utils";
interface Props { interface Props {
projectName: string; projectName: string;
applicationName: string; applicationName: string;
applicationType: string; applicationType: string;
buildLink: string; buildLink: string;
organizationId: string; organizationId: string;
domains: Domain[]; domains: Domain[];
environmentName: string; environmentName: string;
} }
export const sendBuildSuccessNotifications = async ({ export const sendBuildSuccessNotifications = async ({
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
buildLink, buildLink,
organizationId, organizationId,
domains, domains,
environmentName, environmentName,
}: Props) => { }: Props) => {
const date = new Date(); const date = new Date();
const unixDate = ~~(Number(date) / 1000); const unixDate = ~~(Number(date) / 1000);
const notificationList = await db.query.notifications.findMany({ const notificationList = await db.query.notifications.findMany({
where: and( where: and(
eq(notifications.appDeploy, true), eq(notifications.appDeploy, true),
eq(notifications.organizationId, organizationId), eq(notifications.organizationId, organizationId),
), ),
with: { with: {
email: true, email: true,
discord: true, discord: true,
telegram: true, telegram: true,
slack: true, slack: true,
resend: true, resend: true,
gotify: true, gotify: true,
ntfy: true, ntfy: true,
custom: true, custom: true,
lark: true, lark: true,
pushover: true, pushover: true,
teams: true, teams: true,
}, },
}); });
for (const notification of notificationList) { for (const notification of notificationList) {
const { const {
email, email,
resend, resend,
discord, discord,
telegram, telegram,
slack, slack,
gotify, gotify,
ntfy, ntfy,
custom, custom,
lark, lark,
pushover, pushover,
teams, teams,
} = notification; } = notification;
try { try {
if (email || resend) { if (email || resend) {
const template = await renderAsync( const template = await renderAsync(
BuildSuccessEmail({ BuildSuccessEmail({
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
buildLink, buildLink,
date: date.toLocaleString(), date: date.toLocaleString(),
environmentName, environmentName,
}), }),
).catch(); ).catch();
if (email) { if (email) {
await sendEmailNotification( await sendEmailNotification(
email, email,
"Build success for dokploy", "Build success for dokploy",
template, template,
); );
} }
if (resend) { if (resend) {
await sendResendNotification( await sendResendNotification(
resend, resend,
"Build success for dokploy", "Build success for dokploy",
template, template,
); );
} }
} }
if (discord) { if (discord) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${discord.decoration ? decoration : ""} ${text}`.trim(); `${discord.decoration ? decoration : ""} ${text}`.trim();
await sendDiscordNotification(discord, { await sendDiscordNotification(discord, {
title: decorate(">", "`✅` Build Successes"), title: decorate(">", "`✅` Build Successes"),
color: 0x57f287, color: 0x57f287,
fields: [ fields: [
{ {
name: decorate("`🛠️`", "Project"), name: decorate("`🛠️`", "Project"),
value: projectName, value: projectName,
inline: true, inline: true,
}, },
{ {
name: decorate("`⚙️`", "Application"), name: decorate("`⚙️`", "Application"),
value: applicationName, value: applicationName,
inline: true, inline: true,
}, },
{ {
name: decorate("`🌍`", "Environment"), name: decorate("`🌍`", "Environment"),
value: environmentName, value: environmentName,
inline: true, inline: true,
}, },
{ {
name: decorate("`❔`", "Type"), name: decorate("`❔`", "Type"),
value: applicationType, value: applicationType,
inline: true, inline: true,
}, },
{ {
name: decorate("`📅`", "Date"), name: decorate("`📅`", "Date"),
value: `<t:${unixDate}:D>`, value: `<t:${unixDate}:D>`,
inline: true, inline: true,
}, },
{ {
name: decorate("`⌚`", "Time"), name: decorate("`⌚`", "Time"),
value: `<t:${unixDate}:t>`, value: `<t:${unixDate}:t>`,
inline: true, inline: true,
}, },
{ {
name: decorate("`❓`", "Type"), name: decorate("`❓`", "Type"),
value: "Successful", value: "Successful",
inline: true, inline: true,
}, },
{ {
name: decorate("`🧷`", "Build Link"), name: decorate("`🧷`", "Build Link"),
value: `[Click here to access build link](${buildLink})`, value: `[Click here to access build link](${buildLink})`,
}, },
], ],
timestamp: date.toISOString(), timestamp: date.toISOString(),
footer: { footer: {
text: "Dokploy Build Notification", text: "Dokploy Build Notification",
}, },
}); });
} }
if (gotify) { if (gotify) {
const decorate = (decoration: string, text: string) => const decorate = (decoration: string, text: string) =>
`${gotify.decoration ? decoration : ""} ${text}\n`; `${gotify.decoration ? decoration : ""} ${text}\n`;
await sendGotifyNotification( await sendGotifyNotification(
gotify, gotify,
decorate("✅", "Build Success"), decorate("✅", "Build Success"),
`${decorate("🛠️", `Project: ${projectName}`)}` + `${decorate("🛠️", `Project: ${projectName}`)}` +
`${decorate("⚙️", `Application: ${applicationName}`)}` + `${decorate("⚙️", `Application: ${applicationName}`)}` +
`${decorate("🌍", `Environment: ${environmentName}`)}` + `${decorate("🌍", `Environment: ${environmentName}`)}` +
`${decorate("❔", `Type: ${applicationType}`)}` + `${decorate("❔", `Type: ${applicationType}`)}` +
`${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` +
`${decorate("🔗", `Build details:\n${buildLink}`)}`, `${decorate("🔗", `Build details:\n${buildLink}`)}`,
); );
} }
if (ntfy) { if (ntfy) {
await sendNtfyNotification( await sendNtfyNotification(
ntfy, ntfy,
"Build Success", "Build Success",
"white_check_mark", "white_check_mark",
`view, Build details, ${buildLink}, clear=true;`, `view, Build details, ${buildLink}, clear=true;`,
`🛠Project: ${projectName}\n` + `🛠Project: ${projectName}\n` +
`⚙️Application: ${applicationName}\n` + `⚙️Application: ${applicationName}\n` +
`🌍Environment: ${environmentName}\n` + `🌍Environment: ${environmentName}\n` +
`❔Type: ${applicationType}\n` + `❔Type: ${applicationType}\n` +
`🕒Date: ${date.toLocaleString()}`, `🕒Date: ${date.toLocaleString()}`,
); );
} }
if (telegram) { if (telegram) {
const chunkArray = <T>(array: T[], chunkSize: number): T[][] => const chunkArray = <T>(array: T[], chunkSize: number): T[][] =>
Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) => Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) =>
array.slice(i * chunkSize, i * chunkSize + chunkSize), array.slice(i * chunkSize, i * chunkSize + chunkSize),
); );
const inlineButton = [ const inlineButton = [
[ [
{ {
text: "Deployment Logs", text: "Deployment Logs",
url: buildLink, url: buildLink,
}, },
], ],
...chunkArray(domains, 2).map((chunk) => ...chunkArray(domains, 2).map((chunk) =>
chunk.map((data) => ({ chunk.map((data) => ({
text: data.host, text: data.host,
url: `${data.https ? "https" : "http"}://${data.host}`, url: `${data.https ? "https" : "http"}://${data.host}`,
})), })),
), ),
]; ];
await sendTelegramNotification( await sendTelegramNotification(
telegram, telegram,
`<b>✅ Build Success</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Environment:</b> ${environmentName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format( `<b>✅ Build Success</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Environment:</b> ${environmentName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(
date, date,
"PP", "PP",
)}\n<b>Time:</b> ${format(date, "pp")}`, )}\n<b>Time:</b> ${format(date, "pp")}`,
inlineButton, inlineButton,
); );
} }
if (slack) { if (slack) {
const { channel } = slack; const { channel } = slack;
await sendSlackNotification(slack, { await sendSlackNotification(slack, {
channel: channel, channel: channel,
attachments: [ attachments: [
{ {
color: "#00FF00", color: "#00FF00",
pretext: ":white_check_mark: *Build Success*", pretext: ":white_check_mark: *Build Success*",
fields: [ fields: [
{ {
title: "Project", title: "Project",
value: projectName, value: projectName,
short: true, short: true,
}, },
{ {
title: "Application", title: "Application",
value: applicationName, value: applicationName,
short: true, short: true,
}, },
{ {
title: "Environment", title: "Environment",
value: environmentName, value: environmentName,
short: true, short: true,
}, },
{ {
title: "Type", title: "Type",
value: applicationType, value: applicationType,
short: true, short: true,
}, },
{ {
title: "Time", title: "Time",
value: date.toLocaleString(), value: date.toLocaleString(),
short: true, short: true,
}, },
], {
actions: [ title: "Details",
{ value: `<${buildLink}|View Build Details>`,
type: "button", short: false,
text: "View Build Details", },
url: buildLink, ],
}, },
], ],
}, });
], }
});
}
if (custom) { if (custom) {
await sendCustomNotification(custom, { await sendCustomNotification(custom, {
title: "Build Success", title: "Build Success",
message: "Build completed successfully", message: "Build completed successfully",
projectName, projectName,
applicationName, applicationName,
applicationType, applicationType,
buildLink, buildLink,
timestamp: date.toISOString(), timestamp: date.toISOString(),
date: date.toLocaleString(), date: date.toLocaleString(),
domains: domains.map((domain) => domain.host).join(", "), domains: domains.map((domain) => domain.host).join(", "),
status: "success", status: "success",
type: "build", type: "build",
}); });
} }
if (lark) { if (lark) {
await sendLarkNotification(lark, { await sendLarkNotification(lark, {
msg_type: "interactive", msg_type: "interactive",
card: { card: {
schema: "2.0", schema: "2.0",
config: { config: {
update_multi: true, update_multi: true,
style: { style: {
text_size: { text_size: {
normal_v2: { normal_v2: {
default: "normal", default: "normal",
pc: "normal", pc: "normal",
mobile: "heading", mobile: "heading",
}, },
}, },
}, },
}, },
header: { header: {
title: { title: {
tag: "plain_text", tag: "plain_text",
content: "✅ Build Success", content: "✅ Build Success",
}, },
subtitle: { subtitle: {
tag: "plain_text", tag: "plain_text",
content: "", content: "",
}, },
template: "green", template: "green",
padding: "12px 12px 12px 12px", padding: "12px 12px 12px 12px",
}, },
body: { body: {
direction: "vertical", direction: "vertical",
padding: "12px 12px 12px 12px", padding: "12px 12px 12px 12px",
elements: [ elements: [
{ {
tag: "column_set", tag: "column_set",
columns: [ columns: [
{ {
tag: "column", tag: "column",
width: "weighted", width: "weighted",
elements: [ elements: [
{ {
tag: "markdown", tag: "markdown",
content: `**Project:**\n${projectName}`, content: `**Project:**\n${projectName}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
{ {
tag: "markdown", tag: "markdown",
content: `**Environment:**\n${environmentName}`, content: `**Environment:**\n${environmentName}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
{ {
tag: "markdown", tag: "markdown",
content: `**Type:**\n${applicationType}`, content: `**Type:**\n${applicationType}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
], ],
vertical_align: "top", vertical_align: "top",
weight: 1, weight: 1,
}, },
{ {
tag: "column", tag: "column",
width: "weighted", width: "weighted",
elements: [ elements: [
{ {
tag: "markdown", tag: "markdown",
content: `**Application:**\n${applicationName}`, content: `**Application:**\n${applicationName}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
{ {
tag: "markdown", tag: "markdown",
content: `**Date:**\n${format(date, "PP pp")}`, content: `**Date:**\n${format(date, "PP pp")}`,
text_align: "left", text_align: "left",
text_size: "normal_v2", text_size: "normal_v2",
}, },
], ],
vertical_align: "top", vertical_align: "top",
weight: 1, weight: 1,
}, },
], ],
}, },
{ {
tag: "button", tag: "button",
text: { text: {
tag: "plain_text", tag: "plain_text",
content: "View Build Details", content: "View Build Details",
}, },
type: "primary", type: "primary",
width: "default", width: "default",
size: "medium", size: "medium",
behaviors: [ behaviors: [
{ {
type: "open_url", type: "open_url",
default_url: buildLink, default_url: buildLink,
pc_url: "", pc_url: "",
ios_url: "", ios_url: "",
android_url: "", android_url: "",
}, },
], ],
margin: "0px 0px 0px 0px", margin: "0px 0px 0px 0px",
}, },
], ],
}, },
}, },
}); });
} }
if (pushover) { if (pushover) {
await sendPushoverNotification( await sendPushoverNotification(
pushover, pushover,
"Build Success", "Build Success",
`Project: ${projectName}\nApplication: ${applicationName}\nEnvironment: ${environmentName}\nType: ${applicationType}\nDate: ${date.toLocaleString()}`, `Project: ${projectName}\nApplication: ${applicationName}\nEnvironment: ${environmentName}\nType: ${applicationType}\nDate: ${date.toLocaleString()}`,
); );
} }
if (teams) { if (teams) {
await sendTeamsNotification(teams, { await sendTeamsNotification(teams, {
title: "✅ Build Success", title: "✅ Build Success",
facts: [ facts: [
{ name: "Project", value: projectName }, { name: "Project", value: projectName },
{ name: "Application", value: applicationName }, { name: "Application", value: applicationName },
{ name: "Environment", value: environmentName }, { name: "Environment", value: environmentName },
{ name: "Type", value: applicationType }, { name: "Type", value: applicationType },
{ name: "Date", value: format(date, "PP pp") }, { name: "Date", value: format(date, "PP pp") },
], ],
potentialAction: { potentialAction: {
type: "Action.OpenUrl", type: "Action.OpenUrl",
title: "View Build Details", title: "View Build Details",
url: buildLink, url: buildLink,
}, },
}); });
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
} }
}; };