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 -----------------------------------------------------------------------------------