diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 59238ed5..9b2b20df 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 @@ -95,6 +96,66 @@ 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 update + sudo apt-get install -y build-essential debhelper dpkg-dev lintian pandoc attr + + - name: Download dist tarball + uses: actions/download-artifact@v8 + with: + name: try-dist.tgz + + - name: Download packaging assets + uses: actions/download-artifact@v8 + with: + name: packaging-assets + + - name: Assemble Debian source tree + run: | + tar xzf try-*.tgz + srcdir=$(echo try-*/) + version=${srcdir#try-} + version=${version%/} + 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 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" + + sed -i "1s/UNRELEASED/noble/" "$srcdir/debian/changelog" + 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 + + - 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: @@ -110,7 +171,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 @@ -165,7 +227,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 @@ -373,6 +436,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/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/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/packaging/debian/changelog b/packaging/debian/changelog new file mode 100644 index 00000000..06b6b5f8 --- /dev/null +++ b/packaging/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/packaging/debian/control b/packaging/debian/control new file mode 100644 index 00000000..020ba55e --- /dev/null +++ b/packaging/debian/control @@ -0,0 +1,20 @@ +Source: try +Section: utils +Priority: optional +Maintainer: try maintainers +Build-Depends: debhelper-compat (= 13), autoconf, pandoc, attr +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/packaging/debian/copyright b/packaging/debian/copyright new file mode 100644 index 00000000..9d54945d --- /dev/null +++ b/packaging/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/packaging/debian/rules b/packaging/debian/rules new file mode 100755 index 00000000..84ed6efe --- /dev/null +++ b/packaging/debian/rules @@ -0,0 +1,12 @@ +#!/usr/bin/make -f + +%: + dh $@ + +override_dh_auto_configure: + TRY_SKIP_RUNTIME_CHECKS=yes dh_auto_configure + +override_dh_auto_install: + $(MAKE) install prefix=$(CURDIR)/debian/try/usr + +override_dh_auto_test: diff --git a/packaging/debian/source/format b/packaging/debian/source/format new file mode 100644 index 00000000..163aaf8d --- /dev/null +++ b/packaging/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/scripts/lint.sh b/scripts/lint.sh index bd552620..3fce0be7 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -72,7 +72,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"