Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 90 additions & 69 deletions .github/workflows/build-rpm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,18 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Import GPG key
run: |
echo "$GPG_PRIVATE_KEY" | base64 --decode | gpg --import --batch --yes
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}

- name: Show signing subkey expiration
shell: bash
run: |
gpg --list-secret-keys --with-colons \
| awk -F: '
$1=="ssb" && $12 ~ /s/ {
keyid = $5
expires = $7
if (expires == "" || expires == "0") {
edate = "never"
} else {
cmd = "date -u -d @" expires " +\"%Y-%m-%d %H:%M:%S UTC\""
cmd | getline edate
close(cmd)
}
printf "signing subkey %s expires: %s\n", keyid, edate
}
'
- name: Check signing subkey expiration
uses: OpenCHAMI/gpg-signing-manager/actions/check-subkey-expiration@main
with:
subkey-armored-b64: ${{ secrets.GPG_SUBKEY_B64 }}
warn-days: '30'

- name: Setup RPM signing
id: repo_key
uses: OpenCHAMI/gpg-signing-manager/actions/setup-rpm-signing@main
with:
subkey-armored-b64: ${{ secrets.GPG_SUBKEY_B64 }}
public-key-output: public_gpg_key.asc

- name: Get version
id: get_version
Expand All @@ -70,6 +58,7 @@ jobs:
VERSION=0.0.0
fi
echo "VERSION=${VERSION}" >> $GITHUB_ENV
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Version is ${VERSION}"

- name: Setup RPM build environment
Expand All @@ -80,109 +69,141 @@ jobs:

- name: Create source tarball
run: |
mkdir -p ~/rpmbuild/SOURCES/openchami-${{ env.VERSION }}
cp -r ./* ~/rpmbuild/SOURCES/openchami-${{ env.VERSION }}/
tar -czf ~/rpmbuild/SOURCES/openchami-${{ env.VERSION }}.tar.gz \
-C ~/rpmbuild/SOURCES openchami-${{ env.VERSION }} \
--transform "s|openchami-${{ env.VERSION }}-${{ env.COMMIT_SHA }}|openchami-${{ env.VERSION }}|"
mkdir -p ~/rpmbuild/SOURCES/openchami-${VERSION}
cp -r ./* ~/rpmbuild/SOURCES/openchami-${VERSION}/
tar -czf ~/rpmbuild/SOURCES/openchami-${VERSION}.tar.gz \
-C ~/rpmbuild/SOURCES openchami-${VERSION}
Comment on lines -83 to +75
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to replace ${VERSION} here with ${{ steps.get_version.outputs.version }} here so we can get rid of the echo "VERSION=${VERSION}" >> $GITHUB_ENV above? Just to reduce redundancy. I noticed that the latter is used below, but there is still some mixing of the two.


- name: Sign source tarball
env:
GPG_SIGNING_KEYID: ${{ steps.repo_key.outputs.repo-signing-keyid }}
GPG_SIGNING_FINGERPRINT: ${{ steps.repo_key.outputs.repo-signing-fingerprint }}
run: |
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 --pinentry-mode loopback \
set -euo pipefail
unset GPG_TTY
echo "Signing source tarball with key: ${GPG_SIGNING_KEYID} (${GPG_SIGNING_FINGERPRINT})"
gpg --batch --list-secret-keys --keyid-format LONG "${GPG_SIGNING_FINGERPRINT}"
gpg --batch --yes \
--no-tty --pinentry-mode loopback \
--armor --detach-sign \
--local-user admin@openchami.org \
--output ~/rpmbuild/SOURCES/openchami-${{ env.VERSION }}.tar.gz.asc \
~/rpmbuild/SOURCES/openchami-${{ env.VERSION }}.tar.gz
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
--local-user "${GPG_SIGNING_KEYID}" \
--output ~/rpmbuild/SOURCES/openchami-${VERSION}.tar.gz.asc \
~/rpmbuild/SOURCES/openchami-${VERSION}.tar.gz

- name: Build RPM package
run: |
rpmbuild -ba ~/rpmbuild/SPECS/*.spec \
--define "version ${{ env.VERSION }}" \
--define "version $VERSION" \
--define "rel 1"

- name: Sign RPM packages
run: |
for rpm in $(find ~/rpmbuild/RPMS/ -type f -name "*.rpm"); do
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 --pinentry-mode loopback \
--detach-sign --armor "$rpm"
rpm --define "_gpg_name admin@openchami.org" --addsign "$rpm"
done
shell: bash
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
GPG_SIGNING_KEYID: ${{ steps.repo_key.outputs.repo-signing-keyid }}
GPG_SIGNING_FINGERPRINT: ${{ steps.repo_key.outputs.repo-signing-fingerprint }}
run: |
set -euo pipefail
unset GPG_TTY
echo "Using RPM signing key: ${GPG_SIGNING_KEYID} (${GPG_SIGNING_FINGERPRINT})"
gpg --batch --list-secret-keys --keyid-format LONG "${GPG_SIGNING_FINGERPRINT}"
echo 'Configured ~/.rpmmacros:'
cat ~/.rpmmacros

found=0
while IFS= read -r -d '' rpm_file; do
found=1
echo "Signing RPM: $rpm_file"
rpmsign --key-id "${GPG_SIGNING_KEYID}" --addsign "$rpm_file"
done < <(find ~/rpmbuild/RPMS/ -type f -name "*.rpm" -print0)

if [ "$found" -eq 0 ]; then
echo 'No RPM packages were produced to sign' >&2
exit 1
fi

- name: Verify RPM signatures
shell: bash
run: |
found=0
while IFS= read -r -d '' rpm_file; do
found=1
output=$(rpm --checksig -v "$rpm_file" 2>&1)
printf '%s\n' "$output"

if printf '%s\n' "$output" | grep -q 'SIGNATURES NOT OK'; then
echo "RPM signature verification failed for $rpm_file" >&2
exit 1
fi

if ! printf '%s\n' "$output" | grep -Eiq 'Key ID|RSA/SHA|RSA/sha|EdDSA|pgp'; then
echo "RPM appears unsigned: $rpm_file" >&2
exit 1
fi
done < <(find ~/rpmbuild/RPMS/ -type f -name "*.rpm" -print0)

if [ "$found" -eq 0 ]; then
echo 'No RPM packages were produced to verify' >&2
exit 1
fi

- name: Find RPM file
if: env.VERSION != '0.0.0'
if: steps.get_version.outputs.version != '0.0.0'
id: find_rpm
run: |
rpm_file=$(ls ~/rpmbuild/RPMS/noarch/*.rpm)
echo "rpm_file=${rpm_file}" >> $GITHUB_ENV
echo "::set-output name=path::${rpm_file}"
echo "path=${rpm_file}" >> "$GITHUB_OUTPUT"

- name: Compute RPM Checksum
if: env.VERSION != '0.0.0'
if: steps.get_version.outputs.version != '0.0.0'
id: compute_checksum
run: |
rpm_file=$(ls ~/rpmbuild/RPMS/noarch/*.rpm)
checksum=$(sha256sum "$rpm_file" | awk '{print $1}')
echo "checksum=${checksum}" >> $GITHUB_ENV
echo "::set-output name=checksum::${checksum}"

- name: Export Public GPG Key
if: env.VERSION != '0.0.0'
run: |
gpg --armor --export admin@openchami.org > public_gpg_key.asc

- name: Get Public GPG Key Content
if: env.VERSION != '0.0.0'
id: get_pubkey
run: |
key=$(cat public_gpg_key.asc)
escaped_key=$(echo "$key" | sed ':a;N;$!ba;s/\n/\\n/g')
echo "::set-output name=pubkey::${escaped_key}"
echo "checksum=${checksum}" >> "$GITHUB_OUTPUT"

- name: Genereate release notes
if: env.VERSION != '0.0.0'
if: steps.get_version.outputs.version != '0.0.0'
id: gen_rel_notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
{
echo '# OpenCHAMI v${{ env.VERSION }}'
echo '# OpenCHAMI v${{ steps.get_version.outputs.version }}'
echo ''
echo '**RPM SHA256 Checksum:**'
echo '`${{ steps.compute_checksum.outputs.checksum }}`'
echo ''
gh api "repos/${GITHUB_REPOSITORY}/releases/generate-notes" -F tag_name='v${{ env.VERSION }}' --jq .body
gh api "repos/${GITHUB_REPOSITORY}/releases/generate-notes" -F tag_name='v${{ steps.get_version.outputs.version }}' --jq .body
} > CHANGELOG.md

- name: Create GitHub Release
if: env.VERSION != '0.0.0'
if: steps.get_version.outputs.version != '0.0.0'
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ env.VERSION }}
release_name: v${{ env.VERSION }}
tag_name: v${{ steps.get_version.outputs.version }}
release_name: v${{ steps.get_version.outputs.version }}
draft: false
prerelease: false
body_path: CHANGELOG.md

- name: Upload RPM to GitHub Release
if: env.VERSION != '0.0.0'
if: steps.get_version.outputs.version != '0.0.0'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ steps.find_rpm.outputs.path }}
asset_name: openchami-${{ env.VERSION }}.rpm
asset_name: openchami-${{ steps.get_version.outputs.version }}.rpm
asset_content_type: application/x-rpm

- name: Upload Public GPG Key to GitHub Release
if: env.VERSION != '0.0.0'
if: steps.get_version.outputs.version != '0.0.0'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ Clean built RPMs in repo directory:
make clean
```

## Automated RPM Signing

The GitHub release workflow signs built RPMs with the repository signing subkey
stored in the `GPG_SUBKEY_B64` repository secret. The workflow also exports the
matching ASCII-armored public key as a release asset so downstream consumers can
verify the published RPM signature.

## Current Release

OpenCHAMI is in development without an initial release. We expect a first supported release in Q1 2025. If you would like to follow the most current, stable configuration, each of the partners maintains a deployment recipe that will become a release candidate in our [Deployment Recipes](https://github.com/OpenCHAMI/deployment-recipes) Repository.
Expand Down
Loading