From 5751be129d62cd1014aff8ea4633dd4ab935d0a6 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Sun, 30 Aug 2026 15:42:48 +1000 Subject: [PATCH] OPS-04: restart on crash, real logging, and a deploy that fails when the bot does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker-compose.yml: `restart: unless-stopped` so a panic, bad frame or VPS reboot brings the bot back instead of leaving it dead. Comment explaining why no healthcheck (slim runtime, no HTTP port). - Cargo.toml: enable tracing-subscriber's env-filter feature (declared but never initialised until now). - main.rs: initialise tracing as the first statement in main(), defaulting to `info` — serenity/poise/supabase logs now surface, without leaking student IDs or the service email that the Supabase client emits at `debug`. - deploy.yml: after `up -d`, assert the container is actually Running 30s later and dump its logs and fail if not — `up -d` returns 0 on container creation, not on a working process. - Dockerfile: pin the builder to rust:1-bookworm to match the bookworm-slim runtime, removing the trixie/bookworm glibc mismatch. - README: document the info-level default and the RUST_LOG=debug PII footgun. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017XrE7F9ZuBWdQnS8CZvYDE --- .github/workflows/deploy.yml | 17 +++++++++++++++++ Cargo.lock | 13 +++++++++++++ Cargo.toml | 2 +- Dockerfile | 6 +++++- README.md | 7 +++++++ docker-compose.yml | 7 +++++++ src/main.rs | 10 ++++++++++ 7 files changed, 60 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ae6e01f..e77945d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -42,6 +42,23 @@ jobs: working-directory: ${{ github.workspace }} run: | sudo docker compose up -d --build --force-recreate + echo "Container created." + + # `docker compose up -d` exits 0 once the container is created, not once the + # program inside is running. The bot can panic at boot (a bad .env value, a + # Supabase hiccup) and exit within a second while the deploy still goes green. + # Assert the container is actually alive, and surface its logs if not (OPS-04). + - name: Verify the bot is still running + working-directory: ${{ github.workspace }} + run: | + sleep 30 + id=$(sudo docker compose ps -q dsec_bot) + running=$(sudo docker inspect -f '{{.State.Running}}' "$id") + if [ "$running" != "true" ]; then + echo "::error::dsec_bot is not running 30s after deploy" + sudo docker compose logs --tail=100 dsec_bot + exit 1 + fi echo "Deployment complete." - name: Remove environment file diff --git a/Cargo.lock b/Cargo.lock index 04e9375..6a63aab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1604,6 +1604,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "maybe-rayon" version = "0.1.1" @@ -3533,10 +3542,14 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] diff --git a/Cargo.toml b/Cargo.toml index c917e29..3542690 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,6 @@ reqwest = "0.12.24" serde_json = "1.0.145" serenity = "0.12" tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] } -tracing-subscriber = "0.3.20" +tracing-subscriber = { version = "0.3.20", features = ["env-filter"] } supabase-lib-rs = "0.5.3" serde = "1.0.228" \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8a5dff4..3e32268 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,8 @@ -FROM rust:trixie AS builder +# Pin the builder to the same Debian release as the runtime (bookworm). A binary +# built on a newer release can die at exec on the older one the day a dependency +# reaches for a newer glibc/OpenSSL symbol — with no log and, before OPS-04, no +# restart. Keep this in lockstep with the runtime FROM below. +FROM rust:1-bookworm AS builder # Install build dependencies RUN apt-get update && \ diff --git a/README.md b/README.md index 2d907e8..35c9f3f 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,13 @@ docker-compose build docker-compose up ``` +## Logging + +The bot logs at `info` by default. Do **not** set `RUST_LOG` to `debug` or `trace` +on the VPS or in the `DOT_ENV` secret: at `debug` the Supabase client logs the +generated query URLs (which contain **student IDs**) and the service-account +email. Adjust the level with `RUST_LOG` locally only (e.g. `RUST_LOG=warn`). + ## Rules ### General Rules diff --git a/docker-compose.yml b/docker-compose.yml index ebb4f14..324bb9d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,12 @@ services: dsec_bot: build: . + # Bring the bot back on process exit — a panic, a bad Discord frame, or a VPS + # reboot — instead of leaving it dead until someone notices (OPS-04). No + # `healthcheck:` block: the runtime image is debian:bookworm-slim with only + # ca-certificates (no ps/curl) and the bot serves no HTTP port, so there is + # nothing to probe; `restart: unless-stopped` acts on process exit, which is + # exactly the failure mode here. Do not add one. + restart: unless-stopped env_file: - .env \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9df5e95..e56bf5f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -150,6 +150,16 @@ async fn on_error(error: poise::FrameworkError<'_, Data, Error>) { #[tokio::main] async fn main() { + // Initialise logging first, before anything can log. Default to `info`: + // supabase-lib-rs logs generated query URLs (containing student IDs) and the + // service-account email at `debug`, so RUST_LOG must never be set to debug or + // trace on the VPS. See OPS-04 and the README. + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()), + ) + .init(); + dotenv().ok(); // load env let app_state = AppState::new()