diff --git a/Cargo.lock b/Cargo.lock index e976fd9..8665fe7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -599,7 +599,7 @@ dependencies = [ [[package]] name = "etr" -version = "0.6.5" +version = "0.7.0" dependencies = [ "clap", "clap_complete", diff --git a/Cargo.toml b/Cargo.toml index 0548d48..cb8519f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "etr" -version = "0.6.5" +version = "0.7.0" edition = "2024" description = "A Rust implementation of Eternal Terminal (et)" license = "GPL-3.0-only" @@ -15,6 +15,7 @@ exclude = [ "NOTES.md", "justfile", "scripts/", + "packaging/", ".github/", ] diff --git a/NOTES.md b/NOTES.md index b77c95d..f6022ef 100644 --- a/NOTES.md +++ b/NOTES.md @@ -9,7 +9,35 @@ the link drops. This project uses **QUIC** (via the `quinn` crate) for the tran layer, which provides reliable, ordered, multiplexed streams with congestion control and TLS 1.3 built-in. -## Current state: v0.6.5 — Windows input path + terminal restore on exit +## Current state: v0.7.0 — AUR publishing (etr-terminal-bin) + +New in v0.7.0: + +- **AUR package `etr-terminal-bin`** (x86_64 + aarch64): installs the prebuilt + `etr` and `etrs` binaries from the GitHub release assets. The AUR names + `etr` and `etr-bin` were already taken by an unrelated ECMP-traceroute tool + that also installs `/usr/bin/etr`, so the package is named + `etr-terminal-bin` and declares `conflicts=('etr' 'etr-bin')` — and + deliberately does **not** declare `provides=('etr')`, since that would + wrongly satisfy dependencies on the other tool. +- **`just publish-aur`**: renders `packaging/aur/PKGBUILD.in` and + `packaging/aur/SRCINFO.in` (single source of truth; `.SRCINFO` is never + hand-written), computing sha256 checksums from the *actual downloaded* + GitHub release assets for the current `Cargo.toml` version, then clones + `ssh://aur@aur.archlinux.org/etr-terminal-bin.git`, commits, and pushes. + Hard-fails with instructions if the release assets don't exist yet + (publish ordering: tag → release.yml → crates.io → AUR); exits cleanly + without an empty commit if the AUR repo already matches. Requires an SSH + key registered with an AUR account that owns/co-maintains the package. +- **`just publish` now ends by invoking `just publish-aur`**, so a normal + release publishes crates.io and the AUR in one step. If the AUR step fails + (e.g. release build not finished), crates.io publication is unaffected — + re-run `just publish-aur` alone. +- `packaging/` added to the crates.io `exclude` list; README gained an + "Arch Linux (AUR)" install section. +- No Rust code changes; test count unchanged (112). + +## Previous: v0.6.5 — Windows input path + terminal restore on exit New in v0.6.5 (four independent Windows parity fixes): diff --git a/README.md b/README.md index 40ee98a..150417e 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,16 @@ cargo install etr Both `etr` (client) and `etrs` (server) are installed. The server must be reachable in PATH on the remote host (true automatically when both machines use `cargo install`). +### Arch Linux (AUR) + +Prebuilt binaries are packaged as [`etr-terminal-bin`](https://aur.archlinux.org/packages/etr-terminal-bin) (x86_64 and aarch64): + +```bash +paru -S etr-terminal-bin # or: yay -S etr-terminal-bin +``` + +(The AUR packages named `etr`/`etr-bin` are an unrelated traceroute tool.) + ## Build from source ```bash diff --git a/justfile b/justfile index 5a61236..be8af56 100644 --- a/justfile +++ b/justfile @@ -160,6 +160,67 @@ publish: echo "==> Dry-run passed. Publishing to crates.io..." cargo publish echo "==> Published $(grep '^version' Cargo.toml | head -1 | sed 's/.*\"\(.*\)\"/\1/') to crates.io." + echo "==> Publishing AUR package..." + just publish-aur + +# Publish/update the AUR package (etr-terminal-bin) from the current version's GitHub release +publish-aur: + #!/usr/bin/env bash + set -euo pipefail + VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') + AUR_PKG="etr-terminal-bin" + AUR_REMOTE="ssh://aur@aur.archlinux.org/${AUR_PKG}.git" + BASE_URL="https://github.com/l1a/etr/releases/download/v${VERSION}" + ASSETS=(etr-linux-x86_64 etrs-linux-x86_64 etr-linux-aarch64 etrs-linux-aarch64) + + # The AUR package points at GitHub release assets, so the v$VERSION release + # must be fully built before this can run (tag → release.yml → here). + echo "==> Verifying GitHub release v${VERSION} assets exist..." + for a in "${ASSETS[@]}"; do + if ! curl -fsIL "${BASE_URL}/${a}" >/dev/null 2>&1; then + echo "ERROR: ${BASE_URL}/${a} not found." >&2 + echo "The v${VERSION} GitHub release must exist before publishing to the AUR:" >&2 + echo " git tag v${VERSION} && git push origin v${VERSION}" >&2 + echo "then wait for the Release workflow to finish and re-run: just publish-aur" >&2 + exit 1 + fi + done + + WORK=$(mktemp -d) + trap 'rm -rf "$WORK"' EXIT + + echo "==> Downloading release assets and computing sha256 checksums..." + declare -A SHA + for a in "${ASSETS[@]}"; do + curl -fsSL -o "${WORK}/${a}" "${BASE_URL}/${a}" + SHA[$a]=$(sha256sum "${WORK}/${a}" | cut -d' ' -f1) + echo " ${a} ${SHA[$a]}" + done + + # Render PKGBUILD and .SRCINFO from the same templates with the same + # substitutions so the two can never disagree. + render() { + sed -e "s/@VERSION@/${VERSION}/g" \ + -e "s/@SHA_ETR_X86_64@/${SHA[etr-linux-x86_64]}/g" \ + -e "s/@SHA_ETRS_X86_64@/${SHA[etrs-linux-x86_64]}/g" \ + -e "s/@SHA_ETR_AARCH64@/${SHA[etr-linux-aarch64]}/g" \ + -e "s/@SHA_ETRS_AARCH64@/${SHA[etrs-linux-aarch64]}/g" \ + "$1" + } + + echo "==> Cloning ${AUR_REMOTE}..." + git clone "${AUR_REMOTE}" "${WORK}/aur" + render "{{justfile_directory()}}/packaging/aur/PKGBUILD.in" > "${WORK}/aur/PKGBUILD" + render "{{justfile_directory()}}/packaging/aur/SRCINFO.in" > "${WORK}/aur/.SRCINFO" + + if [ -z "$(git -C "${WORK}/aur" status --porcelain)" ]; then + echo "==> AUR package already up to date (v${VERSION}); nothing to push." + exit 0 + fi + git -C "${WORK}/aur" add PKGBUILD .SRCINFO + git -C "${WORK}/aur" commit -m "Update to v${VERSION}" + git -C "${WORK}/aur" push + echo "==> Published ${AUR_PKG} v${VERSION} to the AUR." # ── Build ───────────────────────────────────────────────────────────────────── diff --git a/packaging/aur/PKGBUILD.in b/packaging/aur/PKGBUILD.in new file mode 100644 index 0000000..240d79b --- /dev/null +++ b/packaging/aur/PKGBUILD.in @@ -0,0 +1,30 @@ +# Maintainer: Ken Tobias +# +# This file is generated from packaging/aur/PKGBUILD.in in the etr repository +# by `just publish-aur` — do not edit it in the AUR repo directly. +# +# Note: the AUR packages `etr` and `etr-bin` are an unrelated tool (an ECMP +# traceroute) that also installs /usr/bin/etr, hence the name and conflicts. + +pkgname=etr-terminal-bin +pkgver=@VERSION@ +pkgrel=1 +pkgdesc="Reconnecting remote shell over QUIC — a Rust implementation of Eternal Terminal (et)" +arch=('x86_64' 'aarch64') +url="https://github.com/l1a/etr" +license=('GPL-3.0-only') +depends=('glibc' 'libutempter' 'openssh') +conflicts=('etr' 'etr-bin') +source_x86_64=("etr-${pkgver}-linux-x86_64::${url}/releases/download/v${pkgver}/etr-linux-x86_64" + "etrs-${pkgver}-linux-x86_64::${url}/releases/download/v${pkgver}/etrs-linux-x86_64") +source_aarch64=("etr-${pkgver}-linux-aarch64::${url}/releases/download/v${pkgver}/etr-linux-aarch64" + "etrs-${pkgver}-linux-aarch64::${url}/releases/download/v${pkgver}/etrs-linux-aarch64") +sha256sums_x86_64=('@SHA_ETR_X86_64@' + '@SHA_ETRS_X86_64@') +sha256sums_aarch64=('@SHA_ETR_AARCH64@' + '@SHA_ETRS_AARCH64@') + +package() { + install -Dm755 "${srcdir}/etr-${pkgver}-linux-${CARCH}" "${pkgdir}/usr/bin/etr" + install -Dm755 "${srcdir}/etrs-${pkgver}-linux-${CARCH}" "${pkgdir}/usr/bin/etrs" +} diff --git a/packaging/aur/SRCINFO.in b/packaging/aur/SRCINFO.in new file mode 100644 index 0000000..07c91c2 --- /dev/null +++ b/packaging/aur/SRCINFO.in @@ -0,0 +1,23 @@ +pkgbase = etr-terminal-bin + pkgdesc = Reconnecting remote shell over QUIC — a Rust implementation of Eternal Terminal (et) + pkgver = @VERSION@ + pkgrel = 1 + url = https://github.com/l1a/etr + arch = x86_64 + arch = aarch64 + license = GPL-3.0-only + depends = glibc + depends = libutempter + depends = openssh + conflicts = etr + conflicts = etr-bin + source_x86_64 = etr-@VERSION@-linux-x86_64::https://github.com/l1a/etr/releases/download/v@VERSION@/etr-linux-x86_64 + source_x86_64 = etrs-@VERSION@-linux-x86_64::https://github.com/l1a/etr/releases/download/v@VERSION@/etrs-linux-x86_64 + sha256sums_x86_64 = @SHA_ETR_X86_64@ + sha256sums_x86_64 = @SHA_ETRS_X86_64@ + source_aarch64 = etr-@VERSION@-linux-aarch64::https://github.com/l1a/etr/releases/download/v@VERSION@/etr-linux-aarch64 + source_aarch64 = etrs-@VERSION@-linux-aarch64::https://github.com/l1a/etr/releases/download/v@VERSION@/etrs-linux-aarch64 + sha256sums_aarch64 = @SHA_ETR_AARCH64@ + sha256sums_aarch64 = @SHA_ETRS_AARCH64@ + +pkgname = etr-terminal-bin