mirror of
https://github.com/dsec-hub/dsec-discord-bot.git
synced 2026-09-22 07:44:26 +00:00
OPS-04: restart on crash, real logging, and a deploy that fails when the bot does
- 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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017XrE7F9ZuBWdQnS8CZvYDE
This commit is contained in:
parent
0a76f73de5
commit
5751be129d
7 changed files with 60 additions and 2 deletions
17
.github/workflows/deploy.yml
vendored
17
.github/workflows/deploy.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
13
Cargo.lock
generated
13
Cargo.lock
generated
|
|
@ -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",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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 && \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
10
src/main.rs
10
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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue