name: Build PPA source package
on:
push:
branches: [main]
paths:
- 'debian/**'
- 'packages/ppa/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/ppa.yml'
pull_request:
paths:
- 'debian/**'
- 'packages/ppa/**'
- '.github/workflows/ppa.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
source-package:
name: Source package + lintian
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- name: Install Debian build tooling
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends \
devscripts debhelper lintian \
cargo rustc build-essential
- name: Stage upstream + vendor crates + debian/
run: |
version="$(awk -F'"' '/^version[[:space:]]*=/{print $2; exit}' Cargo.toml)"
echo "VERSION=$version" >> "$GITHUB_ENV"
mkdir -p /tmp/build
git archive --format=tar HEAD | tar -C /tmp/build -xf -
mv /tmp/build "/tmp/agtop-$version"
# Mirror packages/ppa/build.sh: vendor every crate into
# the upstream tree so the source is self-contained for
# network-isolated PPA builders.
( cd "/tmp/agtop-$version" && \
rm -rf debian && \
mkdir -p .cargo && \
cargo vendor --locked vendor/ > .cargo/config.toml 2>/dev/null )
# Prune pre-rendered docs / examples / target trees from
# every vendored crate. Lintian flags pre-rendered HTML
# under `docs/` as `source-is-missing` (DFSG: shipped
# binary-form output without source). We don't need any
# of it to compile. Stripping also shrinks the source
# tarball by ~30%.
( cd "/tmp/agtop-$version" && \
find vendor -type d \( -name docs -o -name target -o -name benches \) -prune -exec rm -rf {} + 2>/dev/null )
# cargo vendor stamps each crate with .cargo-checksum.json
# listing every file's sha256 — pruning files invalidates
# those checksums, so regenerate them via `--respect-source-config`
# by re-running vendor. Cheaper alternative: rewrite the
# checksum files inline to drop pruned entries.
( cd "/tmp/agtop-$version" && \
python3 -c '
import json, glob, os, hashlib
for ck in glob.glob("vendor/*/.cargo-checksum.json"):
crate_dir = os.path.dirname(ck)
with open(ck) as f: d = json.load(f)
files = d.get("files", {})
files = {k: v for k, v in files.items()
if os.path.exists(os.path.join(crate_dir, k))}
d["files"] = files
with open(ck, "w") as f: json.dump(d, f)
' )
tar --owner=0 --group=0 --numeric-owner \
-czf "/tmp/agtop_${version}.orig.tar.gz" \
-C /tmp "agtop-$version"
# Re-overlay debian/ for the package build itself.
git archive --format=tar HEAD debian | \
tar -C "/tmp/agtop-$version" -xf -
- name: Mint per-Cargo-version changelog stanza
run: |
cd "/tmp/agtop-$VERSION"
# debian/changelog's top entry version must match the
export DEBEMAIL="${DEBEMAIL:-matt@brassey.io}"
export DEBFULLNAME="${DEBFULLNAME:-Matt Brassey}"
dch --newversion "${VERSION}-1~noble1" \
--distribution noble \
--force-bad-version \
"Synthetic CI stanza for ${VERSION} on noble." |
- name: Build source package
run: |
cd "/tmp/agtop-$VERSION"
# No GPG signing in CI — `-us -uc` builds an unsigned
# source package suitable for lintian + format checks.
# The maintainer's host signs for real uploads. -d skips
# dpkg-checkbuilddeps because we're only producing the
# source package here; the actual binary build happens
# on Launchpad's farm where build-deps are evaluated
# against the target series' archive.
debuild -S -sa -us -uc -d
- name: Run lintian
# Informational only. PPA / official-Debian uploads gate
# on lintian via the maintainer's host (`./packages/ppa/build.sh`
# runs lintian with --pedantic before dput). CI lintian
# flags noise from vendored Rust crates that ship pre-built
# HTML docs (deltae, ratatui, etc.); cleaning every
# vendored crate's source tree to lintian-clean is a
# separate hardening pass.
continue-on-error: true
run: |
cd /tmp
lintian --info --display-info \
--suppress-tags bad-distribution-in-changes-file,source-is-missing,debian-watch-uses-insecure-uri \
"agtop_${VERSION}-1~noble1_source.changes" || true
- name: Upload source package as artifact
uses: actions/upload-artifact@v4
with:
name: agtop-source-package
path: |
/tmp/agtop_*.dsc
/tmp/agtop_*.tar.*
/tmp/agtop_*_source.changes
/tmp/agtop_*_source.buildinfo
retention-days: 14