From b1b0bfbf0e4441a30e43c0a83e87c60bc672bf1a Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Tue, 20 Oct 2026 00:16:49 +0700 Subject: [PATCH] docs(linux): fix stale CI facts and supersede ADRs instead of editing --- .claude/rules/ci.md | 5 +++-- linux/AGENTS.md | 4 ++-- linux/ARCHITECTURE.md | 2 +- linux/CONTRIBUTING.md | 2 +- linux/README.md | 2 +- linux/ROADMAP.md | 2 +- linux/docs/README.md | 2 +- .../docs/decisions/0017-distribution-channels.md | 2 +- linux/docs/decisions/README.md | 15 +++++++++++---- linux/docs/testing.md | 13 +------------ 10 files changed, 23 insertions(+), 26 deletions(-) diff --git a/.claude/rules/ci.md b/.claude/rules/ci.md index 89c49f647b..29fed01d9f 100644 --- a/.claude/rules/ci.md +++ b/.claude/rules/ci.md @@ -13,7 +13,7 @@ paths: # CI -The required check names are in `AGENTS.md` (CI). Reading a red check: `.claude/skills/fix-issue/references/verification-apple.md`, Reading CI. Release tags: `apple/RELEASING.md`. +The required checks are in rulesets 23957966 and 25367692 below; `gh api repos/TableProApp/TablePro/rules/branches/main` lists them live. Reading a red check: `.claude/skills/fix-issue/references/verification-apple.md`, Reading CI. Release tags: `apple/RELEASING.md`. ## Rulesets @@ -22,7 +22,8 @@ The required check names are in `AGENTS.md` (CI). Reading a red check: `.claude/ | 25308039 "tags never move" | tags `v*`, `linux-v*`, `libs-*` | update, deletion | none | | 23959123 "release tags are created by admins" | tags `v*`, `linux-v*`, `libs-*`, `plugin-*` | creation | admins | | 25308049 "release branches are created by admins" | `release/*` | creation | admins | -| 23957966 "main and release branches require green gates" | default branch, `release/*` | the required checks, `do_not_enforce_on_create` | none | +| 23957966 "main and release branches require green gates" | default branch, `release/*` | required checks `macOS Tests`, `iOS and Package Tests`, `SwiftLint`, `Repo Hygiene`, `PR title`; `do_not_enforce_on_create` | admins, `pull_request` mode | +| 25367692 "main requires Linux" | default branch | required check `Linux`; `do_not_enforce_on_create` | admins, `pull_request` mode | | 25129799 "branches keep their history" | default branch, `release/*`, `gh-pages` | deletion, non-fast-forward | none | - `gh-pages` takes no required checks (`apple/RELEASING.md`, Keys and environments). diff --git a/linux/AGENTS.md b/linux/AGENTS.md index 2020b323e8..39d264053e 100644 --- a/linux/AGENTS.md +++ b/linux/AGENTS.md @@ -10,7 +10,7 @@ This is the guide for work under `linux/`. The root `AGENTS.md` holds the rules 2. **Native only.** GTK 4 and libadwaita, used the way the GNOME Human Interface Guidelines describe, with the widget the toolkit provides before anything drawn by hand. No web views, no cross-platform toolkit. 3. **One-directional crates.** The domain crate (`tablepro-core`) never imports the GUI or a driver, and a new database engine is one crate. `ARCHITECTURE.md` has the graph. 4. **Drivers are linked in at compile time.** There is no plugin system and no plugin ABI (`docs/decisions/0001-no-plugin-system.md`). -5. **Decisions are recorded.** A change that reverses a decision in `docs/decisions/` says so and updates the record. +5. **Decisions are recorded.** A change that reverses a decision in `docs/decisions/` adds an ADR that supersedes it; the old one changes only its Status line (`docs/decisions/README.md`). ## Map @@ -51,4 +51,4 @@ From the repository root, through the verification wrapper, which keeps the full ## CI -The Linux workflows are `.github/workflows/build-linux.yml`, `.github/workflows/linux-packages.yml` and `.github/workflows/release-linux.yml`. `docs/testing.md`, CI, lists every job, what starts it and what it runs; read it before changing a workflow or reading a red check. Every action is pinned by commit SHA; a new one is too. +The Linux workflows are `.github/workflows/build-linux.yml`, `.github/workflows/linux-packages.yml` and `.github/workflows/release-linux.yml`. Each one's `on:`, job `if:` and steps are the record of what runs and when; read the workflow before changing it or reading a red check. Every action is pinned by commit SHA; a new one is too. diff --git a/linux/ARCHITECTURE.md b/linux/ARCHITECTURE.md index 6e6afd9029..7c9b22b024 100644 --- a/linux/ARCHITECTURE.md +++ b/linux/ARCHITECTURE.md @@ -316,7 +316,7 @@ A restore deletes the drafts no saved or open tab names, except while a moved-as Meson is the build system and Cargo is the Rust compiler; see [ADR 0006](docs/decisions/0006-meson-cargo-build.md). `meson setup _build && meson compile -C _build` produces `tablepro` and `tablepro-askpass`, and `meson test -C _build` runs the `unit`, `gtk`, `data` and `packaging` suites. -The platform floor is GNOME 50 ([ADR 0015](docs/decisions/0015-gnome-50-platform-floor.md)), and `meson.build` refuses to configure below it. [docs/testing.md](docs/testing.md#ci) lists every CI job, what starts it and where it runs. +The platform floor is GNOME 50 ([ADR 0015](docs/decisions/0015-gnome-50-platform-floor.md)), and `meson.build` refuses to configure below it. [docs/testing.md](docs/testing.md#ci) names the CI workflows. ## Out of scope diff --git a/linux/CONTRIBUTING.md b/linux/CONTRIBUTING.md index 516cbc4ed4..938f81fcaf 100644 --- a/linux/CONTRIBUTING.md +++ b/linux/CONTRIBUTING.md @@ -54,7 +54,7 @@ meson dist -C _build --no-tests --formats xztar Inside a desktop session, `dbus-run-session -- meson test -C _build` runs the same suites without xvfb. -The fast job also runs a few source greps and the lychee line below, from the repository root. The supply-chain and Docker jobs run the rest, among others; [docs/testing.md](docs/testing.md#ci) describes every job, and the Docker job runs the last line once per package that has Docker tests: +The fast job also runs a few source greps and the lychee line below, from the repository root. The supply-chain and Docker jobs run the rest, among others; `.github/workflows/build-linux.yml` has every job, and the Docker job runs the last line once per package that has Docker tests: ```bash cargo deny --locked check advisories bans licenses sources diff --git a/linux/README.md b/linux/README.md index 74c50ed27c..055dd260fa 100644 --- a/linux/README.md +++ b/linux/README.md @@ -275,7 +275,7 @@ says where the realm, the KDC and the tickets come from there. | State management: windows, sessions, background work | [docs/state-management.md](docs/state-management.md) | | Persistence: secrets, settings, files | [docs/storage.md](docs/storage.md) | | Error handling conventions | [docs/error-handling.md](docs/error-handling.md) | -| Testing conventions, suites and CI jobs | [docs/testing.md](docs/testing.md) | +| Testing conventions and suites | [docs/testing.md](docs/testing.md) | | Saved passwords, SSH, Kerberos, logs and crash reports, for users | [docs/troubleshooting.md](docs/troubleshooting.md) | | Release setup, releases and packaging fixes | [docs/releasing.md](docs/releasing.md) | | Every guide and driver page | [docs/README.md](docs/README.md) | diff --git a/linux/ROADMAP.md b/linux/ROADMAP.md index 7f27a4239a..b4c034280c 100644 --- a/linux/ROADMAP.md +++ b/linux/ROADMAP.md @@ -109,7 +109,7 @@ The app runs on GNOME 50 ([ADR 0015](docs/decisions/0015-gnome-50-platform-floor | Capability | Detail | |---|---| -| Flatpak | The Devel manifest builds on GNOME 51 for x86_64 and aarch64 with every Meson suite in the sandbox, and is linted, on every pull request that touches `linux/` | +| Flatpak | The Devel manifest builds on GNOME 51 for x86_64 and aarch64 with every Meson suite in the sandbox, and is linted, in the nightly Linux run | | .deb and .rpm | Ubuntu 26.04 and 26.10 and Fedora 44, built offline in CI the way Launchpad and COPR build them, linted, then installed and started in fresh containers; a `linux-v*` tag uploads to the PPA and starts the COPR build ([ADR 0018](docs/decisions/0018-ppa-copr-and-flathub-later.md)) | | Desktop integration | Desktop file with Open With for SQLite files, D-Bus activation, a man page, metainfo with screenshots, and SVG icons | | Translations | The app's own strings go through gettext, and CI fails when `POTFILES.in` is stale. The template is generated on demand with gettext 1.0. Some error details from the core crates still reach the user in English (see Release criteria) | diff --git a/linux/docs/README.md b/linux/docs/README.md index 93d1db66f2..4692404079 100644 --- a/linux/docs/README.md +++ b/linux/docs/README.md @@ -10,7 +10,7 @@ The reference for working on the Linux app. Start with [ARCHITECTURE.md](../ARCH | [error-handling.md](error-handling.md) | The error types each layer returns, their categories, and the text and logs the app makes of them | | [state-management.md](state-management.md) | Where the application, window, workspace and tab state lives, and the rules every view follows | | [storage.md](storage.md) | Which store holds which data: files, GSettings, the Secret Service and SQLite | -| [testing.md](testing.md) | The test suites, the conformance and Docker tests, and the CI jobs | +| [testing.md](testing.md) | The test suites, the conformance and Docker tests, and the CI workflows | | [troubleshooting.md](troubleshooting.md) | For users: saved passwords, SSH, Kerberos, logs, crash reports, bug reports and downgrades | | [regression-tests.md](regression-tests.md) | The tests that guard each critical audit finding | | [releasing.md](releasing.md) | The setup before the first release, a release, a packaging fix and a fix release | diff --git a/linux/docs/decisions/0017-distribution-channels.md b/linux/docs/decisions/0017-distribution-channels.md index d7e79e0241..eedd60789d 100644 --- a/linux/docs/decisions/0017-distribution-channels.md +++ b/linux/docs/decisions/0017-distribution-channels.md @@ -1,6 +1,6 @@ # 0017: Distribution channels -- **Status**: Superseded by 0018 +- **Status**: Superseded by 0018. The `LINUX_BRANCH` default below is no longer `linux`; `release-linux.yml` has the current one. - **Date**: 2026-10-14 ## Context diff --git a/linux/docs/decisions/README.md b/linux/docs/decisions/README.md index 3cf5065f9f..a42ec280fd 100644 --- a/linux/docs/decisions/README.md +++ b/linux/docs/decisions/README.md @@ -1,6 +1,6 @@ # Architecture Decision Records -These are short documents recording the **reasoning** behind major technical choices. Once an ADR is accepted, its decision stays as recorded. When a later ADR or change replaces part of it, the Status line says which part, and names the ADR or the date that replaced it. Any part that describes the current system is kept true. +These are short documents recording the **reasoning** behind major technical choices. An ADR records the decision as it stood on its date, and is not kept current. The code, the workflows and the rest of `docs/` describe the system as it is now. Every load-bearing decision in the Linux subproject has an ADR. If a contributor asks "why did we pick X", the answer should already be in this folder. If it is not, we missed an ADR. @@ -35,10 +35,16 @@ Brief note on each alternative and why it lost. Context, Decision and Consequences are always there. Rationale and Alternatives considered are there when other options were weighed. A section an ADR needs beyond these, such as a matrix or a dated note, comes after them. -The Status is `Accepted`, `Superseded by 000M` or `Deprecated`. An accepted ADR that a later one changed in part reads `Accepted; superseded by 000M` (replaced) or `amended by 000M` (extended), or `amended ` when the change came without an ADR. +The Status is `Accepted`, `Superseded by 000M` or `Deprecated`. An accepted ADR that a later one changed in part reads `Accepted; superseded by 000M` (replaced) or `amended by 000M` (extended). The `amended ` statuses below predate this rule. ADRs are short on purpose. If yours is more than a page, you are probably arguing instead of recording. +## Changing a decision + +A new ADR supersedes the old one, as in Michael Nygard's [Documenting Architecture Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions). The new ADR says what it replaces and why. The old ADR's only edit is its Status line, naming the new one, plus the same change to its row in the index. Do not rewrite an old ADR's body to match the current system. + +A fact the repository keeps elsewhere, such as a workflow trigger, a branch, a variable's default or a ruleset, is pointed to from an ADR, not copied into it, so the ADR stays true without edits. + ## Index | # | Title | Status | Summary | @@ -67,5 +73,6 @@ ADRs are short on purpose. If yours is more than a page, you are probably arguin 1. Take the number after the highest one. Never reuse a number, even a deprecated ADR's. 2. Copy the format above into a new file. Use a dash-separated lowercase title slug. -3. Open a PR. ADRs go through the same review as code. -4. After merge, link from the index above. +3. If it replaces an earlier decision, set the earlier ADR's Status to `Superseded by 000N`, or `Accepted; superseded by 000N`, in the same PR. +4. Open a PR. ADRs go through the same review as code. +5. After merge, link from the index above. diff --git a/linux/docs/testing.md b/linux/docs/testing.md index 1aa3a667bf..c64c554c60 100644 --- a/linux/docs/testing.md +++ b/linux/docs/testing.md @@ -408,18 +408,7 @@ The tests in `crates/app/src/ui/editor/script_runner.rs` drive `run_batches` und ## CI -GitHub Actions (`.github/workflows/build-linux.yml`), Ubuntu runners. Its `on:` lists what starts it. Flatpak Devel and Minimum Rust version run only on its schedule and by hand. Every action is pinned by commit SHA and every tool by version. - -1. **Fast checks**: lychee, offline, over every Markdown file under `linux/`, with heading anchors checked, then `meson setup`, `cargo fmt --all -- --check`, the source greps (no `thread_local!` in services, no blocking file I/O under `ui`, no action group inserted as `win`, no `set_qdata`, no em dash in user-facing text), clippy with and without default features, `meson compile`, `xvfb-run -a dbus-run-session -- meson test --print-errorlogs`, a Secret Service step under `gnome-keyring-daemon`, then `meson dist`. Runs in an `ubuntu:26.04` container, which ships GLib 2.88 plus the meson, appstream and desktop-file-utils packages. A failed run keeps `_build/meson-logs/testlog.txt` as the `meson-testlog` artifact. [CONTRIBUTING.md](../CONTRIBUTING.md#fast-job-commands) lists the same commands. -2. **Docker tests** (`integration`, `integration-session`, `integration-app`): runs after fast checks pass, and keeps each package's JUnit report as a `junit-` artifact, `junit--` for a release entry. One matrix entry per package with docker tests (the PostgreSQL driver with PgBouncer, the MySQL driver with MariaDB, the SQL Server and ClickHouse drivers, all four with their TLS suites, `tablepro-ssh` against an OpenSSH server container, and `tablepro-test-fixtures` for the fixtures themselves) runs that package's ignored docker tests through cargo-nextest on the host runner's Docker, one test at a time per package. The driver packages have an entry more for each older or newer server release ([Server releases](#server-releases)). `tablepro-session` builds storage, which needs GLib 2.88, so its job runs in the fast job's `ubuntu:26.04` image with the host's Docker socket mounted. The app's docker tests (`crates/app/tests/tracker_save_postgres.rs`) run the same way, since the app links GTK; that job names its test targets, because the app's `startup` test needs Meson. The SQLite driver needs no container: its suites run in the fast job. -3. **Supply chain**: `cargo deny check` against `deny.toml` (advisories, bans, licenses and sources, with every feature, both Linux targets and the dev-dependencies), `cargo shear` for unused or misplaced dependencies, and `build-aux/update-third-party-licenses.sh`, failing when `data/licenses`, `build-aux/debian/copyright` or the spec's `License` tag differ from what it writes. Then `zizmor` over the three Linux workflows. -4. **Translations**: in `ubuntu:26.10`, whose gettext 1.0 reads path-qualified Rust calls such as `crate::i18n::gettext(...)`. `po/POTFILES.in` must match `git ls-files`, and `meson setup --fatal-meson-warnings` must pass. `po/tablepro.pot` is not committed; `meson compile -C _build tablepro-pot` writes it, with gettext 1.0 or newer (`po/README.md`). -5. **Flatpak Devel**: the Devel manifest built in the `gnome-51` Flatpak image for x86_64 and aarch64, with every Meson suite run inside the build sandbox from a tree with no `.git`. The x86_64 job lints the manifest with `flatpak-builder-lint` and `build-aux/flatpak/lint-exceptions.json`. The repository holds no Flathub manifest ([ADR 0018](decisions/0018-ppa-copr-and-flathub-later.md)). -6. **Minimum Rust version**: in `ubuntu:26.04`, `build-aux/packaging/add-rust-toolchain-ppa.sh` adds `ppa:rust-toolchain/staging`, `apt-get build-dep -P nocheck` installs the .deb's build dependencies without the test-only ones, and `cargo-1.97 check --workspace --all-targets --locked` runs with and without default features: the compiler the PPA builds with, at the workspace `rust-version`. - -A `Changes (Linux)` job runs `scripts/ci/detect-changed-paths.sh linux`, and every job but Flatpak Devel and Minimum Rust version waits for it: a change that touches nothing the Linux jobs read skips them, and a schedule or manual run takes every job. The `Linux` job needs all of them and fails when any failed or was cancelled, so it is the one check a branch rule requires; a skipped job counts as passed. - -`.github/workflows/linux-packages.yml` builds the packages from the release source and vendor tarballs. For each Ubuntu series the PPA builds for, 26.04 and 26.10, it writes the Debian source package with `build-aux/packaging/build-source.sh`, then `build-deb.sh` builds the binaries from it the way Launchpad does: in a fresh container of that series with only the declared build dependencies, offline, as a user that is not root, running every Meson suite, then lintian. `build-rpm.sh` builds the .rpm in `fedora:44` with only its BuildRequires, running every Meson suite, and checks it with `rpmlint --strict`. Each package is then installed in a fresh container and started. Its `on:` lists what starts it. A pull request or the nightly run builds x86_64 only. Run by hand with `arm64` ticked, it builds, tests and installs both packages on an arm64 runner too. `.github/workflows/release-linux.yml` calls it on a `linux-v*` tag before it publishes, on both architectures ([ADR 0018](decisions/0018-ppa-copr-and-flathub-later.md)). Run by hand on a branch with a released tag and a revision, `release-linux.yml` calls it on that release's tarballs with the branch's .deb packaging, then uploads the result to the PPA as a new revision ([releasing.md](releasing.md#a-packaging-fix)). `build-aux/packaging/build-packages.sh` runs the same steps locally. +`.github/workflows/build-linux.yml` builds and tests the app, `.github/workflows/linux-packages.yml` builds, installs and starts the .deb and .rpm, and `.github/workflows/release-linux.yml` publishes a `linux-v*` tag. Each workflow's `on:` and each job's `if:` say when it runs; its steps say what it runs. To run the same checks locally: the [fast-job commands](../CONTRIBUTING.md#fast-job-commands) and `build-aux/packaging/build-packages.sh`. ## Coverage