Cache Kernels #292
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Cache Kernels | |
on: | |
merge_group: | |
schedule: | |
- cron: "5 0 * * *" # 0005 UTC everyday | |
workflow_dispatch: | |
pull_request: | |
branches: | |
- main | |
paths-ignore: | |
- '.github/workflows/cleanup*.yml' | |
env: | |
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }} | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.fedora_version }} | |
cancel-in-progress: true | |
jobs: | |
build: | |
name: kernel-cache | |
runs-on: ubuntu-24.04 | |
permissions: | |
contents: read | |
packages: write | |
id-token: write | |
strategy: | |
fail-fast: false | |
matrix: | |
kernel_flavor: | |
- asus | |
- fsync | |
- fsync-ba | |
- bazzite | |
- surface | |
- main | |
- coreos-stable | |
- coreos-testing | |
fedora_version: | |
- 39 | |
- 40 | |
- 41 | |
exclude: | |
- fedora_version: 39 | |
kernel_flavor: asus | |
- fedora_version: 39 | |
kernel_flavor: coreos-testing | |
- fedora_version: 39 | |
kernel_flavor: fsync | |
- fedora_version: 39 | |
kernel_flavor: fsync-ba | |
- fedora_version: 41 | |
kernel_flavor: fsync | |
- fedora_version: 41 | |
kernel_flavor: fsync-ba | |
- fedora_version: 39 | |
kernel_flavor: bazzite | |
- fedora_version: 40 | |
kernel_flavor: bazzite | |
- fedora_version: 41 | |
kernel_flavor: coreos-stable | |
- fedora_version: 40 | |
kernel_flavor: coreos-testing | |
- fedora_version: 41 | |
kernel_flavor: surface | |
steps: | |
- name: Checkout Push to Registry action | |
uses: actions/checkout@v4 | |
- name: Pull Image | |
uses: Wandalen/[email protected] | |
with: | |
attempt_limit: 3 | |
attempt_delay: 15000 | |
command: | | |
build_image="quay.io/fedora/fedora:${{ matrix.fedora_version }}" | |
echo "build_image=$build_image" >> "$GITHUB_ENV" | |
podman pull "$build_image" | |
- name: Get Kernel Version | |
id: Version | |
uses: Wandalen/[email protected] | |
with: | |
attempt_limit: 3 | |
attempt_delay: 15000 | |
command: | | |
if [[ ${{ matrix.kernel_flavor }} =~ asus|fsync|fsync-ba|surface ]]; then | |
container_name="fq-$(uuidgen)" | |
dnf="podman exec $container_name dnf" | |
podman run --entrypoint /bin/bash --name "$container_name" -dt "${{ env.build_image }}" | |
$dnf install -y dnf-plugins-core | |
fi | |
coreos_kernel () { | |
coreos_version=${1} | |
image_linux=$(skopeo inspect docker://quay.io/fedora/fedora-coreos:${coreos_version} | jq -r '.Labels["ostree.linux"]') | |
major_minor_patch=$(echo $image_linux | grep -oP '^\d+\.\d+\.\d+') | |
kernel_rel_part=$(echo $image_linux | grep -oP '^\d+\.\d+\.\d+\-\K([123][0]{2})') | |
arch=$(echo $image_linux | grep -oP 'fc\d+\.\K.*$') | |
kernel_rel="$kernel_rel_part.fc${{ matrix.fedora_version }}" | |
kernel_version="$major_minor_patch-$kernel_rel.$arch" | |
URL="https://kojipkgs.fedoraproject.org/packages/kernel/"$major_minor_patch"/"$kernel_rel"/"$arch"/kernel-"$kernel_version".rpm" | |
echo "Querying koji for ${coreos_version} kernel: $kernel_version" | |
echo "$URL" | |
HTTP_RESP=$(curl -sI "$URL" | grep ^HTTP) | |
linux="" | |
if grep -qv "200 OK" <<< "${HTTP_RESP}"; then | |
echo "Koji failed to find $coreos_version kernel: $kernel_version" | |
case "$kernel_rel_part" in | |
"300") | |
kernel_rel_part="200" | |
;; | |
"200") | |
kernel_rel_part="100" | |
;; | |
"100") | |
;; | |
*) | |
echo "unexpected kernel_rel_part ${kernel_rel_part}" | |
;; | |
esac | |
kernel_rel="$kernel_rel_part.fc${{ matrix.fedora_version }}" | |
kernel_version="$major_minor_patch-$kernel_rel.$arch" | |
URL="https://kojipkgs.fedoraproject.org/packages/kernel/"$major_minor_patch"/"$kernel_rel"/"$arch"/kernel-"$kernel_version".rpm" | |
echo "Re-querying koji for ${coreos_version} kernel: $kernel_version" | |
echo "$URL" | |
HTTP_RESP=$(curl -sI "$URL" | grep ^HTTP) | |
if grep -qv "200 OK" <<< "${HTTP_RESP}"; then | |
echo "Koji failed to find $coreos_version kernel: $kernel_version" | |
fi | |
fi | |
if grep -q "200 OK" <<< "${HTTP_RESP}"; then | |
linux=$kernel_version | |
fi | |
} | |
case ${{ matrix.kernel_flavor }} in | |
"asus") | |
$dnf copr enable -y lukenukem/asus-kernel | |
linux=$($dnf repoquery --repoid copr:copr.fedorainfracloud.org:lukenukem:asus-kernel --whatprovides kernel | sort -V | tail -n1 | sed 's/.*://') | |
;; | |
"fsync") | |
$dnf copr enable -y sentry/kernel-fsync | |
linux=$($dnf repoquery --repoid copr:copr.fedorainfracloud.org:sentry:kernel-fsync --whatprovides kernel | sort -V | tail -n1 | sed 's/.*://') | |
;; | |
"fsync-ba") | |
$dnf copr enable -y sentry/kernel-ba | |
linux=$($dnf repoquery --repoid copr:copr.fedorainfracloud.org:sentry:kernel-ba --whatprovides kernel | sort -V | tail -n1 | sed 's/.*://') | |
;; | |
"bazzite") | |
latest="$(curl "https://api.github.com/repos/hhd-dev/kernel-bazzite/releases/latest" )" | |
linux=$(echo -E "$latest" | jq -r '.assets[].name' | grep -E 'kernel-.*.rpm' | grep "fc${{ matrix.fedora_version }}.x86_64" | head -1 | sed "s/kernel-//g" | sed "s/.rpm//g" ) | |
build_tag=$(echo -E $latest | jq -r '.tag_name') | |
;; | |
"surface") | |
$dnf config-manager --add-repo=https://pkg.surfacelinux.com/fedora/linux-surface.repo | |
linux=$($dnf repoquery --repoid linux-surface --whatprovides kernel-surface | sort -V | tail -n1 | sed 's/.*://') | |
;; | |
"main") | |
linux=$(skopeo inspect docker://quay.io/fedora-ostree-desktops/base:${{ matrix.fedora_version }} | jq -r '.Labels["ostree.linux"]' ) | |
;; | |
"coreos-stable") | |
coreos_kernel stable | |
;; | |
"coreos-testing") | |
coreos_kernel testing | |
;; | |
*) | |
echo "unexpected kernel_flavor '${{ matrix.kernel_flavor }}' for query" | |
;; | |
esac | |
if [ -z "$linux" ] || [ "null" = "$linux" ]; then | |
echo "inspected image linux version must not be empty or null" | |
exit 1 | |
fi | |
major=$(echo "$linux" | cut -d '.' -f 1) | |
minor=$(echo "$linux" | cut -d '.' -f 2) | |
patch=$(echo "$linux" | cut -d '.' -f 3) | |
kernel_major_minor_patch="${major}.${minor}.${patch}" | |
echo "Kernel Version is ${linux}" | |
echo "kernel_release=${linux}" >> $GITHUB_ENV | |
echo "kernel_build_tag=${build_tag}" >> $GITHUB_ENV | |
echo "kernel_major_minor_patch=${kernel_major_minor_patch}" >> $GITHUB_ENV | |
- name: Generate Tags | |
id: generate_tags | |
shell: bash | |
run: | | |
tag="${{ env.kernel_release }}" | |
short_tag=$(echo ${{ env.kernel_major_minor_patch }} | cut -d "-" -f 1) | |
COMMIT_TAGS=() | |
COMMIT_TAGS+=("pr-${{ github.event.number }}-${{ matrix.fedora_version }}") | |
COMMIT_TAGS+=("pr-${{ github.event.number }}-${{ matrix.fedora_version }}-${short_tag}") | |
COMMIT_TAGS+=("pr-${{ github.event.number }}-${{ matrix.fedora_version }}-${tag}") | |
COMMIT_TAGS+=("pr-${{ github.event.number }}-${tag}") | |
COMMIT_TAGS+=("${GITHUB_SHA::7}-${{ matrix.fedora_version }}") | |
COMMIT_TAGS+=("${GITHUB_SHA::7}-${{ matrix.fedora_version }}-${short_tag}") | |
COMMIT_TAGS+=("${GITHUB_SHA::7}-${{ matrix.fedora_version }}-${tag}") | |
COMMIT_TAGS+=("${GITHUB_SHA::7}-${tag}") | |
BUILD_TAGS=() | |
BUILD_TAGS+=("${{ matrix.fedora_version }}") | |
BUILD_TAGS+=(${{ matrix.fedora_version }}-${short_tag}) | |
BUILD_TAGS+=(${{ matrix.fedora_version }}-${tag}) | |
BUILD_TAGS+=(${tag}) | |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
# echo "Generated the following commit tags: " | |
# for TAG in "${COMMIT_TAGS[@]}"; do | |
# echo "${TAG}" | |
# done | |
alias_tags=("${COMMIT_TAGS[@]}") | |
else | |
alias_tags=("${BUILD_TAGS[@]}") | |
fi | |
echo "Generated the following tags: " | |
for TAG in "${alias_tags[@]}"; do | |
echo "${TAG}" | |
done | |
echo "alias_tags=${alias_tags[*]}" >> $GITHUB_OUTPUT | |
echo "date=$(date '+%Y%m%d.0')" >> $GITHUB_ENV | |
- name: Build Metadata | |
uses: docker/metadata-action@v5 | |
id: meta | |
with: | |
images: | | |
${{ matrix.kernel_flavor }}-kernel | |
labels: | | |
org.opencontainers.image.title=${{ matrix.kernel_flavor }} cached kernel | |
org.opencontainers.image.description=A caching layer for kernels. Contains ${{ matrix.kernel_flavor }} kernel. | |
org.opencontainers.image.version=${{ env.kernel_release}}.${{ env.date }} | |
ostree.linux=${{ env.kernel_release }} | |
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ github.repository }}/main/README.md | |
io.artifacthub.package.logo-url=https://avatars.githubusercontent.com/u/1728152?s=200&v=4 | |
- name: Retrieve Signing Key | |
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group' | |
shell: bash | |
run: | | |
mkdir -p certs | |
if [[ "${{ github.event_name }}" == 'pull_request' ]]; then | |
echo "This should not have run... exiting..." | |
exit 1 | |
else | |
echo "${{ secrets.KERNEL_PRIVKEY }}" > certs/private_key.priv | |
echo "${{ secrets.AKMOD_PRIVKEY_20230518 }}" > certs/private_key_2.priv | |
# DEBUG: get character count of key | |
wc -c certs/private_key.priv | |
wc -c certs/private_key_2.priv | |
fi | |
- name: Build Image | |
id: build_image | |
uses: redhat-actions/buildah-build@v2 | |
with: | |
containerfiles: | | |
./Containerfile | |
image: ${{ matrix.kernel_flavor }}-kernel | |
tags: ${{ steps.generate_tags.outputs.alias_tags }} | |
build-args: | | |
FEDORA_VERSION=${{ matrix.fedora_version }} | |
KERNEL_VERSION=${{ env.kernel_release }} | |
KERNEL_BUILD_TAG=${{ env.kernel_build_tag }} | |
KERNEL_FLAVOR=${{ matrix.kernel_flavor }} | |
DUAL_SIGN=true | |
labels: ${{ steps.meta.outputs.labels }} | |
oci: false | |
- name: Check Secureboot Signatures | |
shell: bash | |
run: | | |
set -x | |
if [[ ! $(command -v sbverify) || ! $(command -v curl) || ! $(command -v openssl) || ! $(command -v rpm2cpio) ]]; then | |
sudo apt update | |
sudo apt install sbsigntool curl openssl rpm2cpio | |
fi | |
podman create --name "${{ matrix.kernel_flavor}}"-kernel-"$(echo "${{ steps.generate_tags.outputs.alias_tags }}" | cut -d " " -f 1)" "${{ matrix.kernel_flavor}}"-kernel:$(echo "${{ steps.generate_tags.outputs.alias_tags }}" | cut -d " " -f 1) sh | |
podman export "${{ matrix.kernel_flavor}}"-kernel-"$(echo "${{ steps.generate_tags.outputs.alias_tags }}" | cut -d " " -f 1)" > /tmp/"${{ matrix.kernel_flavor}}"-kernel-"$(echo "${{ steps.generate_tags.outputs.alias_tags }}" | cut -d " " -f 1)".tar | |
tar xvf /tmp/"${{ matrix.kernel_flavor}}"-kernel-"$(echo "${{ steps.generate_tags.outputs.alias_tags }}" | cut -d " " -f 1)".tar -C /tmp | |
cd /tmp/tmp/rpms/ | |
if [[ "${{ matrix.kernel_flavor }}" == "surface" ]]; then | |
rpm2cpio kernel-surface-core-"${{ env.kernel_release }}".rpm | cpio -idmv | |
else | |
rpm2cpio kernel-core-"${{ env.kernel_release }}".rpm | cpio -idmv | |
fi | |
cd ./lib/modules/"${{ env.kernel_release }}"/ | |
sbverify --list vmlinuz | |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
curl --retry 3 -Lo kernel-sign.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key.der.test | |
curl --retry 3 -Lo akmods.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key_2.der.test | |
else | |
curl --retry 3 -Lo kernel-sign.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key.der | |
curl --retry 3 -Lo akmods.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key_2.der | |
fi | |
openssl x509 -in kernel-sign.der -out kernel-sign.crt | |
openssl x509 -in akmods.der -out akmods.crt | |
sbverify --cert kernel-sign.crt vmlinuz || exit 1 | |
sbverify --cert akmods.crt vmlinuz || exit 1 | |
cd $HOME | |
- name: Lowercase Registry | |
id: registry_case | |
uses: ASzc/change-string-case-action@v6 | |
with: | |
string: ${{ env.IMAGE_REGISTRY }} | |
- name: Push to GHCR | |
uses: Wandalen/[email protected] | |
id: push | |
if: github.event_name != 'pull_request' | |
env: | |
REGISTRY_USER: ${{ github.actor }} | |
REGISTRY_PASSWORD: ${{ github.token }} | |
with: | |
action: redhat-actions/push-to-registry@v2 | |
attempt_limit: 3 | |
attempt_delay: 15000 | |
with: | | |
image: ${{ steps.build_image.outputs.image }} | |
tags: ${{ steps.build_image.outputs.tags }} | |
registry: ${{ steps.registry_case.outputs.lowercase }} | |
username: ${{ env.REGISTRY_USER }} | |
password: ${{ env.REGISTRY_PASSWORD }} | |
extra-args: | | |
--disable-content-trust | |
- name: Login to GitHub Container Registry | |
uses: docker/login-action@v3 | |
if: github.event_name != 'pull_request' | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
# Sign container | |
- uses: sigstore/[email protected] | |
if: github.event_name != 'pull_request' | |
- name: Sign container image | |
if: github.event_name != 'pull_request' | |
run: | | |
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${{ steps.registry_case.outputs.lowercase }}/${{ steps.build_image.outputs.image }}@${TAGS} | |
env: | |
TAGS: ${{ steps.push.outputs.outputs && fromJSON(steps.push.outputs.outputs).digest }} | |
COSIGN_EXPERIMENTAL: false | |
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }} | |
- name: Echo outputs | |
if: github.event_name != 'pull_request' | |
run: | | |
echo "${{ toJSON(steps.push.outputs) }}" | |
check: | |
name: Check all builds successful | |
runs-on: ubuntu-latest | |
needs: [build] | |
steps: | |
- name: Exit on failure | |
if: ${{ needs.build.result == 'failure' }} | |
shell: bash | |
run: exit 1 | |
- name: Exit | |
shell: bash | |
run: exit 0 |