From ef6c3686155ad1e538c4b4c84e9cae8173dd6286 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 4 Nov 2026 14:46:58 -0500 Subject: [PATCH] Linux: let the shared makepkg job build the Arch package (#2322) package.sh built its own Arch package with nfpm while the shared release workflow also built one with makepkg, because has-arch defaults to true. Both wrote designcraft--linux-.pkg.tar.zst, the draft release merges the release-* artifacts last-writer-wins, and 0.17.0 shipped the nfpm copy, which declared fewer dependencies than the makepkg template. Drop arch from the formats this script builds and remove the archlinux section from nfpm.yaml, so the shared action is the single builder. It names the package after the .desktop bundle id, declares the same provides/conflicts against the AUR packages, and adds the optdepends nfpm could not express. --- packaging/linux/nfpm.yaml | 23 ++------------ packaging/linux/package.sh | 62 +++++++++++++------------------------- 2 files changed, 23 insertions(+), 62 deletions(-) diff --git a/packaging/linux/nfpm.yaml b/packaging/linux/nfpm.yaml index c547e49e6..d7d88a24c 100644 --- a/packaging/linux/nfpm.yaml +++ b/packaging/linux/nfpm.yaml @@ -1,6 +1,6 @@ -# .deb/.rpm/Arch packages (nfpm: https://nfpm.goreleaser.com). Run by package.sh, which stages +# .deb/.rpm packages (nfpm: https://nfpm.goreleaser.com). Run by package.sh, which stages # the file tree, substitutes its path for ${STAGE} (nfpm doesn't expand env vars in `src`) and -# exports VERSION and NFPM_ARCH. +# exports VERSION and NFPM_ARCH. The Arch package is built by the release workflow's makepkg job. # # nfpm package -f packaging/linux/nfpm.yaml -p deb -t dist/release/ name: designcraft @@ -63,25 +63,6 @@ overrides: - libXrandr - mesa-vulkan-drivers - xdg-desktop-portal - # Named ai.storyteller.designcraft, not designcraft: the AUR already has designcraft, designcraft-bin and - # designcraft-git, and an AUR helper treats any installed package with an AUR name as its own and - # rebuilds it on the next update. ArtCraft Launcher also uses the bundle id to tell this package - # (which it updates with `pacman -U`) from an AUR build (which it leaves to the AUR helper). - # nfpm has no optdepends for Arch, so the recommends above have no equivalent here. - archlinux: - depends: - - glibc - - gcc-libs - - hicolor-icon-theme - - libxkbcommon - - libxkbcommon-x11 - - vulkan-icd-loader - provides: - - designcraft - conflicts: - - designcraft - - designcraft-bin - - designcraft-git contents: - src: ${STAGE}/usr/bin/designcraft diff --git a/packaging/linux/package.sh b/packaging/linux/package.sh index 5bbbb01b0..f6c3e9cc0 100755 --- a/packaging/linux/package.sh +++ b/packaging/linux/package.sh @@ -5,12 +5,17 @@ # $DIST/designcraft--linux-.AppImage.zsync delta updates (needs zsyncmake) # $DIST/designcraft--linux-.deb Debian, Ubuntu, Mint, Pop!_OS, ... # $DIST/designcraft--linux-.rpm Fedora, openSUSE, RHEL, ... -# $DIST/designcraft--linux-.pkg.tar.zst Arch, Manjaro, EndeavourOS, ... # $DIST/designcraft--linux-.tar.gz plain FHS-style tree (bin/, share/) # -# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm arch tar"] +# The Arch package (.pkg.tar.zst) is not built here. The release workflow builds it with +# craft-common-actions/actions/arch-package from this script's tarball, which names it after the +# .desktop bundle id (ai.storyteller.designcraft, not designcraft, so an AUR helper does not claim +# it) and declares provides/conflicts against the AUR packages. Building a second one here under +# the same asset name is what made the published package depend on upload order. # -# Needs: cargo; nfpm for deb/rpm/arch (https://nfpm.goreleaser.com); appimagetool for the AppImage +# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar"] +# +# 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, # glibc 2.35) so the binaries run on newer ones. Optional: desktop-file-validate, appstreamcli, # zsyncmake (the zsync package) for the AppImage's .zsync. @@ -21,7 +26,7 @@ HERE="$ROOT/packaging/linux" APP_ID=ai.storyteller.designcraft SKIP_BUILD=0 -FORMATS="appimage deb rpm arch tar" +FORMATS="appimage deb rpm tar" while [[ $# -gt 0 ]]; do case "$1" in --skip-build) SKIP_BUILD=1; shift ;; @@ -43,6 +48,16 @@ BASENAME="designcraft-$VERSION-linux-$ARCH" echo "==> DesignCraft $VERSION for Linux $ARCH ($FORMATS)" +has() { + local fmt="$1" + case " $FORMATS " in *" $fmt "*) return 0 ;; *) return 1 ;; esac +} + +if has arch; then + echo "error: the Arch package is built by the release workflow's makepkg job, not by this script" >&2 + exit 2 +fi + if [[ "$SKIP_BUILD" = 0 ]]; then if [[ -n "${CROSS_TARGET:-}" ]]; then (cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli --target "$CROSS_TARGET") @@ -77,11 +92,6 @@ if command -v appstreamcli >/dev/null; then appstreamcli validate --no-net --explain "$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml" fi -has() { - local fmt="$1" - case " $FORMATS " in *" $fmt "*) return 0 ;; *) return 1 ;; esac -} - # ---- .tar.gz ------------------------------------------------------------------------------------ if has tar; then mkdir -p "$WORK/tar" @@ -90,8 +100,8 @@ if has tar; then echo "wrote $DIST/$BASENAME.tar.gz" fi -# ---- .deb / .rpm / .pkg.tar.zst ----------------------------------------------------------------- -if has deb || has rpm || has arch; then +# ---- .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; } export VERSION export NFPM_ARCH="$DEB_ARCH" @@ -100,36 +110,6 @@ if has deb || has rpm || has arch; then for fmt in deb rpm; do if has "$fmt"; then (cd "$ROOT" && nfpm package -f "$WORK/nfpm.yaml" -p "$fmt" -t "$DIST/$BASENAME.$fmt"); fi done - # The Arch package is named by the bundle id (see `archlinux` in nfpm.yaml), which nfpm can't - # override per format, and `archlinux.packager` isn't env-expanded, so both are written here. - if has arch; then - sed "s|^name: designcraft\$|name: $APP_ID|" "$WORK/nfpm.yaml" >"$WORK/nfpm-arch.yaml" - grep -qx "name: $APP_ID" "$WORK/nfpm-arch.yaml" || { echo "error: couldn't rename the Arch package" >&2; exit 1; } - printf 'archlinux:\n packager: "%s"\n' "$DESIGNCRAFT_MAINTAINER" >>"$WORK/nfpm-arch.yaml" - # nfpm (2.47, 2.48) writes Go's directory bit into the mode of each directory a `type: tree` - # entry walks (0o20000000755), and pacman then warns "directory permissions differ" on every - # shared directory under /usr/share. List the tree's files one by one instead: nfpm gives their - # parent directories a plain 0755. - if find "$STAGE/usr/share" ! -type d ! -type f | grep -q .; then - echo "error: only plain files can be listed in the Arch package's usr/share" >&2; exit 1 - fi - find "$STAGE/usr/share" -type f | LC_ALL=C sort | while IFS= read -r f; do - printf ' - src: "%s"\n dst: "%s"\n' "$f" "${f#"$STAGE"}" - done >"$WORK/arch-share.yaml" - awk -v files="$WORK/arch-share.yaml" -v tree=" - src: $STAGE/usr/share/" ' - $0 == tree { while ((getline line < files) > 0) print line; skip = 2; next } - skip > 0 { skip--; next } - { print } - ' "$WORK/nfpm-arch.yaml" >"$WORK/nfpm-arch.yaml.new" - mv "$WORK/nfpm-arch.yaml.new" "$WORK/nfpm-arch.yaml" - if grep -q 'type: tree' "$WORK/nfpm-arch.yaml"; then - echo "error: couldn't list the Arch package's files" >&2; exit 1 - fi - # Without a fixed time nfpm stamps the files and .MTREE a moment apart, and `pacman -Qkk` - # reports every file as modified. The commit time also makes the package reproducible. - epoch="${SOURCE_DATE_EPOCH:-$(git -C "$ROOT" log -1 --format=%ct 2>/dev/null || date +%s)}" - (cd "$ROOT" && SOURCE_DATE_EPOCH="$epoch" nfpm package -f "$WORK/nfpm-arch.yaml" -p archlinux -t "$DIST/$BASENAME.pkg.tar.zst") - fi fi # ---- AppImage -----------------------------------------------------------------------------------