From a6aac5db32f823da8b6e93e57ccf4bab75a61d9f Mon Sep 17 00:00:00 2001 From: Hendrik Brombeer Date: Sun, 3 May 2026 20:28:20 +0200 Subject: [PATCH 1/4] feat: add grounds-velocity, plugin-velocity-jar, grounds-gamemode charts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three Helm charts the platform-test environment's PlatformBundle references but that didn't exist yet — without them the forge bundle deploy fails with "chart not found" on every component except the existing grounds-service. - plugin-velocity-jar: Tiny pod that hosts a single Velocity plugin JAR over HTTP at /plugin.jar. Init-container `cp`s the JAR from the plugin image into a shared emptyDir; main container runs busybox httpd. The plugin image only needs to ship the JAR at a known path — no httpd/entrypoint requirements. DevSpace can sync new builds directly into /shared/plugin.jar to hot-swap. - grounds-velocity: Velocity proxy with one fetch init-container per entry in `.plugins[]`. Each init-container curls http://:8080/plugin.jar into /app/plugins/.jar before Velocity starts. Pulls VELOCITY_FORWARDING_SECRET from the existing velocity-forwarding-secret Secret (provisioned out-of-band). Plugin set is data, not code — engineers control composition via overrides, not by rebuilding a velocity image. - grounds-gamemode: Toggles between Deployment+Service and Agones Fleet based on `.agones.enabled`. Deployment-mode for minestom-lobby (single replica, fixed port). Fleet-mode for paper-game (autoscaled, dynamic ports). `.kind` selects which velocity-secret env var the container expects: lobby → GROUNDS_LOBBY_VELOCITY_SECRET paper/match/game → PAPER_VELOCITY_SECRET Wires the three new charts into the CI lint/template/package matrix, the release publish matrix, and release-please config + manifest at 0.0.0 baseline. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 3 + .github/workflows/release.yml | 3 + .release-please-manifest.json | 5 +- charts/grounds-gamemode/Chart.lock | 6 ++ charts/grounds-gamemode/Chart.yaml | 10 +++ .../grounds-gamemode/templates/_helpers.tpl | 31 +++++++ .../templates/deployment.yaml | 54 +++++++++++++ charts/grounds-gamemode/templates/fleet.yaml | 61 ++++++++++++++ .../grounds-gamemode/templates/service.yaml | 25 ++++++ charts/grounds-gamemode/values.yaml | 66 +++++++++++++++ charts/grounds-velocity/Chart.lock | 6 ++ charts/grounds-velocity/Chart.yaml | 10 +++ .../templates/deployment.yaml | 81 +++++++++++++++++++ .../grounds-velocity/templates/service.yaml | 25 ++++++ charts/grounds-velocity/values.yaml | 59 ++++++++++++++ charts/plugin-velocity-jar/Chart.lock | 6 ++ charts/plugin-velocity-jar/Chart.yaml | 10 +++ .../templates/deployment.yaml | 73 +++++++++++++++++ .../templates/service.yaml | 22 +++++ charts/plugin-velocity-jar/values.yaml | 50 ++++++++++++ release-please-config.json | 9 +++ 21 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 charts/grounds-gamemode/Chart.lock create mode 100644 charts/grounds-gamemode/Chart.yaml create mode 100644 charts/grounds-gamemode/templates/_helpers.tpl create mode 100644 charts/grounds-gamemode/templates/deployment.yaml create mode 100644 charts/grounds-gamemode/templates/fleet.yaml create mode 100644 charts/grounds-gamemode/templates/service.yaml create mode 100644 charts/grounds-gamemode/values.yaml create mode 100644 charts/grounds-velocity/Chart.lock create mode 100644 charts/grounds-velocity/Chart.yaml create mode 100644 charts/grounds-velocity/templates/deployment.yaml create mode 100644 charts/grounds-velocity/templates/service.yaml create mode 100644 charts/grounds-velocity/values.yaml create mode 100644 charts/plugin-velocity-jar/Chart.lock create mode 100644 charts/plugin-velocity-jar/Chart.yaml create mode 100644 charts/plugin-velocity-jar/templates/deployment.yaml create mode 100644 charts/plugin-velocity-jar/templates/service.yaml create mode 100644 charts/plugin-velocity-jar/values.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a95d007..5c4caf8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,9 @@ jobs: - cockpit - grounds-service - agones-fleet + - grounds-velocity + - plugin-velocity-jar + - grounds-gamemode steps: - name: 📥 Checkout code uses: actions/checkout@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9624e58..da36f66 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,9 @@ jobs: - cockpit - grounds-service - agones-fleet + - grounds-velocity + - plugin-velocity-jar + - grounds-gamemode env: MATCHES_REF: ${{ startsWith(github.ref, format('refs/tags/{0}-v', matrix.chart)) }} steps: diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7d252a8..341b82d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -3,5 +3,8 @@ "charts/grounds-api": "0.2.0", "charts/cockpit": "0.1.1", "charts/grounds-service": "0.1.0", - "charts/agones-fleet": "0.2.0" + "charts/agones-fleet": "0.2.0", + "charts/grounds-velocity": "0.0.0", + "charts/plugin-velocity-jar": "0.0.0", + "charts/grounds-gamemode": "0.0.0" } diff --git a/charts/grounds-gamemode/Chart.lock b/charts/grounds-gamemode/Chart.lock new file mode 100644 index 0000000..428ee53 --- /dev/null +++ b/charts/grounds-gamemode/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://ghcr.io/groundsgg/charts + version: 0.2.0 +digest: sha256:cc3072b8b38019dbcb82c3adde2774f0ade4c29ea47b961c49936a99d44556d2 +generated: "2026-05-03T20:27:15.738113+02:00" diff --git a/charts/grounds-gamemode/Chart.yaml b/charts/grounds-gamemode/Chart.yaml new file mode 100644 index 0000000..f4c86e4 --- /dev/null +++ b/charts/grounds-gamemode/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +name: grounds-gamemode +description: Minecraft game-server (Paper / Minestom) — Deployment by default, Agones Fleet when scaling +type: application +version: 0.1.0 + +dependencies: + - name: common + version: "0.2.0" + repository: "oci://ghcr.io/groundsgg/charts" diff --git a/charts/grounds-gamemode/templates/_helpers.tpl b/charts/grounds-gamemode/templates/_helpers.tpl new file mode 100644 index 0000000..eb8b57a --- /dev/null +++ b/charts/grounds-gamemode/templates/_helpers.tpl @@ -0,0 +1,31 @@ +{{/* +Returns the env block for the game-server container, picking the right +velocity-secret env-var name based on `.Values.kind`. +*/}} +{{- define "grounds-gamemode.env" -}} +{{- $secretEnvName := "" -}} +{{- if eq .Values.kind "lobby" -}} +{{- $secretEnvName = "GROUNDS_LOBBY_VELOCITY_SECRET" -}} +{{- else -}} +{{- $secretEnvName = "PAPER_VELOCITY_SECRET" -}} +{{- end -}} +- name: {{ $secretEnvName }} + valueFrom: + secretKeyRef: + name: {{ .Values.forwardingSecret.name }} + key: {{ .Values.forwardingSecret.key }} +{{- with .Values.extraEnv }} +{{ toYaml . }} +{{- end }} +{{- end -}} + +{{/* +Resolves the fully-qualified image reference. +*/}} +{{- define "grounds-gamemode.image" -}} +{{- $repo := .Values.image.repository -}} +{{- if .Values.image.registry -}} +{{- $repo = printf "%s/%s" .Values.image.registry .Values.image.repository -}} +{{- end -}} +{{ printf "%s:%s" $repo .Values.image.tag }} +{{- end -}} diff --git a/charts/grounds-gamemode/templates/deployment.yaml b/charts/grounds-gamemode/templates/deployment.yaml new file mode 100644 index 0000000..505fe13 --- /dev/null +++ b/charts/grounds-gamemode/templates/deployment.yaml @@ -0,0 +1,54 @@ +{{- if not .Values.agones.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + grounds/component: gamemode + grounds/server-type: {{ .Values.kind }} + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "common.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "common.podLabels" . | nindent 8 }} + grounds/component: gamemode + grounds/server-type: {{ .Values.kind }} + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + containers: + - name: {{ .Release.Name }} + image: {{ include "grounds-gamemode.image" . | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.command }} + command: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: minecraft + containerPort: {{ .Values.containerPort }} + protocol: TCP + env: + {{- include "grounds-gamemode.env" . | nindent 12 }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} +{{- end }} diff --git a/charts/grounds-gamemode/templates/fleet.yaml b/charts/grounds-gamemode/templates/fleet.yaml new file mode 100644 index 0000000..e1363d0 --- /dev/null +++ b/charts/grounds-gamemode/templates/fleet.yaml @@ -0,0 +1,61 @@ +{{- if .Values.agones.enabled }} +apiVersion: agones.dev/v1 +kind: Fleet +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + grounds/component: gamemode + grounds/server-type: {{ .Values.kind }} + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.agones.fleet.minReplicas }} + template: + metadata: + labels: + grounds/component: gamemode + grounds/server-type: {{ .Values.kind }} + spec: + ports: + - name: minecraft + portPolicy: Dynamic + containerPort: {{ .Values.containerPort }} + protocol: TCP + container: {{ .Release.Name }} + sdkServer: + logLevel: Info + httpPort: 9358 + health: + disabled: true + template: + metadata: + labels: + {{- include "common.podLabels" . | nindent 12 }} + grounds/component: gamemode + grounds/server-type: {{ .Values.kind }} + spec: + containers: + - name: {{ .Release.Name }} + image: {{ include "grounds-gamemode.image" . | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.command }} + command: + {{- toYaml . | nindent 16 }} + {{- end }} + ports: + - name: minecraft + containerPort: {{ .Values.containerPort }} + protocol: TCP + env: + {{- include "grounds-gamemode.env" . | nindent 16 }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 16 }} + {{- end }} +{{- end }} diff --git a/charts/grounds-gamemode/templates/service.yaml b/charts/grounds-gamemode/templates/service.yaml new file mode 100644 index 0000000..248771c --- /dev/null +++ b/charts/grounds-gamemode/templates/service.yaml @@ -0,0 +1,25 @@ +{{- if not .Values.agones.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + grounds/server-type: {{ .Values.kind }} + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.containerPort }} + targetPort: minecraft + protocol: TCP + name: minecraft + selector: + {{- include "common.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/grounds-gamemode/values.yaml b/charts/grounds-gamemode/values.yaml new file mode 100644 index 0000000..3c15cd3 --- /dev/null +++ b/charts/grounds-gamemode/values.yaml @@ -0,0 +1,66 @@ +# Default values for grounds-gamemode. +# +# A grounds-gamemode release is one Minecraft game-server kind. The +# chart picks between two backings: +# - `agones.enabled: true` → Agones Fleet (autoscaled, dynamic ports) +# - `agones.enabled: false` → Deployment + Service (fixed port 25565) +# +# Used in the platform-test environment for both: +# - minestom-lobby (kind: lobby, Deployment, single replica) +# - paper-game (kind: paper, Agones Fleet, scales 0..N) +# +# kind drives which Velocity-secret env-var the container expects: +# - "lobby" → GROUNDS_LOBBY_VELOCITY_SECRET +# - "paper" → PAPER_VELOCITY_SECRET +# - "match" → PAPER_VELOCITY_SECRET +# - "game" → PAPER_VELOCITY_SECRET + +global: + commonLabels: {} + commonAnnotations: {} + +# Logical kind of the game-server. See note above. +kind: "paper" + +image: + registry: "ghcr.io" + repository: "groundsgg/paper-game" + tag: "latest" + pullPolicy: IfNotPresent + +# Agones Fleet mode — set agones.enabled=true to switch from Deployment +# to a Fleet. Bundle.yaml's `helm.agones.fleet` map maps directly here. +agones: + enabled: false + fleet: + minReplicas: 0 + maxReplicas: 2 + +# Deployment-mode config (ignored when agones.enabled). +replicas: 1 + +# velocity-forwarding-secret is provisioned out-of-band; the chart +# only references it. Same convention as grounds-velocity. +forwardingSecret: + name: "velocity-forwarding-secret" + key: "secret" + +# Container port. Minecraft default 25565. +containerPort: 25565 + +# Optional command override. +command: [] + +# extraEnv merges into env after the kind-specific velocity-secret. +extraEnv: [] + +resources: + requests: + cpu: "500m" + memory: "2Gi" + limits: + cpu: "2" + memory: "4Gi" + +service: + type: ClusterIP diff --git a/charts/grounds-velocity/Chart.lock b/charts/grounds-velocity/Chart.lock new file mode 100644 index 0000000..6ba69c7 --- /dev/null +++ b/charts/grounds-velocity/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://ghcr.io/groundsgg/charts + version: 0.2.0 +digest: sha256:cc3072b8b38019dbcb82c3adde2774f0ade4c29ea47b961c49936a99d44556d2 +generated: "2026-05-03T20:26:58.10509+02:00" diff --git a/charts/grounds-velocity/Chart.yaml b/charts/grounds-velocity/Chart.yaml new file mode 100644 index 0000000..58a59d7 --- /dev/null +++ b/charts/grounds-velocity/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +name: grounds-velocity +description: Velocity Minecraft proxy with per-plugin JAR fetching for the platform-test environment +type: application +version: 0.1.0 + +dependencies: + - name: common + version: "0.2.0" + repository: "oci://ghcr.io/groundsgg/charts" diff --git a/charts/grounds-velocity/templates/deployment.yaml b/charts/grounds-velocity/templates/deployment.yaml new file mode 100644 index 0000000..10ba1ea --- /dev/null +++ b/charts/grounds-velocity/templates/deployment.yaml @@ -0,0 +1,81 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + grounds/component: velocity + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "common.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "common.podLabels" . | nindent 8 }} + grounds/component: velocity + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- $imageRepo := .Values.image.repository }} + {{- if .Values.image.registry }} + {{- $imageRepo = printf "%s/%s" .Values.image.registry .Values.image.repository }} + {{- end }} + initContainers: + {{- range $plugin := .Values.plugins }} + - name: fetch-{{ $plugin }} + image: {{ $.Values.fetcher.image | quote }} + imagePullPolicy: IfNotPresent + command: + - sh + - -c + - >- + curl --fail --silent --show-error + --max-time {{ $.Values.fetcher.timeoutSeconds }} + --retry 5 --retry-delay 2 --retry-connrefused + -o /plugins/{{ $plugin }}.jar + http://{{ $plugin }}:8080/plugin.jar + volumeMounts: + - name: plugins + mountPath: /plugins + {{- end }} + containers: + - name: velocity + image: "{{ $imageRepo }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: minecraft + containerPort: {{ .Values.ports.minecraft }} + protocol: TCP + env: + - name: VELOCITY_FORWARDING_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.forwardingSecret.name }} + key: {{ .Values.forwardingSecret.key }} + {{- with .Values.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: plugins + mountPath: /app/plugins + volumes: + - name: plugins + emptyDir: {} diff --git a/charts/grounds-velocity/templates/service.yaml b/charts/grounds-velocity/templates/service.yaml new file mode 100644 index 0000000..b633a53 --- /dev/null +++ b/charts/grounds-velocity/templates/service.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- with .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + ports: + - port: {{ .Values.ports.minecraft }} + targetPort: minecraft + protocol: TCP + name: minecraft + selector: + {{- include "common.selectorLabels" . | nindent 4 }} diff --git a/charts/grounds-velocity/values.yaml b/charts/grounds-velocity/values.yaml new file mode 100644 index 0000000..8d8dcca --- /dev/null +++ b/charts/grounds-velocity/values.yaml @@ -0,0 +1,59 @@ +# Default values for grounds-velocity. +# +# Per-engineer Velocity proxy. Each plugin in `.plugins[]` corresponds +# to a sibling `plugin-velocity-jar` Helm release in the same namespace +# whose Service serves the JAR over HTTP at /plugin.jar. At pod start +# Velocity runs one init-container per entry to fetch each JAR into the +# emptyDir mounted at /app/plugins. + +global: + commonLabels: {} + commonAnnotations: {} + +replicas: 1 + +image: + registry: "ghcr.io" + repository: "groundsgg/velocity" + tag: "latest" + pullPolicy: IfNotPresent + +# Each entry is the Helm release name of a sibling plugin-velocity-jar +# release. Velocity fetches `http://:8080/plugin.jar` and writes +# it to `/app/plugins/.jar`. Order is preserved. +plugins: [] +# Example: +# plugins: +# - plugin-social +# - plugin-chat + +# Image used for the per-plugin fetch init-containers. +fetcher: + image: "curlimages/curl:8.18.0" + timeoutSeconds: 60 + +resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2" + memory: "2Gi" + +# Velocity exposes the player port (modern Minecraft proxy) and an +# optional metrics port via the velocity-prometheus-exporter plugin. +ports: + minecraft: 25577 + +service: + type: ClusterIP + externalTrafficPolicy: "" + +# velocity-forwarding-secret is provisioned out-of-band (Pulumi/sealed +# secret) so all proxies + game-servers in the namespace share one +# secret. The chart only references it. +forwardingSecret: + name: "velocity-forwarding-secret" + key: "secret" + +env: [] diff --git a/charts/plugin-velocity-jar/Chart.lock b/charts/plugin-velocity-jar/Chart.lock new file mode 100644 index 0000000..173d78f --- /dev/null +++ b/charts/plugin-velocity-jar/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://ghcr.io/groundsgg/charts + version: 0.2.0 +digest: sha256:cc3072b8b38019dbcb82c3adde2774f0ade4c29ea47b961c49936a99d44556d2 +generated: "2026-05-03T20:26:40.440813+02:00" diff --git a/charts/plugin-velocity-jar/Chart.yaml b/charts/plugin-velocity-jar/Chart.yaml new file mode 100644 index 0000000..e5f3ebf --- /dev/null +++ b/charts/plugin-velocity-jar/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +name: plugin-velocity-jar +description: Hosts a Velocity-plugin JAR so the grounds-velocity proxy can fetch it at startup +type: application +version: 0.1.0 + +dependencies: + - name: common + version: "0.2.0" + repository: "oci://ghcr.io/groundsgg/charts" diff --git a/charts/plugin-velocity-jar/templates/deployment.yaml b/charts/plugin-velocity-jar/templates/deployment.yaml new file mode 100644 index 0000000..87383d9 --- /dev/null +++ b/charts/plugin-velocity-jar/templates/deployment.yaml @@ -0,0 +1,73 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + grounds/component: plugin-velocity-jar + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "common.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "common.podLabels" . | nindent 8 }} + grounds/component: plugin-velocity-jar + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- $imageRepo := .Values.image.repository }} + {{- if .Values.image.registry }} + {{- $imageRepo = printf "%s/%s" .Values.image.registry .Values.image.repository }} + {{- end }} + initContainers: + - name: copy-jar + image: "{{ $imageRepo }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - sh + - -c + - 'cp "{{ .Values.jarPath }}" /shared/plugin.jar && ls -la /shared/plugin.jar' + volumeMounts: + - name: shared + mountPath: /shared + containers: + - name: httpd + image: {{ .Values.httpd.image | quote }} + imagePullPolicy: IfNotPresent + command: ["httpd", "-f", "-p", "{{ .Values.httpd.port }}", "-h", "/shared"] + ports: + - name: http + containerPort: {{ .Values.httpd.port }} + protocol: TCP + readinessProbe: + httpGet: + path: /plugin.jar + port: http + initialDelaySeconds: 1 + periodSeconds: 5 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: shared + mountPath: /shared + readOnly: true + volumes: + - name: shared + emptyDir: {} diff --git a/charts/plugin-velocity-jar/templates/service.yaml b/charts/plugin-velocity-jar/templates/service.yaml new file mode 100644 index 0000000..08a5ead --- /dev/null +++ b/charts/plugin-velocity-jar/templates/service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + labels: + {{- include "common.labels" . | nindent 4 }} + {{- with .Values.global.commonLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.global.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "common.selectorLabels" . | nindent 4 }} diff --git a/charts/plugin-velocity-jar/values.yaml b/charts/plugin-velocity-jar/values.yaml new file mode 100644 index 0000000..637b60a --- /dev/null +++ b/charts/plugin-velocity-jar/values.yaml @@ -0,0 +1,50 @@ +# Default values for plugin-velocity-jar. +# +# A plugin-velocity-jar release runs a tiny pod that exposes a single +# Velocity-plugin JAR over HTTP at `/plugin.jar`. The grounds-velocity +# proxy fetches it via init-containers at startup. +# +# Pod layout: +# initContainer "copy-jar" +# image: # carries the JAR at jarPath +# command: cp /shared/plugin.jar +# container "httpd" +# image: busybox httpd -f -h /shared -p 8080 +# mounts /shared (emptyDir, read by httpd) +# +# This indirection means the plugin image only needs to ship the JAR +# at a known path — no httpd or entrypoint requirements. DevSpace can +# sync new builds directly into /shared/plugin.jar to hot-swap. + +global: + commonLabels: {} + commonAnnotations: {} + +# The plugin-image: must contain the JAR at `jarPath`. Entrypoint is +# irrelevant — we override it to `cp` in the init-container. +image: + registry: "" + repository: "plugin-velocity-jar" + tag: "latest" + pullPolicy: IfNotPresent + +# Where the JAR lives inside the plugin-image. +jarPath: "/jar/plugin.jar" + +# httpd image used to serve the JAR. Override only if you need a +# pinned mirror. +httpd: + image: "busybox:1.37" + port: 8080 + +resources: + requests: + cpu: "10m" + memory: "16Mi" + limits: + cpu: "50m" + memory: "32Mi" + +service: + type: ClusterIP + port: 8080 diff --git a/release-please-config.json b/release-please-config.json index 9473f5f..eedf2e6 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -16,6 +16,15 @@ }, "charts/agones-fleet": { "release-type": "helm" + }, + "charts/grounds-velocity": { + "release-type": "helm" + }, + "charts/plugin-velocity-jar": { + "release-type": "helm" + }, + "charts/grounds-gamemode": { + "release-type": "helm" } } } From f50825eaad49612e95263e62e391e4d3297683eb Mon Sep 17 00:00:00 2001 From: Hendrik Brombeer Date: Sun, 3 May 2026 20:30:31 +0200 Subject: [PATCH 2/4] ci: nudge to trigger CI From ea0aa7afdfdcc64d6e7a9f85de184bf12a71072a Mon Sep 17 00:00:00 2001 From: Hendrik Brombeer Date: Sun, 3 May 2026 20:36:29 +0200 Subject: [PATCH 3/4] fix(plugin-velocity-jar): drop readOnly on shared volume so DevSpace can sync JARs in-place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The jar-sync-pod-restart workflow needs to sync a freshly-built JAR into the running plugin pod's /shared/plugin.jar. With readOnly the sync would fail. RW is fine — the only writer is DevSpace's sync target during dev iteration; the init-container's cp still works either way. Co-Authored-By: Claude Opus 4.7 (1M context) --- charts/plugin-velocity-jar/templates/deployment.yaml | 1 - charts/plugin-velocity-jar/values.yaml | 9 ++++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/charts/plugin-velocity-jar/templates/deployment.yaml b/charts/plugin-velocity-jar/templates/deployment.yaml index 87383d9..6493091 100644 --- a/charts/plugin-velocity-jar/templates/deployment.yaml +++ b/charts/plugin-velocity-jar/templates/deployment.yaml @@ -67,7 +67,6 @@ spec: volumeMounts: - name: shared mountPath: /shared - readOnly: true volumes: - name: shared emptyDir: {} diff --git a/charts/plugin-velocity-jar/values.yaml b/charts/plugin-velocity-jar/values.yaml index 637b60a..d309b51 100644 --- a/charts/plugin-velocity-jar/values.yaml +++ b/charts/plugin-velocity-jar/values.yaml @@ -10,11 +10,14 @@ # command: cp /shared/plugin.jar # container "httpd" # image: busybox httpd -f -h /shared -p 8080 -# mounts /shared (emptyDir, read by httpd) +# mounts /shared (emptyDir, RW so DevSpace can sync new JARs) # # This indirection means the plugin image only needs to ship the JAR -# at a known path — no httpd or entrypoint requirements. DevSpace can -# sync new builds directly into /shared/plugin.jar to hot-swap. +# at a known path — no httpd or entrypoint requirements. The DevSpace +# `jar-sync-pod-restart` workflow targets this pod's /shared/plugin.jar +# directly: sync a freshly-built JAR there, then `kubectl rollout +# restart deployment/` so the velocity pod's init-containers +# re-fetch the updated JARs. global: commonLabels: {} From f1572fdeaf693c90d9684bbb4f5e4adc023e704c Mon Sep 17 00:00:00 2001 From: Lukas Jost Date: Mon, 4 May 2026 00:04:27 +0200 Subject: [PATCH 4/4] fix: tighten chart values and velocity init containers - Render Velocity initContainers only when plugins are configured - Clarify current Agones Fleet replica behavior in gamemode values - Remove unsupported Velocity metrics port wording - Ignore local AI tool metadata --- .gitignore | 3 +++ .release-please-manifest.json | 6 +++--- charts/grounds-gamemode/values.yaml | 2 ++ charts/grounds-velocity/templates/deployment.yaml | 4 +++- charts/grounds-velocity/values.yaml | 3 +-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 03a15b1..1b9732f 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ build/ *.tar *.tar.gz +# AI +.codex +.cursor diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 341b82d..91d617c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -4,7 +4,7 @@ "charts/cockpit": "0.1.1", "charts/grounds-service": "0.1.0", "charts/agones-fleet": "0.2.0", - "charts/grounds-velocity": "0.0.0", - "charts/plugin-velocity-jar": "0.0.0", - "charts/grounds-gamemode": "0.0.0" + "charts/grounds-velocity": "0.0.1", + "charts/plugin-velocity-jar": "0.0.1", + "charts/grounds-gamemode": "0.0.1" } diff --git a/charts/grounds-gamemode/values.yaml b/charts/grounds-gamemode/values.yaml index 3c15cd3..587faee 100644 --- a/charts/grounds-gamemode/values.yaml +++ b/charts/grounds-gamemode/values.yaml @@ -30,6 +30,8 @@ image: # Agones Fleet mode — set agones.enabled=true to switch from Deployment # to a Fleet. Bundle.yaml's `helm.agones.fleet` map maps directly here. +# This chart currently uses only `minReplicas` as the Fleet `.spec.replicas` +# value; it does not define a FleetAutoscaler. agones: enabled: false fleet: diff --git a/charts/grounds-velocity/templates/deployment.yaml b/charts/grounds-velocity/templates/deployment.yaml index 10ba1ea..7c9427f 100644 --- a/charts/grounds-velocity/templates/deployment.yaml +++ b/charts/grounds-velocity/templates/deployment.yaml @@ -34,8 +34,9 @@ spec: {{- if .Values.image.registry }} {{- $imageRepo = printf "%s/%s" .Values.image.registry .Values.image.repository }} {{- end }} + {{- with .Values.plugins }} initContainers: - {{- range $plugin := .Values.plugins }} + {{- range $plugin := . }} - name: fetch-{{ $plugin }} image: {{ $.Values.fetcher.image | quote }} imagePullPolicy: IfNotPresent @@ -52,6 +53,7 @@ spec: - name: plugins mountPath: /plugins {{- end }} + {{- end }} containers: - name: velocity image: "{{ $imageRepo }}:{{ .Values.image.tag }}" diff --git a/charts/grounds-velocity/values.yaml b/charts/grounds-velocity/values.yaml index 8d8dcca..a8efd96 100644 --- a/charts/grounds-velocity/values.yaml +++ b/charts/grounds-velocity/values.yaml @@ -40,8 +40,7 @@ resources: cpu: "2" memory: "2Gi" -# Velocity exposes the player port (modern Minecraft proxy) and an -# optional metrics port via the velocity-prometheus-exporter plugin. +# Velocity exposes the player port (modern Minecraft proxy). ports: minecraft: 25577