Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
478f3a3b87 | ||
|
|
d91572b831 |
@@ -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
@@ -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" \
|
||||||
|
|||||||
@@ -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" });
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export function GET(): Response {
|
||||||
|
return Response.json(
|
||||||
|
{ status: "ok" },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Cache-Control": "no-store",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## 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.
|
||||||
* **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.
|
||||||
* **Refine**: Corrected the Velocity Java and Gradle namespace to the repository owner's `games.dmg` reverse domain.
|
* **Refine**: Corrected the Velocity Java and Gradle namespace to the repository owner's `games.dmg` reverse domain.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ 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:01:47Z
|
timestamp: 2026-08-01T19:46:09Z
|
||||||
story_id: US-016
|
story_id: US-016
|
||||||
status: implemented
|
status: implemented
|
||||||
---
|
---
|
||||||
@@ -14,14 +14,15 @@ As a platform operator, I want automated validation and semantic releases, so th
|
|||||||
|
|
||||||
# Acceptance Criteria
|
# Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Pushes and pull requests run OKF validation, linting, type checks, tests, the web build, and the Velocity build.
|
- [x] Pushes and pull requests run OKF validation, linting, type checks, tests, the web build, and the Velocity build.
|
||||||
- [ ] Pull requests validate conventional commit messages.
|
- [x] Pull requests validate conventional commit messages.
|
||||||
- [ ] CI uploads the development Velocity JAR as a workflow artifact.
|
- [x] CI uploads the development Velocity JAR as a workflow artifact.
|
||||||
- [ ] Main-branch conventional commits determine the next semantic version and create a `vMAJOR.MINOR.PATCH` tag.
|
- [x] Main-branch conventional commits determine the next semantic version and create a `vMAJOR.MINOR.PATCH` tag.
|
||||||
- [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.
|
||||||
- [ ] 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.
|
||||||
- [ ] 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` migration images that run versioned Drizzle migrations.
|
- [ ] 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] 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. A test `1.2.3` JAR was generated with matching Velocity metadata. Workflow YAML parses successfully. Container builds and remote publication remain pending because the local Docker daemon is unavailable and the first push is intentionally paused until repository secrets are configured.
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user