From 9cdb3922c94c1cedbf7ddb0300ce42795dcbf133 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Tue, 1 Sep 2026 13:05:05 -0400 Subject: [PATCH 01/12] Add Debian source packaging (debian/) for PPA releases, verified in CI on tag pushes --- .github/workflows/test.yaml | 54 +++++++++++++++++++ debian/changelog | 5 ++ debian/control | 20 +++++++ debian/copyright | 26 +++++++++ debian/patches/series | 1 + .../skip-runtime-checks-at-configure.patch | 35 ++++++++++++ debian/rules | 13 +++++ debian/source/format | 1 + 8 files changed, 155 insertions(+) create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/patches/series create mode 100644 debian/patches/skip-runtime-checks-at-configure.patch create mode 100755 debian/rules create mode 100644 debian/source/format diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 59238ed5..ef11b64a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -58,6 +58,16 @@ jobs: name: packaging-assets path: packaging.tgz + - name: Package Debian packaging assets + run: | + tar czf debian-packaging.tgz debian + + - name: Upload Debian packaging assets + uses: actions/upload-artifact@v7 + with: + name: debian-packaging + path: debian-packaging.tgz + package: needs: [dist, test-dist] runs-on: ubuntu-latest @@ -95,6 +105,50 @@ jobs: dist-packages/try*.deb dist-packages/try*.rpm + ppa-source-check: + needs: [dist, test-dist] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Install dependencies + run: | + sudo apt-get install -y debhelper dpkg-dev lintian pandoc + + - name: Download dist tarball + uses: actions/download-artifact@v8 + with: + name: try-dist.tgz + + - name: Download Debian packaging assets + uses: actions/download-artifact@v8 + with: + name: debian-packaging + + - name: Assemble Debian source tree + run: | + # keep the try-VERSION/ directory from the dist tarball intact -- + # dpkg-buildpackage needs the source in a properly named + # directory next to its .orig tarball, unlike the flattened tree + # the "package" job builds from. + tar xzf try-*.tgz + srcdir=$(echo try-*/) + version=${srcdir#try-} + version=${version%/} + tar czf "try_${version}.orig.tar.gz" "$srcdir" + tar xzf debian-packaging.tgz -C "$srcdir" + rm -f try-*.tgz debian-packaging.tgz + echo "SRCDIR=$srcdir" >> "$GITHUB_ENV" + + - name: Build the Debian source package + run: | + cd "$SRCDIR" + dpkg-buildpackage -S -us -uc -sa + + - name: Lint the source package + run: | + lintian try_*_source.changes + test-dist: needs: dist strategy: diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 00000000..6bed6f1a --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +try (0.2.0-1) UNRELEASED; urgency=medium + + * Initial Debian packaging. + + -- try maintainers Tue, 01 Sep 2026 10:08:54 -0400 diff --git a/debian/control b/debian/control new file mode 100644 index 00000000..9430f8fe --- /dev/null +++ b/debian/control @@ -0,0 +1,20 @@ +Source: try +Section: utils +Priority: optional +Maintainer: try maintainers +Build-Depends: debhelper-compat (= 13), autoconf, pandoc +Standards-Version: 4.6.2 +Homepage: https://github.com/binpash/try +Rules-Requires-Root: no + +Package: try +Architecture: any +Depends: attr, ${shlibs:Depends}, ${misc:Depends} +Description: run a command and inspect its effects before changing your live system + try lets you run a command, inspect the changes it would make to your + filesystem, and then decide whether to commit or discard them, without + actually touching your live system. + . + It works by running the command inside a copy-on-write overlay, so + nothing is written to the real filesystem until you explicitly commit + the change. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 00000000..9d54945d --- /dev/null +++ b/debian/copyright @@ -0,0 +1,26 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: try +Source: https://github.com/binpash/try + +Files: * +Copyright: 2020 The PaSh Authors +License: MIT + +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 00000000..75ba5ffa --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +skip-runtime-checks-at-configure.patch diff --git a/debian/patches/skip-runtime-checks-at-configure.patch b/debian/patches/skip-runtime-checks-at-configure.patch new file mode 100644 index 00000000..d1a7070e --- /dev/null +++ b/debian/patches/skip-runtime-checks-at-configure.patch @@ -0,0 +1,35 @@ +Description: Skip TRY_REQUIRE_PROG's runtime environment checks during packaging builds + configure.ac's TRY_REQUIRE_PROG macro checks things like overlayfs kernel + module availability (via lsmod) and unshare namespace support. These are + real runtime requirements for using `try`, but they are properties of the + machine `try` will run on, not of the machine building the package -- a + build chroot (sbuild/pbuilder/OBS/etc.) commonly has no kernel module + visibility and no namespace privileges at all, so these checks fail + `./configure` unconditionally in any such environment. + . + This mirrors the same workaround already used by packaging/build_packages.sh + for the GitHub Releases build. +Author: try packaging +Forwarded: not-needed +--- a/configure.ac ++++ b/configure.ac +@@ -82,18 +82,7 @@ + AC_PROG_INSTALL + + dnl TRY_REQUIRE_PROG(progname, checking_msg, pre, true_if_failed, post, fail_msg) +-AC_DEFUN([TRY_REQUIRE_PROG], [ +-AC_MSG_CHECKING([ifelse([$2], [], [for $1], [$2])]) +-$3 +-if ifelse([$4], [], [! type -p $1 >/dev/null 2>&1], [$4]) +-then +- AC_MSG_RESULT([no]) +- AC_MSG_ERROR([try needs $1 to work, but ifelse([$6], [], [it could not be found], [$6]).]) +-else +- AC_MSG_RESULT([yes]) +- $5 +-fi +-]) ++AC_DEFUN([TRY_REQUIRE_PROG], []) + + # symlinks + AC_PROG_LN_S diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000..e7268344 --- /dev/null +++ b/debian/rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f + +%: + dh $@ + +# Makefile.in's install target uses $(bindir)/$(mandir) directly and has no +# $(DESTDIR) support, so dh_auto_install's default "make install +# DESTDIR=debian/try" would install straight onto the build machine instead +# of into the staging directory. Point prefix directly at the staging +# directory instead, matching what packaging/build_packages.sh already does +# for the GitHub Releases build. +override_dh_auto_install: + $(MAKE) install prefix=$(CURDIR)/debian/try/usr diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 00000000..163aaf8d --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) From fcf3991be38b273ad9253c34d3aa161a66e0ef73 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Tue, 1 Sep 2026 13:44:24 -0400 Subject: [PATCH 02/12] lint.sh: exempt debian/rules (tabs) and *.patch trailing spaces --- scripts/lint.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index bd552620..504fc6b6 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -51,6 +51,12 @@ trailing_newline() { trailing_whitespace() { file="$1" + # unified diffs use a lone trailing space to mark a blank context + # line -- it's part of the format, not a mistake + case "$file" in + (*.patch) return;; + esac + [ -f "$file" ] || warn "trailing_whitespace: '$file' is not a normal file" # empty file is fine @@ -72,7 +78,7 @@ tabs() { # it's supposed to be there! case "$file" in - (*Makefile*) return;; + (*Makefile*|*/debian/rules) return;; esac [ -f "$file" ] || warn "tabs: '$file' is not a normal file" From 0b615a8e0e808d6eec504f36456817d52b369e22 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Wed, 2 Sep 2026 11:20:52 -0400 Subject: [PATCH 03/12] fix for stale mirror metadata --- .github/workflows/test.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ef11b64a..b52e52b6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,8 @@ jobs: - name: Install dependencies run: | - sudo apt-get install expect mergerfs attr pandoc + sudo apt-get update + sudo apt-get install -y expect mergerfs attr pandoc - name: Checkout uses: actions/checkout@v7 @@ -164,7 +165,8 @@ jobs: - name: Install dependencies run: | - sudo apt-get install expect mergerfs attr pandoc + sudo apt-get update + sudo apt-get install -y expect mergerfs attr pandoc - name: Download dist tarball uses: actions/download-artifact@v8 @@ -219,7 +221,8 @@ jobs: - name: Install dependencies run: | - sudo apt-get install expect mergerfs attr pandoc + sudo apt-get update + sudo apt-get install -y expect mergerfs attr pandoc - name: Checkout uses: actions/checkout@v7 From 66b9071f5f4631236867d84f57e315099480a4f9 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Wed, 2 Sep 2026 11:29:11 -0400 Subject: [PATCH 04/12] ppa-source-check required build-essential --- .github/workflows/test.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b52e52b6..f05d292c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -114,7 +114,8 @@ jobs: steps: - name: Install dependencies run: | - sudo apt-get install -y debhelper dpkg-dev lintian pandoc + sudo apt-get update + sudo apt-get install -y build-essential debhelper dpkg-dev lintian pandoc - name: Download dist tarball uses: actions/download-artifact@v8 From 96a8c4a4ab09d5f6cfd34778d7a4178cafe405c8 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Tue, 8 Sep 2026 10:32:16 -0400 Subject: [PATCH 05/12] debian: skip dh_auto_test (build chroots lack unshare/overlayfs privileges), bump to 0.2.0-2 --- debian/changelog | 7 +++++++ debian/rules | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index 6bed6f1a..4eb3c4d9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +try (0.2.0-2) UNRELEASED; urgency=medium + + * Skip dh_auto_test: build chroots lack the privileges try's test suite + needs (unshare namespaces, overlayfs). + + -- try maintainers Tue, 08 Sep 2026 10:31:33 -0400 + try (0.2.0-1) UNRELEASED; urgency=medium * Initial Debian packaging. diff --git a/debian/rules b/debian/rules index e7268344..dec7d850 100755 --- a/debian/rules +++ b/debian/rules @@ -3,11 +3,11 @@ %: dh $@ -# Makefile.in's install target uses $(bindir)/$(mandir) directly and has no -# $(DESTDIR) support, so dh_auto_install's default "make install -# DESTDIR=debian/try" would install straight onto the build machine instead -# of into the staging directory. Point prefix directly at the staging -# directory instead, matching what packaging/build_packages.sh already does -# for the GitHub Releases build. override_dh_auto_install: $(MAKE) install prefix=$(CURDIR)/debian/try/usr + +override_dh_auto_test: + # try's test suite needs kernel privileges (unshare namespaces, + # overlayfs) that package build chroots don't grant -- same reasoning + # as the TRY_REQUIRE_PROG configure-time patch. Tests already run + # separately in CI (test-dist/test-checkout) with real privileges. From 5f92b88726dbd78355de704959aa4b236afa9966 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Tue, 8 Sep 2026 17:22:55 -0400 Subject: [PATCH 06/12] CI: deterministic orig tarball for PPA uploads, gate publish-ppa behind ppa-release environment, add debian/README --- .github/workflows/test.yaml | 53 +++++++++++++++++-- debian/README | 30 +++++++++++ .../skip-runtime-checks-at-configure.patch | 11 +--- 3 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 debian/README diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f05d292c..c3806ef0 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -129,17 +129,16 @@ jobs: - name: Assemble Debian source tree run: | - # keep the try-VERSION/ directory from the dist tarball intact -- - # dpkg-buildpackage needs the source in a properly named - # directory next to its .orig tarball, unlike the flattened tree - # the "package" job builds from. tar xzf try-*.tgz srcdir=$(echo try-*/) version=${srcdir#try-} version=${version%/} - tar czf "try_${version}.orig.tar.gz" "$srcdir" + tar --sort=name --owner=0 --group=0 --numeric-owner \ + --mtime='UTC 2020-01-01' -cf - "$srcdir" \ + | gzip -n -9 > "try_${version}.orig.tar.gz" tar xzf debian-packaging.tgz -C "$srcdir" rm -f try-*.tgz debian-packaging.tgz + sed -i "1s/UNRELEASED/noble/" "$srcdir/debian/changelog" echo "SRCDIR=$srcdir" >> "$GITHUB_ENV" - name: Build the Debian source package @@ -151,6 +150,17 @@ jobs: run: | lintian try_*_source.changes + - name: Upload Debian source package + uses: actions/upload-artifact@v7 + with: + name: try-ppa-source + path: | + try_*.dsc + try_*.orig.tar.gz + try_*.debian.tar.xz + try_*_source.changes + try_*_source.buildinfo + test-dist: needs: dist strategy: @@ -431,6 +441,39 @@ jobs: --generate-notes \ try-*.tgz ./try*.deb ./try*.rpm + publish-ppa: + needs: ppa-source-check + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + environment: ppa-release + + steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y devscripts dput gnupg + + - name: Download the Debian source package + uses: actions/download-artifact@v8 + with: + name: try-ppa-source + + - name: Import GPG signing key + env: + GPG_PRIVATE_KEY: ${{ secrets.PPA_GPG_PRIVATE_KEY }} + run: | + echo "$GPG_PRIVATE_KEY" | gpg --batch --import + echo "KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec/ {print $5; exit}')" >> "$GITHUB_ENV" + + - name: Sign and upload to the PPA + env: + GPG_PASSPHRASE: ${{ secrets.PPA_GPG_PASSPHRASE }} + run: | + echo "$GPG_PASSPHRASE" > /tmp/gpg-passphrase + debsign -k"$KEYID" -p"gpg --batch --yes --pinentry-mode loopback --passphrase-file /tmp/gpg-passphrase" try_*_source.changes + rm -f /tmp/gpg-passphrase + dput "${{ vars.PPA_TARGET }}" try_*_source.changes + prerelease: needs: - test-checkout diff --git a/debian/README b/debian/README new file mode 100644 index 00000000..025e6254 --- /dev/null +++ b/debian/README @@ -0,0 +1,30 @@ +This directory holds the Debian source packaging for `try`, used to build and +publish the package to a PPA. It's independent of `packaging/`, which builds the `.deb`/`.rpm` +attached to GitHub Releases. The two aren't related and don't share build +logic. + +# Building +`dpkg-buildpackage -S` from a checkout builds a source package. CI +(`ppa-source-check` in `.github/workflows/test.yaml`) does this on every tag +push and lints the result with `lintian`; `publish-ppa` signs and uploads it +to the configured PPA via `dput`. + +# Testing that a published PPA package actually installs and works + +Once a build succeeds on Launchpad, verify it installs cleanly in an +isolated environment: + +```sh +docker run -it --rm ubuntu:24.04 bash +``` + +```sh +apt-get update +apt-get install -y software-properties-common +add-apt-repository ppa:yourusername/try +apt-get update +apt-get install -y try + +try -v +man try +``` diff --git a/debian/patches/skip-runtime-checks-at-configure.patch b/debian/patches/skip-runtime-checks-at-configure.patch index d1a7070e..48a8b6a4 100644 --- a/debian/patches/skip-runtime-checks-at-configure.patch +++ b/debian/patches/skip-runtime-checks-at-configure.patch @@ -1,14 +1,5 @@ Description: Skip TRY_REQUIRE_PROG's runtime environment checks during packaging builds - configure.ac's TRY_REQUIRE_PROG macro checks things like overlayfs kernel - module availability (via lsmod) and unshare namespace support. These are - real runtime requirements for using `try`, but they are properties of the - machine `try` will run on, not of the machine building the package -- a - build chroot (sbuild/pbuilder/OBS/etc.) commonly has no kernel module - visibility and no namespace privileges at all, so these checks fail - `./configure` unconditionally in any such environment. - . - This mirrors the same workaround already used by packaging/build_packages.sh - for the GitHub Releases build. + Author: try packaging Forwarded: not-needed --- a/configure.ac From 8017a6788703957b5292e909a94f952c4888e1e6 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Tue, 8 Sep 2026 17:39:48 -0400 Subject: [PATCH 07/12] debian: bump to 0.2.0-3, fix dry-run README to build via make dist (matches what CI actually uploads) --- debian/README | 130 +++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 8 +++ 2 files changed, 138 insertions(+) diff --git a/debian/README b/debian/README index 025e6254..c4da3aff 100644 --- a/debian/README +++ b/debian/README @@ -9,6 +9,136 @@ logic. push and lints the result with `lintian`; `publish-ppa` signs and uploads it to the configured PPA via `dput`. +# Dry-running a release against your own PPA + +Validates the build/sign/upload chain against a real PPA before trusting it +to CI. Requires a Launchpad account with a registered OpenPGP key (Account +-> Personal details -> OpenPGP keys) and a PPA already created. + +The source tree used for the orig tarball must come from `make dist`, same +as CI's `dist` job -- not `git archive` or a raw checkout. `git archive` +includes everything git tracks (`.github/`, `debian/`, `packaging/`, ...); +`make dist` only includes what `Makefile.in`'s `$(DISTDIR)` rule lists. +Building the orig tarball from the wrong one produces a tarball with +different content under the same filename, which Launchpad rejects on any +later upload that references that filename (CI's build included) -- it +requires byte-identical content for every upload referencing a given +`orig.tar.gz`, forever. + +On macOS, none of `dpkg-buildpackage`/`devscripts`/`dput`/`autoconf`'s +`overlayfs`/`unshare` checks work natively, so this runs inside a container. +A plain bind mount of the repo can pick up macOS filesystem metadata that +breaks `dpkg-source`'s patch application, so transfer the repo via a +`git bundle` instead. + +## 1. Prep, on macOS + +```sh +cd /path/to/try +git bundle create /tmp/try-repo.bundle HEAD +gpg --armor --export-secret-keys > /tmp/my-signing-key.asc +``` + +## 2. Start the container + +```sh +open -a Docker +until docker info >/dev/null 2>&1; do sleep 2; done && echo "Docker is ready" + +docker run -it --rm \ + -v /tmp/try-repo.bundle:/tmp/repo.bundle:ro \ + -v /tmp/my-signing-key.asc:/tmp/my-signing-key.asc:ro \ + ubuntu:24.04 bash +``` + +## 3. Inside the container: install tools, set up a clean GPG home + +```sh +apt-get update +apt-get install -y git build-essential autoconf pandoc debhelper dpkg-dev devscripts dput gnupg + +mkdir -p /run/user/$(id -u) +chmod 700 /run/user/$(id -u) +export XDG_RUNTIME_DIR=/run/user/$(id -u) + +export GNUPGHOME=/tmp/gnupg-fresh +mkdir -m 700 -p "$GNUPGHOME" +gpg --batch --import /tmp/my-signing-key.asc +gpg --list-secret-keys --keyid-format long # note your key ID for step 6 +``` + +## 4. Build the dist tarball via `make dist` + +`./configure`'s `TRY_REQUIRE_PROG` checks (overlayfs via `lsmod`, `unshare`) +test the machine `try` will *run* on, not the one building it -- they fail +unconditionally in a plain container. Patch them out to let `./configure` +succeed, same as `packaging/build_packages.sh` does, but restore the +original `configure.ac` before running `make dist` -- otherwise the patched +macro ends up baked into the dist tarball itself, which is a different bug +of the same shape (CI's real `dist` job runs on a VM with real privileges, +so it never patches `configure.ac` at all; the resulting tarball must match +that). + +```sh +git clone /tmp/repo.bundle /work/src +cd /work/src + +cp configure.ac /tmp/configure.ac.orig +sed -i '/^AC_DEFUN(\[TRY_REQUIRE_PROG\]/,/^])$/c\AC_DEFUN([TRY_REQUIRE_PROG], [])' configure.ac +autoconf +./configure +cp /tmp/configure.ac.orig configure.ac + +make dist +mv try-*.tgz /work/ +cd /work +tar xzf try-*.tgz +``` + +## 5. Assemble the Debian source tree and build + +```sh +tar --sort=name --owner=0 --group=0 --numeric-owner \ + --mtime='UTC 2020-01-01' -cf - try-0.2.0 \ + | gzip -n -9 > try_0.2.0.orig.tar.gz + +cp -R /work/src/debian try-0.2.0/debian + +# debian/changelog stays "UNRELEASED" in source control; finalize it to a +# real series here, same as ppa-source-check does in CI -- Launchpad +# rejects uploads still targeting UNRELEASED. +sed -i '1s/UNRELEASED/noble/' try-0.2.0/debian/changelog + +cd try-0.2.0 +dpkg-buildpackage -S -us -uc -sa +cd .. +``` + +## 6. Sign explicitly with your key ID, then verify + +```sh +debsign -k try_*_source.changes +head -1 try_*_source.changes # should show -----BEGIN PGP SIGNED MESSAGE----- +``` + +`debsign` needs `-k` here rather than relying on its default (matching the +`Maintainer:`/`Changed-By:` identity) since `debian/control`'s `Maintainer:` +is a placeholder, not tied to any real key. + +## 7. Upload + +```sh +dput ppa:yourusername/try try_*_source.changes +``` + +Then check `launchpad.net/~yourusername/+archive/ubuntu/try` for the build. +Launchpad also emails on both acceptance/rejection and build completion. + +A local `gpg: ... SignatureVerifyError: 0` warning from `dput`'s own +pre-upload check is a known, benign `gpgme`-vs-keyring quirk in these +containers -- it doesn't block the actual upload, and Launchpad does its own +real signature verification server-side regardless. + # Testing that a published PPA package actually installs and works Once a build succeeds on Launchpad, verify it installs cleanly in an diff --git a/debian/changelog b/debian/changelog index 4eb3c4d9..793286b6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +try (0.2.0-3) UNRELEASED; urgency=medium + + * No packaging changes; previous manual test upload used a source tree + built via `git archive` rather than `make dist`, producing an + orig.tar.gz that doesn't match what CI actually builds. + + -- try maintainers Tue, 08 Sep 2026 17:33:57 -0400 + try (0.2.0-2) UNRELEASED; urgency=medium * Skip dh_auto_test: build chroots lack the privileges try's test suite From 06ff05cbb505ab5f335d0c7ed10b0c707b6db344 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Tue, 8 Sep 2026 18:10:34 -0400 Subject: [PATCH 08/12] reset to clean state --- debian/README | 130 ----------------------------------------------- debian/changelog | 15 ------ 2 files changed, 145 deletions(-) diff --git a/debian/README b/debian/README index c4da3aff..025e6254 100644 --- a/debian/README +++ b/debian/README @@ -9,136 +9,6 @@ logic. push and lints the result with `lintian`; `publish-ppa` signs and uploads it to the configured PPA via `dput`. -# Dry-running a release against your own PPA - -Validates the build/sign/upload chain against a real PPA before trusting it -to CI. Requires a Launchpad account with a registered OpenPGP key (Account --> Personal details -> OpenPGP keys) and a PPA already created. - -The source tree used for the orig tarball must come from `make dist`, same -as CI's `dist` job -- not `git archive` or a raw checkout. `git archive` -includes everything git tracks (`.github/`, `debian/`, `packaging/`, ...); -`make dist` only includes what `Makefile.in`'s `$(DISTDIR)` rule lists. -Building the orig tarball from the wrong one produces a tarball with -different content under the same filename, which Launchpad rejects on any -later upload that references that filename (CI's build included) -- it -requires byte-identical content for every upload referencing a given -`orig.tar.gz`, forever. - -On macOS, none of `dpkg-buildpackage`/`devscripts`/`dput`/`autoconf`'s -`overlayfs`/`unshare` checks work natively, so this runs inside a container. -A plain bind mount of the repo can pick up macOS filesystem metadata that -breaks `dpkg-source`'s patch application, so transfer the repo via a -`git bundle` instead. - -## 1. Prep, on macOS - -```sh -cd /path/to/try -git bundle create /tmp/try-repo.bundle HEAD -gpg --armor --export-secret-keys > /tmp/my-signing-key.asc -``` - -## 2. Start the container - -```sh -open -a Docker -until docker info >/dev/null 2>&1; do sleep 2; done && echo "Docker is ready" - -docker run -it --rm \ - -v /tmp/try-repo.bundle:/tmp/repo.bundle:ro \ - -v /tmp/my-signing-key.asc:/tmp/my-signing-key.asc:ro \ - ubuntu:24.04 bash -``` - -## 3. Inside the container: install tools, set up a clean GPG home - -```sh -apt-get update -apt-get install -y git build-essential autoconf pandoc debhelper dpkg-dev devscripts dput gnupg - -mkdir -p /run/user/$(id -u) -chmod 700 /run/user/$(id -u) -export XDG_RUNTIME_DIR=/run/user/$(id -u) - -export GNUPGHOME=/tmp/gnupg-fresh -mkdir -m 700 -p "$GNUPGHOME" -gpg --batch --import /tmp/my-signing-key.asc -gpg --list-secret-keys --keyid-format long # note your key ID for step 6 -``` - -## 4. Build the dist tarball via `make dist` - -`./configure`'s `TRY_REQUIRE_PROG` checks (overlayfs via `lsmod`, `unshare`) -test the machine `try` will *run* on, not the one building it -- they fail -unconditionally in a plain container. Patch them out to let `./configure` -succeed, same as `packaging/build_packages.sh` does, but restore the -original `configure.ac` before running `make dist` -- otherwise the patched -macro ends up baked into the dist tarball itself, which is a different bug -of the same shape (CI's real `dist` job runs on a VM with real privileges, -so it never patches `configure.ac` at all; the resulting tarball must match -that). - -```sh -git clone /tmp/repo.bundle /work/src -cd /work/src - -cp configure.ac /tmp/configure.ac.orig -sed -i '/^AC_DEFUN(\[TRY_REQUIRE_PROG\]/,/^])$/c\AC_DEFUN([TRY_REQUIRE_PROG], [])' configure.ac -autoconf -./configure -cp /tmp/configure.ac.orig configure.ac - -make dist -mv try-*.tgz /work/ -cd /work -tar xzf try-*.tgz -``` - -## 5. Assemble the Debian source tree and build - -```sh -tar --sort=name --owner=0 --group=0 --numeric-owner \ - --mtime='UTC 2020-01-01' -cf - try-0.2.0 \ - | gzip -n -9 > try_0.2.0.orig.tar.gz - -cp -R /work/src/debian try-0.2.0/debian - -# debian/changelog stays "UNRELEASED" in source control; finalize it to a -# real series here, same as ppa-source-check does in CI -- Launchpad -# rejects uploads still targeting UNRELEASED. -sed -i '1s/UNRELEASED/noble/' try-0.2.0/debian/changelog - -cd try-0.2.0 -dpkg-buildpackage -S -us -uc -sa -cd .. -``` - -## 6. Sign explicitly with your key ID, then verify - -```sh -debsign -k try_*_source.changes -head -1 try_*_source.changes # should show -----BEGIN PGP SIGNED MESSAGE----- -``` - -`debsign` needs `-k` here rather than relying on its default (matching the -`Maintainer:`/`Changed-By:` identity) since `debian/control`'s `Maintainer:` -is a placeholder, not tied to any real key. - -## 7. Upload - -```sh -dput ppa:yourusername/try try_*_source.changes -``` - -Then check `launchpad.net/~yourusername/+archive/ubuntu/try` for the build. -Launchpad also emails on both acceptance/rejection and build completion. - -A local `gpg: ... SignatureVerifyError: 0` warning from `dput`'s own -pre-upload check is a known, benign `gpgme`-vs-keyring quirk in these -containers -- it doesn't block the actual upload, and Launchpad does its own -real signature verification server-side regardless. - # Testing that a published PPA package actually installs and works Once a build succeeds on Launchpad, verify it installs cleanly in an diff --git a/debian/changelog b/debian/changelog index 793286b6..6bed6f1a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,18 +1,3 @@ -try (0.2.0-3) UNRELEASED; urgency=medium - - * No packaging changes; previous manual test upload used a source tree - built via `git archive` rather than `make dist`, producing an - orig.tar.gz that doesn't match what CI actually builds. - - -- try maintainers Tue, 08 Sep 2026 17:33:57 -0400 - -try (0.2.0-2) UNRELEASED; urgency=medium - - * Skip dh_auto_test: build chroots lack the privileges try's test suite - needs (unshare namespaces, overlayfs). - - -- try maintainers Tue, 08 Sep 2026 10:31:33 -0400 - try (0.2.0-1) UNRELEASED; urgency=medium * Initial Debian packaging. From f2189ad2006e57497dc7643fa0caa6cca20d78f8 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Wed, 9 Sep 2026 12:55:43 -0400 Subject: [PATCH 09/12] CI write detected version number in debian config files for releases --- .github/workflows/test.yaml | 4 ++++ debian/changelog | 2 +- debian/control | 2 +- debian/rules | 4 ---- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c3806ef0..5dedce5a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -138,6 +138,10 @@ jobs: | gzip -n -9 > "try_${version}.orig.tar.gz" tar xzf debian-packaging.tgz -C "$srcdir" rm -f try-*.tgz debian-packaging.tgz + + revision=$(sed -n "1s/^try ([^)-]*-\([0-9]*\)).*/\1/p" "$srcdir/debian/changelog") + sed -i "1s/^try ([^)]*)/try (${version}-${revision})/" "$srcdir/debian/changelog" + sed -i "1s/UNRELEASED/noble/" "$srcdir/debian/changelog" echo "SRCDIR=$srcdir" >> "$GITHUB_ENV" diff --git a/debian/changelog b/debian/changelog index 6bed6f1a..06b6b5f8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,4 +2,4 @@ try (0.2.0-1) UNRELEASED; urgency=medium * Initial Debian packaging. - -- try maintainers Tue, 01 Sep 2026 10:08:54 -0400 + -- try maintainers Tue, 01 Sep 2026 10:08:54 -0400 diff --git a/debian/control b/debian/control index 9430f8fe..b705b487 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: try Section: utils Priority: optional -Maintainer: try maintainers +Maintainer: try maintainers Build-Depends: debhelper-compat (= 13), autoconf, pandoc Standards-Version: 4.6.2 Homepage: https://github.com/binpash/try diff --git a/debian/rules b/debian/rules index dec7d850..746bc8b0 100755 --- a/debian/rules +++ b/debian/rules @@ -7,7 +7,3 @@ override_dh_auto_install: $(MAKE) install prefix=$(CURDIR)/debian/try/usr override_dh_auto_test: - # try's test suite needs kernel privileges (unshare namespaces, - # overlayfs) that package build chroots don't grant -- same reasoning - # as the TRY_REQUIRE_PROG configure-time patch. Tests already run - # separately in CI (test-dist/test-checkout) with real privileges. From 383f7b8da3d0893363527c9b22e382228758e68b Mon Sep 17 00:00:00 2001 From: AksharNana Date: Thu, 10 Sep 2026 15:21:13 -0400 Subject: [PATCH 10/12] Removed need to use patch, adjusted configure.ac --- configure.ac | 7 +++-- debian/control | 2 +- debian/patches/series | 1 - .../skip-runtime-checks-at-configure.patch | 26 ------------------- debian/rules | 3 +++ 5 files changed, 9 insertions(+), 30 deletions(-) delete mode 100644 debian/patches/series delete mode 100644 debian/patches/skip-runtime-checks-at-configure.patch diff --git a/configure.ac b/configure.ac index 980fd081..9959ebcd 100644 --- a/configure.ac +++ b/configure.ac @@ -120,7 +120,7 @@ TRY_REQUIRE_PROG([findmnt]) TRY_REQUIRE_PROG([sort]) TRY_REQUIRE_PROG([getfattr]) -TRY_REQUIRE_PROG([overlayfs],[for overlayfs],[],[! lsmod | grep -q overlay], [], [the overlay module did not appear in the output of lsmod]) +TRY_REQUIRE_PROG([overlayfs],[for overlayfs],[],[test "$TRY_SKIP_RUNTIME_CHECKS" != yes && ! lsmod | grep -q overlay], [], [the overlay module did not appear in the output of lsmod]) AC_CHECK_PROG([mergerfs], [mergerfs], [yes], [no]) AC_CHECK_PROG([unionfs], [unionfs], [yes], [no]) @@ -135,9 +135,12 @@ fi TRY_REQUIRE_PROG([readlink]) TRY_REQUIRE_PROG([unshare], [for unshare], [ +if test "$TRY_SKIP_RUNTIME_CHECKS" != yes +then res=$(unshare --mount --map-root-user --user --pid --fork -- ls $PWD/try 2>/dev/null) +fi ], [ -test "$?" != 0 || test "$res" != "$PWD/try" +test "$TRY_SKIP_RUNTIME_CHECKS" != yes && (test "$?" != 0 || test "$res" != "$PWD/try") ], [], [could not run unshare]) # for manpages diff --git a/debian/control b/debian/control index b705b487..020ba55e 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: try Section: utils Priority: optional Maintainer: try maintainers -Build-Depends: debhelper-compat (= 13), autoconf, pandoc +Build-Depends: debhelper-compat (= 13), autoconf, pandoc, attr Standards-Version: 4.6.2 Homepage: https://github.com/binpash/try Rules-Requires-Root: no diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 75ba5ffa..00000000 --- a/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ -skip-runtime-checks-at-configure.patch diff --git a/debian/patches/skip-runtime-checks-at-configure.patch b/debian/patches/skip-runtime-checks-at-configure.patch deleted file mode 100644 index 48a8b6a4..00000000 --- a/debian/patches/skip-runtime-checks-at-configure.patch +++ /dev/null @@ -1,26 +0,0 @@ -Description: Skip TRY_REQUIRE_PROG's runtime environment checks during packaging builds - -Author: try packaging -Forwarded: not-needed ---- a/configure.ac -+++ b/configure.ac -@@ -82,18 +82,7 @@ - AC_PROG_INSTALL - - dnl TRY_REQUIRE_PROG(progname, checking_msg, pre, true_if_failed, post, fail_msg) --AC_DEFUN([TRY_REQUIRE_PROG], [ --AC_MSG_CHECKING([ifelse([$2], [], [for $1], [$2])]) --$3 --if ifelse([$4], [], [! type -p $1 >/dev/null 2>&1], [$4]) --then -- AC_MSG_RESULT([no]) -- AC_MSG_ERROR([try needs $1 to work, but ifelse([$6], [], [it could not be found], [$6]).]) --else -- AC_MSG_RESULT([yes]) -- $5 --fi --]) -+AC_DEFUN([TRY_REQUIRE_PROG], []) - - # symlinks - AC_PROG_LN_S diff --git a/debian/rules b/debian/rules index 746bc8b0..84ed6efe 100755 --- a/debian/rules +++ b/debian/rules @@ -3,6 +3,9 @@ %: dh $@ +override_dh_auto_configure: + TRY_SKIP_RUNTIME_CHECKS=yes dh_auto_configure + override_dh_auto_install: $(MAKE) install prefix=$(CURDIR)/debian/try/usr From 00a7eb7cb0ae404fe91d8db3bfc0640b7043f216 Mon Sep 17 00:00:00 2001 From: AksharNana Date: Thu, 10 Sep 2026 17:55:00 -0400 Subject: [PATCH 11/12] Moved debian into packaging --- .github/workflows/test.yaml | 19 +++-------- debian/README | 30 ------------------ packaging/debian/README | 37 ++++++++++++++++++++++ {debian => packaging/debian}/changelog | 0 {debian => packaging/debian}/control | 0 {debian => packaging/debian}/copyright | 0 {debian => packaging/debian}/rules | 0 {debian => packaging/debian}/source/format | 0 scripts/lint.sh | 6 ---- 9 files changed, 42 insertions(+), 50 deletions(-) delete mode 100644 debian/README create mode 100644 packaging/debian/README rename {debian => packaging/debian}/changelog (100%) rename {debian => packaging/debian}/control (100%) rename {debian => packaging/debian}/copyright (100%) rename {debian => packaging/debian}/rules (100%) rename {debian => packaging/debian}/source/format (100%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5dedce5a..3cdd1c2a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -59,16 +59,6 @@ jobs: name: packaging-assets path: packaging.tgz - - name: Package Debian packaging assets - run: | - tar czf debian-packaging.tgz debian - - - name: Upload Debian packaging assets - uses: actions/upload-artifact@v7 - with: - name: debian-packaging - path: debian-packaging.tgz - package: needs: [dist, test-dist] runs-on: ubuntu-latest @@ -122,10 +112,10 @@ jobs: with: name: try-dist.tgz - - name: Download Debian packaging assets + - name: Download packaging assets uses: actions/download-artifact@v8 with: - name: debian-packaging + name: packaging-assets - name: Assemble Debian source tree run: | @@ -136,8 +126,9 @@ jobs: tar --sort=name --owner=0 --group=0 --numeric-owner \ --mtime='UTC 2020-01-01' -cf - "$srcdir" \ | gzip -n -9 > "try_${version}.orig.tar.gz" - tar xzf debian-packaging.tgz -C "$srcdir" - rm -f try-*.tgz debian-packaging.tgz + tar xzf packaging.tgz + cp -R packaging/debian "$srcdir/debian" + rm -f try-*.tgz packaging.tgz revision=$(sed -n "1s/^try ([^)-]*-\([0-9]*\)).*/\1/p" "$srcdir/debian/changelog") sed -i "1s/^try ([^)]*)/try (${version}-${revision})/" "$srcdir/debian/changelog" diff --git a/debian/README b/debian/README deleted file mode 100644 index 025e6254..00000000 --- a/debian/README +++ /dev/null @@ -1,30 +0,0 @@ -This directory holds the Debian source packaging for `try`, used to build and -publish the package to a PPA. It's independent of `packaging/`, which builds the `.deb`/`.rpm` -attached to GitHub Releases. The two aren't related and don't share build -logic. - -# Building -`dpkg-buildpackage -S` from a checkout builds a source package. CI -(`ppa-source-check` in `.github/workflows/test.yaml`) does this on every tag -push and lints the result with `lintian`; `publish-ppa` signs and uploads it -to the configured PPA via `dput`. - -# Testing that a published PPA package actually installs and works - -Once a build succeeds on Launchpad, verify it installs cleanly in an -isolated environment: - -```sh -docker run -it --rm ubuntu:24.04 bash -``` - -```sh -apt-get update -apt-get install -y software-properties-common -add-apt-repository ppa:yourusername/try -apt-get update -apt-get install -y try - -try -v -man try -``` diff --git a/packaging/debian/README b/packaging/debian/README new file mode 100644 index 00000000..8bfa8fb5 --- /dev/null +++ b/packaging/debian/README @@ -0,0 +1,37 @@ +This directory holds the Debian source packaging for `try`, used to build and +publish the package to a PPA. Its build logic is independent of the rest of +`packaging/`, which builds the `.deb`/`.rpm` attached to GitHub Releases; the +two don't share anything. + +It lives here rather than at the repo root purely to keep the top level +tidy. To build or test locally first run: +```sh +cp -R packaging/debian debian +``` + +# Building +With `debian/` staged at the repo root as above, `dpkg-buildpackage -S` +builds a source package. CI (`ppa-source-check` in +`.github/workflows/test.yaml`) does this on every tag push and lints the +result with `lintian`; `publish-ppa` signs and uploads it to the configured +PPA via `dput`. + +# Testing that a published PPA package actually installs and works + +Once a build succeeds on Launchpad, verify it installs cleanly in an +isolated environment: + +```sh +docker run -it --rm ubuntu:24.04 bash +``` + +```sh +apt-get update +apt-get install -y software-properties-common +add-apt-repository ppa:yourusername/try +apt-get update +apt-get install -y try + +try -v +man try +``` diff --git a/debian/changelog b/packaging/debian/changelog similarity index 100% rename from debian/changelog rename to packaging/debian/changelog diff --git a/debian/control b/packaging/debian/control similarity index 100% rename from debian/control rename to packaging/debian/control diff --git a/debian/copyright b/packaging/debian/copyright similarity index 100% rename from debian/copyright rename to packaging/debian/copyright diff --git a/debian/rules b/packaging/debian/rules similarity index 100% rename from debian/rules rename to packaging/debian/rules diff --git a/debian/source/format b/packaging/debian/source/format similarity index 100% rename from debian/source/format rename to packaging/debian/source/format diff --git a/scripts/lint.sh b/scripts/lint.sh index 504fc6b6..3fce0be7 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -51,12 +51,6 @@ trailing_newline() { trailing_whitespace() { file="$1" - # unified diffs use a lone trailing space to mark a blank context - # line -- it's part of the format, not a mistake - case "$file" in - (*.patch) return;; - esac - [ -f "$file" ] || warn "trailing_whitespace: '$file' is not a normal file" # empty file is fine From ebd0b041616c18bc872951b22afb2510837de94e Mon Sep 17 00:00:00 2001 From: AksharNana Date: Thu, 10 Sep 2026 18:00:37 -0400 Subject: [PATCH 12/12] install attr for ppa-source-check --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 3cdd1c2a..9b2b20df 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -105,7 +105,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y build-essential debhelper dpkg-dev lintian pandoc + sudo apt-get install -y build-essential debhelper dpkg-dev lintian pandoc attr - name: Download dist tarball uses: actions/download-artifact@v8