Skip to content

fix: Use our issue tracker for kernel panic QR code #80

fix: Use our issue tracker for kernel panic QR code

fix: Use our issue tracker for kernel panic QR code #80

Workflow file for this run

name: Build (fedora)
on:
workflow_dispatch:
inputs:
version:
description: 'Enter a tagged OGC kernel version in the format <kernel-version>-ogc<rev>'
required: true
push:
tags:
- 'v*'
env:
OCI_REPO: ghcr.io/${{ github.repository }}-fedora
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-rpm:
strategy:
fail-fast: false
matrix:
target:
- id: fc43
image: 'fedora:43'
- id: fc44
image: 'fedora:44'
- id: el10
image: 'quay.io/centos/centos:stream10'
base_config_fedora: '43'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
attestations: write
artifact-metadata: write
container:
image: ${{ matrix.target.image }}
volumes:
- /usr:/usr-host
- /opt:/opt-host
options: --privileged
steps:
- name: Prepare environment
shell: bash
run: |
# Lowercase the image uri
echo "OCI_REPO=${OCI_REPO,,}" >> ${GITHUB_ENV}
- name: Maximize build space
run: |
df -h
rm -rf /usr-host/share/dotnet
rm -rf /usr-host/share/swift
rm -rf /usr-host/share/java
rm -rf /usr-host/local/lib/android
rm -rf /opt-host/ghc
rm -rf /opt-host/hostedtoolcache
rm -rf /opt-host/az
df -h
- name: Checkout sources
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Get version
id: version
shell: bash
run: |
if [ -n "${{ github.event.inputs.version }}" ]; then
OGC_VERSION="${{ github.event.inputs.version }}"
else
TAG="${{ github.ref_name }}"
OGC_VERSION="${TAG#v}"
fi
KERNEL_VERSION="${OGC_VERSION%-ogc*}"
if [[ "$KERNEL_VERSION" == *-lts ]]; then
IS_LTS=true
KERNEL_VERSION="${KERNEL_VERSION%-lts}"
else
IS_LTS=false
fi
if [[ "$KERNEL_VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
echo "::warning::Kernel version '$KERNEL_VERSION' from '$OGC_VERSION' is missing its sublevel; building as ${KERNEL_VERSION}.0. Use the full x.y.z version when tagging so the artifact tag matches the package version."
KERNEL_VERSION="${KERNEL_VERSION}.0"
elif ! [[ "$KERNEL_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ || "$KERNEL_VERSION" =~ ^[0-9]+\.[0-9]+-rc[0-9]+$ ]]; then
echo "::error::Invalid kernel version '$KERNEL_VERSION' from '$OGC_VERSION': expected x.y.z or x.y-rcN"
exit 1
fi
MAJOR_VERSION="${KERNEL_VERSION%%.*}.x"
OGC_REV="${OGC_VERSION##*-ogc}"
if [[ "$KERNEL_VERSION" == *-rc* ]]; then
# Mainline release candidates (x.y-rcN) have no stable sublevel
IS_RC=true
RC_VER="${KERNEL_VERSION##*-}"
BASE_KVER="${KERNEL_VERSION%-rc*}"
STABLE_KVER="0"
TAR_KVER="$KERNEL_VERSION"
else
IS_RC=false
RC_VER="none"
BASE_KVER="${KERNEL_VERSION%.*}"
STABLE_KVER="${KERNEL_VERSION##*.}"
if [ "$STABLE_KVER" = "0" ]; then
TAR_KVER="$BASE_KVER"
else
TAR_KVER="$KERNEL_VERSION"
fi
fi
if [ "$IS_RC" = "true" ]; then
STREAM_TAG=""
elif [ "$IS_LTS" = "true" ]; then
STREAM_TAG="lts"
else
STREAM_TAG="latest"
fi
echo "ogc_version=$OGC_VERSION" >> "$GITHUB_OUTPUT"
echo "kernel_version=$KERNEL_VERSION" >> "$GITHUB_OUTPUT"
echo "major_version=$MAJOR_VERSION" >> "$GITHUB_OUTPUT"
echo "ogc_rev=$OGC_REV" >> "$GITHUB_OUTPUT"
echo "base_kver=$BASE_KVER" >> "$GITHUB_OUTPUT"
echo "stable_kver=$STABLE_KVER" >> "$GITHUB_OUTPUT"
echo "tar_kver=$TAR_KVER" >> "$GITHUB_OUTPUT"
echo "is_rc=$IS_RC" >> "$GITHUB_OUTPUT"
echo "rc_ver=$RC_VER" >> "$GITHUB_OUTPUT"
echo "stream_tag=$STREAM_TAG" >> "$GITHUB_OUTPUT"
- name: Setup ORAS
uses: oras-project/setup-oras@22ce207df3b08e061f537244349aac6ae1d214f6 # v1
- name: Enable EL repositories
if: startsWith(matrix.target.id, 'el')
shell: bash
run: |
set -euo pipefail
# EL ships dnf 4, so use dnf-plugins-core rather than dnf5-plugins.
# kabi-dw, asciidoc, xmlto and libbabeltrace-devel live in EPEL;
# the -devel packages perf needs live in CRB.
dnf -y install dnf-plugins-core
dnf config-manager --set-enabled crb
dnf -y install epel-release
- name: Fetch base kernel config
shell: bash
env:
BASE_CONFIG_FEDORA: ${{ matrix.target.base_config_fedora }}
run: |
set -euo pipefail
CACHE="${GITHUB_WORKSPACE}/pkgcache"
mkdir -p "$CACHE"
if [ -n "${BASE_CONFIG_FEDORA:-}" ]; then
# This target is not Fedora, but wants Fedora's config as its
# base, so pull kernel-core straight from the Fedora mirrors
# instead of the container's own repos. --nogpgcheck is safe
# here: nothing is installed, we only extract the config file.
dnf -y install cpio
MIRROR="https://dl.fedoraproject.org/pub/fedora/linux"
dnf download --destdir "$CACHE" --nogpgcheck \
--repofrompath "fedora,${MIRROR}/releases/${BASE_CONFIG_FEDORA}/Everything/x86_64/os/" \
--repofrompath "updates,${MIRROR}/updates/${BASE_CONFIG_FEDORA}/Everything/x86_64/" \
--repo fedora --repo updates \
kernel-core
else
dnf -y install dnf5-plugins cpio
dnf download --destdir "$CACHE" kernel-core
fi
RPM=$(find "$CACHE" -maxdepth 1 -name 'kernel-core-*.rpm' -type f)
if [ "$(printf '%s\n' "$RPM" | wc -l)" -ne 1 ] || [ -z "$RPM" ]; then
echo "::error::Expected exactly one kernel-core package, found: ${RPM:-none}"
exit 1
fi
echo "::notice::Base config from $(basename "$RPM")"
CFG=$(rpm -qlp "$RPM" | grep -E '^/lib/modules/[^/]+/config$' || true)
if [ "$(printf '%s\n' "$CFG" | wc -l)" -ne 1 ] || [ -z "$CFG" ]; then
echo "::error::Expected exactly one kernel config in $RPM, found: ${CFG:-none}"
exit 1
fi
rpm2cpio "$RPM" | cpio -i --to-stdout ".${CFG}" > distro-base.config
if [ ! -s distro-base.config ]; then
echo "::error::Extracted kernel config is empty"
exit 1
fi
rm -rf "$CACHE"
- name: Compute content hash
id: content-hash
shell: bash
run: |
HASH=$(
{
echo "ogc_version=${{ steps.version.outputs.ogc_version }}"
echo "target=${{ matrix.target.id }}"
sha256sum \
fedora/kernel.spec \
distro-base.config \
fedora/kvm_stat.logrotate \
config/fedora.config.set \
config/ogc.config.set \
config/fedora.config.unset \
config/ogc.config.unset \
.github/workflows/fedora.yaml
} | sha256sum | cut -d' ' -f1
)
SHORT_HASH="${HASH:0:12}"
echo "hash=$SHORT_HASH" >> "$GITHUB_OUTPUT"
echo "Content hash: $SHORT_HASH"
- name: Check for existing build
id: check-existing
shell: bash
run: |
REPO="${OCI_REPO,,}"
TAG="sha-${{ steps.content-hash.outputs.hash }}-${{ matrix.target.id }}"
if oras manifest fetch "${REPO}:${TAG}" > /dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "::notice::Skipping build, artifact with content hash ${TAG} already exists"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "No existing artifact for ${TAG}, proceeding with build"
fi
- name: Get build number
if: steps.check-existing.outputs.exists != 'true'
id: buildnum
shell: bash
run: |
VERSION_PREFIX="${{ steps.version.outputs.ogc_version }}"
REPO="${OCI_REPO,,}"
EXISTING=$(oras repo tags "${REPO}" 2>/dev/null || true)
EXISTING=$(echo "$EXISTING" | { grep -cE "^${VERSION_PREFIX}\.[0-9]+-${{ matrix.target.id }}$" || true; })
BUILD_NUM=$((EXISTING + 1))
echo "build_num=$BUILD_NUM" >> "$GITHUB_OUTPUT"
echo "Build number: $BUILD_NUM"
- name: Substitute versions
if: steps.check-existing.outputs.exists != 'true'
shell: bash
run: |
sed -i \
-e "s/@@BASEKVER@@/${{ steps.version.outputs.base_kver }}/" \
-e "s/@@STABLEKVER@@/${{ steps.version.outputs.stable_kver }}/" \
-e "s/@@RCVER@@/${{ steps.version.outputs.rc_ver }}/" \
-e "s/@@OGCVER@@/${{ steps.version.outputs.ogc_rev }}/" \
-e "s/@@BUILDNUM@@/${{ steps.buildnum.outputs.build_num }}/" \
fedora/kernel.spec
- name: Dependencies
if: steps.check-existing.outputs.exists != 'true'
run: |
dnf -y builddep fedora/kernel.spec
dnf -y install git gnupg2 jq sed wget
- name: Build dwarves from source
if: steps.check-existing.outputs.exists != 'true'
shell: bash
run: |
# Fedora ships pahole 1.30, which breaks sched_ext. Fixed in 1.31.
dnf -y install cmake make gcc elfutils-devel zlib-devel
wget https://fedorapeople.org/~acme/dwarves/dwarves-1.31.tar.xz
echo "0a7f255ccacf8cc7f8cd119099eb327179b4b3c67cb015af646af6d0cb03054d dwarves-1.31.tar.xz" | sha256sum -c
tar -xf dwarves-1.31.tar.xz
cmake -B dwarves-1.31/build -S dwarves-1.31 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-D__LIB=lib
make -C dwarves-1.31/build -j"$(nproc)" install
command -v pahole
pahole --version
- name: Download and verify kernel source
if: steps.check-existing.outputs.exists != 'true'
shell: bash
run: |
TAR_KVER="${{ steps.version.outputs.tar_kver }}"
MAJOR_VERSION="${{ steps.version.outputs.major_version }}"
OGC_VERSION="${{ steps.version.outputs.ogc_version }}"
IS_RC="${{ steps.version.outputs.is_rc }}"
wget https://github.com/OpenGamingCollective/linux/releases/download/v${OGC_VERSION}/monolithic.patch
wget https://github.com/OpenGamingCollective/linux/releases/download/v${OGC_VERSION}/monolithic.patch.sig
KORG_KEYS="https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/plain/keys"
for KEY in ABAF11C65A2970B130ABE3C479BE3E4300411886:79BE3E4300411886 \
647F28654894E3BD457199BE38DBBDC86092693E:38DBBDC86092693E; do
KEYID="${KEY#*:}"
wget -O "${KEYID}.asc" "${KORG_KEYS}/${KEYID}.asc"
gpg --import "${KEYID}.asc"
# Confirm the key landed under its expected full fingerprint
gpg --list-keys "${KEY%:*}" > /dev/null
done
# Import OGC patch signing key
gpg --import $GITHUB_WORKSPACE/public.key
if [ "$IS_RC" = "true" ]; then
# kernel.org publishes no tarball or detached signature for
# mainline release candidates, so build the tarball from the
# signed git tag instead
git clone --depth=1 --branch v${TAR_KVER} \
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git \
linux-${TAR_KVER}.git
git -C linux-${TAR_KVER}.git verify-tag v${TAR_KVER}
git -C linux-${TAR_KVER}.git archive --format=tar \
--prefix=linux-${TAR_KVER}/ v${TAR_KVER} \
| xz -T0 -0 > linux-${TAR_KVER}.tar.xz
rm -rf linux-${TAR_KVER}.git
else
wget https://cdn.kernel.org/pub/linux/kernel/v${MAJOR_VERSION}/linux-${TAR_KVER}.tar.xz
wget https://cdn.kernel.org/pub/linux/kernel/v${MAJOR_VERSION}/linux-${TAR_KVER}.tar.sign
# Verify kernel tarball signature
xz -dc linux-${TAR_KVER}.tar.xz | gpg --verify linux-${TAR_KVER}.tar.sign -
fi
# Verify OGC monolithic patch signature
gpg --verify monolithic.patch.sig monolithic.patch
tar -xf linux-${TAR_KVER}.tar.xz
cd linux-${TAR_KVER}
patch -Np1 < ../monolithic.patch
- name: Merge kernel configuration files
if: steps.check-existing.outputs.exists != 'true'
uses: OpenGamingCollective/kernel-configurator@5b4abc58a2edf89941180dbbe33b26415db23b0b # v1.0.1
with:
config: distro-base.config
set: |
config/fedora.config.set
config/ogc.config.set
unset: |
config/fedora.config.unset
config/ogc.config.unset
output: linux-${{ steps.version.outputs.tar_kver }}/.config
- name: Validate combined kernel config file
if: steps.check-existing.outputs.exists != 'true'
shell: bash
run: |
cd linux-${{ steps.version.outputs.tar_kver }}
make olddefconfig
- name: Build
if: steps.check-existing.outputs.exists != 'true'
run: |
TAR_KVER="${{ steps.version.outputs.tar_kver }}"
TOPDIR="$(pwd)/rpmbuild"
mkdir -p "$TOPDIR"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
# Pre-populate SOURCES with already-downloaded files
cp linux-${TAR_KVER}.tar.xz "$TOPDIR/SOURCES/"
cp monolithic.patch "$TOPDIR/SOURCES/"
cp fedora/kvm_stat.logrotate "$TOPDIR/SOURCES/"
# Copy patched config
cp linux-${TAR_KVER}/.config "$TOPDIR/SOURCES/config"
rpmbuild --define "_topdir $TOPDIR" -ba ./fedora/kernel.spec
- name: Setup Cosign
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
- name: Login to ghcr.io
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | oras login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push OCI artifact
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
id: push
run: |
VERSION="${{ steps.version.outputs.ogc_version }}.${{ steps.buildnum.outputs.build_num }}"
REPO="${{ env.OCI_REPO }}"
TOPDIR="$(pwd)/rpmbuild"
mkdir -p /tmp/rpms
cp "$TOPDIR"/RPMS/x86_64/*.rpm /tmp/rpms/ 2>/dev/null || true
cp "$TOPDIR"/RPMS/noarch/*.rpm /tmp/rpms/ 2>/dev/null || true
cd /tmp/rpms
DIGEST=$(oras push --format json "${REPO}:${VERSION}-${{ matrix.target.id }}" ./*.rpm | jq -r '.digest')
if [ -z "$DIGEST" ]; then
echo "::error::Failed to capture digest from oras push"
exit 1
fi
STREAM_TAG="${{ steps.version.outputs.stream_tag }}"
if [ -n "$STREAM_TAG" ]; then
oras tag "${REPO}:${VERSION}-${{ matrix.target.id }}" "${STREAM_TAG}-${{ matrix.target.id }}"
fi
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
- name: Tag with content hash
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
run: |
REPO="${{ env.OCI_REPO }}"
VERSION="${{ steps.version.outputs.ogc_version }}.${{ steps.buildnum.outputs.build_num }}"
oras tag "${REPO}:${VERSION}-${{ matrix.target.id }}" \
"sha-${{ steps.content-hash.outputs.hash }}-${{ matrix.target.id }}"
- name: Sign artifacts
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
run: |
VERSION="${{ steps.version.outputs.ogc_version }}.${{ steps.buildnum.outputs.build_num }}"
REPO="${{ env.OCI_REPO }}"
STREAM_TAG="${{ steps.version.outputs.stream_tag }}"
cosign sign --yes "${REPO}:${VERSION}-${{ matrix.target.id }}"
if [ -n "$STREAM_TAG" ]; then
cosign sign --yes "${REPO}:${STREAM_TAG}-${{ matrix.target.id }}"
fi
- name: Attest build provenance
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4
with:
subject-name: ${{ env.OCI_REPO }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
- name: Verify signature
if: startsWith(github.ref, 'refs/tags/') && steps.check-existing.outputs.exists != 'true'
run: |
VERSION="${{ steps.version.outputs.ogc_version }}.${{ steps.buildnum.outputs.build_num }}"
REPO="${{ env.OCI_REPO }}"
cosign verify \
--certificate-identity-regexp=".*" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
"${REPO}:${VERSION}-${{ matrix.target.id }}"