From 58691e7d63183ae205a7758c8eefe5523a95ae0c Mon Sep 17 00:00:00 2001 From: Sopwit <131982697+Sopwit@users.noreply.github.com> Date: Sun, 22 Mar 2026 22:46:49 +0300 Subject: [PATCH] build: add Fedora multi-arch release pipeline --- .github/workflows/release.yml | 213 ++++++++++++++++++++++++++-------- CHANGELOG.md | 2 + README.md | 2 +- README.tr.md | 2 +- docs/RELEASE.md | 6 +- packaging/rpm/README.md | 22 ++++ packaging/rpm/ro-control.spec | 25 ++-- 7 files changed, 211 insertions(+), 61 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 43e09cf..4e20cb1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,21 +5,114 @@ on: tags: - "v*" workflow_dispatch: + inputs: + version: + description: "Release version without the leading v" + required: true + type: string + +permissions: + contents: write + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false jobs: - artifacts: - name: Build Release Artifacts + metadata: + name: Resolve Release Metadata runs-on: ubuntu-latest + + outputs: + version: ${{ steps.meta.outputs.version }} + tag_name: ${{ steps.meta.outputs.tag_name }} + archive_prefix: ${{ steps.meta.outputs.archive_prefix }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Resolve version + id: meta + run: | + if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then + VERSION="${{ inputs.version }}" + else + VERSION="${GITHUB_REF_NAME#v}" + fi + + if [[ -z "${VERSION}" ]]; then + echo "Release version could not be determined." >&2 + exit 1 + fi + + PROJECT_VERSION="$(sed -n 's/^[[:space:]]*VERSION[[:space:]]\([0-9.][0-9.]*\)$/\1/p' CMakeLists.txt | head -n1)" + SPEC_DEFAULT_VERSION="$(sed -n 's/^%global upstream_version %{!?upstream_version:\([0-9.][0-9.]*\)}%{?upstream_version}$/\1/p' packaging/rpm/ro-control.spec | head -n1)" + + if [[ "${VERSION}" != "${PROJECT_VERSION}" ]]; then + echo "Tag/workflow version (${VERSION}) does not match CMake project version (${PROJECT_VERSION})." >&2 + exit 1 + fi + + if [[ "${VERSION}" != "${SPEC_DEFAULT_VERSION}" ]]; then + echo "Tag/workflow version (${VERSION}) does not match RPM spec default version (${SPEC_DEFAULT_VERSION})." >&2 + exit 1 + fi + + echo "version=${VERSION}" >> "${GITHUB_OUTPUT}" + echo "tag_name=v${VERSION}" >> "${GITHUB_OUTPUT}" + echo "archive_prefix=ro-control-${VERSION}" >> "${GITHUB_OUTPUT}" + + source-archives: + name: Build Source Archives + runs-on: ubuntu-latest + needs: metadata + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Create source archives + env: + ARCHIVE_PREFIX: ${{ needs.metadata.outputs.archive_prefix }} + run: | + git archive --format=tar.gz --prefix="${ARCHIVE_PREFIX}/" --output="${ARCHIVE_PREFIX}.tar.gz" "${GITHUB_SHA}" + git archive --format=zip --prefix="${ARCHIVE_PREFIX}/" --output="${ARCHIVE_PREFIX}.zip" "${GITHUB_SHA}" + + - name: Upload source archives + uses: actions/upload-artifact@v4 + with: + name: ro-control-source-${{ needs.metadata.outputs.version }} + path: | + ${{ needs.metadata.outputs.archive_prefix }}.tar.gz + ${{ needs.metadata.outputs.archive_prefix }}.zip + + rpm: + name: Build Fedora RPM (${{ matrix.arch }}) + needs: [metadata, source-archives] + runs-on: ${{ matrix.runs_on }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + runs_on: ubuntu-24.04 + - arch: aarch64 + runs_on: ubuntu-24.04-arm container: image: fedora:42 - permissions: - contents: read - steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Download source archives + uses: actions/download-artifact@v4 + with: + name: ro-control-source-${{ needs.metadata.outputs.version }} + path: dist + - name: Install packaging dependencies run: | dnf install -y \ @@ -37,73 +130,97 @@ jobs: kf6-qqc2-desktop-style \ polkit-devel - - name: Derive release version + - name: Build RPM artifacts + env: + VERSION: ${{ needs.metadata.outputs.version }} + ARCHIVE_PREFIX: ${{ needs.metadata.outputs.archive_prefix }} + RPM_ARCH: ${{ matrix.arch }} run: | - VERSION="${GITHUB_REF_NAME#v}" - echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" + mkdir -p ~/rpmbuild/SOURCES ~/rpmbuild/SPECS dist/rpm + cp "dist/${ARCHIVE_PREFIX}.tar.gz" "${HOME}/rpmbuild/SOURCES/" + cp packaging/rpm/ro-control.spec "${HOME}/rpmbuild/SPECS/ro-control.spec" - - name: Create source archives + rpmbuild -ba "${HOME}/rpmbuild/SPECS/ro-control.spec" \ + --define "_topdir ${HOME}/rpmbuild" \ + --define "upstream_version ${VERSION}" \ + --define "dist .fc42" + + cp ~/rpmbuild/RPMS/*/*.rpm dist/rpm/ + + if [[ "${RPM_ARCH}" == "x86_64" ]]; then + cp ~/rpmbuild/SRPMS/*.src.rpm dist/rpm/ + fi + + - name: Verify package metadata + env: + VERSION: ${{ needs.metadata.outputs.version }} + RPM_ARCH: ${{ matrix.arch }} run: | - PREFIX="ro-control-${VERSION}" - git archive --format=tar.gz --prefix="${PREFIX}/" --output="${PREFIX}.tar.gz" "${GITHUB_SHA}" - git archive --format=zip --prefix="${PREFIX}/" --output="${PREFIX}.zip" "${GITHUB_SHA}" + RPM_FILE="$(find dist/rpm -maxdepth 1 -type f -name "*.${RPM_ARCH}.rpm" | head -n1)" + if [[ -z "${RPM_FILE}" ]]; then + echo "Failed to locate built ${RPM_ARCH} RPM." >&2 + exit 1 + fi - - name: Build RPM artifacts + rpm -qp --info "${RPM_FILE}" > "dist/rpm/ro-control-${VERSION}-${RPM_ARCH}-info.txt" + rpm -qp --requires "${RPM_FILE}" | sort > "dist/rpm/ro-control-${VERSION}-${RPM_ARCH}-requires.txt" + + - name: Install and smoke-test RPM + env: + VERSION: ${{ needs.metadata.outputs.version }} + RPM_ARCH: ${{ matrix.arch }} run: | - mkdir -p ~/rpmbuild/SOURCES ~/rpmbuild/SPECS - cp "ro-control-${VERSION}.tar.gz" "${HOME}/rpmbuild/SOURCES/" - cp packaging/rpm/ro-control.spec "${HOME}/rpmbuild/SPECS/ro-control.spec" - rpmbuild -ba "${HOME}/rpmbuild/SPECS/ro-control.spec" \ - --define "_topdir ${HOME}/rpmbuild" - cp ~/rpmbuild/SRPMS/*.src.rpm . - cp ~/rpmbuild/RPMS/*/*.rpm . + RPM_FILE="$(find dist/rpm -maxdepth 1 -type f -name "*.${RPM_ARCH}.rpm" | head -n1)" + dnf install -y --nogpgcheck "${RPM_FILE}" - - name: Generate checksums + INSTALLED_VERSION="$(ro-control --version | tr -d '\n')" + if [[ "${INSTALLED_VERSION}" != "${VERSION}" ]]; then + echo "Installed CLI version (${INSTALLED_VERSION}) does not match release version (${VERSION})." >&2 + exit 1 + fi + + ro-control --help > /dev/null + + - name: Generate per-arch checksums + env: + VERSION: ${{ needs.metadata.outputs.version }} + RPM_ARCH: ${{ matrix.arch }} run: | - sha256sum \ - "ro-control-${VERSION}.tar.gz" \ - "ro-control-${VERSION}.zip" \ - *.rpm \ - *.src.rpm > "ro-control-${VERSION}-SHA256SUMS.txt" + ( + cd dist/rpm + sha256sum * > "ro-control-${VERSION}-${RPM_ARCH}-SHA256SUMS.txt" + ) - - name: Upload release artifacts + - name: Upload RPM artifacts uses: actions/upload-artifact@v4 with: - name: ro-control-release-${{ env.VERSION }} - path: | - ro-control-${{ env.VERSION }}.tar.gz - ro-control-${{ env.VERSION }}.zip - *.rpm - *.src.rpm - ro-control-${{ env.VERSION }}-SHA256SUMS.txt + name: ro-control-rpm-${{ matrix.arch }}-${{ needs.metadata.outputs.version }} + path: dist/rpm/* release: name: Create GitHub Release runs-on: ubuntu-latest - needs: artifacts - - permissions: - contents: write + needs: [metadata, source-archives, rpm] steps: - - name: Derive release version - run: | - VERSION="${GITHUB_REF_NAME#v}" - echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" - - - name: Download release artifacts + - name: Download all release artifacts uses: actions/download-artifact@v4 with: - name: ro-control-release-${{ env.VERSION }} + pattern: ro-control-* path: dist + merge-multiple: true - name: Publish release uses: softprops/action-gh-release@v2 with: + tag_name: ${{ needs.metadata.outputs.tag_name }} + target_commitish: ${{ github.sha }} generate_release_notes: true files: | - dist/ro-control-${{ env.VERSION }}.tar.gz - dist/ro-control-${{ env.VERSION }}.zip + dist/ro-control-${{ needs.metadata.outputs.version }}.tar.gz + dist/ro-control-${{ needs.metadata.outputs.version }}.zip dist/*.rpm dist/*.src.rpm - dist/ro-control-${{ env.VERSION }}-SHA256SUMS.txt + dist/*SHA256SUMS.txt + dist/*-requires.txt + dist/*-info.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index f894f64..d202cc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Test suite expanded to cover monitor metric ranges and detector reporting - Repository metadata and packaging references aligned with the active GitHub organization - Privileged command flow now uses a dedicated allowlisted helper instead of raw `pkexec` command dispatch +- GitHub release automation now targets Fedora `x86_64` and `aarch64` RPM publication from tagged builds ### Fixed - Command execution path preserves stdout reliably @@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updater API/header alignment and monitor test compatibility issues resolved - Repository cleanup for stray macOS metadata files - PolicyKit metadata, helper install path, and packaged action identifiers are now consistent +- Release packaging now validates tag/CMake/spec version alignment before publishing assets --- diff --git a/README.md b/README.md index fea0e2b..f554cda 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ Additional PNG screenshots should be added before wider store distribution. ### RPM Package -Download the latest `.rpm` from [Releases](https://github.com/Project-Ro-ASD/ro-Control/releases): +Download the latest Fedora `.rpm` from [Releases](https://github.com/Project-Ro-ASD/ro-Control/releases) and choose the package that matches your machine architecture (`x86_64` or `aarch64`): ```bash sudo dnf install ./ro-control-*.rpm diff --git a/README.tr.md b/README.tr.md index a83f8a7..7d20420 100644 --- a/README.tr.md +++ b/README.tr.md @@ -101,7 +101,7 @@ Daha geniş mağaza / distro dağıtımı öncesinde PNG ekran görüntüleri ek ### RPM Paketi -[Releases](https://github.com/Project-Ro-ASD/ro-Control/releases) sayfasından en son `.rpm` dosyasını indirin: +[Releases](https://github.com/Project-Ro-ASD/ro-Control/releases) sayfasından sistem mimarinize (`x86_64` veya `aarch64`) uygun en güncel Fedora `.rpm` paketini indirin: ```bash sudo dnf install ./ro-control-*.rpm diff --git a/docs/RELEASE.md b/docs/RELEASE.md index 1bafd18..71d0475 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -27,15 +27,17 @@ Use this checklist for every production release. ## 4. Packaging - [ ] `packaging/rpm/ro-control.spec` release/version fields are correct. -- [ ] Build RPM artifacts successfully. +- [ ] Build Fedora RPM artifacts successfully for both `x86_64` and `aarch64`. - [ ] Verify installation and launch on the target desktop environment. - [ ] Verify `man ro-control` and shell completions install correctly. +- [ ] Confirm release tag version matches `CMakeLists.txt` and `packaging/rpm/ro-control.spec`. ## 5. Tag and Publish - [ ] Create annotated tag: `vX.Y.Z`. - [ ] Push tag to trigger release workflow. -- [ ] Verify GitHub Release includes source archives. +- [ ] Verify GitHub Release includes source archives, one `x86_64` RPM, one `aarch64` RPM, and one source RPM. +- [ ] Verify the attached checksum and RPM metadata files are present. ## 6. Post-release diff --git a/packaging/rpm/README.md b/packaging/rpm/README.md index 0cef387..9b198bf 100644 --- a/packaging/rpm/README.md +++ b/packaging/rpm/README.md @@ -7,6 +7,7 @@ This directory contains the RPM recipe for ro-Control. - Produce a reproducible RPM from a release tarball - Require translation tooling so localized builds are never emitted partially - Run the upstream Qt test suite during `%check` +- Publish GitHub Release RPMs for both `x86_64` and `aarch64` ## Source archive expectations @@ -34,6 +35,14 @@ spectool -g -R packaging/rpm/ro-control.spec rpmbuild -ba packaging/rpm/ro-control.spec ``` +To build a different release version from the same spec, override the version +macro explicitly: + +```bash +rpmbuild -ba packaging/rpm/ro-control.spec \ + --define "upstream_version 0.1.0" +``` + If you build from a Git checkout instead of a published source archive, create the tarball first so `%Source0` matches the spec contract. @@ -43,3 +52,16 @@ The RPM installs the PolicyKit helper policy as It also installs the CLI manual page and shell completions for Bash, Zsh, and Fish so command discovery works out of the box on release systems. + +## Release automation + +The GitHub release workflow builds: + +- source archives (`.tar.gz`, `.zip`) +- one Fedora binary RPM for `x86_64` +- one Fedora binary RPM for `aarch64` +- one source RPM + +Each architecture job also performs a smoke install with `dnf install` and +verifies that `ro-control --version` matches the tagged release version before +publishing assets. diff --git a/packaging/rpm/ro-control.spec b/packaging/rpm/ro-control.spec index ff71cd3..ea4b535 100644 --- a/packaging/rpm/ro-control.spec +++ b/packaging/rpm/ro-control.spec @@ -1,11 +1,14 @@ +%global upstream_version %{!?upstream_version:0.1.0}%{?upstream_version} + Name: ro-control -Version: 0.1.0 -Release: 2%{?dist} +Version: %{upstream_version} +Release: 1%{?dist} Summary: Smart NVIDIA driver manager and system monitor License: GPL-3.0-or-later URL: https://github.com/Project-Ro-ASD/ro-Control Source0: %{name}-%{version}.tar.gz +ExclusiveArch: x86_64 aarch64 BuildRequires: cmake BuildRequires: gcc-c++ @@ -24,11 +27,17 @@ Requires: qt6-qtdeclarative Requires: qt6-qtwayland Requires: kf6-qqc2-desktop-style Requires: polkit -Requires: dnf +Requires: /usr/bin/dnf Requires: /usr/bin/pkexec +Requires: /usr/bin/rpm Requires: pciutils +Requires: /usr/bin/free Recommends: mokutil Recommends: kmod +Recommends: /usr/bin/sensors +Recommends: /usr/sbin/akmods +Recommends: /usr/bin/dracut +Recommends: /usr/sbin/grubby %description ro-Control is a Qt6/KDE Plasma desktop application that helps users @@ -66,9 +75,7 @@ tar -xzf %{SOURCE0} --strip-components=1 %{_datadir}/polkit-1/actions/io.github.ProjectRoASD.rocontrol.policy %changelog -* Mon Mar 16 2026 ro-Control Maintainers - 0.1.0-2 -- Fix Fedora runtime dependencies for DNF and pkexec -- Restore standard RPM artifact naming to avoid output collisions - -* Fri Mar 06 2026 ro-Control Maintainers - 0.1.0-1 -- Initial RPM packaging spec +* Sun Mar 22 2026 ro-Control Maintainers - 0.1.0-1 +- Prepare first GitHub Release RPMs for x86_64 and aarch64 +- Add explicit Fedora runtime command dependencies and recommendations +- Align RPM release automation with tagged versioned source archives