Remove the admin update service, command, and related files, and update Docker configurations.
This commit is contained in:
@@ -1,247 +0,0 @@
|
||||
import { createCommand } from "@shared/lib/utils";
|
||||
import { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, ComponentType } from "discord.js";
|
||||
import { UpdateService } from "@shared/modules/admin/update.service";
|
||||
import {
|
||||
getCheckingEmbed,
|
||||
getNoUpdatesEmbed,
|
||||
getUpdatesAvailableMessage,
|
||||
getPreparingEmbed,
|
||||
getUpdatingEmbed,
|
||||
getCancelledEmbed,
|
||||
getTimeoutEmbed,
|
||||
getErrorEmbed,
|
||||
getRollbackSuccessEmbed,
|
||||
getRollbackFailedEmbed,
|
||||
getDeployNotAvailableEmbed,
|
||||
getDeployCheckingEmbed,
|
||||
getDeployProgressEmbed,
|
||||
getDeploySuccessEmbed,
|
||||
getDeployErrorEmbed
|
||||
} from "@/modules/admin/update.view";
|
||||
|
||||
export const update = createCommand({
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("update")
|
||||
.setDescription("Check for updates and restart the bot")
|
||||
.addSubcommand(sub =>
|
||||
sub.setName("check")
|
||||
.setDescription("Check for and apply available updates")
|
||||
.addBooleanOption(option =>
|
||||
option.setName("force")
|
||||
.setDescription("Force update even if no changes detected")
|
||||
.setRequired(false)
|
||||
)
|
||||
)
|
||||
.addSubcommand(sub =>
|
||||
sub.setName("rollback")
|
||||
.setDescription("Rollback to the previous version")
|
||||
)
|
||||
.addSubcommand(sub =>
|
||||
sub.setName("deploy")
|
||||
.setDescription("Pull latest code and rebuild container (production only)")
|
||||
)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
|
||||
|
||||
execute: async (interaction) => {
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
|
||||
if (subcommand === "rollback") {
|
||||
await handleRollback(interaction);
|
||||
} else if (subcommand === "deploy") {
|
||||
await handleDeploy(interaction);
|
||||
} else {
|
||||
await handleUpdate(interaction);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function handleUpdate(interaction: any) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
const force = interaction.options.getBoolean("force") || false;
|
||||
|
||||
try {
|
||||
// 1. Check for updates (now includes requirements in one call)
|
||||
await interaction.editReply({ embeds: [getCheckingEmbed()] });
|
||||
const updateInfo = await UpdateService.checkForUpdates();
|
||||
|
||||
if (!updateInfo.hasUpdates && !force) {
|
||||
await interaction.editReply({
|
||||
embeds: [getNoUpdatesEmbed(updateInfo.currentCommit)]
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Extract requirements from the combined response
|
||||
const { requirements } = updateInfo;
|
||||
const categories = UpdateService.categorizeChanges(requirements.changedFiles);
|
||||
|
||||
// 3. Show confirmation with details
|
||||
const { embeds, components } = getUpdatesAvailableMessage(
|
||||
updateInfo,
|
||||
requirements,
|
||||
categories,
|
||||
force
|
||||
);
|
||||
const response = await interaction.editReply({ embeds, components });
|
||||
|
||||
// 4. Wait for confirmation
|
||||
try {
|
||||
const confirmation = await response.awaitMessageComponent({
|
||||
filter: (i: any) => i.user.id === interaction.user.id,
|
||||
componentType: ComponentType.Button,
|
||||
time: 30000
|
||||
});
|
||||
|
||||
if (confirmation.customId === "confirm_update") {
|
||||
await confirmation.update({
|
||||
embeds: [getPreparingEmbed()],
|
||||
components: []
|
||||
});
|
||||
|
||||
// 5. Save rollback point
|
||||
const previousCommit = await UpdateService.saveRollbackPoint();
|
||||
|
||||
// 6. Prepare restart context
|
||||
await UpdateService.prepareRestartContext({
|
||||
channelId: interaction.channelId,
|
||||
userId: interaction.user.id,
|
||||
timestamp: Date.now(),
|
||||
runMigrations: requirements.needsMigrations,
|
||||
installDependencies: requirements.needsRootInstall || requirements.needsWebInstall,
|
||||
buildWebAssets: requirements.needsWebBuild,
|
||||
previousCommit: previousCommit.substring(0, 7),
|
||||
newCommit: updateInfo.latestCommit
|
||||
});
|
||||
|
||||
// 7. Show updating status
|
||||
await interaction.editReply({
|
||||
embeds: [getUpdatingEmbed(requirements)]
|
||||
});
|
||||
|
||||
// 8. Perform update
|
||||
await UpdateService.performUpdate(updateInfo.branch);
|
||||
|
||||
// 9. Trigger restart
|
||||
await UpdateService.triggerRestart();
|
||||
|
||||
} else {
|
||||
await confirmation.update({
|
||||
embeds: [getCancelledEmbed()],
|
||||
components: []
|
||||
});
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.message.includes("time")) {
|
||||
await interaction.editReply({
|
||||
embeds: [getTimeoutEmbed()],
|
||||
components: []
|
||||
});
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Update failed:", error);
|
||||
await interaction.editReply({
|
||||
embeds: [getErrorEmbed(error)],
|
||||
components: []
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRollback(interaction: any) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
try {
|
||||
const hasRollback = await UpdateService.hasRollbackPoint();
|
||||
|
||||
if (!hasRollback) {
|
||||
await interaction.editReply({
|
||||
embeds: [getRollbackFailedEmbed("No rollback point available. Rollback is only possible after a recent update.")]
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await UpdateService.rollback();
|
||||
|
||||
if (result.success) {
|
||||
await interaction.editReply({
|
||||
embeds: [getRollbackSuccessEmbed(result.message.split(" ").pop() || "unknown")]
|
||||
});
|
||||
|
||||
// Restart after rollback
|
||||
setTimeout(() => UpdateService.triggerRestart(), 1000);
|
||||
} else {
|
||||
await interaction.editReply({
|
||||
embeds: [getRollbackFailedEmbed(result.message)]
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Rollback failed:", error);
|
||||
await interaction.editReply({
|
||||
embeds: [getErrorEmbed(error)]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDeploy(interaction: any) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
try {
|
||||
// Check if deploy is available
|
||||
const available = await UpdateService.isDeployAvailable();
|
||||
if (!available) {
|
||||
await interaction.editReply({
|
||||
embeds: [getDeployNotAvailableEmbed()]
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Show checking status
|
||||
await interaction.editReply({
|
||||
embeds: [getDeployCheckingEmbed()]
|
||||
});
|
||||
|
||||
// Perform deployment with progress updates
|
||||
const result = await UpdateService.performDeploy((step) => {
|
||||
interaction.editReply({
|
||||
embeds: [getDeployProgressEmbed(step)]
|
||||
});
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
// Save restart context so we can notify on startup
|
||||
await UpdateService.prepareRestartContext({
|
||||
channelId: interaction.channelId,
|
||||
userId: interaction.user.id,
|
||||
timestamp: Date.now(),
|
||||
runMigrations: true, // Always check migrations on deploy
|
||||
installDependencies: false, // Handled by Docker build
|
||||
buildWebAssets: false, // Handled by Docker build
|
||||
previousCommit: result.previousCommit,
|
||||
newCommit: result.newCommit
|
||||
});
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [getDeploySuccessEmbed(
|
||||
result.previousCommit,
|
||||
result.newCommit,
|
||||
result.output
|
||||
)]
|
||||
});
|
||||
} else {
|
||||
await interaction.editReply({
|
||||
embeds: [getDeployErrorEmbed(result.error || "Unknown error")]
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Deploy failed:", error);
|
||||
await interaction.editReply({
|
||||
embeds: [getDeployErrorEmbed(error instanceof Error ? error.message : String(error))]
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,7 @@ const event: Event<Events.ClientReady> = {
|
||||
console.log(`Ready! Logged in as ${c.user.tag}`);
|
||||
schedulerService.start();
|
||||
|
||||
// Handle post-update tasks
|
||||
const { UpdateService } = await import("@shared/modules/admin/update.service");
|
||||
await UpdateService.handlePostRestart(c);
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
export interface RestartContext {
|
||||
channelId: string;
|
||||
userId: string;
|
||||
timestamp: number;
|
||||
runMigrations: boolean;
|
||||
installDependencies: boolean;
|
||||
buildWebAssets: boolean;
|
||||
previousCommit: string;
|
||||
newCommit: string;
|
||||
}
|
||||
|
||||
export interface UpdateCheckResult {
|
||||
needsRootInstall: boolean;
|
||||
needsWebInstall: boolean;
|
||||
needsWebBuild: boolean;
|
||||
needsMigrations: boolean;
|
||||
changedFiles: string[];
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
export interface UpdateInfo {
|
||||
hasUpdates: boolean;
|
||||
branch: string;
|
||||
currentCommit: string;
|
||||
latestCommit: string;
|
||||
commitCount: number;
|
||||
commits: CommitInfo[];
|
||||
}
|
||||
|
||||
export interface CommitInfo {
|
||||
hash: string;
|
||||
message: string;
|
||||
author: string;
|
||||
}
|
||||
@@ -1,419 +0,0 @@
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
|
||||
import { createInfoEmbed, createSuccessEmbed, createWarningEmbed, createErrorEmbed } from "@lib/embeds";
|
||||
import type { UpdateInfo, UpdateCheckResult } from "./update.types";
|
||||
|
||||
// Constants for UI
|
||||
const LOG_TRUNCATE_LENGTH = 800;
|
||||
const OUTPUT_TRUNCATE_LENGTH = 400;
|
||||
|
||||
function truncate(text: string, maxLength: number): string {
|
||||
if (!text) return "";
|
||||
return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
|
||||
}
|
||||
|
||||
// ============ Pre-Update Embeds ============
|
||||
|
||||
export function getCheckingEmbed() {
|
||||
return createInfoEmbed("🔍 Fetching latest changes from remote...", "Checking for Updates");
|
||||
}
|
||||
|
||||
export function getNoUpdatesEmbed(currentCommit: string) {
|
||||
return createSuccessEmbed(
|
||||
`You're running the latest version.\n\n**Current:** \`${currentCommit}\``,
|
||||
"✅ Already Up to Date"
|
||||
);
|
||||
}
|
||||
|
||||
export function getUpdatesAvailableMessage(
|
||||
updateInfo: UpdateInfo,
|
||||
requirements: UpdateCheckResult,
|
||||
changeCategories: Record<string, number>,
|
||||
force: boolean
|
||||
) {
|
||||
const { branch, currentCommit, latestCommit, commitCount, commits } = updateInfo;
|
||||
const { needsRootInstall, needsWebInstall, needsWebBuild, needsMigrations } = requirements;
|
||||
|
||||
// Build commit list (max 5)
|
||||
const commitList = commits
|
||||
.slice(0, 5)
|
||||
.map(c => `\`${c.hash}\` ${truncate(c.message, 50)}`)
|
||||
.join("\n");
|
||||
|
||||
const moreCommits = commitCount > 5 ? `\n*...and ${commitCount - 5} more*` : "";
|
||||
|
||||
// Build change categories
|
||||
const categoryList = Object.entries(changeCategories)
|
||||
.map(([cat, count]) => `• ${cat}: ${count} file${count > 1 ? "s" : ""}`)
|
||||
.join("\n");
|
||||
|
||||
// Build requirements list
|
||||
const reqs: string[] = [];
|
||||
if (needsRootInstall) reqs.push("📦 Install root dependencies");
|
||||
if (needsWebInstall) reqs.push("🌐 Install web dependencies");
|
||||
if (needsWebBuild) reqs.push("🏗️ Build web dashboard");
|
||||
if (needsMigrations) reqs.push("🗃️ Run database migrations");
|
||||
if (reqs.length === 0) reqs.push("⚡ Quick update (no extra steps)");
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("📥 Updates Available")
|
||||
.setColor(force ? 0xFF6B6B : 0x5865F2)
|
||||
.addFields(
|
||||
{
|
||||
name: "Version",
|
||||
value: `\`${currentCommit}\` → \`${latestCommit}\``,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Branch",
|
||||
value: `\`${branch}\``,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Commits",
|
||||
value: `${commitCount} new commit${commitCount > 1 ? "s" : ""}`,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Recent Changes",
|
||||
value: commitList + moreCommits || "No commits",
|
||||
inline: false
|
||||
},
|
||||
{
|
||||
name: "Files Changed",
|
||||
value: categoryList || "Unknown",
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Update Actions",
|
||||
value: reqs.join("\n"),
|
||||
inline: true
|
||||
}
|
||||
)
|
||||
.setFooter({ text: force ? "⚠️ Force mode enabled" : "This will restart the bot" })
|
||||
.setTimestamp();
|
||||
|
||||
const confirmButton = new ButtonBuilder()
|
||||
.setCustomId("confirm_update")
|
||||
.setLabel(force ? "Force Update" : "Update Now")
|
||||
.setEmoji(force ? "⚠️" : "🚀")
|
||||
.setStyle(force ? ButtonStyle.Danger : ButtonStyle.Success);
|
||||
|
||||
const cancelButton = new ButtonBuilder()
|
||||
.setCustomId("cancel_update")
|
||||
.setLabel("Cancel")
|
||||
.setStyle(ButtonStyle.Secondary);
|
||||
|
||||
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(confirmButton, cancelButton);
|
||||
|
||||
return { embeds: [embed], components: [row] };
|
||||
}
|
||||
|
||||
// ============ Update Progress Embeds ============
|
||||
|
||||
export function getPreparingEmbed() {
|
||||
return createInfoEmbed(
|
||||
"🔒 Saving rollback point...\n📥 Preparing to download updates...",
|
||||
"⏳ Preparing Update"
|
||||
);
|
||||
}
|
||||
|
||||
export function getUpdatingEmbed(requirements: UpdateCheckResult) {
|
||||
const steps: string[] = ["✅ Rollback point saved"];
|
||||
|
||||
steps.push("📥 Downloading updates...");
|
||||
|
||||
if (requirements.needsRootInstall || requirements.needsWebInstall) {
|
||||
steps.push("📦 Dependencies will be installed after restart");
|
||||
}
|
||||
if (requirements.needsWebBuild) {
|
||||
steps.push("🏗️ Web dashboard will be rebuilt after restart");
|
||||
}
|
||||
if (requirements.needsMigrations) {
|
||||
steps.push("🗃️ Migrations will run after restart");
|
||||
}
|
||||
|
||||
steps.push("\n🔄 **Restarting now...**");
|
||||
|
||||
return createWarningEmbed(steps.join("\n"), "🚀 Updating");
|
||||
}
|
||||
|
||||
export function getCancelledEmbed() {
|
||||
return createInfoEmbed("Update cancelled. No changes were made.", "❌ Cancelled");
|
||||
}
|
||||
|
||||
export function getTimeoutEmbed() {
|
||||
return createWarningEmbed(
|
||||
"No response received within 30 seconds.\nRun `/update` again when ready.",
|
||||
"⏰ Timed Out"
|
||||
);
|
||||
}
|
||||
|
||||
export function getErrorEmbed(error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
return createErrorEmbed(
|
||||
`The update could not be completed:\n\`\`\`\n${truncate(message, 500)}\n\`\`\``,
|
||||
"❌ Update Failed"
|
||||
);
|
||||
}
|
||||
|
||||
// ============ Post-Restart Embeds ============
|
||||
|
||||
export interface PostRestartResult {
|
||||
installSuccess: boolean;
|
||||
installOutput: string;
|
||||
webBuildSuccess: boolean;
|
||||
webBuildOutput: string;
|
||||
migrationSuccess: boolean;
|
||||
migrationOutput: string;
|
||||
ranInstall: boolean;
|
||||
ranWebBuild: boolean;
|
||||
ranMigrations: boolean;
|
||||
previousCommit?: string;
|
||||
newCommit?: string;
|
||||
}
|
||||
|
||||
export function getPostRestartEmbed(result: PostRestartResult, hasRollback: boolean) {
|
||||
const isSuccess = result.installSuccess && result.webBuildSuccess && result.migrationSuccess;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(isSuccess ? "✅ Update Complete" : "⚠️ Update Completed with Issues")
|
||||
.setColor(isSuccess ? 0x57F287 : 0xFEE75C)
|
||||
.setTimestamp();
|
||||
|
||||
// Version info
|
||||
if (result.previousCommit && result.newCommit) {
|
||||
embed.addFields({
|
||||
name: "Version",
|
||||
value: `\`${result.previousCommit}\` → \`${result.newCommit}\``,
|
||||
inline: false
|
||||
});
|
||||
}
|
||||
|
||||
// Results summary
|
||||
const results: string[] = [];
|
||||
|
||||
if (result.ranInstall) {
|
||||
results.push(result.installSuccess
|
||||
? "✅ Dependencies installed"
|
||||
: "❌ Dependency installation failed"
|
||||
);
|
||||
}
|
||||
|
||||
if (result.ranWebBuild) {
|
||||
results.push(result.webBuildSuccess
|
||||
? "✅ Web dashboard built"
|
||||
: "❌ Web dashboard build failed"
|
||||
);
|
||||
}
|
||||
|
||||
if (result.ranMigrations) {
|
||||
results.push(result.migrationSuccess
|
||||
? "✅ Migrations applied"
|
||||
: "❌ Migration failed"
|
||||
);
|
||||
}
|
||||
|
||||
if (results.length > 0) {
|
||||
embed.addFields({
|
||||
name: "Actions Performed",
|
||||
value: results.join("\n"),
|
||||
inline: false
|
||||
});
|
||||
}
|
||||
|
||||
// Output details (collapsed if too long)
|
||||
if (result.installOutput && !result.installSuccess) {
|
||||
embed.addFields({
|
||||
name: "Install Output",
|
||||
value: `\`\`\`\n${truncate(result.installOutput, OUTPUT_TRUNCATE_LENGTH)}\n\`\`\``,
|
||||
inline: false
|
||||
});
|
||||
}
|
||||
|
||||
if (result.webBuildOutput && !result.webBuildSuccess) {
|
||||
embed.addFields({
|
||||
name: "Web Build Output",
|
||||
value: `\`\`\`\n${truncate(result.webBuildOutput, OUTPUT_TRUNCATE_LENGTH)}\n\`\`\``,
|
||||
inline: false
|
||||
});
|
||||
}
|
||||
|
||||
if (result.migrationOutput && !result.migrationSuccess) {
|
||||
embed.addFields({
|
||||
name: "Migration Output",
|
||||
value: `\`\`\`\n${truncate(result.migrationOutput, OUTPUT_TRUNCATE_LENGTH)}\n\`\`\``,
|
||||
inline: false
|
||||
});
|
||||
}
|
||||
|
||||
// Footer with rollback hint
|
||||
if (!isSuccess && hasRollback) {
|
||||
embed.setFooter({ text: "💡 Use /update rollback to revert if needed" });
|
||||
}
|
||||
|
||||
// Build components
|
||||
const components: ActionRowBuilder<ButtonBuilder>[] = [];
|
||||
|
||||
if (!isSuccess && hasRollback) {
|
||||
const rollbackButton = new ButtonBuilder()
|
||||
.setCustomId("rollback_update")
|
||||
.setLabel("Rollback")
|
||||
.setEmoji("↩️")
|
||||
.setStyle(ButtonStyle.Danger);
|
||||
|
||||
components.push(new ActionRowBuilder<ButtonBuilder>().addComponents(rollbackButton));
|
||||
}
|
||||
|
||||
return { embeds: [embed], components };
|
||||
}
|
||||
|
||||
export function getInstallingDependenciesEmbed() {
|
||||
return createInfoEmbed(
|
||||
"📦 Installing dependencies for root and web projects...\nThis may take a moment.",
|
||||
"⏳ Installing Dependencies"
|
||||
);
|
||||
}
|
||||
|
||||
export function getRunningMigrationsEmbed() {
|
||||
return createInfoEmbed(
|
||||
"🗃️ Applying database migrations...",
|
||||
"⏳ Running Migrations"
|
||||
);
|
||||
}
|
||||
|
||||
export function getBuildingWebEmbed() {
|
||||
return createInfoEmbed(
|
||||
"🌐 Building web dashboard assets...\nThis may take a moment.",
|
||||
"⏳ Building Web Dashboard"
|
||||
);
|
||||
}
|
||||
|
||||
export interface PostRestartProgress {
|
||||
installDeps: boolean;
|
||||
buildWeb: boolean;
|
||||
runMigrations: boolean;
|
||||
currentStep: "starting" | "install" | "build" | "migrate" | "done";
|
||||
installDone?: boolean;
|
||||
buildDone?: boolean;
|
||||
migrateDone?: boolean;
|
||||
}
|
||||
|
||||
export function getPostRestartProgressEmbed(progress: PostRestartProgress) {
|
||||
const steps: string[] = [];
|
||||
|
||||
// Installation step
|
||||
if (progress.installDeps) {
|
||||
if (progress.currentStep === "install") {
|
||||
steps.push("⏳ Installing dependencies...");
|
||||
} else if (progress.installDone) {
|
||||
steps.push("✅ Dependencies installed");
|
||||
} else {
|
||||
steps.push("⬚ Install dependencies");
|
||||
}
|
||||
}
|
||||
|
||||
// Web build step
|
||||
if (progress.buildWeb) {
|
||||
if (progress.currentStep === "build") {
|
||||
steps.push("⏳ Building web dashboard...");
|
||||
} else if (progress.buildDone) {
|
||||
steps.push("✅ Web dashboard built");
|
||||
} else {
|
||||
steps.push("⬚ Build web dashboard");
|
||||
}
|
||||
}
|
||||
|
||||
// Migrations step
|
||||
if (progress.runMigrations) {
|
||||
if (progress.currentStep === "migrate") {
|
||||
steps.push("⏳ Running migrations...");
|
||||
} else if (progress.migrateDone) {
|
||||
steps.push("✅ Migrations applied");
|
||||
} else {
|
||||
steps.push("⬚ Run migrations");
|
||||
}
|
||||
}
|
||||
|
||||
if (steps.length === 0) {
|
||||
steps.push("⚡ Quick restart (no extra steps needed)");
|
||||
}
|
||||
|
||||
return createInfoEmbed(steps.join("\n"), "🔄 Post-Update Tasks");
|
||||
}
|
||||
|
||||
export function getRollbackSuccessEmbed(commit: string) {
|
||||
return createSuccessEmbed(
|
||||
`Successfully rolled back to commit \`${commit}\`.\nThe bot will restart now.`,
|
||||
"↩️ Rollback Complete"
|
||||
);
|
||||
}
|
||||
|
||||
export function getRollbackFailedEmbed(error: string) {
|
||||
return createErrorEmbed(
|
||||
`Could not rollback:\n\`\`\`\n${error}\n\`\`\``,
|
||||
"❌ Rollback Failed"
|
||||
);
|
||||
}
|
||||
|
||||
// ============ Deploy Embeds ============
|
||||
|
||||
export function getDeployNotAvailableEmbed() {
|
||||
return createErrorEmbed(
|
||||
"Docker is not available in this environment.\n\n" +
|
||||
"Deploy via Discord requires Docker socket access. " +
|
||||
"Use the deploy script manually:\n" +
|
||||
"```bash\ncd ~/Aurora && bash shared/scripts/deploy.sh\n```",
|
||||
"❌ Deploy Unavailable"
|
||||
);
|
||||
}
|
||||
|
||||
export function getDeployCheckingEmbed() {
|
||||
return createInfoEmbed(
|
||||
"🔍 Checking for updates and preparing deployment...",
|
||||
"🚀 Deploy"
|
||||
);
|
||||
}
|
||||
|
||||
export function getDeployProgressEmbed(step: string) {
|
||||
return createInfoEmbed(
|
||||
step,
|
||||
"🚀 Deploying"
|
||||
);
|
||||
}
|
||||
|
||||
export function getDeploySuccessEmbed(previousCommit: string, newCommit: string, output: string) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🚀 Deployment Triggered")
|
||||
.setColor(0x57F287)
|
||||
.addFields(
|
||||
{
|
||||
name: "Version",
|
||||
value: `\`${previousCommit}\` → \`${newCommit}\``,
|
||||
inline: false
|
||||
},
|
||||
{
|
||||
name: "Status",
|
||||
value: output || "Container rebuilding...",
|
||||
inline: false
|
||||
}
|
||||
)
|
||||
.setFooter({ text: "Container will restart shortly" })
|
||||
.setTimestamp();
|
||||
|
||||
return embed;
|
||||
}
|
||||
|
||||
export function getDeployNoChangesEmbed(currentCommit: string) {
|
||||
return createSuccessEmbed(
|
||||
`Already running the latest version.\n\n**Current:** \`${currentCommit}\``,
|
||||
"✅ Up to Date"
|
||||
);
|
||||
}
|
||||
|
||||
export function getDeployErrorEmbed(error: string) {
|
||||
return createErrorEmbed(
|
||||
`Deployment failed:\n\`\`\`\n${truncate(error, 500)}\n\`\`\``,
|
||||
"❌ Deploy Failed"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user