refactor(ci): Use dnf builddep for RPM build dependencies

Move build dependency installation after SRPM generation to use dnf
builddep, eliminating duplication between CI config and spec file.
Dependencies are now sourced directly from the SRPM, ensuring consistency
and reducing maintenance.

Also fix test installation to properly fail when dependencies cannot be
met, removing the fallback to --nodeps which could hide packaging issues.
This commit is contained in:
Tom Foster 2025-09-04 10:29:17 +01:00
commit 7be651a307

View file

@ -81,7 +81,7 @@ jobs:
# Aggressive GC since cache restores don't increment counter # Aggressive GC since cache restores don't increment counter
echo "CARGO_INCREMENTAL_GC_TRIGGER=5" >> $GITHUB_ENV echo "CARGO_INCREMENTAL_GC_TRIGGER=5" >> $GITHUB_ENV
- name: Install build dependencies - name: Install base RPM tools
run: | run: |
dnf install -y --setopt=keepcache=1 \ dnf install -y --setopt=keepcache=1 \
wget \ wget \
@ -91,25 +91,14 @@ jobs:
rpkg \ rpkg \
cargo-rpm-macros \ cargo-rpm-macros \
systemd-rpm-macros \ systemd-rpm-macros \
clang \
liburing-devel \
rust \
cargo \
gcc \
gcc-c++ \
make \
openssl-devel \
pkg-config \
python3-pip python3-pip
- name: Setup build environment and build SRPM - name: Setup build environment and build SRPM
run: | run: |
# Configure git for rpkg
git config --global --add safe.directory "$GITHUB_WORKSPACE" git config --global --add safe.directory "$GITHUB_WORKSPACE"
git config --global user.email "ci@continuwuity.org" git config --global user.email "ci@continuwuity.org"
git config --global user.name "Continuwuity" git config --global user.name "Continuwuity"
# Setup RPM build tree
rpmdev-setuptree rpmdev-setuptree
cd "$GITHUB_WORKSPACE" cd "$GITHUB_WORKSPACE"
@ -143,10 +132,8 @@ jobs:
fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg
fi fi
# Build the SRPM
rpkg srpm --outdir "$HOME/rpmbuild/SRPMS" rpkg srpm --outdir "$HOME/rpmbuild/SRPMS"
# Show SRPM info
ls -la $HOME/rpmbuild/SRPMS/ ls -la $HOME/rpmbuild/SRPMS/
- name: Setup GPG for RPM signing - name: Setup GPG for RPM signing
@ -157,23 +144,32 @@ jobs:
exit 0 exit 0
fi fi
# Import the signing key
echo "${{ secrets.RPM_SIGNING_KEY }}" | gpg --batch --import echo "${{ secrets.RPM_SIGNING_KEY }}" | gpg --batch --import
# Get the key ID (look for the sec line, not the uid line) # Get the key ID (look for the sec line, not the uid line)
KEY_ID=$(gpg --list-secret-keys --keyid-format=long | grep "^sec" | head -1 | awk '{print $2}' | cut -d'/' -f2) KEY_ID=$(gpg --list-secret-keys --keyid-format=long | grep "^sec" | head -1 | awk '{print $2}' | cut -d'/' -f2)
echo "Using GPG key: $KEY_ID" echo "Using GPG key: $KEY_ID"
# Configure RPM macros for signing
cat > ~/.rpmmacros << EOF cat > ~/.rpmmacros << EOF
%_signature gpg %_signature gpg
%_gpg_name $KEY_ID %_gpg_name $KEY_ID
%__gpg /usr/bin/gpg %__gpg /usr/bin/gpg
EOF EOF
- name: Install build dependencies from SRPM
run: |
SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1)
if [ -z "$SRPM" ]; then
echo "Error: No SRPM file found"
exit 1
fi
echo "Installing build dependencies from: $(basename $SRPM)"
dnf builddep -y "$SRPM"
- name: Build RPM from SRPM - name: Build RPM from SRPM
run: | run: |
# Find the SRPM file
SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1) SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1)
if [ -z "$SRPM" ]; then if [ -z "$SRPM" ]; then
@ -183,7 +179,6 @@ jobs:
echo "Building from SRPM: $SRPM" echo "Building from SRPM: $SRPM"
# Build the binary RPM
rpmbuild --rebuild "$SRPM" \ rpmbuild --rebuild "$SRPM" \
--define "_topdir $HOME/rpmbuild" \ --define "_topdir $HOME/rpmbuild" \
--define "_sourcedir $GITHUB_WORKSPACE" \ --define "_sourcedir $GITHUB_WORKSPACE" \
@ -197,32 +192,20 @@ jobs:
exit 0 exit 0
fi fi
# Track signing failures
FAILED_COUNT=0
TOTAL_COUNT=0
# Export GPG_TTY to avoid terminal warnings # Export GPG_TTY to avoid terminal warnings
export GPG_TTY=/dev/null export GPG_TTY=/dev/null
# Sign all RPMs (binary and source)
for rpm in $(find "$HOME/rpmbuild" -name "*.rpm" -type f); do for rpm in $(find "$HOME/rpmbuild" -name "*.rpm" -type f); do
echo "Signing: $(basename $rpm)" echo "Signing: $(basename $rpm)"
TOTAL_COUNT=$((TOTAL_COUNT + 1))
# Use expect or provide empty passphrase via stdin for batch signing # Use expect or provide empty passphrase via stdin for batch signing
if ! echo "" | rpmsign --addsign "$rpm" 2>&1; then if ! echo "" | rpmsign --addsign "$rpm" 2>&1; then
echo "ERROR: Failed to sign $rpm" echo "ERROR: Failed to sign $rpm"
FAILED_COUNT=$((FAILED_COUNT + 1)) exit 1
fi fi
done done
# Fail if any RPMs failed to sign echo "Successfully signed all RPMs"
if [ "$FAILED_COUNT" -gt 0 ]; then
echo "ERROR: Failed to sign $FAILED_COUNT out of $TOTAL_COUNT RPMs"
exit 1
fi
echo "Successfully signed all $TOTAL_COUNT RPMs"
- name: Verify RPM signatures - name: Verify RPM signatures
run: | run: |
@ -232,15 +215,12 @@ jobs:
exit 0 exit 0
fi fi
# Import our public key for verification
echo "Importing GPG public key for verification..." echo "Importing GPG public key for verification..."
rpm --import fedora/RPM-GPG-KEY-continuwuity.asc rpm --import fedora/RPM-GPG-KEY-continuwuity.asc
# Track verification failures
FAILED_COUNT=0 FAILED_COUNT=0
TOTAL_COUNT=0 TOTAL_COUNT=0
# Verify all RPMs
for rpm in $(find "$HOME/rpmbuild" -name "*.rpm" -type f); do for rpm in $(find "$HOME/rpmbuild" -name "*.rpm" -type f); do
echo -n "Verifying $(basename $rpm): " echo -n "Verifying $(basename $rpm): "
TOTAL_COUNT=$((TOTAL_COUNT + 1)) TOTAL_COUNT=$((TOTAL_COUNT + 1))
@ -281,8 +261,8 @@ jobs:
echo "" echo ""
rpm -qpl "$RPM" rpm -qpl "$RPM"
# Actually install it (would need --nodeps if dependencies aren't met) # Actually install it
dnf install -y "$RPM" || rpm -ivh --nodeps "$RPM" dnf install -y "$RPM"
# Verify installation # Verify installation
rpm -qa | grep continuwuity rpm -qa | grep continuwuity
@ -305,11 +285,9 @@ jobs:
run: | run: |
mkdir -p artifacts mkdir -p artifacts
# Copy all RPMs to artifacts directory
find "$HOME/rpmbuild/RPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \; find "$HOME/rpmbuild/RPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \;
find "$HOME/rpmbuild/SRPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \; find "$HOME/rpmbuild/SRPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \;
# Create metadata file
cd artifacts cd artifacts
echo "Build Information:" > BUILD_INFO.txt echo "Build Information:" > BUILD_INFO.txt
echo "==================" >> BUILD_INFO.txt echo "==================" >> BUILD_INFO.txt
@ -336,7 +314,6 @@ jobs:
! -name "*.src.rpm" \ ! -name "*.src.rpm" \
-type f) -type f)
# Create temp directory for this artifact
mkdir -p upload-bin mkdir -p upload-bin
cp $BIN_RPM upload-bin/ cp $BIN_RPM upload-bin/
@ -367,7 +344,6 @@ jobs:
exit 0 exit 0
fi fi
# Extract version from RPM filename
RPM_BASENAME=$(basename "$RPM") RPM_BASENAME=$(basename "$RPM")
echo "Publishing: $RPM_BASENAME" echo "Publishing: $RPM_BASENAME"
@ -383,7 +359,6 @@ jobs:
GROUP=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]' | cut -c1-30) GROUP=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]' | cut -c1-30)
fi fi
# Extract package info from RPM for deletion
PACKAGE_INFO=$(rpm -qpi "$RPM" 2>/dev/null) PACKAGE_INFO=$(rpm -qpi "$RPM" 2>/dev/null)
PACKAGE_NAME=$(echo "$PACKAGE_INFO" | grep "^Name" | awk '{print $3}') PACKAGE_NAME=$(echo "$PACKAGE_INFO" | grep "^Name" | awk '{print $3}')
PACKAGE_VERSION=$(echo "$PACKAGE_INFO" | grep "^Version" | awk '{print $3}') PACKAGE_VERSION=$(echo "$PACKAGE_INFO" | grep "^Version" | awk '{print $3}')
@ -393,15 +368,20 @@ jobs:
# Full version includes release # Full version includes release
FULL_VERSION="${PACKAGE_VERSION}-${PACKAGE_RELEASE}" FULL_VERSION="${PACKAGE_VERSION}-${PACKAGE_RELEASE}"
# Try to delete existing package first (ignore errors if it doesn't exist) # Forgejo's RPM registry cannot overwrite existing packages, so we must delete first
# 404 is OK if package doesn't exist yet
echo "Removing any existing package: $PACKAGE_NAME-$FULL_VERSION.$PACKAGE_ARCH" echo "Removing any existing package: $PACKAGE_NAME-$FULL_VERSION.$PACKAGE_ARCH"
curl -X DELETE \ RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
"https://forgejo.ellis.link/api/packages/continuwuation/rpm/$GROUP/package/$PACKAGE_NAME/$FULL_VERSION/$PACKAGE_ARCH" \ "https://forgejo.ellis.link/api/packages/continuwuation/rpm/$GROUP/package/$PACKAGE_NAME/$FULL_VERSION/$PACKAGE_ARCH")
|| echo "Package didn't exist or deletion failed (this is OK)" HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then
echo "ERROR: Failed to delete package (HTTP $HTTP_CODE)"
echo "$RESPONSE" | head -n -1
exit 1
fi
# Upload to Forgejo package registry
# Using the RPM registry endpoint with group support
curl --fail-with-body \ curl --fail-with-body \
-X PUT \ -X PUT \
-H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
@ -422,7 +402,6 @@ jobs:
for DEBUG_RPM in $DEBUG_RPMS; do for DEBUG_RPM in $DEBUG_RPMS; do
echo "Publishing: $(basename "$DEBUG_RPM")" echo "Publishing: $(basename "$DEBUG_RPM")"
# Extract debug RPM info
DEBUG_INFO=$(rpm -qpi "$DEBUG_RPM" 2>/dev/null) DEBUG_INFO=$(rpm -qpi "$DEBUG_RPM" 2>/dev/null)
DEBUG_NAME=$(echo "$DEBUG_INFO" | grep "^Name" | awk '{print $3}') DEBUG_NAME=$(echo "$DEBUG_INFO" | grep "^Name" | awk '{print $3}')
DEBUG_VERSION=$(echo "$DEBUG_INFO" | grep "^Version" | awk '{print $3}') DEBUG_VERSION=$(echo "$DEBUG_INFO" | grep "^Version" | awk '{print $3}')
@ -430,13 +409,18 @@ jobs:
DEBUG_ARCH=$(echo "$DEBUG_INFO" | grep "^Architecture" | awk '{print $2}') DEBUG_ARCH=$(echo "$DEBUG_INFO" | grep "^Architecture" | awk '{print $2}')
DEBUG_FULL_VERSION="${DEBUG_VERSION}-${DEBUG_RELEASE}" DEBUG_FULL_VERSION="${DEBUG_VERSION}-${DEBUG_RELEASE}"
# Try to delete existing debug package first # Must delete existing package first (Forgejo limitation)
curl -X DELETE \ RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
"https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-debug/package/$DEBUG_NAME/$DEBUG_FULL_VERSION/$DEBUG_ARCH" \ "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-debug/package/$DEBUG_NAME/$DEBUG_FULL_VERSION/$DEBUG_ARCH")
|| echo "Debug package didn't exist or deletion failed (this is OK)" HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then
echo "ERROR: Failed to delete debug package (HTTP $HTTP_CODE)"
echo "$RESPONSE" | head -n -1
exit 1
fi
# Upload debug RPM
curl --fail-with-body \ curl --fail-with-body \
-X PUT \ -X PUT \
-H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
@ -455,19 +439,24 @@ jobs:
echo "Publishing source RPM: $(basename "$SRPM")" echo "Publishing source RPM: $(basename "$SRPM")"
echo "Publishing to group: ${GROUP}-src" echo "Publishing to group: ${GROUP}-src"
# Extract SRPM info
SRPM_INFO=$(rpm -qpi "$SRPM" 2>/dev/null) SRPM_INFO=$(rpm -qpi "$SRPM" 2>/dev/null)
SRPM_NAME=$(echo "$SRPM_INFO" | grep "^Name" | awk '{print $3}') SRPM_NAME=$(echo "$SRPM_INFO" | grep "^Name" | awk '{print $3}')
SRPM_VERSION=$(echo "$SRPM_INFO" | grep "^Version" | awk '{print $3}') SRPM_VERSION=$(echo "$SRPM_INFO" | grep "^Version" | awk '{print $3}')
SRPM_RELEASE=$(echo "$SRPM_INFO" | grep "^Release" | awk '{print $3}') SRPM_RELEASE=$(echo "$SRPM_INFO" | grep "^Release" | awk '{print $3}')
SRPM_FULL_VERSION="${SRPM_VERSION}-${SRPM_RELEASE}" SRPM_FULL_VERSION="${SRPM_VERSION}-${SRPM_RELEASE}"
# Try to delete existing SRPM first # Must delete existing SRPM first (Forgejo limitation)
echo "Removing any existing SRPM: $SRPM_NAME-$SRPM_FULL_VERSION.src" echo "Removing any existing SRPM: $SRPM_NAME-$SRPM_FULL_VERSION.src"
curl -X DELETE \ RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
"https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-src/package/$SRPM_NAME/$SRPM_FULL_VERSION/src" \ "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-src/package/$SRPM_NAME/$SRPM_FULL_VERSION/src")
|| echo "SRPM didn't exist or deletion failed (this is OK)" HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then
echo "ERROR: Failed to delete SRPM (HTTP $HTTP_CODE)"
echo "$RESPONSE" | head -n -1
exit 1
fi
curl --fail-with-body \ curl --fail-with-body \
-X PUT \ -X PUT \