Fix #423: publish a standalone Linux CLI archive (#613)

On Linux, pdfcraft-cli shipped only inside the desktop packages (about
55 MB), while macOS already publishes pdfcraft-cli-<v>-macos-universal.zip.
Servers, CI and agent sandboxes only need the headless CLI.

packaging/linux/package.sh gains a `cli` format, on by default, that writes
pdfcraft-cli-<v>-linux-<arch>.tar.gz: the stripped pdfcraft-cli from the
shared staging tree plus the licences/README via copy_docs. copy_docs now
also copies NOTICE (every package benefits). The release job already
uploads and checksums every file in dist/release; its package check now
lists the archive and runs the extracted binary. README and
docs/releasing.md list the new artifact and state the glibc 2.35 baseline.

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Brandon ThomasandClaude Opus 5.5 authored and GitHub committed 2026-10-09 16:45:13 -04:00
1 parent efb3439cb9
commit d483d6d475
5 files changed
+33 -8

No files matched your search

+7 -1
View File
@@ -213,7 +213,7 @@ jobs:
- name: Apply version override
if: inputs.version != ''
run: cargo xtask version set "$PDFCRAFT_VERSION"
- name: Build and package (AppImage, deb, rpm, tar.gz)
- name: Build and package (AppImage, deb, rpm, tar.gz, CLI tar.gz)
env:
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
@@ -223,6 +223,12 @@ jobs:
dpkg-deb --info dist/release/*.deb
dpkg-deb --contents dist/release/*.deb | grep -E 'usr/bin/pdfcraft$|metainfo|applications'
ldd target/release/pdfcraft
# The CLI-only archive: the binary and its licences, and it runs.
cli="dist/release/pdfcraft-cli-$PDFCRAFT_VERSION-linux-${{ matrix.arch }}.tar.gz"
tar -tzf "$cli" | grep -E '/pdfcraft-cli$'
tar -tzf "$cli" | grep -E '/LICENSE-APACHE$'
mkdir -p "$RUNNER_TEMP/cli" && tar -xzf "$cli" -C "$RUNNER_TEMP/cli"
"$RUNNER_TEMP/cli/pdfcraft-cli-$PDFCRAFT_VERSION-linux-${{ matrix.arch }}/pdfcraft-cli" --version
python3 -c "import yaml; m = yaml.safe_load(open('packaging/linux/flatpak/ai.storyteller.pdfcraft.yml')); assert m['id'] == 'ai.storyteller.pdfcraft'"
for appimage in dist/release/*.AppImage; do
chmod +x "$appimage"
+3
View File
@@ -451,6 +451,9 @@ Use the MSI for your architecture. Per-user installation overrides are not suppo
| Debian/Ubuntu | `pdfcraft-<ver>-linux-x86_64.deb` | `pdfcraft-<ver>-linux-aarch64.deb` | |
| Fedora/RHEL/openSUSE | `pdfcraft-<ver>-linux-x86_64.rpm` | `pdfcraft-<ver>-linux-aarch64.rpm` | |
| Tarball | `pdfcraft-<ver>-linux-x86_64.tar.gz` | `pdfcraft-<ver>-linux-aarch64.tar.gz` | Unpack anywhere |
| Command-line tool | `pdfcraft-cli-<ver>-linux-x86_64.tar.gz` | `pdfcraft-cli-<ver>-linux-aarch64.tar.gz` | `pdfcraft-cli` alone (and its opt-in MCP server), for servers, CI and agents |
Every Linux build needs glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+, Fedora 36+, RHEL 10).
### FreeBSD
+5 -3
View File
@@ -48,8 +48,8 @@ published (`gh workflow run release.yml --ref <branch>`).
| Windows 10+ x64 | `pdfcraft-<v>-windows-x64.msi`, `pdfcraft-<v>-windows-x64-portable.zip` | `windows-latest` |
| Windows 10+ x86 (32-bit) | `pdfcraft-<v>-windows-x86.msi`, `pdfcraft-<v>-windows-x86-portable.zip` | `windows-latest` |
| Windows 11 on ARM64 | `pdfcraft-<v>-windows-arm64.msi`, `pdfcraft-<v>-windows-arm64-portable.zip` | `windows-latest` (cross-compiled) |
| Linux x86_64 | `pdfcraft-<v>-linux-x86_64.{AppImage,AppImage.zsync,deb,rpm,tar.gz}` | `ubuntu-22.04` |
| Linux aarch64 | `pdfcraft-<v>-linux-aarch64.{AppImage,AppImage.zsync,deb,rpm,tar.gz}` | `ubuntu-22.04-arm` |
| Linux x86_64 | `pdfcraft-<v>-linux-x86_64.{AppImage,AppImage.zsync,deb,rpm,tar.gz}`, `pdfcraft-cli-<v>-linux-x86_64.tar.gz` | `ubuntu-22.04` |
| Linux aarch64 | `pdfcraft-<v>-linux-aarch64.{AppImage,AppImage.zsync,deb,rpm,tar.gz}`, `pdfcraft-cli-<v>-linux-aarch64.tar.gz` | `ubuntu-22.04-arm` |
| Flatpak x86_64 | `pdfcraft-<v>-linux-x86_64.flatpak` | `ubuntu-24.04` (repackages the Linux tarball) |
| Flatpak aarch64 | `pdfcraft-<v>-linux-aarch64.flatpak` | `ubuntu-24.04-arm` (repackages the Linux tarball) |
| FreeBSD 14 x86_64 | `pdfcraft-<v>-freebsd-x86_64.tar.gz` | FreeBSD VM on `ubuntu-latest` |
@@ -131,7 +131,9 @@ Locally: `dotnet tool install -g wix --version 5.0.2`, then `pwsh packaging/wind
`packaging/linux/package.sh` stages one FHS tree (both binaries, the desktop entry, hicolor icons,
AppStream metainfo) and makes every format from it: an **AppImage** (any distribution, nothing to
install), a **.deb** and an **.rpm** (built with [nfpm](https://nfpm.goreleaser.com) from
`nfpm.yaml`; they integrate with the menu, MIME and icon caches), and a **.tar.gz**.
`nfpm.yaml`; they integrate with the menu, MIME and icon caches), a **.tar.gz**, and a CLI-only
**`pdfcraft-cli-<v>-linux-<arch>.tar.gz`** (the stripped `pdfcraft-cli` plus the licences and
README, for servers, CI and agent sandboxes). `--formats` picks a subset (`appimage deb rpm tar cli`).
The binaries are built on Ubuntu 22.04, the oldest GitHub-hosted image, so they need only
**glibc ≥ 2.35**: Ubuntu 22.04+, Debian 12+, Fedora 36+, RHEL 10. Windowing (X11, Wayland,
+1 -1
View File
@@ -47,7 +47,7 @@ warn() {
# Copy licence and readme files that exist into a package directory.
copy_docs() {
local dest="$1" f
for f in README.md LICENSE LICENSE-MIT LICENSE-APACHE COPYRIGHT; do
for f in README.md LICENSE LICENSE-MIT LICENSE-APACHE COPYRIGHT NOTICE; do
if [ -f "$ROOT/$f" ]; then cp "$ROOT/$f" "$dest/"; fi
done
copy_font_licences "$dest"
+17 -3
View File
@@ -6,8 +6,9 @@
# $DIST/pdfcraft-<version>-linux-<arch>.deb Debian, Ubuntu, Mint, Pop!_OS, ...
# $DIST/pdfcraft-<version>-linux-<arch>.rpm Fedora, openSUSE, RHEL, ...
# $DIST/pdfcraft-<version>-linux-<arch>.tar.gz plain FHS-style tree (bin/, share/)
# $DIST/pdfcraft-cli-<version>-linux-<arch>.tar.gz the headless CLI alone (servers, CI, agents)
#
# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar"]
# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar cli"]
#
# Needs: cargo; nfpm for deb/rpm (https://nfpm.goreleaser.com); appimagetool for the AppImage
# (downloaded into $CARGO_TARGET_DIR if missing). Build on an old distro (CI: Ubuntu 22.04,
@@ -20,12 +21,12 @@ HERE="$ROOT/packaging/linux"
APP_ID=ai.storyteller.pdfcraft
SKIP_BUILD=0
FORMATS="appimage deb rpm tar"
FORMATS="appimage deb rpm tar cli"
while [ $# -gt 0 ]; do
case "$1" in
--skip-build) SKIP_BUILD=1; shift ;;
--formats) FORMATS="$2"; shift 2 ;;
-h | --help) sed -n '2,15p' "$0"; exit 0 ;;
-h | --help) sed -n '2,16p' "$0"; exit 0 ;;
*) echo "unknown argument: $1" >&2; exit 2 ;;
esac
done
@@ -80,6 +81,19 @@ if has tar; then
echo "wrote $DIST/$BASENAME.tar.gz"
fi
# ---- CLI-only .tar.gz ---------------------------------------------------------------------------
# The stripped pdfcraft-cli (and its opt-in MCP server) with the licences, for machines that never
# open a window. Like the other formats it needs glibc >= the build host's.
if has cli; then
CLI_NAME="pdfcraft-cli-$VERSION-linux-$ARCH"
CLI_DIR="$WORK/cli/$CLI_NAME"
mkdir -p "$CLI_DIR"
cp "$STAGE/usr/bin/pdfcraft-cli" "$CLI_DIR/"
copy_docs "$CLI_DIR"
tar -C "$WORK/cli" -czf "$DIST/$CLI_NAME.tar.gz" "$CLI_NAME"
echo "wrote $DIST/$CLI_NAME.tar.gz"
fi
# ---- .deb / .rpm --------------------------------------------------------------------------------
if has deb || has rpm; then
command -v nfpm >/dev/null || { echo "error: nfpm not found (https://nfpm.goreleaser.com/install/)" >&2; exit 1; }