mirror of
https://github.com/dsec-hub/dsec-discord-bot.git
synced 2026-09-22 15:53:56 +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 }}
|
working-directory: ${{ github.workspace }}
|
||||||
run: |
|
run: |
|
||||||
sudo docker compose up -d --build --force-recreate
|
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."
|
echo "Deployment complete."
|
||||||
|
|
||||||
- name: Remove environment file
|
- name: Remove environment file
|
||||||
|
|
|
||||||
13
Cargo.lock
generated
13
Cargo.lock
generated
|
|
@ -1604,6 +1604,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maybe-rayon"
|
name = "maybe-rayon"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -3533,10 +3542,14 @@ version = "0.3.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
|
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex-automata",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@ reqwest = "0.12.24"
|
||||||
serde_json = "1.0.145"
|
serde_json = "1.0.145"
|
||||||
serenity = "0.12"
|
serenity = "0.12"
|
||||||
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
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"
|
supabase-lib-rs = "0.5.3"
|
||||||
serde = "1.0.228"
|
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
|
# Install build dependencies
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,13 @@ docker-compose build
|
||||||
docker-compose up
|
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
|
## Rules
|
||||||
|
|
||||||
### General Rules
|
### General Rules
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
services:
|
services:
|
||||||
dsec_bot:
|
dsec_bot:
|
||||||
build: .
|
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_file:
|
||||||
- .env
|
- .env
|
||||||
10
src/main.rs
10
src/main.rs
|
|
@ -150,6 +150,16 @@ async fn on_error(error: poise::FrameworkError<'_, Data, Error>) {
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn 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
|
dotenv().ok(); // load env
|
||||||
|
|
||||||
let app_state = AppState::new()
|
let app_state = AppState::new()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue