Files
StepForge/packaging/linux/fedora/package.sh
T
TylerandClaude Fable 5 575d893f90
Template tests / tests (pull_request) Failing after 33s
Add production .rpm packaging and dnf setup; share runtime staging
Phase 3 of the improvement plan (PR 9 of the sequence): the dnf/Fedora
packaging half, in separate Linux-specific files, mirroring the apt/.deb work.

- packaging/linux/common/stage-runtime.sh: shared runtime-only payload staging
  extracted from the .deb builder so the two package formats never drift. It
  copies app code + a fixed Electron runtime + production npm deps (npm ls
  --omit=dev), guards against dev-dep leaks, and fails without node_modules.
  The .deb builder now delegates to it.
- packaging/linux/fedora/stepforge.spec: runtime Requires (nss, nspr, gtk3,
  …), Recommends (xinput, portal, pipewire), %license, and a %post that makes
  chrome-sandbox setuid and refreshes desktop/MIME/icon caches. No compilation
  — it packages the prebuilt BuildRoot.
- packaging/linux/fedora/package.sh: stages the shared payload, substitutes
  version/maintainer into the spec, and runs rpmbuild against the prebuilt
  BuildRoot with detected arch. Requires rpmbuild + node_modules; emits an
  .rpm + sha256.
- scripts/linux/dnf/install-runtime-deps.sh and install-build-deps.sh:
  separate runtime vs build dependency sets for dnf (runtime installs no build
  tools).
- docs/linux/dnf.md: Fedora/RHEL install + build guide, distinct from apt.md.

Tests: packaging-linux.test.js gains Fedora/dnf structural checks (spec
Requires + MPL-2.0 + %license + sandbox setup, builder shares staging +
requires rpmbuild, dnf build/runtime dep separation, shared staging never
copies the whole dev tree). tests/integration/linux/package-rpm.test.sh builds
a real .rpm and asserts runtime-only contents (honest skip when rpmbuild is
absent, as on this apt host).

Verified: 13 packaging unit tests pass; the refactored .deb builder still
produces a valid runtime-only package (integration test green); the .rpm
integration test skips cleanly where rpmbuild is unavailable.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-03 23:33:11 -05:00

66 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build a production StepForge .rpm from a pruned, runtime-only tree, mirroring
# the .deb builder. Stages the shared payload via common/stage-runtime.sh, then
# packages it with rpmbuild against a prebuilt BuildRoot (no compilation).
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
cd "$ROOT_DIR"
VERSION="$(node -p "require('./package.json').version")"
MAINTAINER="${STEPFORGE_MAINTAINER:-StepForge <[email protected]>}"
OUT_DIR="${STEPFORGE_PACKAGE_DIR:-$ROOT_DIR/build/artifacts}"
mkdir -p "$OUT_DIR"
if ! command -v rpmbuild >/dev/null 2>&1; then
echo "error: rpmbuild is not installed. Run scripts/linux/dnf/install-build-deps.sh" >&2
exit 1
fi
# RPM arch label from the host.
RPM_ARCH="$(rpm --eval '%{_arch}' 2>/dev/null || uname -m)"
BUILD_ROOT="$(mktemp -d "${OUT_DIR%/}/.rpm.XXXXXX")"
trap 'rm -rf "$BUILD_ROOT"' EXIT
STAGE="$BUILD_ROOT/buildroot"
mkdir -p "$STAGE"
# Shared runtime-only payload (fails if node_modules is missing).
ROOT_DIR="$ROOT_DIR" STAGE_ROOT="$STAGE" bash "$ROOT_DIR/packaging/linux/common/stage-runtime.sh"
# License into the RPM's conventional location.
mkdir -p "$STAGE/usr/share/licenses/stepforge"
if [ -f "$ROOT_DIR/LICENSE" ]; then
install -m 0644 "$ROOT_DIR/LICENSE" "$STAGE/usr/share/licenses/stepforge/LICENSE"
elif [ -f "$ROOT_DIR/docs/LICENSE" ]; then
install -m 0644 "$ROOT_DIR/docs/LICENSE" "$STAGE/usr/share/licenses/stepforge/LICENSE"
else
# rpmbuild %license requires the file to exist; write a pointer if absent.
echo "See project LICENSE." > "$STAGE/usr/share/licenses/stepforge/LICENSE"
fi
# Materialize the spec with version/maintainer substituted.
SPEC="$BUILD_ROOT/stepforge.spec"
sed -e "s/@VERSION@/$VERSION/" -e "s#@MAINTAINER@#$MAINTAINER#" \
"$ROOT_DIR/packaging/linux/fedora/stepforge.spec" > "$SPEC"
rpmbuild -bb \
--define "_topdir $BUILD_ROOT/rpmbuild" \
--define "_rpmdir $OUT_DIR" \
--define "_build_id_links none" \
--buildroot "$STAGE" \
--target "$RPM_ARCH" \
"$SPEC" >/dev/null
# rpmbuild writes to $OUT_DIR/<arch>/<name>.rpm — surface the final path.
RPM_FILE="$(find "$OUT_DIR" -name "stepforge-${VERSION}-1*.${RPM_ARCH}.rpm" -newer "$SPEC" | head -1)"
if [ -z "$RPM_FILE" ]; then
RPM_FILE="$(find "$OUT_DIR" -name "stepforge-${VERSION}-1*.rpm" | head -1)"
fi
[ -n "$RPM_FILE" ] || { echo "error: rpmbuild did not produce an .rpm" >&2; exit 1; }
# Checksum.
( cd "$(dirname "$RPM_FILE")" && sha256sum "$(basename "$RPM_FILE")" > "$(basename "$RPM_FILE").sha256" )
echo "$RPM_FILE"