Compare commits

..

1 Commits

Author SHA1 Message Date
sim
c88391b68c ci: pin the toolchain to 1.98.1 in all three jobs
All three jobs used `dtolnay/rust-toolchain@stable`, so the gate resolved to
whatever stable was on the day it ran. A floating lint gate is not a gate: the
same tree goes green or red by date, and that already produced a disagreement
between two people reading the same commit — `collapsible_else_if` is `warn` on
1.92.0 and `allow`-by-default pedantic on 1.98.1, so both readings were correct.

1.98.1 is what run 206 resolved and what `docker/ci/Dockerfile` already pins, so
`docker/ci/run cargo clippy …` on a desktop becomes a true stand-in for this
workflow instead of an approximation. The header says how to bump: the three
refs here and the Dockerfile's `FROM` in one commit, in a PR of its own, where
the lints the new version turns on are the diff.

Also: the corpus-report step's comment quoted `207/0/14`, a tally two baselines
old. It now describes the shape of the problem without pinning a number that
decays.

Closes #15.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 22:21:27 +02:00
2 changed files with 32 additions and 32 deletions

View File

@@ -31,6 +31,24 @@ env:
# So: one job, on the machine that exists, building for the machine that exists.
# If a second architecture is ever wanted here it needs a second RUNNER, not a
# second matrix row.
#
# ── The toolchain is PINNED, in three places, deliberately ───────────────────
#
# All three jobs used `dtolnay/rust-toolchain@stable`, which resolves to whatever
# stable is on the day the job runs. A lint gate that floats is not a gate: the
# same tree goes green or red depending on the date, and this repo has already
# produced a disagreement between two people reading the same commit (#15).
# `collapsible_else_if` is the example — `warn` on 1.92.0, `allow`-by-default
# pedantic on 1.98.1, so a clean local run and a red CI run were both correct.
#
# `1.98.1` is the version run 206 resolved, and `docker/ci/Dockerfile` pins the
# same one, so `docker/ci/run cargo clippy …` on a desktop is a true stand-in for
# this workflow rather than an approximation of it.
#
# To bump: change all three `dtolnay/rust-toolchain@` refs here AND the `FROM
# rust:<version>-bookworm` in `docker/ci/Dockerfile` in one commit, so the two
# can never drift apart silently. A bump is a change to the gate and belongs in
# its own PR, where the new lints it turns on are the diff.
jobs:
# ── Native build, on the one runner there is ────────────────────────────────
@@ -42,13 +60,15 @@ jobs:
- uses: actions/checkout@v4
- name: Install Rust toolchain
# `stable` installs a MINIMAL profile: rustc, cargo, rust-std and no
# Pinned — see the toolchain note at the top of this file.
#
# This action installs a MINIMAL profile: rustc, cargo, rust-std and no
# more. Components have to be named. Without this line the Clippy step
# below dies on "'cargo-clippy' is not installed for the toolchain
# 'stable-aarch64-unknown-linux-gnu'" — which is not a lint result, it
# is the step never having run. The `fmt` job below always got this
# right; this one never did.
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.98.1
with:
components: clippy
@@ -78,7 +98,7 @@ jobs:
run: cargo test --workspace
# The tally above cannot tell you what it verified. `cargo test` reports
# the same 207/0/14 whether the disc corpus was exercised or entirely
# the same count whether the disc corpus was exercised or entirely
# absent -- a gated suite that skips still counts as passed, and the
# `ignored` column is a static count of `#[ignore]` attributes that cannot
# move at runtime. Issue #16. This prints what the run ACTUALLY had, from
@@ -114,7 +134,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install Rust toolchain + WASM target
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.98.1
with:
targets: wasm32-unknown-unknown
@@ -161,7 +181,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@1.98.1
with:
components: rustfmt
- run: cargo fmt --all -- --check

View File

@@ -6,34 +6,14 @@
//! silence. One rule, two outcomes.
use std::path::Path;
use std::sync::OnceLock;
use sylpheed_formats::{slb, PakArchive};
mod common;
use common::skip_without_disc;
/// One archive for the whole binary.
///
/// `PakArchive` holds the entire concatenated payload in memory, and
/// `sound.pak` is **1.01 GB** (`sound.p00`-`.p04`). Opening it per call — which
/// the helpers below did, inside loops — put one copy per test thread in flight,
/// so at the default thread count the suite needed ~6 GB and was SIGKILLed by
/// the CI container's 7 GB cap (`--memory-swap` equals `--memory`, so there is
/// no swap to absorb it). A killed suite prints no `test result:` line at all,
/// so it vanishes from the tally rather than failing visibly.
///
/// The archive is immutable once open and every accessor takes `&self`, so one
/// shared instance is equivalent to N private ones — at 1/N the memory.
fn sound(root: &Path) -> &'static PakArchive {
static SOUND: OnceLock<PakArchive> = OnceLock::new();
// Every caller passes the same `disc_root()`, so first-writer-wins is the
// same archive whichever test initialises it.
SOUND.get_or_init(|| PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"))
}
fn bank(root: &Path, n: u32) -> Vec<u8> {
let snd = sound(root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let path = format!("eng\\etc\\VOICE_D_{n}.slb");
let entry = snd.find_by_name(&path).expect("bank present");
snd.read(entry).expect("read")
@@ -91,7 +71,7 @@ fn all_zero_leading_region_is_skipped() {
}
fn bank_named(root: &Path, path: &str) -> Vec<u8> {
let snd = sound(root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let entry = snd
.find_by_name(path)
.unwrap_or_else(|| panic!("{path} present"));
@@ -174,7 +154,7 @@ fn derived_offset_recovers_voice_banks_without_regressing_etc() {
#[test]
fn scan_data_offset_agrees_with_the_riff_derived_answer() {
skip_without_disc!(root);
let snd = sound(&root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut checked = 0usize;
let mut agreed = 0usize;
for lang in ["eng", "jpn"] {
@@ -218,7 +198,7 @@ fn scan_data_offset_agrees_with_the_riff_derived_answer() {
#[test]
fn scan_only_returns_known_offsets() {
skip_without_disc!(root);
let snd = sound(&root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut seen = 0usize;
for n in 1u32..200 {
for path in [
@@ -252,7 +232,7 @@ fn scan_only_returns_known_offsets() {
#[test]
fn a_waves_declared_size_is_confirmed_by_the_next_seek() {
skip_without_disc!(root);
let snd = sound(&root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut checked = 0usize;
for n in 1u32..400 {
for path in [
@@ -309,7 +289,7 @@ fn a_waves_declared_size_is_confirmed_by_the_next_seek() {
#[test]
fn a_bank_that_states_its_own_header_has_no_leading_segment() {
skip_without_disc!(root);
let snd = sound(&root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
let mut with_header = 0usize;
let mut mid_bank = 0usize;
// Peek at the 56-byte header through the archive's flat data rather than
@@ -347,7 +327,7 @@ fn a_bank_that_states_its_own_header_has_no_leading_segment() {
#[test]
fn the_menu_music_bank_is_exactly_two_sub_waves() {
skip_without_disc!(root);
let snd = sound(&root);
let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak");
for (name, sizes) in [
("BGM_103.slb", [3_876_864usize, 3_930_112]),
("BGM_001.slb", [4_466_688, 4_673_536]),