mirror of
https://github.com/ublue-os/akmods.git
synced 2026-11-03 23:09:54 -09:00
391 lines
16 KiB
YAML
391 lines
16 KiB
YAML
name: build-akmod
|
|
run-name: "Build ${{ inputs.akmods_target != 'common' && format('akmods-{0}', inputs.akmods_target) || 'akmods' }}:${{ inputs.kernel_flavor }}-${{ inputs.version }}"
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
akmods_target:
|
|
description: "The akmods to build: common, zfs, nvidia-lts, nvidia-open"
|
|
required: true
|
|
type: string
|
|
architecture:
|
|
description: "JSON string of architectures to build, '[aarch64, x86_64]'"
|
|
default: "['x86_64']"
|
|
required: false
|
|
type: string
|
|
kernel_flavor:
|
|
description: "The Kernel flavor: main, coreos-stable, longterm-6.12, etc"
|
|
required: true
|
|
type: string
|
|
version:
|
|
description: "Release Version: 10, 41, 42, etc"
|
|
required: true
|
|
type: string
|
|
kernel_cache_key:
|
|
description: "The Key for the Kernel Cache"
|
|
required: true
|
|
type: string
|
|
force:
|
|
description: "Force a build, ignoring the fingerprint guard"
|
|
default: false
|
|
required: false
|
|
type: boolean
|
|
workflow_dispatch:
|
|
inputs:
|
|
akmods_target:
|
|
description: "The akmods to build: common, zfs, nvidia-lts, nvidia-open"
|
|
required: true
|
|
type: string
|
|
architecture:
|
|
description: "JSON string of architectures to build, '[aarch64, x86_64]'"
|
|
default: "['x86_64']"
|
|
required: false
|
|
type: string
|
|
kernel_flavor:
|
|
description: "The Kernel flavor: main, coreos-stable, longterm-6.12, etc"
|
|
required: true
|
|
type: string
|
|
version:
|
|
description: "Release Version: 10, 41, 42, etc"
|
|
required: true
|
|
type: string
|
|
kernel_cache_key:
|
|
description: "The Key for the Kernel Cache"
|
|
required: true
|
|
type: string
|
|
force:
|
|
description: "Force a build, ignoring the fingerprint guard"
|
|
default: false
|
|
required: false
|
|
type: boolean
|
|
env:
|
|
AKMODS_KERNEL: ${{ inputs.kernel_flavor }}
|
|
AKMODS_TARGET: ${{ inputs.akmods_target }}
|
|
AKMODS_VERSION: ${{ inputs.version }}
|
|
KCKEY: ${{ inputs.kernel_cache_key }}
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.version }}-${{ inputs.kernel_flavor }}-${{ inputs.akmods_target }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build-akmods:
|
|
name: Build ${{ matrix.architecture }}
|
|
runs-on: ${{ matrix.architecture == 'x86_64' && 'ubuntu-26.04' || 'ubuntu-26.04-arm' }}
|
|
permissions:
|
|
actions: read
|
|
contents: read
|
|
packages: write
|
|
container:
|
|
image: "ghcr.io/ublue-os/devcontainer:latest@sha256:1c42755a3ab617139cc68e65248609eb2033de0e9ab5219746082ea192a182d8"
|
|
options: "--privileged --volume /:/host-sys --volume /var/lib/containers:/var/lib/containers --security-opt seccomp=unconfined --security-opt label=disable --user 0:0"
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
architecture: ${{ fromJson(inputs.architecture) }}
|
|
steps:
|
|
- name: Checkout Repo
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Mark Directory as Safe
|
|
run: git config --system --add safe.directory "$GITHUB_WORKSPACE"
|
|
|
|
- name: Export GITHUB_WORKSPACE
|
|
id: gh-workspace
|
|
run: echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Cache Kernel RPMs
|
|
id: cache-kernel
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ${{ steps.gh-workspace.outputs.GITHUB_WORKSPACE }}/build/${{ env.AKMODS_KERNEL }}-${{ env.AKMODS_VERSION }}/KCWD/rpms
|
|
fail-on-cache-miss: true
|
|
key: ${{ env.KCKEY }}-${{ matrix.architecture }}
|
|
restore-keys: |
|
|
${{ matrix.architecture }}-${{ env.KCKEY }}
|
|
${{ matrix.architecture }}-${{ env.AKMODS_KERNEL }}
|
|
|
|
- name: Install Cosign
|
|
continue-on-error: true
|
|
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
with:
|
|
cosign-release: "v3.1.4"
|
|
|
|
# Every event prepares the snapshot, so test and build pin the same inputs
|
|
- name: Prepare Fingerprint
|
|
continue-on-error: true
|
|
run: just fingerprint || just fingerprint-clear
|
|
|
|
- name: Check if build needed
|
|
id: guard
|
|
continue-on-error: true
|
|
env:
|
|
AKMODS_FORCE_BUILD: ${{ inputs.force || github.event_name == 'pull_request' }}
|
|
AKMODS_MAX_AGE_DAYS: ${{ vars.AKMODS_MAX_AGE_DAYS }}
|
|
run: just build-needed
|
|
|
|
- name: Maximize build space
|
|
if: ${{ !(steps.guard.outcome == 'success' && steps.guard.outputs.skip == 'true') }}
|
|
shell: bash
|
|
run: |
|
|
set -xeuo pipefail
|
|
df -h
|
|
# Remove host toolchains, browsers
|
|
shopt -s nullglob
|
|
printf '/host-sys%s\0' /opt/PyPy /opt/az /opt/node/ /opt/pipx /opt/go /opt/Ruby \
|
|
/usr/lib/llvm-* /usr/local/julia* /usr/local/lib/android /usr/share/dotnet \
|
|
/usr/share/swift /usr/local/.ghcup /usr/lib/firefox /opt/google/chrome \
|
|
/opt/microsoft/msedge \
|
|
| xargs -0 -n1 -P4 rm -rf
|
|
df -h
|
|
|
|
- name: Retrieve Signing Key
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name) && !(steps.guard.outcome == 'success' && steps.guard.outputs.skip == 'true')
|
|
shell: bash
|
|
run: |
|
|
mkdir -p certs
|
|
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
|
|
|
|
- name: Test Image
|
|
if: ${{ !(steps.guard.outcome == 'success' && steps.guard.outputs.skip == 'true') }}
|
|
run: just test
|
|
|
|
- name: Build Image
|
|
if: ${{ !(steps.guard.outcome == 'success' && steps.guard.outputs.skip == 'true') }}
|
|
run: just build
|
|
|
|
- name: Push and Sign Image
|
|
if: (contains(fromJson('["schedule", "merge_group"]'), github.event_name) || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')) && !(steps.guard.outcome == 'success' && steps.guard.outputs.skip == 'true')
|
|
run: |
|
|
just login
|
|
just push
|
|
env:
|
|
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
|
|
REGISTRY_ACTOR: ${{ github.actor }}
|
|
REGISTRY_TOKEN: ${{ github.token }}
|
|
|
|
manifest:
|
|
name: "Generate ${{ inputs.akmods_target != 'common' && format('akmods-{0}', inputs.akmods_target) || 'akmods' }}:${{ inputs.kernel_flavor }}-${{ inputs.version }} Manifest"
|
|
runs-on: ubuntu-26.04
|
|
needs: [build-akmods]
|
|
outputs:
|
|
image_name: ${{ steps.digest.outputs.image_name }}
|
|
manifest: ${{ steps.digest.outputs.manifest }}
|
|
manifest_kernel: ${{ steps.digest.outputs.manifest_kernel }}
|
|
container:
|
|
image: "ghcr.io/ublue-os/devcontainer:latest@sha256:1c42755a3ab617139cc68e65248609eb2033de0e9ab5219746082ea192a182d8"
|
|
options: "--privileged --volume /var/lib/containers:/var/lib/containers --security-opt seccomp=unconfined --security-opt label=disable --user 0:0"
|
|
permissions:
|
|
actions: read
|
|
attestations: write
|
|
contents: read
|
|
id-token: write
|
|
packages: write
|
|
steps:
|
|
- name: Exit on failure
|
|
if: needs.build-akmods.result != 'success'
|
|
run: exit 1
|
|
|
|
- name: Checkout Repo
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Mark Directory as Safe
|
|
run: git config --system --add safe.directory "$GITHUB_WORKSPACE"
|
|
|
|
- name: Export GITHUB_WORKSPACE
|
|
id: gh-workspace
|
|
run: echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Cache Kernel RPMs
|
|
id: cache-kernel
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ${{ steps.gh-workspace.outputs.GITHUB_WORKSPACE }}/build/${{ env.AKMODS_KERNEL }}-${{ env.AKMODS_VERSION }}/KCWD/rpms
|
|
key: ${{ env.KCKEY }}-x86_64
|
|
restore-keys: |
|
|
${{ env.KCKEY }}-aarch64
|
|
|
|
- name: Install Cosign
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name)
|
|
continue-on-error: true
|
|
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
with:
|
|
cosign-release: "v3.1.4"
|
|
|
|
# Attestations and digests always run, so provenance gets repaired even when this skips
|
|
- name: Check if manifest needed
|
|
id: manifest-guard
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name)
|
|
continue-on-error: true
|
|
run: just manifest-needed
|
|
|
|
- name: Generate Manifest
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name) && !(steps.manifest-guard.outcome == 'success' && steps.manifest-guard.outputs.skip == 'true')
|
|
run: |
|
|
just login
|
|
just manifest
|
|
env:
|
|
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
|
|
REGISTRY_ACTOR: ${{ github.actor }}
|
|
REGISTRY_TOKEN: ${{ github.token }}
|
|
|
|
- name: Get Manifest Digests
|
|
id: digest
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name)
|
|
run: |
|
|
IMAGE_NAME="${{ inputs.akmods_target != 'common' && format('akmods-{0}', inputs.akmods_target) || 'akmods' }}"
|
|
MANIFEST_TAG="${{ inputs.kernel_flavor }}-${{ inputs.version }}"
|
|
KERNEL_RELEASE="$(jq -r '.kernel_release' < "$GITHUB_WORKSPACE/build/${{ env.AKMODS_KERNEL }}-${{ env.AKMODS_VERSION }}/KCWD/rpms/cache.json" | sed 's/\.x86_64\|\.aarch64//g')"
|
|
MANIFEST_TAG_KERNEL="${MANIFEST_TAG}-${KERNEL_RELEASE}"
|
|
|
|
DIGEST="$(skopeo inspect --format '{{.Digest}}' "docker://ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${MANIFEST_TAG}")"
|
|
echo "manifest=${DIGEST}" >> "$GITHUB_OUTPUT"
|
|
|
|
DIGEST_KERNEL="$(skopeo inspect --format '{{.Digest}}' "docker://ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${MANIFEST_TAG_KERNEL}")"
|
|
echo "manifest_kernel=${DIGEST_KERNEL}" >> "$GITHUB_OUTPUT"
|
|
|
|
echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Attest Manifest Image
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name)
|
|
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4
|
|
with:
|
|
subject-name: ghcr.io/${{ github.repository_owner }}/${{ steps.digest.outputs.image_name }}
|
|
subject-digest: ${{ steps.digest.outputs.manifest }}
|
|
push-to-registry: false
|
|
|
|
- name: Attest Manifest Kernel Image
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name)
|
|
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4
|
|
with:
|
|
subject-name: ghcr.io/${{ github.repository_owner }}/${{ steps.digest.outputs.image_name }}
|
|
subject-digest: ${{ steps.digest.outputs.manifest_kernel }}
|
|
push-to-registry: false
|
|
|
|
verify-publication:
|
|
name: Verify Published Signatures and Provenance
|
|
runs-on: ubuntu-26.04
|
|
needs: [manifest]
|
|
if: contains(fromJson('["schedule", "workflow_dispatch", "merge_group"]'), github.event_name)
|
|
permissions:
|
|
actions: read
|
|
attestations: write
|
|
contents: read
|
|
id-token: write
|
|
packages: read
|
|
steps:
|
|
- name: Checkout Repo
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Install Skopeo
|
|
shell: bash
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install --yes skopeo
|
|
command -v skopeo
|
|
skopeo --version
|
|
|
|
- name: Install Cosign
|
|
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
with:
|
|
cosign-release: "v3.1.4"
|
|
|
|
- name: Verify Published Subjects
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
IMAGE: ghcr.io/${{ github.repository_owner }}/${{ needs.manifest.outputs.image_name }}
|
|
MANIFEST_DIGEST: ${{ needs.manifest.outputs.manifest }}
|
|
MANIFEST_KERNEL_DIGEST: ${{ needs.manifest.outputs.manifest_kernel }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
cosign version
|
|
command -v gh
|
|
gh --version
|
|
|
|
retry() {
|
|
local attempt
|
|
for attempt in 1 2 3 4 5; do
|
|
"$@" && return 0
|
|
if [[ "$attempt" -eq 5 ]]; then
|
|
return 1
|
|
fi
|
|
sleep $((attempt * 5))
|
|
done
|
|
}
|
|
|
|
verify_cosign() {
|
|
local image="$1"
|
|
retry cosign verify --key cosign.pub "$image"
|
|
retry cosign verify --new-bundle-format=false --key cosign.pub "$image"
|
|
}
|
|
|
|
policy_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$policy_dir"' EXIT
|
|
cat > "$policy_dir/policy.json" <<'EOF'
|
|
{
|
|
"default": [{"type": "reject"}],
|
|
"transports": {
|
|
"docker": {
|
|
"ghcr.io/ublue-os/akmods": [{"type": "sigstoreSigned", "keyPath": "cosign.pub", "signedIdentity": {"type": "matchRepository"}}],
|
|
"ghcr.io/ublue-os/akmods-nvidia-lts": [{"type": "sigstoreSigned", "keyPath": "cosign.pub", "signedIdentity": {"type": "matchRepository"}}],
|
|
"ghcr.io/ublue-os/akmods-nvidia-open": [{"type": "sigstoreSigned", "keyPath": "cosign.pub", "signedIdentity": {"type": "matchRepository"}}],
|
|
"ghcr.io/ublue-os/akmods-zfs": [{"type": "sigstoreSigned", "keyPath": "cosign.pub", "signedIdentity": {"type": "matchRepository"}}],
|
|
"ghcr.io/ublue-os/akmods-extra": [{"type": "sigstoreSigned", "keyPath": "cosign.pub", "signedIdentity": {"type": "matchRepository"}}]
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
mkdir "$policy_dir/registries.d"
|
|
cat > "$policy_dir/registries.d/ghcr.yaml" <<'EOF'
|
|
docker:
|
|
ghcr.io:
|
|
use-sigstore-attachments: true
|
|
EOF
|
|
|
|
verify_policy() {
|
|
local image="$1"
|
|
local destination
|
|
destination="$(mktemp -d)"
|
|
retry skopeo copy --policy "$policy_dir/policy.json" --registries.d "$policy_dir/registries.d" "$image" "dir:$destination"
|
|
rm -rf "$destination"
|
|
}
|
|
|
|
manifest_tag="${{ inputs.kernel_flavor }}-${{ inputs.version }}"
|
|
subjects=(
|
|
"$IMAGE@$MANIFEST_DIGEST"
|
|
"$IMAGE@$MANIFEST_KERNEL_DIGEST"
|
|
)
|
|
for architecture in $(jq -r '.[]' <<'EOF'
|
|
${{ inputs.architecture }}
|
|
EOF
|
|
); do
|
|
release_digest="$(retry skopeo inspect --format '{{.Digest}}' "docker://$IMAGE:${manifest_tag}-${architecture}")"
|
|
subjects+=("$IMAGE@$release_digest")
|
|
done
|
|
|
|
for subject in "${subjects[@]}"; do
|
|
verify_cosign "$subject"
|
|
verify_policy "docker://$subject"
|
|
done
|
|
|
|
unsigned="quay.io/fedora/fedora-bootc@sha256:0cb32268d1a864801a6edc4032506f50f385d9f49c0b68a4eebecaaa555ecce6"
|
|
if cosign verify --key cosign.pub "$unsigned"; then
|
|
exit 1
|
|
fi
|
|
if cosign verify --new-bundle-format=false --key cosign.pub "$unsigned"; then
|
|
exit 1
|
|
fi
|
|
unsigned_destination="$(mktemp -d)"
|
|
if skopeo copy --policy "$policy_dir/policy.json" --registries.d "$policy_dir/registries.d" "docker://$unsigned" "dir:$unsigned_destination"; then
|
|
rm -rf "$unsigned_destination"
|
|
exit 1
|
|
fi
|
|
rm -rf "$unsigned_destination"
|
|
|
|
retry gh attestation verify "oci://$IMAGE@$MANIFEST_DIGEST" --repo ublue-os/akmods
|
|
retry gh attestation verify "oci://$IMAGE@$MANIFEST_KERNEL_DIGEST" --repo ublue-os/akmods
|