feat: add bot-triggered deployment via /update deploy command
Some checks failed
Deploy to Production / test (push) Failing after 20s
Deploy to Production / build (push) Has been skipped
Deploy to Production / deploy (push) Has been skipped

- Added Docker socket mount to docker-compose.prod.yml
- Added project directory mount for git operations
- Added performDeploy, isDeployAvailable methods to UpdateService
- Added /update deploy subcommand for Discord-triggered deployments
- Added deploy-related embeds to update.view.ts
This commit is contained in:
syntaxbullet
2026-01-30 14:26:38 +01:00
parent 73531f38ae
commit ebefd8c0df
4 changed files with 236 additions and 2 deletions

View File

@@ -11,7 +11,12 @@ import {
getTimeoutEmbed,
getErrorEmbed,
getRollbackSuccessEmbed,
getRollbackFailedEmbed
getRollbackFailedEmbed,
getDeployNotAvailableEmbed,
getDeployCheckingEmbed,
getDeployProgressEmbed,
getDeploySuccessEmbed,
getDeployErrorEmbed
} from "@/modules/admin/update.view";
export const update = createCommand({
@@ -31,6 +36,10 @@ export const update = createCommand({
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) => {
@@ -38,6 +47,8 @@ export const update = createCommand({
if (subcommand === "rollback") {
await handleRollback(interaction);
} else if (subcommand === "deploy") {
await handleDeploy(interaction);
} else {
await handleUpdate(interaction);
}
@@ -175,3 +186,50 @@ async function handleRollback(interaction: any) {
});
}
}
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) {
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))]
});
}
}