feat(deploy): publish Discord bot image
CI / validate (push) Successful in 4m39s
Release / release (push) Successful in 6m23s

This commit is contained in:
dmg
2026-08-01 15:47:27 -04:00
parent d91572b831
commit 478f3a3b87
8 changed files with 64 additions and 4 deletions
+15
View File
@@ -135,6 +135,21 @@ jobs:
docker push "git.garvis.dev/dmg/minecraft-account-manager:${VERSION}" docker push "git.garvis.dev/dmg/minecraft-account-manager:${VERSION}"
docker push git.garvis.dev/dmg/minecraft-account-manager:latest docker push git.garvis.dev/dmg/minecraft-account-manager:latest
- name: Build and push Discord bot image
if: steps.release.outputs.created == 'true'
env:
VERSION: ${{ steps.release.outputs.version }}
run: |
docker build \
--platform linux/amd64 \
--target bot \
--build-arg VERSION="$VERSION" \
-t "git.garvis.dev/dmg/minecraft-account-manager-bot:${VERSION}" \
-t git.garvis.dev/dmg/minecraft-account-manager-bot:latest \
.
docker push "git.garvis.dev/dmg/minecraft-account-manager-bot:${VERSION}"
docker push git.garvis.dev/dmg/minecraft-account-manager-bot:latest
- name: Build and push migration image - name: Build and push migration image
if: steps.release.outputs.created == 'true' if: steps.release.outputs.created == 'true'
env: env:
+14
View File
@@ -34,6 +34,20 @@ USER app
EXPOSE 3000 EXPOSE 3000
CMD ["node", "apps/web/server.js"] CMD ["node", "apps/web/server.js"]
FROM dependencies AS bot
ARG VERSION=development
LABEL org.opencontainers.image.title="Minecraft Account Manager Discord Bot" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.source="https://git.garvis.dev/dmg/minecraft-account-manager"
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system app && adduser --system --ingroup app app
COPY --chown=app:app package.json package-lock.json tsconfig.base.json ./
COPY --chown=app:app apps/discord-bot ./apps/discord-bot
COPY --chown=app:app packages ./packages
USER app
CMD ["npm", "run", "start", "--workspace", "@minecraft-account-manager/discord-bot"]
FROM dependencies AS migrate FROM dependencies AS migrate
ARG VERSION=development ARG VERSION=development
LABEL org.opencontainers.image.title="Minecraft Account Manager Migrations" \ LABEL org.opencontainers.image.title="Minecraft Account Manager Migrations" \
+12
View File
@@ -0,0 +1,12 @@
import { describe, expect, it } from "vitest";
import { GET } from "./route";
describe("health endpoint", () => {
it("reports process readiness without requiring external services", async () => {
const response = GET();
expect(response.status).toBe(200);
expect(response.headers.get("cache-control")).toBe("no-store");
expect(await response.json()).toEqual({ status: "ok" });
});
});
+10
View File
@@ -0,0 +1,10 @@
export function GET(): Response {
return Response.json(
{ status: "ok" },
{
headers: {
"Cache-Control": "no-store",
},
},
);
}
+1
View File
@@ -2,6 +2,7 @@
## 2026-08-01 ## 2026-08-01
* **Extend**: Added a releasable Discord bot image and a dependency-free web health endpoint for Kubernetes deployment.
* **Verify**: Confirmed the initial `v1.0.0` release, public Velocity JAR, and versioned and `latest` web and migration image manifests. * **Verify**: Confirmed the initial `v1.0.0` release, public Velocity JAR, and versioned and `latest` web and migration image manifests.
* **Create**: Added Gitea CI and semantic-release pipelines for downloadable Velocity JARs and versioned web and migration images. * **Create**: Added Gitea CI and semantic-release pipelines for downloadable Velocity JARs and versioned web and migration images.
* **Document**: Added container deployment order, artifact names, and required repository secrets. * **Document**: Added container deployment order, artifact names, and required repository secrets.
+2 -1
View File
@@ -3,7 +3,7 @@ type: User Story
title: Deploy and operate the platform securely title: Deploy and operate the platform securely
description: Operators have repeatable builds, migrations, credential provisioning, configuration, and security checks. description: Operators have repeatable builds, migrations, credential provisioning, configuration, and security checks.
tags: [operations, security, database, deployment] tags: [operations, security, database, deployment]
timestamp: 2026-08-01T19:01:47Z timestamp: 2026-08-01T19:46:09Z
story_id: US-015 story_id: US-015
status: verified status: verified
--- ---
@@ -21,6 +21,7 @@ As a platform operator, I want reproducible deployment and security controls, so
- [x] The Velocity Gradle wrapper produces a tested shaded JAR. - [x] The Velocity Gradle wrapper produces a tested shaded JAR.
- [x] Environment examples document database, Keycloak, Discord, trusted proxy, and ProxyCheck settings without secrets. - [x] Environment examples document database, Keycloak, Discord, trusted proxy, and ProxyCheck settings without secrets.
- [x] The web application sets CSP, framing, MIME, referrer, and permissions headers. - [x] The web application sets CSP, framing, MIME, referrer, and permissions headers.
- [x] The web runtime provides a dependency-free health endpoint for orchestration probes.
- [x] npm dependency audit and Semgrep security review complete without findings at the last verified change. - [x] npm dependency audit and Semgrep security review complete without findings at the last verified change.
- [x] Architecture, Keycloak, API error, security, bot, and Velocity operating documentation is available. - [x] Architecture, Keycloak, API error, security, bot, and Velocity operating documentation is available.
+4 -3
View File
@@ -3,9 +3,9 @@ type: User Story
title: Build and publish versioned releases title: Build and publish versioned releases
description: Gitea Actions validate every change and publish semantically versioned Velocity and container artifacts. description: Gitea Actions validate every change and publish semantically versioned Velocity and container artifacts.
tags: [operations, ci, release, velocity, docker] tags: [operations, ci, release, velocity, docker]
timestamp: 2026-08-01T19:18:42Z timestamp: 2026-08-01T19:46:09Z
story_id: US-016 story_id: US-016
status: verified status: implemented
--- ---
# User Story # User Story
@@ -21,6 +21,7 @@ As a platform operator, I want automated validation and semantic releases, so th
- [x] A release build embeds the semantic version in the Velocity plugin and JAR filename. - [x] A release build embeds the semantic version in the Velocity plugin and JAR filename.
- [x] A public Gitea release exposes the versioned Velocity JAR as a downloadable asset. - [x] A public Gitea release exposes the versioned Velocity JAR as a downloadable asset.
- [x] Releases publish versioned and `latest` web runtime images to the Gitea registry. - [x] Releases publish versioned and `latest` web runtime images to the Gitea registry.
- [ ] Releases publish versioned and `latest` Discord bot images to the Gitea registry.
- [x] Releases publish versioned and `latest` migration images that run versioned Drizzle migrations. - [x] Releases publish versioned and `latest` migration images that run versioned Drizzle migrations.
- [x] Runtime containers use unprivileged users and exclude development source and secrets where practical. - [x] Runtime containers use unprivileged users and exclude development source and secrets where practical.
- [x] Operators are told which repository secrets must be configured before the first push. - [x] Operators are told which repository secrets must be configured before the first push.
@@ -36,7 +37,7 @@ As a platform operator, I want automated validation and semantic releases, so th
# Validation # Validation
Local OKF, lint, typecheck, test, Next.js build, and versioned Velocity JAR checks pass. Initial Gitea CI and release runs succeeded. Release `v1.0.0` provides a publicly downloadable JAR whose Velocity metadata reports `1.0.0`. Registry manifests were resolved for versioned and `latest` web and migration images. Pull-request commitlint configuration is present; its conditional execution will be exercised by the first pull request. Local OKF, lint, typecheck, test, Next.js build, and versioned Velocity JAR checks pass. Initial Gitea CI and release runs succeeded. Release `v1.0.0` provides a publicly downloadable JAR whose Velocity metadata reports `1.0.0`. Registry manifests were resolved for versioned and `latest` web and migration images. Discord bot image publication is implemented for the next feature release. Pull-request commitlint configuration is present; its conditional execution will be exercised by the first pull request.
# Related Stories # Related Stories
+6
View File
@@ -33,11 +33,17 @@ Each release creates:
- Gitea release asset `minecraft-account-manager-velocity-VERSION.jar` - Gitea release asset `minecraft-account-manager-velocity-VERSION.jar`
- `git.garvis.dev/dmg/minecraft-account-manager:VERSION` - `git.garvis.dev/dmg/minecraft-account-manager:VERSION`
- `git.garvis.dev/dmg/minecraft-account-manager:latest` - `git.garvis.dev/dmg/minecraft-account-manager:latest`
- `git.garvis.dev/dmg/minecraft-account-manager-bot:VERSION`
- `git.garvis.dev/dmg/minecraft-account-manager-bot:latest`
- `git.garvis.dev/dmg/minecraft-account-manager-migrate:VERSION` - `git.garvis.dev/dmg/minecraft-account-manager-migrate:VERSION`
- `git.garvis.dev/dmg/minecraft-account-manager-migrate:latest` - `git.garvis.dev/dmg/minecraft-account-manager-migrate:latest`
Use immutable version tags for deployments. `latest` is a convenience pointer to the newest release. Use immutable version tags for deployments. `latest` is a convenience pointer to the newest release.
## Discord bot
Run exactly one bot replica with the same immutable release version as the web application. It requires `DATABASE_URL`, `APP_URL`, `DISCORD_BOT_TOKEN`, and `DISCORD_GUILD_ID`. Deploy slash commands separately with the release image when command definitions change.
## Database migration ## Database migration
Run the migration image for the same version before starting or replacing the web container: Run the migration image for the same version before starting or replacing the web container: