name: Replacement boot and rollback proof
run-name: Replacement boot and rollback proof ${{ inputs.source_sha || github.sha }}
on:
push:
branches: [main]
paths:
- .github/workflows/replacement-boot-proof.yml
- scripts/run-boot-replacement-vm.sh
- src/**
- nss/**
- compat/upstream-systemd/**
- Cargo.toml
- Cargo.lock
- build.rs
workflow_dispatch:
inputs:
source_sha:
description: Full Git commit to prove; blank selects the dispatch ref
required: false
type: string
permissions:
contents: read
statuses: write
jobs:
prove:
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Check out exact source
uses: actions/checkout@v4
with:
ref: ${{ inputs.source_sha || github.sha }}
fetch-depth: 1
- name: Verify exact source identity
shell: bash
env:
REQUESTED_SHA: ${{ inputs.source_sha || github.sha }}
run: |
set -euo pipefail
[[ $REQUESTED_SHA =~ ^[0-9a-f]{40}$ ]]
test "$(git rev-parse HEAD)" = "$REQUESTED_SHA"
- name: Install build and QEMU dependencies
shell: bash
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install --yes --no-install-recommends \
debootstrap \
gfortran \
libssl-dev \
liburing-dev \
mtools \
ovmf \
pipx \
python3-pefile \
qemu-system-x86 \
qemu-utils \
systemd-boot
pipx install 'git+https://github.com/systemd/mkosi.git'
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Verify pinned upstream baseline
run: bash scripts/verify-upstream-resolved-baseline.sh
- name: Build release candidate
run: |
cargo build --release --locked
make -C nss all
- name: Boot candidate twice and verify rollback
shell: bash
run: |
set -euo pipefail
export PATH="$HOME/.local/bin:$PATH"
bash scripts/run-boot-replacement-vm.sh \
--binary target/release/systemd-resolved \
--client target/release/resolvectl \
--nss-module nss/libnss_resolve.so.2 \
--output target/boot-replacement-vm
- name: Write bound boot proof
shell: bash
run: |
set -euo pipefail
mkdir -p proof
cp target/boot-replacement-vm/mkosi-build.log proof/
cp target/boot-replacement-vm/qemu-console.log proof/
cp target/boot-replacement-vm/evidence.json proof/
python3 scripts/write-replacement-proof.py \
--gate boot-replacement \
--result pass \
--output proof/boot-replacement.json \
--artifact proof/mkosi-build.log \
--artifact proof/qemu-console.log \
--artifact proof/evidence.json \
--metadata environment=qemu \
--metadata boot-count=2 \
--metadata rollback-verified=true \
--summary 'The candidate daemon, client, and NSS module survived two QEMU boots and the distro resolver rollback was healthy.'
- name: Upload bound boot proof
uses: actions/upload-artifact@v4
with:
name: replacement-boot-proof-${{ inputs.source_sha || github.sha }}
path: proof
if-no-files-found: error
retention-days: 30
- name: Upload boot failure evidence
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: replacement-boot-failure-${{ inputs.source_sha || github.sha }}
path: target/boot-replacement-vm
if-no-files-found: ignore
retention-days: 14
report:
name: Publish boot proof status
if: ${{ always() }}
needs: [prove]
runs-on: ubuntu-24.04
steps:
- name: Publish exact-source status
env:
GH_TOKEN: ${{ github.token }}
SOURCE_SHA: ${{ inputs.source_sha || github.sha }}
RESULT: ${{ needs.prove.result }}
run: |
set -euo pipefail
state=failure
if [[ "$RESULT" == success ]]; then
state=success
fi
payload=$(printf '{"state":"%s","context":"replacement/boot-proof","description":"Boot and rollback proof %s","target_url":"%s"}' "$state" "$state" "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}")
curl --fail-with-body --silent --show-error -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GH_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/statuses/${SOURCE_SHA}" \
--data "$payload" >/dev/null