mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix(docker): ship /app owned by the runtime uid; run the boot-smoke in CI too (#1378)
* fix(release): give the Docker boot-smoke a writable /app, and run it in CI The v1.2.0-alpha.3 release run died at "Boot-smoke Docker image": a bare `docker run` of the distroless image has nowhere the uid-65532 server can write — /app is root-owned, and the VOLUME /app/data anonymous volume is created root-owned too — so config.Load failed on "writing default config: open config.yaml: permission denied" and the container exited. Real deployments bind-mount config.yaml and data/, which is why the image itself is fine. Move the smoke into Server/scripts/docker-smoke.sh, run the container with `--tmpfs /app --tmpfs /app/data` (Docker's tmpfs default mode is 1777, so the non-root server can write both), and call the same script from ci.yml's docker-build job — loading the image it already builds — so the smoke is exercised on every PR to main instead of for the first time at tag time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(docker): ship /app and /app/data owned by the runtime uid so a bare run boots The tmpfs approach did not survive CI: runc re-applies the underlying directory's mode to a tmpfs mounted over an existing path, so /app stayed root:755 and the write still failed. Fix the image instead of the harness: stage /app/data in the builder, chown it to 65532, COPY --chown it into the distroless stage before WORKDIR. Docker seeds the VOLUME's anonymous volume from that image dir, ownership included, so `docker run <image>` with no mounts now boots and answers /health — which is also the contract the smoke should be testing, so it goes back to a bare `docker run`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Boot-smoke a freshly built server image: start it, wait for
|
||||
# `/chatserver healthcheck` to pass, print the logs, tear it down.
|
||||
#
|
||||
# Used by both ci.yml (every PR to main) and release.yml (before anything is
|
||||
# signed or pushed), so a boot regression is caught pre-merge instead of at
|
||||
# tag time. Usage: docker-smoke.sh <image>
|
||||
#
|
||||
# Deliberately a bare `docker run` — no mounts, no env, no config. That is
|
||||
# the contract being tested: the image boots on its own, as uid 65532, and
|
||||
# writes its default config.yaml and data/ into the /app skeleton the
|
||||
# Dockerfile ships owned by that uid. The first v1.2.0-alpha.3 release run
|
||||
# died exactly here ("writing default config: permission denied") when /app
|
||||
# was still root-owned; adding mounts to the smoke would only hide a repeat.
|
||||
set -euo pipefail
|
||||
|
||||
image="${1:?usage: docker-smoke.sh <image>}"
|
||||
name="owncord-smoke-$$"
|
||||
|
||||
cleanup() { docker rm -f "$name" >/dev/null 2>&1 || true; }
|
||||
trap cleanup EXIT
|
||||
|
||||
docker run -d --name "$name" "$image" >/dev/null
|
||||
|
||||
ok=0
|
||||
for _ in $(seq 1 30); do
|
||||
sleep 1
|
||||
if [ "$(docker inspect -f '{{.State.Running}}' "$name")" != "true" ]; then
|
||||
echo "::error::container exited during boot smoke"
|
||||
docker logs "$name"
|
||||
exit 1
|
||||
fi
|
||||
if docker exec "$name" /chatserver healthcheck; then ok=1; break; fi
|
||||
done
|
||||
docker logs "$name"
|
||||
if [ "$ok" != "1" ]; then
|
||||
echo "::error::container never reported healthy within 30s"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user