From 6003a79b3ef71d1d7fe873ff5b294d9fa5dbbce9 Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Wed, 22 Jul 2026 11:45:59 -0600 Subject: [PATCH 1/7] wip: initial idea, needs some tweaks and awaits changes to metadata-service Signed-off-by: Sean Tronsen --- .github/workflows/PRBuild.yaml | 54 ++++++++++++++++++++ .github/workflows/Release.yaml | 32 ++++++++++++ Makefile | 25 ++++++++- packaging/metadata-service.spec | 54 ++++++++++++++++++++ packaging/systemd/metadata-data.volume | 8 +++ packaging/systemd/metadata-service.container | 38 ++++++++++++++ 6 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 packaging/metadata-service.spec create mode 100644 packaging/systemd/metadata-data.volume create mode 100644 packaging/systemd/metadata-service.container diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml index 26b47bc..6841222 100644 --- a/.github/workflows/PRBuild.yaml +++ b/.github/workflows/PRBuild.yaml @@ -105,3 +105,57 @@ jobs: subject-name: ghcr.io/openchami/metadata-service subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} push-to-registry: true + + rpm-build: + runs-on: ubuntu-latest + container: + image: rockylinux:9 + + steps: + - name: Install build dependencies + run: dnf install -y -q git make rpm-build rpmlint podman tar gzip cpio + + - name: Mark workspace as a safe git directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + - uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 + fetch-tags: 1 + + - name: Build RPM + run: make rpm-build + + # RPM VALIDATION + - name: Verify installed file list is exactly what's expected + run: | + rpm -qlp dist/rpmbuild/RPMS/noarch/*.rpm | sort > /tmp/actual-files.txt + cat /tmp/actual-files.txt + sort > /tmp/expected-files.txt <<'EOF' + /usr/share/containers/systemd/metadata-data.volume + /usr/share/containers/systemd/metadata-service.container + /usr/share/licenses/metadata-service + /usr/share/licenses/metadata-service/MIT.txt + EOF + diff /tmp/expected-files.txt /tmp/actual-files.txt + + - name: rpmlint + run: rpmlint dist/rpmbuild/RPMS/noarch/*.rpm || true + + - name: Validate Quadlet units are discovered by systemd's generator + run: | + set -e + mkdir -p /tmp/extracted /tmp/genout + rpm2cpio dist/rpmbuild/RPMS/noarch/*.rpm | (cd /tmp/extracted && cpio -idm) + + cat > /tmp/extracted/usr/share/containers/systemd/openchami-internal.network <<'EOF' + [Network] + NetworkName=openchami-internal + EOF + + QUADLET_UNIT_DIRS=/tmp/extracted/usr/share/containers/systemd \ + /usr/lib/systemd/system-generators/podman-system-generator /tmp/genout /tmp/genout /tmp/genout + + test -f /tmp/genout/metadata-service.service + test -f /tmp/genout/metadata-data-volume.service + cat /tmp/genout/metadata-service.service diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml index 24862a8..b3e5334 100644 --- a/.github/workflows/Release.yaml +++ b/.github/workflows/Release.yaml @@ -81,3 +81,35 @@ jobs: subject-name: ghcr.io/openchami/metadata-service subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} push-to-registry: true + + rpm-build: + needs: build + + runs-on: ubuntu-latest + container: + image: rockylinux:9 + + steps: + - name: Install build dependencies + run: dnf install -y -q git make rpm-build rpmlint tar gzip + + - name: Mark workspace as a safe git directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + - name: Checkout + uses: actions/checkout@v6.0.2 + with: + fetch-tags: 1 + fetch-depth: 0 + + - name: Build RPM + run: make rpm-build + + - name: rpmlint + run: rpmlint dist/rpmbuild/RPMS/noarch/*.rpm || true + + - name: Upload RPM artifact + uses: actions/upload-artifact@v4 + with: + name: metadata-service-rpm + path: dist/rpmbuild/RPMS/noarch/*.rpm diff --git a/Makefile b/Makefile index 4258ceb..2154957 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: MIT -.PHONY: help build test lint clean install run container-build container-run generate generate-check dev +.PHONY: help build test lint clean install run container-build container-run generate generate-check dev rpm-build rpm-clean # Variables BINARY_NAME=ochami-metadata @@ -15,6 +15,12 @@ DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") CONTAINER_PROG ?= $(shell command -v docker 2>/dev/null) CONTAINER_TAG ?= latest CONTAINER_GO_VERSION ?= $(shell awk '/^go / {print $$2; exit}' go.mod) +# RPM version/release: strip the leading 'v' and rewrite git-describe's +# '-N-gHASH[-dirty]' suffix into RPM-legal dot separators (hyphens aren't +# allowed in an RPM Version field). An exact tag like v0.1.2 becomes 0.1.2. +RPM_VERSION ?= $(shell echo "$(VERSION)" | sed -e 's/^v//' -e 's/-/./g') +RPM_RELEASE ?= 1 +RPM_TOPDIR ?= $(CURDIR)/dist/rpmbuild LDFLAGS=-ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.date=$(DATE)" FABRICA_CMD ?= go run github.com/openchami/fabrica/cmd/fabrica@latest FABRICA_SOURCE_ARG ?= @@ -102,6 +108,23 @@ container-run: container-build ## Build and run Docker container release-snapshot: ## Create a snapshot release with GoReleaser goreleaser release --snapshot --clean +rpm-build: ## Build the metadata-service RPM (VERSION/RPM_RELEASE override the derived defaults) + @command -v rpmbuild >/dev/null 2>&1 || { echo "rpmbuild is required but not installed."; exit 1; } + rm -rf $(RPM_TOPDIR) + mkdir -p $(RPM_TOPDIR)/SOURCES/metadata-service-$(RPM_VERSION)/LICENSES + cp packaging/systemd/* $(RPM_TOPDIR)/SOURCES/metadata-service-$(RPM_VERSION)/ + cp LICENSES/MIT.txt $(RPM_TOPDIR)/SOURCES/metadata-service-$(RPM_VERSION)/LICENSES/ + tar -C $(RPM_TOPDIR)/SOURCES -czf $(RPM_TOPDIR)/SOURCES/metadata-service-$(RPM_VERSION).tar.gz \ + metadata-service-$(RPM_VERSION) + rpmbuild --define "_topdir $(RPM_TOPDIR)" \ + --define "version $(RPM_VERSION)" \ + --define "rel $(RPM_RELEASE)" \ + -bb packaging/metadata-service.spec + @echo "Built: $(RPM_TOPDIR)/RPMS/noarch/$$(ls $(RPM_TOPDIR)/RPMS/noarch)" + +rpm-clean: ## Remove local RPM build artifacts + rm -rf $(RPM_TOPDIR) + fmt: ## Format code $(GO) fmt ./... goimports -w . diff --git a/packaging/metadata-service.spec b/packaging/metadata-service.spec new file mode 100644 index 0000000..e513ee2 --- /dev/null +++ b/packaging/metadata-service.spec @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# SPDX-License-Identifier: MIT +# +# See `make rpm-build` and docs/RPM_PACKAGING.md for the tag-to-version +# mapping and how the packaged quadlet's image tag is pinned to it. + +Name: metadata-service +Version: %{version} +Release: %{rel}%{?dist} +Summary: OpenCHAMI metadata-service Quadlet units + +License: MIT +URL: https://github.com/OpenCHAMI/metadata-service +Source0: %{name}-%{version}.tar.gz + +BuildArch: noarch + + +# TODO: FIXME: metadata-service depends on smd and tokensmith, which do not +# exist as standalone RPMs yet. +# Requires: smd +# Requires: tokensmith +Requires: podman + +%description +Podman Quadlet unit files (container + volume) for running metadata-service +as part of an OpenCHAMI deployment. + +%prep +%setup -q + +%install +mkdir -p %{buildroot}/usr/share/containers/systemd + +sed "s|@IMAGE_TAG@|v%{version}|" metadata-service.container \ + > %{buildroot}/usr/share/containers/systemd/metadata-service.container +chmod 644 %{buildroot}/usr/share/containers/systemd/metadata-service.container + +install -m 644 metadata-data.volume \ + %{buildroot}/usr/share/containers/systemd/metadata-data.volume + + +%files +%license LICENSES/MIT.txt +/usr/share/containers/systemd/metadata-service.container +/usr/share/containers/systemd/metadata-data.volume + +%post +# reload systemd so the new Quadlet-generated unit is seen +systemctl daemon-reload + +%postun +# reload systemd so the removed unit is dropped +systemctl daemon-reload diff --git a/packaging/systemd/metadata-data.volume b/packaging/systemd/metadata-data.volume new file mode 100644 index 0000000..4060aeb --- /dev/null +++ b/packaging/systemd/metadata-data.volume @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# SPDX-License-Identifier: MIT + +[Unit] +Description=metadata-service Data Volume + +[Volume] +VolumeName=metadata-service-data diff --git a/packaging/systemd/metadata-service.container b/packaging/systemd/metadata-service.container new file mode 100644 index 0000000..c7d8e33 --- /dev/null +++ b/packaging/systemd/metadata-service.container @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# SPDX-License-Identifier: MIT + +[Unit] +Description=The metadata-service container +Requires=smd.service tokensmith.service +After=smd.service tokensmith.service +PartOf=openchami.target + +[Container] +ContainerName=metadata-service +HostName=metadata-service +Image=ghcr.io/openchami/metadata-service:@IMAGE_TAG@ + +# VOLUME +Volume=metadata-data.volume:/data + +# NETWORK +Network=openchami-internal.network + +# ENVIRONMENT +EnvironmentFile=/etc/openchami/configs/openchami.env +Secret=metadata-service-bootstrap-token,type=env,target=TOKENSMITH_BOOTSTRAP_TOKEN + +# EXTRAS +# for wireguard tunnel creation +AddCapability=cap_net_admin +AddDevice=/dev/net/tun + +# Proxy settings +PodmanArgs=--http-proxy=false + +# TODO: CHANGE ME TO USE THE CONFIG FILE +Exec=serve --tokensmith-url=http://tokensmith:8080 + +[Service] +ExecStartPre=/usr/sbin/tokensmith_bootstrap_token metadata-service +Restart=always From 77f84dbbe97f3ac66cae2fffda2cf6ba358b6763 Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Tue, 28 Jul 2026 16:16:50 -0600 Subject: [PATCH 2/7] wip - needs dry refactor: add gpg-signing-manager steps Signed-off-by: Sean Tronsen --- .github/workflows/PRBuild.yaml | 88 ++++++++++++++++++++ .github/workflows/Release.yaml | 142 +++++++++++++++++++++++++++++++-- 2 files changed, 225 insertions(+), 5 deletions(-) diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml index 6841222..5208a2d 100644 --- a/.github/workflows/PRBuild.yaml +++ b/.github/workflows/PRBuild.yaml @@ -123,9 +123,97 @@ jobs: fetch-depth: 0 fetch-tags: 1 + # ------------------------------------------------------------------ + # 2. Gate: fail fast if the repo key is expiring soon + # ------------------------------------------------------------------ + # todo: change this to use the action from the gpg signing repo + - name: Check repo key expiration + uses: OpenCHAMI/gpg-signing-manager/actions/check-key-expiration@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + with: + key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} + warn-days: '30' + + # ------------------------------------------------------------------ + # 3. Generate a short-lived ephemeral key certified by the repo key + # ------------------------------------------------------------------ + - name: Generate ephemeral release key + id: ephemeral + uses: OpenCHAMI/gpg-signing-manager/actions/gpg-ephemeral-key@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + with: + cert-key-armored-b64: ${{ secrets.GPG_REPO_CERT_KEY_B64 }} + name: '${{ github.repository }} Release' + comment: 'ephemeral key for ${{ github.ref_name }}' + email: 'release@packages.openchami.org' + expire: '1d' + + # ------------------------------------------------------------------ + # 4. Set up RPM signing using the ephemeral key as the direct signer + # ------------------------------------------------------------------ + - name: Setup RPM signing (ephemeral key) + id: rpm_signing + uses: OpenCHAMI/gpg-signing-manager/actions/setup-rpm-signing@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + with: + repo-key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} + ephemeral-fingerprint: ${{ steps.ephemeral.outputs.ephemeral-fingerprint }} + public-key-output: repo-public.asc + + # ------------------------------------------------------------------ + # 5. Build RPMs (adapt this step to your build system) + # ------------------------------------------------------------------ - name: Build RPM run: make rpm-build + # ------------------------------------------------------------------ + # 6. Sign each RPM with the ephemeral key + # ------------------------------------------------------------------ + - name: Sign RPMs + run: | + EPHEM_FPR="${{ steps.ephemeral.outputs.ephemeral-fingerprint }}" + shopt -s nullglob + rpms=($(find dist -name '*.rpm')) + if [[ ${#rpms[@]} -eq 0 ]]; then + echo "No RPM files found in dist/ — skipping signing step." + exit 0 + fi + for rpm in "${rpms[@]}"; do + echo "Signing: $rpm" + rpm --define "_gpg_name ${EPHEM_FPR}" --addsign "$rpm" + done + + # ------------------------------------------------------------------ + # 7. Export and decode the ephemeral public key for release artifacts + # ------------------------------------------------------------------ + - name: Export ephemeral public key + run: | + printf '%s' '${{ steps.ephemeral.outputs.ephemeral-public-key }}' \ + | base64 -d > ephemeral-public.asc + + # ------------------------------------------------------------------ + # 8. Verify the full chain before publishing (optional but recommended) + # ------------------------------------------------------------------ + - name: Verify trust chain + if: hashFiles('dist/*.rpm') != '' + run: | + # Import master public key if available as a secret. + if [ -n '${{ secrets.MASTER_PUBLIC_ASC }}' ]; then + printf '%s' '${{ secrets.MASTER_PUBLIC_ASC }}' > master-public.asc + else + echo "MASTER_PUBLIC_ASC secret not set; skipping master chain check." + exit 0 + fi + shopt -s nullglob + rpms=($(find dist -name '*.rpm')) + rpm_args=() + for r in "${rpms[@]}"; do rpm_args+=(--rpm "$r"); done + + curl -LO curl -LO \ + https://raw.githubusercontent.com/OpenCHAMI/gpg-signing-manager/main/scripts/verify-chain.sh + bash ./verify-chain.sh \ + --master master-public.asc \ + --repo repo-public.asc \ + --ephemeral ephemeral-public.asc \ + "${rpm_args[@]}" + # RPM VALIDATION - name: Verify installed file list is exactly what's expected run: | diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml index b3e5334..b5544fe 100644 --- a/.github/workflows/Release.yaml +++ b/.github/workflows/Release.yaml @@ -102,14 +102,146 @@ jobs: fetch-tags: 1 fetch-depth: 0 + # ------------------------------------------------------------------ + # 2. Gate: fail fast if the repo key is expiring soon + # ------------------------------------------------------------------ + # todo: change this to use the action from the gpg signing repo + - name: Check repo key expiration + uses: OpenCHAMI/gpg-signing-manager/actions/check-key-expiration@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + with: + key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} + warn-days: '30' + + # ------------------------------------------------------------------ + # 3. Generate a short-lived ephemeral key certified by the repo key + # ------------------------------------------------------------------ + - name: Generate ephemeral release key + id: ephemeral + uses: OpenCHAMI/gpg-signing-manager/actions/gpg-ephemeral-key@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + with: + cert-key-armored-b64: ${{ secrets.GPG_REPO_CERT_KEY_B64 }} + name: '${{ github.repository }} Release' + comment: 'ephemeral key for ${{ github.ref_name }}' + email: 'release@packages.openchami.org' + expire: '1d' + + # ------------------------------------------------------------------ + # 4. Set up RPM signing using the ephemeral key as the direct signer + # ------------------------------------------------------------------ + - name: Setup RPM signing (ephemeral key) + id: rpm_signing + uses: OpenCHAMI/gpg-signing-manager/actions/setup-rpm-signing@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + with: + repo-key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} + ephemeral-fingerprint: ${{ steps.ephemeral.outputs.ephemeral-fingerprint }} + public-key-output: repo-public.asc + + # ------------------------------------------------------------------ + # 5. Build RPMs (adapt this step to your build system) + # ------------------------------------------------------------------ - name: Build RPM run: make rpm-build + # ------------------------------------------------------------------ + # 6. Sign each RPM with the ephemeral key + # ------------------------------------------------------------------ + - name: Sign RPMs + run: | + EPHEM_FPR="${{ steps.ephemeral.outputs.ephemeral-fingerprint }}" + shopt -s nullglob + rpms=($(find dist -name '*.rpm')) + if [[ ${#rpms[@]} -eq 0 ]]; then + echo "No RPM files found in dist/ — skipping signing step." + exit 0 + fi + for rpm in "${rpms[@]}"; do + echo "Signing: $rpm" + rpm --define "_gpg_name ${EPHEM_FPR}" --addsign "$rpm" + done + + # ------------------------------------------------------------------ + # 7. Export and decode the ephemeral public key for release artifacts + # ------------------------------------------------------------------ + - name: Export ephemeral public key + run: | + printf '%s' '${{ steps.ephemeral.outputs.ephemeral-public-key }}' \ + | base64 -d > ephemeral-public.asc + + # ------------------------------------------------------------------ + # 8. Verify the full chain before publishing (optional but recommended) + # ------------------------------------------------------------------ + - name: Verify trust chain + if: hashFiles('dist/*.rpm') != '' + run: | + # Import master public key if available as a secret. + if [ -n '${{ secrets.MASTER_PUBLIC_ASC }}' ]; then + printf '%s' '${{ secrets.MASTER_PUBLIC_ASC }}' > master-public.asc + else + echo "MASTER_PUBLIC_ASC secret not set; skipping master chain check." + exit 0 + fi + shopt -s nullglob + rpms=($(find dist -name '*.rpm')) + rpm_args=() + for r in "${rpms[@]}"; do rpm_args+=(--rpm "$r"); done + + curl -LO \ + https://raw.githubusercontent.com/OpenCHAMI/gpg-signing-manager/main/scripts/verify-chain.sh + bash ./verify-chain.sh \ + --master master-public.asc \ + --repo repo-public.asc \ + --ephemeral ephemeral-public.asc \ + "${rpm_args[@]}" + - name: rpmlint - run: rpmlint dist/rpmbuild/RPMS/noarch/*.rpm || true + run: rpmlint $(find dist -name '*.rpm') || true - - name: Upload RPM artifact - uses: actions/upload-artifact@v4 + # ------------------------------------------------------------------ + # 9. Publish release with public keys attached for user verification + # ------------------------------------------------------------------ + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 with: - name: metadata-service-rpm - path: dist/rpmbuild/RPMS/noarch/*.rpm + tag_name: ${{ github.ref_name }} + name: Release ${{ github.ref_name }} + files: | + dist/**/*.rpm + repo-public.asc + ephemeral-public.asc + body: | + ## GPG Signature Verification + + Each RPM in this release is signed with a short-lived ephemeral key that + is certified by the repository signing key, which is itself certified by + the OpenCHAMI offline master key. + + ### Trust chain + + ``` + offline master key + └─[certifies]─> repo key + └─[certifies]─> ephemeral key (${{ github.ref_name }}) + └─[signs]─> RPM files + ``` + + ### How to verify + + 1. Download `repo-public.asc` and `ephemeral-public.asc` from this release. + 2. Import both keys: + ```bash + gpg --import repo-public.asc ephemeral-public.asc + ``` + 3. Verify each RPM: + ```bash + rpm --checksig *.rpm + ``` + 4. For full chain verification (requires the master public key): + ```bash + curl -LO \ + https://raw.githubusercontent.com/OpenCHAMI/gpg-signing-manager/main/scripts/verify-chain.sh + bash verify-chain.sh \ + --master master-public.asc \ + --repo repo-public.asc \ + --ephemeral ephemeral-public.asc \ + --rpm *.rpm + ``` From b61c44f36cdd0e4ffe29c67e67aa70050377e15d Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Wed, 29 Jul 2026 18:50:32 -0600 Subject: [PATCH 3/7] wip: update release workflow to use abstractions Signed-off-by: Sean Tronsen --- .github/workflows/Release.yaml | 167 +++++---------------------------- 1 file changed, 25 insertions(+), 142 deletions(-) diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml index b5544fe..872adaa 100644 --- a/.github/workflows/Release.yaml +++ b/.github/workflows/Release.yaml @@ -11,9 +11,11 @@ on: - v* permissions: write-all # Necessary for the generate-build-provenance action with containers +env: + ARTIFACT_NAME_RPM_SIGNED: 'rpms-signed' + ARTIFACT_NAME_GPG_KEYS_PUBLIC: 'gpg-public-keys' jobs: - build: @@ -82,9 +84,8 @@ jobs: subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} push-to-registry: true - rpm-build: + rpmbuild: needs: build - runs-on: ubuntu-latest container: image: rockylinux:9 @@ -102,146 +103,28 @@ jobs: fetch-tags: 1 fetch-depth: 0 - # ------------------------------------------------------------------ - # 2. Gate: fail fast if the repo key is expiring soon - # ------------------------------------------------------------------ - # todo: change this to use the action from the gpg signing repo - - name: Check repo key expiration - uses: OpenCHAMI/gpg-signing-manager/actions/check-key-expiration@d4366a45c94be50cbb7f90d229c10f395b6d10d8 - with: - key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} - warn-days: '30' - - # ------------------------------------------------------------------ - # 3. Generate a short-lived ephemeral key certified by the repo key - # ------------------------------------------------------------------ - - name: Generate ephemeral release key - id: ephemeral - uses: OpenCHAMI/gpg-signing-manager/actions/gpg-ephemeral-key@d4366a45c94be50cbb7f90d229c10f395b6d10d8 - with: - cert-key-armored-b64: ${{ secrets.GPG_REPO_CERT_KEY_B64 }} - name: '${{ github.repository }} Release' - comment: 'ephemeral key for ${{ github.ref_name }}' - email: 'release@packages.openchami.org' - expire: '1d' - - # ------------------------------------------------------------------ - # 4. Set up RPM signing using the ephemeral key as the direct signer - # ------------------------------------------------------------------ - - name: Setup RPM signing (ephemeral key) - id: rpm_signing - uses: OpenCHAMI/gpg-signing-manager/actions/setup-rpm-signing@d4366a45c94be50cbb7f90d229c10f395b6d10d8 - with: - repo-key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} - ephemeral-fingerprint: ${{ steps.ephemeral.outputs.ephemeral-fingerprint }} - public-key-output: repo-public.asc - - # ------------------------------------------------------------------ - # 5. Build RPMs (adapt this step to your build system) - # ------------------------------------------------------------------ - name: Build RPM run: make rpm-build - # ------------------------------------------------------------------ - # 6. Sign each RPM with the ephemeral key - # ------------------------------------------------------------------ - - name: Sign RPMs - run: | - EPHEM_FPR="${{ steps.ephemeral.outputs.ephemeral-fingerprint }}" - shopt -s nullglob - rpms=($(find dist -name '*.rpm')) - if [[ ${#rpms[@]} -eq 0 ]]; then - echo "No RPM files found in dist/ — skipping signing step." - exit 0 - fi - for rpm in "${rpms[@]}"; do - echo "Signing: $rpm" - rpm --define "_gpg_name ${EPHEM_FPR}" --addsign "$rpm" - done - - # ------------------------------------------------------------------ - # 7. Export and decode the ephemeral public key for release artifacts - # ------------------------------------------------------------------ - - name: Export ephemeral public key - run: | - printf '%s' '${{ steps.ephemeral.outputs.ephemeral-public-key }}' \ - | base64 -d > ephemeral-public.asc - - # ------------------------------------------------------------------ - # 8. Verify the full chain before publishing (optional but recommended) - # ------------------------------------------------------------------ - - name: Verify trust chain - if: hashFiles('dist/*.rpm') != '' - run: | - # Import master public key if available as a secret. - if [ -n '${{ secrets.MASTER_PUBLIC_ASC }}' ]; then - printf '%s' '${{ secrets.MASTER_PUBLIC_ASC }}' > master-public.asc - else - echo "MASTER_PUBLIC_ASC secret not set; skipping master chain check." - exit 0 - fi - shopt -s nullglob - rpms=($(find dist -name '*.rpm')) - rpm_args=() - for r in "${rpms[@]}"; do rpm_args+=(--rpm "$r"); done - - curl -LO \ - https://raw.githubusercontent.com/OpenCHAMI/gpg-signing-manager/main/scripts/verify-chain.sh - bash ./verify-chain.sh \ - --master master-public.asc \ - --repo repo-public.asc \ - --ephemeral ephemeral-public.asc \ - "${rpm_args[@]}" - - - name: rpmlint - run: rpmlint $(find dist -name '*.rpm') || true - - # ------------------------------------------------------------------ - # 9. Publish release with public keys attached for user verification - # ------------------------------------------------------------------ - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 + - name: Upload RPM + uses: actions/upload-artifact@v7 with: - tag_name: ${{ github.ref_name }} - name: Release ${{ github.ref_name }} - files: | - dist/**/*.rpm - repo-public.asc - ephemeral-public.asc - body: | - ## GPG Signature Verification - - Each RPM in this release is signed with a short-lived ephemeral key that - is certified by the repository signing key, which is itself certified by - the OpenCHAMI offline master key. - - ### Trust chain - - ``` - offline master key - └─[certifies]─> repo key - └─[certifies]─> ephemeral key (${{ github.ref_name }}) - └─[signs]─> RPM files - ``` - - ### How to verify - - 1. Download `repo-public.asc` and `ephemeral-public.asc` from this release. - 2. Import both keys: - ```bash - gpg --import repo-public.asc ephemeral-public.asc - ``` - 3. Verify each RPM: - ```bash - rpm --checksig *.rpm - ``` - 4. For full chain verification (requires the master public key): - ```bash - curl -LO \ - https://raw.githubusercontent.com/OpenCHAMI/gpg-signing-manager/main/scripts/verify-chain.sh - bash verify-chain.sh \ - --master master-public.asc \ - --repo repo-public.asc \ - --ephemeral ephemeral-public.asc \ - --rpm *.rpm - ``` + name: ${{ inputs.artifact-name-signed-rpms }} + path: '**/*.rpm' + + rpmsign: + needs: rpmbuild + uses: OpenCHAMI/github-actions/.github/workflows/gpg-sign-artifacts.yml@ + secrets: inherit + with: + artifact-name-signed-rpms: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} + artifact-name-public-keys: ${{ env.ARTIFACT_NAME_GPG_KEYS_PUBLIC }} + + release: + needs: rpmsign + uses: OpenCHAMI/github-actions/.github/workflows/release-signed-artifacts.yml@ + secrets: inherit + with: + artifact-name-signed-rpms: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} + artifact-name-public-keys: ${{ env.ARTIFACT_NAME_GPG_KEYS_PUBLIC }} + From d5559d420b47dc060e88f75cf2f2456529a47f7f Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Thu, 30 Jul 2026 10:42:11 -0600 Subject: [PATCH 4/7] wip: refactor/abstract common routines to org actions repository Signed-off-by: Sean Tronsen --- .github/workflows/PRBuild.yaml | 257 +++++++-------------------------- .github/workflows/Release.yaml | 119 +++------------ 2 files changed, 72 insertions(+), 304 deletions(-) diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml index 5208a2d..bc6af14 100644 --- a/.github/workflows/PRBuild.yaml +++ b/.github/workflows/PRBuild.yaml @@ -1,9 +1,7 @@ -# Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC -# +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC # SPDX-License-Identifier: MIT name: Build each PR for testing and validation - on: pull_request: branches: @@ -17,207 +15,79 @@ on: type: string permissions: write-all # Necessary for the generate-build-provenance action with containers +env: + ARTIFACT_NAME_RPM_UNSIGNED: 'rpms-unsigned' + ARTIFACT_NAME_RPM_SIGNED: 'rpms-signed' + ARTIFACT_NAME_GPG_KEYS_PUBLIC: 'gpg-public-keys' jobs: build: - - - runs-on: ubuntu-latest - - steps: - - name: Set up latest stable Go - uses: actions/setup-go@v6.4.0 - with: - go-version: stable - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver-opts: | - image=moby/buildkit:master - network=host - - name: Docker Login - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Checkout - uses: actions/checkout@v6.0.2 - with: - fetch-tags: 1 - fetch-depth: 0 - # Set environment variables required by GoReleaser - - name: Set build environment variables - run: | - echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV - echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV - echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV - echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV - echo "CGO_ENABLED=0" >> $GITHUB_ENV - echo "IS_PR_BUILD=true" >> $GITHUB_ENV - - - name: Docker Login - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Create Tag for PR - if: github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && inputs.pr_number != '') - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - PR_NUM="${{ github.event.number }}" - if [[ "${{ inputs.pr_number }}" != "" ]]; then - PR_NUM="${{ inputs.pr_number }}" - fi - git tag -f -a pr-${PR_NUM} -m "PR Release" - - - name: Build/Push container with goreleaser - uses: goreleaser/goreleaser-action@v6 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - version: '~> 2' - args: release --clean --skip=announce,validate,archive - id: goreleaser - - name: Process goreleaser output - id: process_goreleaser_output - run: | - echo "const fs = require('fs');" > process.js - echo 'const artifacts = ${{ steps.goreleaser.outputs.artifacts }}' >> process.js - echo "const firstNonNullDigest = artifacts.find(artifact => artifact.extra && artifact.extra.Digest != null)?.extra.Digest;" >> process.js - echo "console.log(firstNonNullDigest);" >> process.js - echo "fs.writeFileSync('digest.txt', firstNonNullDigest);" >> process.js - node process.js - echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT - - name: Attest Binaries - uses: actions/attest-build-provenance@v4.1.0 - with: - subject-path: dist/** - - name: generate build provenance - uses: actions/attest-build-provenance@v4.1.0 - with: - subject-name: ghcr.io/openchami/metadata-service - subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} - push-to-registry: true - - rpm-build: + uses: OpenCHAMI/github-actions/.github/workflows/build-publish-container-goreleaser.yml@dev-rpm-quadlets + secrets: inherit + with: + cgo_enabled: 0 + registry_subject_name: ghcr.io/openchami/metadata-service + is_pr_build: true + pr_number: ${{ inputs.pr_number || github.event.pull_request.number || 0 }} + + rpmbuild: + needs: build + uses: OpenCHAMI/github-actions/.github/workflows/build-rpm-quadlet.yml@dev-rpm-quadlets + secrets: inherit + with: + artifact-name-unsigned-rpms: ${{ env.ARTIFACT_NAME_RPM_UNSIGNED }} + + rpmsign: + needs: rpmbuild + uses: OpenCHAMI/github-actions/.github/workflows/gpg-sign-artifacts.yml@dev-rpm-quadlets + secrets: inherit + with: + artifact-name-unsigned-rpms: ${{ env.ARTIFACT_NAME_RPM_UNSIGNED }} + artifact-name-signed-rpms: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} + artifact-name-public-keys: ${{ env.ARTIFACT_NAME_GPG_KEYS_PUBLIC }} + + rpmvalidate: + needs: rpmsign runs-on: ubuntu-latest container: image: rockylinux:9 - steps: + - name: Install build dependencies - run: dnf install -y -q git make rpm-build rpmlint podman tar gzip cpio + run: dnf install -y -q git rpmlint tar gzip - name: Mark workspace as a safe git directory run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - uses: actions/checkout@v6.0.2 with: + fetch-tags: true fetch-depth: 0 - fetch-tags: 1 - - # ------------------------------------------------------------------ - # 2. Gate: fail fast if the repo key is expiring soon - # ------------------------------------------------------------------ - # todo: change this to use the action from the gpg signing repo - - name: Check repo key expiration - uses: OpenCHAMI/gpg-signing-manager/actions/check-key-expiration@d4366a45c94be50cbb7f90d229c10f395b6d10d8 - with: - key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} - warn-days: '30' - - # ------------------------------------------------------------------ - # 3. Generate a short-lived ephemeral key certified by the repo key - # ------------------------------------------------------------------ - - name: Generate ephemeral release key - id: ephemeral - uses: OpenCHAMI/gpg-signing-manager/actions/gpg-ephemeral-key@d4366a45c94be50cbb7f90d229c10f395b6d10d8 - with: - cert-key-armored-b64: ${{ secrets.GPG_REPO_CERT_KEY_B64 }} - name: '${{ github.repository }} Release' - comment: 'ephemeral key for ${{ github.ref_name }}' - email: 'release@packages.openchami.org' - expire: '1d' - - # ------------------------------------------------------------------ - # 4. Set up RPM signing using the ephemeral key as the direct signer - # ------------------------------------------------------------------ - - name: Setup RPM signing (ephemeral key) - id: rpm_signing - uses: OpenCHAMI/gpg-signing-manager/actions/setup-rpm-signing@d4366a45c94be50cbb7f90d229c10f395b6d10d8 + + - name: Download signed RPM artifacts + uses: actions/download-artifact@v8 with: - repo-key-armored-b64: ${{ secrets.GPG_REPO_KEY_B64 }} - ephemeral-fingerprint: ${{ steps.ephemeral.outputs.ephemeral-fingerprint }} - public-key-output: repo-public.asc - - # ------------------------------------------------------------------ - # 5. Build RPMs (adapt this step to your build system) - # ------------------------------------------------------------------ - - name: Build RPM - run: make rpm-build - - # ------------------------------------------------------------------ - # 6. Sign each RPM with the ephemeral key - # ------------------------------------------------------------------ - - name: Sign RPMs - run: | - EPHEM_FPR="${{ steps.ephemeral.outputs.ephemeral-fingerprint }}" - shopt -s nullglob - rpms=($(find dist -name '*.rpm')) - if [[ ${#rpms[@]} -eq 0 ]]; then - echo "No RPM files found in dist/ — skipping signing step." - exit 0 - fi - for rpm in "${rpms[@]}"; do - echo "Signing: $rpm" - rpm --define "_gpg_name ${EPHEM_FPR}" --addsign "$rpm" - done - - # ------------------------------------------------------------------ - # 7. Export and decode the ephemeral public key for release artifacts - # ------------------------------------------------------------------ - - name: Export ephemeral public key - run: | - printf '%s' '${{ steps.ephemeral.outputs.ephemeral-public-key }}' \ - | base64 -d > ephemeral-public.asc - - # ------------------------------------------------------------------ - # 8. Verify the full chain before publishing (optional but recommended) - # ------------------------------------------------------------------ - - name: Verify trust chain - if: hashFiles('dist/*.rpm') != '' + name: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} + path: dist/rpms + + - name: Find Quadlet RPM run: | - # Import master public key if available as a secret. - if [ -n '${{ secrets.MASTER_PUBLIC_ASC }}' ]; then - printf '%s' '${{ secrets.MASTER_PUBLIC_ASC }}' > master-public.asc - else - echo "MASTER_PUBLIC_ASC secret not set; skipping master chain check." - exit 0 + set -euo pipefail + + quadlet_rpm=$(find . -type f -iname "*.rpm" | head -n 1) + if [ -z "${quadlet_rpm}" ]; then + echo "could not locate quadlet rpm file" + exit 1 fi - shopt -s nullglob - rpms=($(find dist -name '*.rpm')) - rpm_args=() - for r in "${rpms[@]}"; do rpm_args+=(--rpm "$r"); done - - curl -LO curl -LO \ - https://raw.githubusercontent.com/OpenCHAMI/gpg-signing-manager/main/scripts/verify-chain.sh - bash ./verify-chain.sh \ - --master master-public.asc \ - --repo repo-public.asc \ - --ephemeral ephemeral-public.asc \ - "${rpm_args[@]}" - - # RPM VALIDATION + + echo "using QUADLET_RPM_PATH=${quadlet_rpm}" + echo "QUADLET_RPM_PATH=${quadlet_rpm}" >> "$GITHUB_ENV" + + - name: Verify installed file list is exactly what's expected run: | - rpm -qlp dist/rpmbuild/RPMS/noarch/*.rpm | sort > /tmp/actual-files.txt + rpm -qlp "${QUADLET_RPM_PATH}" | sort > /tmp/actual-files.txt cat /tmp/actual-files.txt sort > /tmp/expected-files.txt <<'EOF' /usr/share/containers/systemd/metadata-data.volume @@ -226,24 +96,3 @@ jobs: /usr/share/licenses/metadata-service/MIT.txt EOF diff /tmp/expected-files.txt /tmp/actual-files.txt - - - name: rpmlint - run: rpmlint dist/rpmbuild/RPMS/noarch/*.rpm || true - - - name: Validate Quadlet units are discovered by systemd's generator - run: | - set -e - mkdir -p /tmp/extracted /tmp/genout - rpm2cpio dist/rpmbuild/RPMS/noarch/*.rpm | (cd /tmp/extracted && cpio -idm) - - cat > /tmp/extracted/usr/share/containers/systemd/openchami-internal.network <<'EOF' - [Network] - NetworkName=openchami-internal - EOF - - QUADLET_UNIT_DIRS=/tmp/extracted/usr/share/containers/systemd \ - /usr/lib/systemd/system-generators/podman-system-generator /tmp/genout /tmp/genout /tmp/genout - - test -f /tmp/genout/metadata-service.service - test -f /tmp/genout/metadata-data-volume.service - cat /tmp/genout/metadata-service.service diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml index 872adaa..0db10e2 100644 --- a/.github/workflows/Release.yaml +++ b/.github/workflows/Release.yaml @@ -1,9 +1,7 @@ -# Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC -# +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC # SPDX-License-Identifier: MIT -name: Release with goreleaser - +name: Release on: workflow_dispatch: push: @@ -12,119 +10,40 @@ on: permissions: write-all # Necessary for the generate-build-provenance action with containers env: + ARTIFACT_NAME_RPM_UNSIGNED: 'rpms-unsigned' ARTIFACT_NAME_RPM_SIGNED: 'rpms-signed' ARTIFACT_NAME_GPG_KEYS_PUBLIC: 'gpg-public-keys' jobs: - build: - - - runs-on: ubuntu-latest - steps: - - name: Set up latest stable Go - uses: actions/setup-go@v6.4.0 - with: - go-version: stable - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver-opts: | - image=moby/buildkit:master - network=host - - name: Docker Login - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Checkout - uses: actions/checkout@v6.0.2 - with: - fetch-tags: 1 - fetch-depth: 0 - # Set environment variables required by GoReleaser - - name: Set build environment variables - run: | - echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV - echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV - echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV - echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV - echo "CGO_ENABLED=0" >> $GITHUB_ENV - echo "IS_PR_BUILD=false" >> $GITHUB_ENV - - - name: Release with goreleaser - uses: goreleaser/goreleaser-action@v6 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - version: latest - args: release --clean - id: goreleaser - - name: Process goreleaser output - id: process_goreleaser_output - run: | - echo "const fs = require('fs');" > process.js - echo 'const artifacts = ${{ steps.goreleaser.outputs.artifacts }}' >> process.js - echo "const firstNonNullDigest = artifacts.find(artifact => artifact.extra && artifact.extra.Digest != null)?.extra.Digest;" >> process.js - echo "console.log(firstNonNullDigest);" >> process.js - echo "fs.writeFileSync('digest.txt', firstNonNullDigest);" >> process.js - node process.js - echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT - - name: Attest Binaries - uses: actions/attest-build-provenance@v1 - with: - subject-path: dist/** - - name: generate build provenance - uses: actions/attest-build-provenance@v1 - with: - subject-name: ghcr.io/openchami/metadata-service - subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} - push-to-registry: true + build: + uses: OpenCHAMI/github-actions/.github/workflows/build-publish-container-goreleaser.yml@dev-rpm-quadlets + secrets: inherit + with: + cgo_enabled: 0 + is_pr_build: false + registry_subject_name: ghcr.io/openchami/metadata-service rpmbuild: needs: build - runs-on: ubuntu-latest - container: - image: rockylinux:9 - - steps: - - name: Install build dependencies - run: dnf install -y -q git make rpm-build rpmlint tar gzip - - - name: Mark workspace as a safe git directory - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - - - name: Checkout - uses: actions/checkout@v6.0.2 - with: - fetch-tags: 1 - fetch-depth: 0 - - - name: Build RPM - run: make rpm-build - - - name: Upload RPM - uses: actions/upload-artifact@v7 - with: - name: ${{ inputs.artifact-name-signed-rpms }} - path: '**/*.rpm' + uses: OpenCHAMI/github-actions/.github/workflows/build-rpm-quadlet.yml@dev-rpm-quadlets + secrets: inherit + with: + artifact-name-unsigned-rpms: ${{ env.ARTIFACT_NAME_RPM_UNSIGNED }} rpmsign: needs: rpmbuild - uses: OpenCHAMI/github-actions/.github/workflows/gpg-sign-artifacts.yml@ + uses: OpenCHAMI/github-actions/.github/workflows/gpg-sign-artifacts.yml@dev-rpm-quadlets secrets: inherit - with: + with: + artifact-name-unsigned-rpms: ${{ env.ARTIFACT_NAME_RPM_UNSIGNED }} artifact-name-signed-rpms: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} artifact-name-public-keys: ${{ env.ARTIFACT_NAME_GPG_KEYS_PUBLIC }} release: needs: rpmsign - uses: OpenCHAMI/github-actions/.github/workflows/release-signed-artifacts.yml@ + uses: OpenCHAMI/github-actions/.github/workflows/release-signed-artifacts.yml@dev-rpm-quadlets secrets: inherit - with: + with: artifact-name-signed-rpms: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} artifact-name-public-keys: ${{ env.ARTIFACT_NAME_GPG_KEYS_PUBLIC }} - From 5aa5b73c75703a05f893d8c76214382006dc7e7d Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Thu, 30 Jul 2026 10:55:16 -0600 Subject: [PATCH 5/7] wip: spotfix Signed-off-by: Sean Tronsen --- .github/workflows/PRBuild.yaml | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml index bc6af14..f56ee18 100644 --- a/.github/workflows/PRBuild.yaml +++ b/.github/workflows/PRBuild.yaml @@ -15,13 +15,23 @@ on: type: string permissions: write-all # Necessary for the generate-build-provenance action with containers -env: - ARTIFACT_NAME_RPM_UNSIGNED: 'rpms-unsigned' - ARTIFACT_NAME_RPM_SIGNED: 'rpms-signed' - ARTIFACT_NAME_GPG_KEYS_PUBLIC: 'gpg-public-keys' - jobs: + config: + runs-on: ubuntu-latest + outputs: + rpm-unsigned: ${{ steps.names.outputs.rpm-unsigned }} + rpm-signed: ${{ steps.names.outputs.rpm-signed }} + keys-public: ${{ steps.names.outputs.keys-public }} + steps: + - id: names + run: | + { + echo "rpm-unsigned=rpms-unsigned" + echo "rpm-signed=rpms-signed" + echo "keys-public=public-keys" + } >> "$GITHUB_OUTPUT" + build: uses: OpenCHAMI/github-actions/.github/workflows/build-publish-container-goreleaser.yml@dev-rpm-quadlets secrets: inherit @@ -32,23 +42,23 @@ jobs: pr_number: ${{ inputs.pr_number || github.event.pull_request.number || 0 }} rpmbuild: - needs: build + needs: [config, build] uses: OpenCHAMI/github-actions/.github/workflows/build-rpm-quadlet.yml@dev-rpm-quadlets secrets: inherit with: - artifact-name-unsigned-rpms: ${{ env.ARTIFACT_NAME_RPM_UNSIGNED }} + artifact-name-unsigned-rpms: ${{ needs.config.outputs.rpm-unsigned }} rpmsign: - needs: rpmbuild + needs: [config, rpmbuild] uses: OpenCHAMI/github-actions/.github/workflows/gpg-sign-artifacts.yml@dev-rpm-quadlets secrets: inherit with: - artifact-name-unsigned-rpms: ${{ env.ARTIFACT_NAME_RPM_UNSIGNED }} - artifact-name-signed-rpms: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} - artifact-name-public-keys: ${{ env.ARTIFACT_NAME_GPG_KEYS_PUBLIC }} + artifact-name-unsigned-rpms: ${{ needs.config.outputs.rpm-unsigned }} + artifact-name-signed-rpms: ${{ needs.config.outputs.rpm-signed }} + artifact-name-public-keys: ${{ needs.config.outputs.keys-public }} rpmvalidate: - needs: rpmsign + needs: [config, rpmsign] runs-on: ubuntu-latest container: image: rockylinux:9 @@ -68,7 +78,7 @@ jobs: - name: Download signed RPM artifacts uses: actions/download-artifact@v8 with: - name: ${{ env.ARTIFACT_NAME_RPM_SIGNED }} + name: ${{ needs.config.outputs.rpm-signed }} path: dist/rpms - name: Find Quadlet RPM From 2d272bda1facecbcf09991801405f38c1d86238a Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Thu, 30 Jul 2026 11:03:22 -0600 Subject: [PATCH 6/7] refactor/abstract away common rpm validation logic Signed-off-by: Sean Tronsen --- .github/workflows/PRBuild.yaml | 57 ++++++---------------------------- 1 file changed, 10 insertions(+), 47 deletions(-) diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml index f56ee18..ef21b1f 100644 --- a/.github/workflows/PRBuild.yaml +++ b/.github/workflows/PRBuild.yaml @@ -32,6 +32,7 @@ jobs: echo "keys-public=public-keys" } >> "$GITHUB_OUTPUT" + build: uses: OpenCHAMI/github-actions/.github/workflows/build-publish-container-goreleaser.yml@dev-rpm-quadlets secrets: inherit @@ -59,50 +60,12 @@ jobs: rpmvalidate: needs: [config, rpmsign] - runs-on: ubuntu-latest - container: - image: rockylinux:9 - steps: - - - name: Install build dependencies - run: dnf install -y -q git rpmlint tar gzip - - - name: Mark workspace as a safe git directory - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - - - uses: actions/checkout@v6.0.2 - with: - fetch-tags: true - fetch-depth: 0 - - - name: Download signed RPM artifacts - uses: actions/download-artifact@v8 - with: - name: ${{ needs.config.outputs.rpm-signed }} - path: dist/rpms - - - name: Find Quadlet RPM - run: | - set -euo pipefail - - quadlet_rpm=$(find . -type f -iname "*.rpm" | head -n 1) - if [ -z "${quadlet_rpm}" ]; then - echo "could not locate quadlet rpm file" - exit 1 - fi - - echo "using QUADLET_RPM_PATH=${quadlet_rpm}" - echo "QUADLET_RPM_PATH=${quadlet_rpm}" >> "$GITHUB_ENV" - - - - name: Verify installed file list is exactly what's expected - run: | - rpm -qlp "${QUADLET_RPM_PATH}" | sort > /tmp/actual-files.txt - cat /tmp/actual-files.txt - sort > /tmp/expected-files.txt <<'EOF' - /usr/share/containers/systemd/metadata-data.volume - /usr/share/containers/systemd/metadata-service.container - /usr/share/licenses/metadata-service - /usr/share/licenses/metadata-service/MIT.txt - EOF - diff /tmp/expected-files.txt /tmp/actual-files.txt + uses: OpenCHAMI/github-actions/.github/workflows/validate-rpm-quadlet.yml@dev-rpm-quadlets + secrets: inherit + with: + artifact-name-signed-rpms: ${{ needs.config.outputs.rpm-signed }} + expected-files: | + /usr/share/containers/systemd/metadata-data.volume + /usr/share/containers/systemd/metadata-service.container + /usr/share/licenses/metadata-service + /usr/share/licenses/metadata-service/MIT.txt From 0812ab3ee92da1aaa0ff98eebe72726ce5b9156e Mon Sep 17 00:00:00 2001 From: Sean Tronsen Date: Thu, 30 Jul 2026 11:48:30 -0600 Subject: [PATCH 7/7] wip: job trigger Signed-off-by: Sean Tronsen --- .github/workflows/PRBuild.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml index ef21b1f..04f35fd 100644 --- a/.github/workflows/PRBuild.yaml +++ b/.github/workflows/PRBuild.yaml @@ -32,7 +32,6 @@ jobs: echo "keys-public=public-keys" } >> "$GITHUB_OUTPUT" - build: uses: OpenCHAMI/github-actions/.github/workflows/build-publish-container-goreleaser.yml@dev-rpm-quadlets secrets: inherit