Phase 6: Linux distribution packaging (apt / dnf / pacman + signed GitHub Pages repos) - #36
Conversation
…d app_id Prepares the systemd unit and the egui GUI for the deb/rpm/pacman packages. - splitway.service: ExecStart now passes `--config /var/lib/splitway/config.json` and the unit declares StateDirectory=splitway (0700), mirroring nix/module.nix. The daemon creates its config under the persistent, daemon-owned state dir on first run instead of falling back to /root/.config (and logging a warning). - Add the same --config to the commented socket-group opt-in ExecStart override. The bare `ExecStart=` reset fully replaces the command, so without this an opt-in user would silently drop --config and reintroduce the /root/.config fallback this commit removes. (Minor deviation from the "keep the block untouched" plan, for correctness/consistency with the main ExecStart and nix/module.nix.) - splitway-gui: set the ViewportBuilder app_id to io.github.stslex.splitway so Wayland compositors map the window to the packaged .desktop entry + hicolor icon (shipped under that basename by the GUI package). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
Adds the MIT LICENSE (the repo had none) and declares `license = "MIT"` on every workspace crate, then defines the deb + rpm metadata for the core `splitway` package on splitway-daemon. The package ships both binaries — `splitway-daemon` and the `splitway` CLI (from splitway-cli) — plus the systemd unit and README/LICENSE. It is built musl-static (*-unknown-linux-musl) so it has no shared-library dependencies and installs on any glibc/musl baseline; the desktop GUI is a separate package (next commit) that Depends on this one. - [package.metadata.deb]: name=splitway, binaries to /usr/bin, copyright from the MIT text, Recommends network-manager + systemd-resolved (not Depends), empty Depends (static). An (empty) maintainer-scripts dir enables cargo-deb's systemd-units integration to generate the postinst/postrm: enable+start on install, restart on upgrade, stop on remove, daemon-reload. - [package.metadata.generate-rpm]: same layout, auto-req disabled (static), weak-dep Recommends, raw /bin/sh systemd scriptlets (cargo-generate-rpm does not expand %systemd_* macros). Asset-path note (verified by building both packages with cargo-deb 3.7.0 and cargo-generate-rpm 0.21.0): cargo-deb resolves non-`target/` asset paths relative to THIS crate's manifest dir (so workspace-root files use `../`), while cargo-generate-rpm resolves relative to the invocation dir (workspace root, bare paths) — hence the intentional path skew between the two blocks. Version is stamped at the packaging layer (cargo deb --deb-version / cargo generate-rpm --set-metadata) so dev builds get <ver>~dev.<utc>.<sha> without a non-semver string in Cargo.toml. CI builds per-triple with --target (remaps target/release -> target/<triple>/release and stamps the arch). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
…opt-in A separate `splitway-gui` package for the egui desktop GUI (glibc, dynamic), which Depends on the musl-static core `splitway` (>=, the IPC compat contract). - .desktop (io.github.stslex.splitway.desktop, Exec=splitway-gui) + hicolor icons rasterized from assets/icon/splitway-icon.svg (8 PNG sizes + scalable SVG, basename = app_id) via packaging/icons/generate-hicolor.sh. The icon tree is committed so every packaging path ships it without a rasterizer; the .desktop passes desktop-file-validate. - Dependencies (both formats, verified by building real packages): the eframe/glow windowing libs are DLOPEN'd by winit/glow at runtime, so they are absent from the ELF DT_NEEDED and neither cargo-deb's $auto nor cargo-generate-rpm's auto-req can detect them — they MUST be hardcoded. deb: libgl1, libx11-6, libxcursor1, libxi6, libxrandr2, libwayland-client0, libxkbcommon0, libc6 (>= 2.31 floor). rpm: mesa-libGL, libX11, libXcursor, libXi, libXrandr, libwayland-client, libxkbcommon (auto-req still pins the glibc floor from libc/libgcc sonames). Recommends an XDG desktop portal + backend for rfd's file dialog. - Socket-group opt-in (security-sensitive): the maintainer scripts create an EMPTY `splitway` group and install a service drop-in switching the daemon to group-socket mode (0660 root:splitway, dir 0750). EMPTY-GROUP INVARIANT: with no members the posture is identical to the default 0600 root-only; the scripts NEVER add a user — the only grant is a human running `usermod -aG splitway <user>` + re-login. postinst installs the drop-in + reloads + restarts; postrm removes it, groupdel only if empty, reverting to root-only. A loud first-install message prints the exact opt-in one-liner. Validated by building both packages with cargo-deb 3.7.0 / cargo-generate-rpm 0.21.0 and inspecting deps, files, and scriptlets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
…tests New packaging.yml (no secrets — gates the PR). The publish/sign job is added in the next commit. - meta: compute the channel version once (compute-version.sh). Release (push to master) = clean <X.Y.Z>; dev/PR/dispatch = <X.Y.Z>~dev.<utc>.<sha>, which sorts below the release in dpkg and rpm. - build-core (amd64 + arm64): `cross` builds splitway-daemon + splitway CLI musl-static, asserts `file` reports "statically linked", then cargo-deb / cargo-generate-rpm with --target (remaps target/release + sets arch) and the stamped version. Emits deb + rpm + tarball. - build-gui (amd64 + arm64): builds the egui binary INSIDE debian:bullseye (glibc 2.31 floor, so the libc6 (>= 2.31) / rpm GLIBC requires are true), arm64 on a native arm64 runner (no QEMU). Rewrites the core-dependency floor to the built version for dev channels, then packages on the host. - test-install (debian:bookworm, ubuntu:22.04, fedora:latest): installs the built artifacts directly; asserts the binaries run, the unit validates (systemd-analyze verify), the GUI pulls splitway + the GL deps, the empty `splitway` group exists with no members, and the .desktop validates. - test-signed-repo: generates a THROWAWAY gpg key, builds + signs local apt (build-apt-repo.sh) and dnf (build-dnf-repo.sh) repos from the artifacts, serves them over localhost, and installs with signature verification ON — proving metadata + signing + verify end-to-end with no production secret. (Those two repo scripts are reused by the real publish job next commit.) - test-arm64-smoke: best-effort arm64 deb install under QEMU. Validated locally: actionlint clean (incl. shellcheck of run blocks); all helper scripts shellcheck-clean; the deb/rpm builds + --target/--deb-version/ --set-metadata flags exercised against cargo-deb 3.7.0 / cargo-generate-rpm 0.21.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
Adds the publish-pages job (secrets) and the signing plumbing reused by the
PR-time ephemeral-key test.
- publish-pages: runs on push to master (release) / dev (dev) and dispatch,
NEVER on pull_request, gated behind the build + test jobs. Serialized by a
single `pages-deploy` concurrency group (cancel-in-progress: false) so two
deploys queue rather than clobber. Imports the RSA signing key, checks out
(or bootstraps) the persistent gh-pages branch, drops the artifacts into the
correct channel pool, regenerates + signs ONLY that channel's apt + dnf
metadata, publishes the armored pubkey to splitway.gpg, renders index.html,
and commits + pushes — MERGE, never wipe, so old versions and the other
channel survive. Release additionally attaches the tarballs to the v<ver>
GitHub Release. A post-deploy smoke waits for Pages to go live, then installs
from the real repo with signature verification ON (apt + dnf).
- build-apt-repo.sh / build-dnf-repo.sh: optional SPLITWAY_GPG_PASSFILE feeds
the real key's passphrase via loopback (never on a command line); unset for
the passphrase-less ephemeral key.
- render-index.sh: the Pages landing page with per-distro, per-channel
add-repo snippets + the key fingerprint.
- RSA fix: the throwaway test key (and, by requirement, GPG_PRIVATE_KEY) is RSA
— rpm --addsign only produces a verifiable signature with RSA; an EdDSA key
silently yields no RPMTAG_RSAHEADER (found + fixed via local signing tests).
Validated locally: apt InRelease + Release.gpg verify Good; per-arch Packages
filtering correct; dnf repomd.xml.asc verifies; RSA-signed rpm passes rpm -K
("digests signatures OK"). actionlint + shellcheck clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
Closes Arch via a self-hosted, GPG-signed pacman repo (reusing the apt/dnf key + Pages), since AUR registration is disabled. x86_64 for the hosted repo; aarch64 users use the in-repo splitway-bin PKGBUILD. PKGBUILDs in packaging/aur/ (also usable now via `makepkg -si`): - splitway: source build of daemon + CLI from the release tag; makedepends cargo; ships both binaries + unit; splitway.install prints the enable hint (Arch policy: no auto-enable); optdepends networkmanager / systemd-resolvconf. - splitway-bin: prebuilt from the release tarball (x86_64 + aarch64); provides/conflicts splitway. - splitway-gui: source egui GUI; depends splitway + libglvnd/libxkbcommon/ wayland/libx11/libxcursor/libxi/libxrandr; optdepends xdg-desktop-portal; splitway-gui.install mirrors the deb/rpm empty-group + drop-in invariant. CI (packaging.yml): - build-arch: archlinux container, non-root makepkg of the two source PKGBUILDs from THIS checkout (clean version — pacman has no ~dev channel because vercmp does not treat ~ as a pre-release marker), validates .SRCINFO + namcap (advisory). x86_64 .pkg.tar.zst artifacts. - test-arch: pacman -U local install (asserts binaries + unit + empty group), then a throwaway-RSA-key signed repo — repo-add --sign, pacman-key --add/--lsign, SigLevel = Required DatabaseOptional, pacman -Sy with verification ON. - publish-pages (release only): copies the .pkg.tar.zst into the persistent arch/release/x86_64 subtree, detach-signs each with the real key, repo-add (in a container) incrementally (old packages preserved), replaces Pages- hostile db/files symlinks with real signed copies, reuses splitway.gpg. Post-deploy: live `pacman -Sy splitway` with verification ON. - render-index.sh: Arch section (signed repo primary, makepkg alternative, AUR pending). DEFERRED (not here): the automated AUR ssh push — blocked on AUR registration reopening. The in-repo PKGBUILDs are the bridge. Validated locally: all PKGBUILD/.install bash-syntax-clean; actionlint clean; index renders with $arch left literal for pacman. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
Docs only — no code. - README: Install sections for apt / dnf (both channels) and Arch (signed pacman repo primary, in-repo PKGBUILD makepkg alternative; AUR pending), with the key-verification note. NixOS section left as-is. - packaging/README.md: a Distribution packages (deb / rpm / pacman) section — the two-package split, dev vs release channels + ~dev versioning, the glibc 2.31 floor, the dlopen'd GL deps, the GUI socket-group drop-in + empty-group invariant, and the pacman specifics (x86_64-only, no ~dev channel, detached signing, repo-add incrementality). - docs/design/linux-distro-packaging.md: the durable record — decisions 1-7, the channel/version topology, dep lists, signing + merge mechanics across all three formats (incl. the RSA-not-EdDSA and cargo-deb-vs-generate-rpm path-resolution gotchas), the two-layer test design, the pacman-now/AUR-later Arch strategy, and the signing key. - ROADMAP.md: Phase 6 marked done (Linux), noting the two-package design supersedes the original one-package sketch; macOS Homebrew + the automated AUR push remain deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
No behavior change for the current (validated) inputs — robustness only, flagged by an adversarial self-review of the diff: - build-apt-repo.sh: `break` after the first Architecture line in the per-arch Packages filter (the canonical value; a valid stanza has exactly one). - packaging.yml: `g` flag on the GUI core-dep-floor seds (defensive if more `splitway (>=` references are ever added). - packaging.yml: comment that test-arm64-smoke is intentionally not a publish gate (best-effort under QEMU, continue-on-error). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e6f221f05d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
stslex
left a comment
There was a problem hiding this comment.
Review: Phase 6 — Linux distribution packaging
Note: posting as a comment because GitHub won't let me formally "Request changes" on this account's own PR — but treat the must-fix list as change-requesting.
Reviewed the full diff (39 files) both as independent slices (deb/apt, rpm/dnf, pacman/Arch, CI structure, signing/versioning/desktop) and as one cohesive change. Overall this is strong, careful work — the two-package split, the musl-static core vs glibc-floor GUI, the empty-splitway-group opt-in invariant (consistently mirrored across deb/rpm/pacman scriptlets), the upgrade-safe maintainer scripts ($1/$2 and remove|purge guards, members-empty check before groupdel, systemd-presence guards), and the merge-not-wipe channel model are all well thought through and well documented.
CI is currently red on two jobs, one of which is a real build-blocking bug, plus a second bug that makepkg would hit but CI never exercises.
Must-fix (blocking)
build-core (amd64)fails — static-linkage gate greps the wrong string. musl static-PIE binaries arestatic-pie linked, notstatically linked, so the gate aborts before any deb/rpm is built and kills the whole downstream pipeline. (.github/workflows/packaging.yml:69)packaging/aur/splitway-bin/PKGBUILDreferences a non-existent install scriptlet (splitway-bin.installvs the committedsplitway.install) →makepkgfails. Not caught becausebuild-archnever buildssplitway-bin. (PKGBUILD:15)test-archextracts the GPG fingerprint from the wrong colon field ($5instead of$10), yielding an emptyFPRthat breaks the Arch signed-repo test. Thepublish-pagesjob gets this right. (packaging.yml:428)
build-gui (arm64) failure
The second red job is a transient crates.io reset (HTTP2 framing layer … Connection reset by peer), not a code defect — but the container build has no cargo retry/cache, so it's a flakiness vector worth hardening (commented at packaging.yml:136).
Should-fix (security / correctness, non-blocking)
- Publish before verify:
gh-pagesis pushed before any signature is checked; a misconfigured (non-RSA) key would poison the live repo and only fail afterward. Add a pre-pushgpg --verify/rpm -Kgate. (packaging.yml:558) - apt
Releasehas noValid-Until→ no freeze/replay protection. (build-apt-repo.sh:69) sha256sums=('SKIP')on the prebuilt root-daemon tarballs disables integrity checking on privileged binaries. (splitway-bin/PKGBUILD:18)- Dev-channel apt doc snippet never installs the keyring → users following only the dev instructions hit a failing
apt-get update. (render-index.sh:50)
Nits / consistency
- Arch GUI
depends=('splitway')drops the>=floor the deb/rpm contract encodes (splitway-gui/PKGBUILD:15); lockstep version is hand-kept in three places (splitway-gui/Cargo.toml:3); dev-floorsedalso rewrites a comment and doesn't escape/verify$PKGVER(packaging.yml:145); design-doc signing-key fingerprint is still a placeholder while README/index tell users to verify against it; README/index pacman snippets omit thepacman-key --initthat CI itself runs.
Note on coverage
The signed-repo tests (apt + dnf + pacman) only install the core package, so the GUI package's header signature and Requires are never verified under signature enforcement (the unsigned test-install does install the GUI). Worth closing that gap.
One earlier candidate finding — that the arm64 GUI ships a libc6 (>= 2.31) floor it doesn't honor — was checked and dismissed: the debian:bullseye build step (packaging.yml:125) is not arch-gated, so it runs in an arm64 bullseye container on the arm runner and the 2.31 floor holds on both arches.
Reviewed with an independent multi-agent pass (per-build-type checks + holistic full-diff reviews); findings above were individually verified against the code and CI logs, not taken on trust.
Generated by Claude Code
Resolves the Codex + self-review findings on the Phase 6 packaging PR. Build-blocking CI fixes: - static-linkage gate: assert no dynamic interpreter instead of requiring the literal "statically linked" (musl x86_64 is "static-pie linked") — unblocks build-core (amd64) and the whole deb/rpm pipeline - test-arch: read the GPG fingerprint from fpr field 10, not 5 (5 is empty) - AUR splitway-bin: rename splitway.install -> splitway-bin.install so install="$pkgname.install" resolves (makepkg no longer aborts) - build-gui: CARGO_NET_RETRY + a retrying `cargo fetch --locked` before the offline build, hardening the transient arm64 crates.io failure Supply-chain / correctness: - apt: dearmor the published (armored) key into the binary keyring at every consumption site (works on every apt version; the published file stays armored for rpm --import / pacman-key) - publish: fail-closed signature verification (apt InRelease+Release.gpg, dnf repomd + per-rpm RSA header, pacman db+pkg sigs) BEFORE the gh-pages push - apt Release: Valid-Until (APT_VALID_DAYS, default 90d; LC_ALL=C) for freeze/replay protection - dev-floor sed: anchor to the dependency lines (leave the comment), and assert the floor was actually stamped - signed-repo tests (apt/dnf/pacman) now install splitway-gui too, exercising the GUI package under signature enforcement Arch / consistency / docs: - splitway-gui PKGBUILD: splitway>=$pkgver floor + hicolor-icon-theme, desktop-file-utils - new check-pkgver-sync.sh (meta job): daemon version == every PKGBUILD pkgver - render-index/README: dearmor --yes for apt, pacman-key --init, dev-channel keyring install - splitway-bin SKIP digest documented + tracked for the deferred AUR-push phase Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
Review addressed —
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3cb9760de3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…oling Follow-up to the second Codex pass on PR #36. - splitway-bin: `provides=("splitway=$pkgver")` (was unversioned). pacman only satisfies a versioned dependency from a versioned provision, so splitway-gui's new `splitway>=$pkgver` floor could not install against the prebuilt core. - test-signed-repo: install `rpm` in the tooling step. build-dnf-repo.sh needs `rpm --addsign`; it passes today only because ubuntu-latest pre-installs rpm — make it explicit (matches the publish job) so the dnf signing path is robust. - packaging/README.md: document the one-time config relocation for users who ran the daemon by hand as root before packaging (old XDG fallback /root/.config/splitway -> /var/lib/splitway). No maintainer-script migration: no published package used the old path, it is config-not-read (not data loss), and the deb core postinst is cargo-deb-generated (#DEBHELPER#) from an empty dir, so a hand-written migration would risk breaking systemd enablement that the docker install-test (no systemd) could not catch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66634a2276
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The `meta` gate (check-pkgver-sync.sh) requires every packaging/aur/*/PKGBUILD `pkgver=` to equal the daemon version, but release.yml's bump-version job only bumped splitway-daemon/Cargo.toml. So the first post-release auto-bump would leave the three PKGBUILDs behind and fail every later packaging run in `meta` until a human hand-edited all three. - Add packaging/ci/sync-pkgver.sh: the write side of the lockstep invariant (symmetric with check-pkgver-sync.sh, same daemon-version read). It stamps the daemon version into each PKGBUILD `pkgver=` and resets `pkgrel=1` (Arch convention on a version change). The `$pkgver`-derived fields (source URLs, provides, depends floor) follow automatically. - release.yml bump-version: run sync-pkgver.sh after the Cargo.toml bump and `git add` the PKGBUILDs into the same commit. Verified locally: no-op when already in sync (no diff), correct bump on a simulated 0.0.5 -> 0.0.6, and check-pkgver-sync.sh passes against the result. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b3260367b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…review) Two findings from Codex's re-review of b326036: - P2 (splitway-gui/Cargo.toml): the deb declared libgl1 but not libegl1, and the rpm required mesa-libGL but not mesa-libEGL. glow/glutin creates its GL context via EGL on Wayland (glutin_egl_sys is in Cargo.lock; GLX on X11), and libgl1 does NOT pull libegl1 — so a minimal Wayland-only install would succeed and then fail at GL-context creation. Add libegl1 (deb) and mesa-libEGL (rpm); both pull the libglvnd EGL loader, mirroring how libgl1/mesa-libGL pull GLX. Arch is unaffected (libglvnd already provides libGL + libEGL). Doc + comments updated. - P1 (packaging.yml test-arch): the local `pacman -U` smoke preinstalled the GL/X11/wayland libs but not hicolor-icon-theme/desktop-file-utils, which the splitway-gui PKGBUILD declares as hard deps. `pacman -U` on local files only auto-resolves deps from a synced repo DB, so the smoke must not lean on that — preinstall the full declared set explicitly, matching the PKGBUILD. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
stslex
left a comment
There was a problem hiding this comment.
Review — Phase 6 Linux packaging
Reviewed via a multi-agent fan-out: one reviewer per packaging target (apt/deb, dnf/rpm, pacman/AUR, CI workflows, GPG signing + Pages publish, GUI desktop/socket-group) plus three broad passes over the whole diff (correctness bug-hunt, security/supply-chain, docs/consistency/redaction). CI is fully green (23 checks) and all 19 prior review threads are resolved.
Verdict: no P1 / blocking issues. The PR is mergeable. The signing path (RSA-required, fail-closed verify-before-publish, dearmored apt keyring at every site), the empty-splitway-group privilege model, the no-secret-PR / push-only-publish trust split, and the lockstep version invariant are all sound and were each independently confirmed. A few non-blocking items worth a look:
P2 — worth addressing (none block merge)
- Stale README contradicts this PR's own change.
README.md:451-453states the interim egui GUI "does not carry theio.github.stslex.splitwayapp id, so the window rule is Tauri-only" — butsplitway-gui/src/app.rs:41now adds.with_app_id("io.github.stslex.splitway"), and the packagedsplitway-gui(egui) ships that.desktop+StartupWMClass+ icons. The passage is now incorrect. Relatedly, README framesio.github.stslex.splitwayas the Tauri app while the deb/rpm/pacmansplitway-guiinstall instructions actually ship the egui binary under that id — one clarifying line would prevent reader confusion. - GUI deb
postinst:groupaddis unguarded underset -e.getent group splitway || groupadd --system splitway(step 1) — a genuinegroupaddfailure aborts the postinst and dpkg marks the package half-configured. The rpm scriptlet runs withoutset -eso it's tolerant there. Impact is "install fails cleanly" (drop-in not yet written ⇒ no half-applied DNS), hence P2 — but the abort path looks unintended. grep '^version' … | head -1underset -o pipefailincompute-version.sh:21,check-pkgver-sync.sh:12,sync-pkgver.sh:14,release.yml:120. Harmless today (one^versionline), but a latent SIGPIPE trap if a second top-levelversionever appears — would make the guard scripts themselves flake.awk/sed -n '0,/^version/{...}'is robust.splitway-binPKGBUILD dropsoptdepends(networkmanager/systemd-resolvconf) that the sourcesplitwayPKGBUILD and the deb/rpm Recommends carry — same package contents, inconsistent prereq hints.splitway-binsha256sums=('SKIP')on prebuilt privileged-daemon binaries — already documented + deferred to the AUR-push automation (which must stamp per-tag digests). Flagging only so it's tracked to closure beforesplitway-binis actually published; fails no CI today.
P3 — nits
docs/design/linux-distro-packaging.mdDebian dep list omitslibegl1(the debDependsandpackaging/README.mdhave it).- deb-vs-rpm portal-backend skew: deb
Recommendslists gtk/wlr/kde portals, rpm weak-deps only gtk. - rpm signature proof uses
%{RSAHEADER:pgpsig}(rpm ≤5 tag); already noted in-workflow as a future-runner (rpm 6) landmine — fails closed, so safe direction. build-archis a hardneeds:gate forpublish-pages, so an Arch-only failure also blocks dev-channel apt/dnf publishes — worth a deliberate comment if intentional.- AUR
# Maintainer:lines commit a real personal email — standard AUR convention, just confirm it's the intended address. - Post-deploy smoke "live after Ns" message is off by one sleep (cosmetic);
generate-hicolor.shis dev-only / not CI-exercised.
Confirmed correct
Static-linkage gate (accepts musl static-pie + statically linked, rejects dynamic); verify-all-signatures-before-gh-pages-push fail-closed ordering; merge-not-wipe publish + pages-deploy concurrency serialization (no stale-base push race); apt Valid-Until replay/freeze bound; GUI EGL+GL deps on both deb & rpm; empty-group invariant across deb/rpm/AUR/nix (no script ever adds a user); versioned provides/depends floors; release.yml sync-pkgver.sh keeps the three PKGBUILDs in lockstep; no real-infra leakage (RFC-5737/3849 placeholders throughout); MIT LICENSE + license = "MIT" on all crates.
Reviewed with a Claude Code multi-agent fan-out.
Generated by Claude Code
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6de36d7be4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
stslex
left a comment
There was a problem hiding this comment.
Inline notes for the four P2 items from the summary review above — none blocking.
Generated by Claude Code
…iew round 3) Codex re-review (1) + self-review (4) of 6de36d7: - P2 (Codex, splitway-gui): add the X11 xkb runtime lib. winit's default `x11` feature has xkbcommon-dl dlopen libxkbcommon-x11.so (confirmed in Cargo.lock), a SEPARATE package from libxkbcommon on Debian (libxkbcommon-x11-0), Fedora (libxkbcommon-x11) AND Arch (libxkbcommon-x11 — verified via the Arch package API: it provides libxkbcommon-x11.so and is NOT bundled in the base libxkbcommon). Without it an X11 session can fail to load the lib before the window opens. Added to the deb Depends, rpm Requires, the Arch GUI PKGBUILD depends, and both Arch CI preinstall lists. - P2 (postinst): the groupadd under `set -e` was the only unguarded mutating step. Keep the abort (the drop-in is meaningless without the group) but make it deliberate + diagnosable with an explicit error message + exit. - P2 latent (version reads): `grep '^version' … | head -1` SIGPIPEs grep under `set -o pipefail` if a second match ever appears. Replaced with a SIGPIPE-free `awk -F'"' '/^version/{print $2; exit}'` in compute-version.sh, check-pkgver-sync.sh (+ the pkgver read), sync-pkgver.sh and release.yml (x3). - P2 (splitway-bin): surface the same networkmanager / systemd-resolvconf optdepends as the source splitway PKGBUILD (identical daemon, same prereqs). - P2 (README niri): the interim egui GUI now sets `.with_app_id(...)` and the packaged splitway-gui ships the matching .desktop + icons, so the app-id window rule is no longer Tauri-only; clarified the packaged GUI is the egui build. Also quoted "$GITHUB_OUTPUT" in the release.yml blocks touched above (pre-existing SC2086). actionlint + shellcheck clean; awk reads verified to yield 0.0.5 and check-pkgver-sync passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e811e16ef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…emon (Codex P2) The post-release auto-bump stamped the AUR PKGBUILDs with the *next* (unreleased) daemon version, so `makepkg -si` from master pointed at a `v$pkgver` tag / release assets that do not exist yet. - release.yml: run sync-pkgver.sh BEFORE the daemon bump so the PKGBUILDs pin the just-released version; bump the daemon afterwards for the next cycle. - check-pkgver-sync.sh: validate the pinned pkgver names a release tag that EXISTS (all three PKGBUILDs agreeing), with a no-tags bootstrap fallback — instead of requiring equality with the in-tree daemon version. - packaging.yml: fetch-depth: 0 on the meta checkout so the gate sees tags. - docs/design: record the invariant and why the gate checks existence, not "latest" (avoids spurious dev/PR and release-window failures). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EKokH93URrCizdQdVpNCNM
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9998f4cd6b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… daemon (Codex P2) Follow-up to pinning the AUR pkgver to the released tag: the daemon version now intentionally runs ahead of the committed pkgver. build-arch pre-placed the checkout tarball as <pkg>-$VERSION.tar.gz (daemon version), but the PKGBUILD's source= expects <pkg>-$pkgver.tar.gz. When the two diverge makepkg can't find the local archive and silently downloads the old v$pkgver tag, building stale code while the smoke test still passes. Read pkgver from each PKGBUILD and key both the archive filename and the git-archive --prefix on it, so the pre-placed checkout is always the source makepkg uses. Drop the now-unused VERSION env. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EKokH93URrCizdQdVpNCNM
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7154872a62
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…inned tag (Codex P1) The committed PKGBUILD pkgver intentionally lags to the last released tag (so a user's `makepkg -si` resolves an existing tag), but the hosted pacman repo must ship the version being released. The prior approach keyed the build on the committed pkgver, so a release push would publish Arch packages under the PREVIOUS version and Arch users would never receive the new one. build-arch now stamps the daemon/meta version into the EPHEMERAL PKGBUILD (never committed) and pre-places the matching <pkgname>-<VERSION>.tar.gz so makepkg builds THIS checkout as VERSION — no tag download, correct published version. The committed PKGBUILDs and the check-pkgver-sync.sh gate are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EKokH93URrCizdQdVpNCNM
`pacman -Sy <pkg>` refreshes the sync databases without upgrading, leaving the DB ahead of installed packages and resolving deps from a partial-upgrade state. Use `-Syu` in the hosted-index and README install snippets. The CI smoke tests keep `-Sy` (throwaway containers, not user systems). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EKokH93URrCizdQdVpNCNM
|
@codex review |
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Resolves the Codex + self-review findings on the Phase 6 packaging PR. Build-blocking CI fixes: - static-linkage gate: assert no dynamic interpreter instead of requiring the literal "statically linked" (musl x86_64 is "static-pie linked") — unblocks build-core (amd64) and the whole deb/rpm pipeline - test-arch: read the GPG fingerprint from fpr field 10, not 5 (5 is empty) - AUR splitway-bin: rename splitway.install -> splitway-bin.install so install="$pkgname.install" resolves (makepkg no longer aborts) - build-gui: CARGO_NET_RETRY + a retrying `cargo fetch --locked` before the offline build, hardening the transient arm64 crates.io failure Supply-chain / correctness: - apt: dearmor the published (armored) key into the binary keyring at every consumption site (works on every apt version; the published file stays armored for rpm --import / pacman-key) - publish: fail-closed signature verification (apt InRelease+Release.gpg, dnf repomd + per-rpm RSA header, pacman db+pkg sigs) BEFORE the gh-pages push - apt Release: Valid-Until (APT_VALID_DAYS, default 90d; LC_ALL=C) for freeze/replay protection - dev-floor sed: anchor to the dependency lines (leave the comment), and assert the floor was actually stamped - signed-repo tests (apt/dnf/pacman) now install splitway-gui too, exercising the GUI package under signature enforcement Arch / consistency / docs: - splitway-gui PKGBUILD: splitway>=$pkgver floor + hicolor-icon-theme, desktop-file-utils - new check-pkgver-sync.sh (meta job): daemon version == every PKGBUILD pkgver - render-index/README: dearmor --yes for apt, pacman-key --init, dev-channel keyring install - splitway-bin SKIP digest documented + tracked for the deferred AUR-push phase Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oling Follow-up to the second Codex pass on PR #36. - splitway-bin: `provides=("splitway=$pkgver")` (was unversioned). pacman only satisfies a versioned dependency from a versioned provision, so splitway-gui's new `splitway>=$pkgver` floor could not install against the prebuilt core. - test-signed-repo: install `rpm` in the tooling step. build-dnf-repo.sh needs `rpm --addsign`; it passes today only because ubuntu-latest pre-installs rpm — make it explicit (matches the publish job) so the dnf signing path is robust. - packaging/README.md: document the one-time config relocation for users who ran the daemon by hand as root before packaging (old XDG fallback /root/.config/splitway -> /var/lib/splitway). No maintainer-script migration: no published package used the old path, it is config-not-read (not data loss), and the deb core postinst is cargo-deb-generated (#DEBHELPER#) from an empty dir, so a hand-written migration would risk breaking systemd enablement that the docker install-test (no systemd) could not catch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 6 — Linux distribution packaging
Gets Splitway onto non-Nix Linux machines via signed apt / dnf / pacman
repos on GitHub Pages (NixOS path unchanged). Implemented as the ordered commit
sequence below.
What ships
sketch — keeps the security-critical core minimal and statically linked, and
doesn't burden CLI-only installs with the GUI's GL/glibc stack):
splitway— daemon + CLI + unit, musl-static (runs on any glibc/muslbaseline). NetworkManager / systemd-resolved are
Recommends.splitway-gui— egui binary, glibc 2.31 floor,Depends: splitway (>=).splitwaygroup + a service drop-in. Empty group ⇒ posture identical to
0600 root;the only grant is a human running
usermod -aG splitway. Maintainer scriptsnever add a user (mirrors
nix/tests/socket-group.nix).packaging.yml): build (cross-musl core + bullseye-container GUI,amd64+arm64) → install tests (debian/ubuntu/fedora/arch) → ephemeral-key
signed-repo round trip → GPG-signed publish to Pages (dev/release channels,
merge-not-wipe) → live post-deploy smoke. Arch via a self-hosted signed
pacman repo (x86_64) + in-repo PKGBUILDs; the automated AUR push is deferred
(registration disabled).
LICENSEadded (the repo had none) +license = "MIT"on all crates.Commits
feat(packaging)unit StateDirectory/--config+ GUI Wayland app_idfeat(packaging)musl-staticsplitwaycore deb/rpm packagefeat(packaging)splitway-guideb/rpm + socket-group opt-inci(packaging)build (musl core + glibc-floor GUI) + install testsci(packaging)publish signed apt/dnf repos to Pages (push-only)feat(packaging)Arch PKGBUILDs + signed pacman repo (AUR deferred)docs(packaging)install docs + design record + Phase 6 donerefactor(packaging)defensive hardening from self-reviewVerification
cargo fmt/clippy/build/test(43) green;check-no-leaked-infra,actionlint,shellcheckall clean.(cargo-deb 3.7.0 / cargo-generate-rpm 0.21.0) — caught the deb
../path-resolution, the
maintainer-scriptsdir needed for systemd scriptlets,and the dlopen'd GL/X11/wayland deps that auto-detection misses.
signing requires RSA, not EdDSA (EdDSA silently produces no signature).
Maintainer prerequisites (for the publish job — PRs use no secrets)
GPG_PRIVATE_KEY(must be RSA) +GPG_PASSPHRASErepo secrets.gh-pages; Actions workflow permissions = read/write.ubuntu-24.04-armrunner.Out of scope (flagged, not changed)
build.ymlhasbranches: ["dev, master"](one string) — a pre-existing bugthat never matches
master. Untouched here.🤖 Generated with Claude Code
https://claude.ai/code/session_018GKGiqawfPb5fzMGHisrrF