forked from syntaxbullet/aurorabot
feat: Store update restart context in the deployment directory and configure Docker to use the default bun user.
This commit is contained in:
@@ -27,8 +27,8 @@ RUN cd web && bun run build
|
|||||||
FROM oven/bun:latest AS production
|
FROM oven/bun:latest AS production
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Create non-root user for security
|
# Create non-root user for security (bun user already exists with 1000:1000)
|
||||||
RUN groupadd --system appgroup && useradd --system --gid appgroup appuser
|
# No need to create user/group
|
||||||
|
|
||||||
# Install runtime dependencies for update/deploy commands
|
# Install runtime dependencies for update/deploy commands
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
@@ -43,18 +43,18 @@ RUN apt-get update && apt-get install -y \
|
|||||||
&& git config --system --add safe.directory /app/deploy
|
&& git config --system --add safe.directory /app/deploy
|
||||||
|
|
||||||
# Copy only what's needed for production
|
# Copy only what's needed for production
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
|
COPY --from=builder --chown=bun:bun /app/node_modules ./node_modules
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/web/node_modules ./web/node_modules
|
COPY --from=builder --chown=bun:bun /app/web/node_modules ./web/node_modules
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/web/dist ./web/dist
|
COPY --from=builder --chown=bun:bun /app/web/dist ./web/dist
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/web/src ./web/src
|
COPY --from=builder --chown=bun:bun /app/web/src ./web/src
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/bot ./bot
|
COPY --from=builder --chown=bun:bun /app/bot ./bot
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/shared ./shared
|
COPY --from=builder --chown=bun:bun /app/shared ./shared
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/package.json .
|
COPY --from=builder --chown=bun:bun /app/package.json .
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/drizzle.config.ts .
|
COPY --from=builder --chown=bun:bun /app/drizzle.config.ts .
|
||||||
COPY --from=builder --chown=appuser:appgroup /app/tsconfig.json .
|
COPY --from=builder --chown=bun:bun /app/tsconfig.json .
|
||||||
|
|
||||||
# Switch to non-root user
|
# Switch to non-root user
|
||||||
USER appuser
|
USER bun
|
||||||
|
|
||||||
# Expose web dashboard port
|
# Expose web dashboard port
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|||||||
@@ -213,6 +213,18 @@ async function handleDeploy(interaction: any) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (result.success) {
|
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({
|
await interaction.editReply({
|
||||||
embeds: [getDeploySuccessEmbed(
|
embeds: [getDeploySuccessEmbed(
|
||||||
result.previousCommit,
|
result.previousCommit,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { exec, type ExecException } from "child_process";
|
import { exec, type ExecException } from "child_process";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { writeFile, readFile, unlink } from "fs/promises";
|
import { writeFile, readFile, unlink } from "fs/promises";
|
||||||
|
import * as path from "path";
|
||||||
import { Client, TextChannel } from "discord.js";
|
import { Client, TextChannel } from "discord.js";
|
||||||
import { getPostRestartEmbed, getPostRestartProgressEmbed, type PostRestartProgress } from "@/modules/admin/update.view";
|
import { getPostRestartEmbed, getPostRestartProgressEmbed, type PostRestartProgress } from "@/modules/admin/update.view";
|
||||||
import type { PostRestartResult } from "@/modules/admin/update.view";
|
import type { PostRestartResult } from "@/modules/admin/update.view";
|
||||||
@@ -270,7 +271,8 @@ export class UpdateService {
|
|||||||
* Prepare restart context with rollback info
|
* Prepare restart context with rollback info
|
||||||
*/
|
*/
|
||||||
static async prepareRestartContext(context: RestartContext): Promise<void> {
|
static async prepareRestartContext(context: RestartContext): Promise<void> {
|
||||||
await writeFile(this.CONTEXT_FILE, JSON.stringify(context));
|
const filePath = path.join(this.getDeployDir(), this.CONTEXT_FILE);
|
||||||
|
await writeFile(filePath, JSON.stringify(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -325,7 +327,8 @@ export class UpdateService {
|
|||||||
|
|
||||||
private static async loadRestartContext(): Promise<RestartContext | null> {
|
private static async loadRestartContext(): Promise<RestartContext | null> {
|
||||||
try {
|
try {
|
||||||
const contextData = await readFile(this.CONTEXT_FILE, "utf-8");
|
const filePath = path.join(this.getDeployDir(), this.CONTEXT_FILE);
|
||||||
|
const contextData = await readFile(filePath, "utf-8");
|
||||||
return JSON.parse(contextData) as RestartContext;
|
return JSON.parse(contextData) as RestartContext;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
@@ -475,7 +478,8 @@ export class UpdateService {
|
|||||||
|
|
||||||
private static async cleanupContext(): Promise<void> {
|
private static async cleanupContext(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await unlink(this.CONTEXT_FILE);
|
const filePath = path.join(this.getDeployDir(), this.CONTEXT_FILE);
|
||||||
|
await unlink(filePath);
|
||||||
} catch {
|
} catch {
|
||||||
// File may not exist, ignore
|
// File may not exist, ignore
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user