diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 71634a3..40e57e3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -116,11 +116,12 @@ jobs: # commit whose tests are red. Pull requests skip it: their own CI run covers # the code, and the docker job there only proves the image still builds. ci: - # The offline suite's only master/tag run (`ci.yml` has no push trigger). - # Every non-PR push runs it — the gate's own `changes` job skips the heavy - # work for a docs-only diff — independently of whether the image itself is - # rebuilt. - if: github.event_name != 'pull_request' + needs: should-build + # The suite's only master/tag run (`ci.yml` has no push trigger). Gated on + # `should-build` so a release push — which fires a master *and* a tag run for + # one commit — tests once: the master run's `should-build` is false (already + # tagged), so only the tag run gates. + if: needs.should-build.outputs.build == 'true' && github.event_name != 'pull_request' uses: ./.github/workflows/ci.yml with: gate: true diff --git a/AGENTS.md b/AGENTS.md index 696c90a..32eb67d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,7 +89,7 @@ Docker: `docker build -t tgxmb .` then `docker run --rm -d --name tgxmb --env-fi | `Dockerfile` | Multi-stage: cached dep layer via stub sources + `touch *.rs` mtime bump (cargo's freshness is mtime-based and `cargo clean -p` removes 0 files — the touch is what forces the real sources to rebuild while deps stay cached), static ffmpeg from ffmpeg.martin-riedl.de (`FFMPEG_URL` arg, optional `FFMPEG_SHA256` checksum, `unzip -t` integrity check), `debian:bookworm-slim` runtime, entrypoint. Runtime ships **no libssl/libcrypto/CA bundle** — rustls webpki-roots handles all TLS, and the static ffmpeg only processes local files (downloads go through reqwest) | |`docker-entrypoint.sh` | Privilege drop: `useradd` with `LOCAL_USER_ID` (default 9001) + `setpriv` (no gosu on bookworm-slim); rejects a non-numeric or `0` `LOCAL_USER_ID`, which would otherwise survive the drop and run the bot root | | `docker-compose.yml` | The deployment composition, committed as-is: every instance value (token, admins, site credentials, domain) is a `${VAR}` substitution read from the gitignored `.env` beside it, so the file needs no per-deployment edit — and a variable not listed in a service's `environment:` never reaches that container. Ships nginx-proxy + acme-companion: webhook mode needs TLS termination in front (teloxide's axum listener is HTTP-only; `WEBHOOK_CERT` only feeds `set_webhook`), bot exposes `VIRTUAL_HOST`/`VIRTUAL_PORT` on the shared `proxy` network, no host port; container names `nginx-proxy`/`acme-companion`/`tgxmb`, start order via `depends_on` (proxy → acme → bot) | -| `.github/workflows/docker.yml` | CI: build+push to Docker Hub on tag `v*`/master, plus a build-only check on PRs touching the build inputs; the push is gated on `ci.yml`'s offline suite (reused via `workflow_call` with `gate: true` — `ci.yml` has no `push` trigger, so for a master/tag push this gate is the *only* place the suite runs, and the image waits on it); verifies a release tag matches both crate versions; buildx gha cache (`cache-from` always, `cache-to` except on PRs, scope `tgxmb-build`, `mode=max`) so cargo deps + ffmpeg layers are restored across runs; `FFMPEG_URL`/`FFMPEG_SHA256` come from repo variables when set | +| `.github/workflows/docker.yml` | CI: build+push to Docker Hub on tag `v*`/master, plus a build-only check on PRs touching the build inputs; the push is gated on `ci.yml`'s offline suite (reused via `workflow_call` with `gate: true`; `ci.yml` has no `push` trigger, so this gate is where a master/tag push is tested — and it is itself gated on `should-build`, so a release (whose branch and tag push fire two docker runs) still tests once); verifies a release tag matches both crate versions; buildx gha cache (`cache-from` always, `cache-to` except on PRs, scope `tgxmb-build`, `mode=max`) so cargo deps + ffmpeg layers are restored across runs; `FFMPEG_URL`/`FFMPEG_SHA256` come from repo variables when set | | `README.md` | Feature docs + command table (Chinese) | ## Runtime/Tooling Preferences