diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66e2481..ee028cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,3 +87,70 @@ jobs: ECROU_BIN: ${{ github.workspace }}/target/release/ecrou LD_LIBRARY_PATH: /tmp/engine run: cargo test -p ecrou-cli -- --ignored + + snap: + name: snap build + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + # The same pack the release workflow publishes. Building it on + # every change keeps the snap from rotting between tags: the + # cargo part, the libkrun build, and the libkrunfw digest pins + # all break here first. + - uses: snapcore/action-build@v1 + id: build + + - uses: actions/upload-artifact@v4 + with: + name: snap-amd64 + path: ${{ steps.build.outputs.snap }} + + e2e: + name: snap e2e — apt install + needs: snap + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/download-artifact@v4 + with: + name: snap-amd64 + path: snap + + - name: Install the snap + run: | + test -c /dev/kvm || { echo "::error::no /dev/kvm on this runner"; exit 1; } + test -w /dev/kvm || sudo chmod 666 /dev/kvm + sudo snap install --dangerous ./snap/*.snap + sudo snap connect ecrou:kvm + + # Diagnostics for whatever fails below: KVM state, the engine + # load from the snap's staged libraries, the cache directory. + - name: Probe + run: ecrou probe || true + + # T8's first half, on the packaged binary: a guest kernel that + # differs from the host's, inside strict confinement. Fast, so a + # broken environment fails here instead of deep in the apt run. + - name: Smoke — boot alpine under confinement + run: | + set -euo pipefail + guest="$(timeout 10m ecrou run -q alpine -- uname -r | tail -n 1)" + host="$(uname -r)" + echo "guest kernel: $guest / host kernel: $host" + test -n "$guest" && test "$guest" != "$host" + + # T8's second half: a real package install end to end — apt + # through the TSI proxy, mkfs and debugfs through the snap's + # staged e2fsprogs, the payload's exit code back through the + # control file. The ln driver's known throughput limit makes + # this the long pole; how long it takes is the standing + # re-measurement the Networking section calls for on every + # engine update. + - name: apt update && install fastfetch + run: | + set -euo pipefail + timeout 35m ecrou run -q -e DEBIAN_FRONTEND=noninteractive ubuntu -- \ + "apt update && apt install -y fastfetch && fastfetch" | tee /tmp/e2e.log + grep -E "^OS:" /tmp/e2e.log diff --git a/SPEC.md b/SPEC.md index c2eb5ce..6d391ca 100644 --- a/SPEC.md +++ b/SPEC.md @@ -269,6 +269,14 @@ stop: with shares: zero hits. This test is the founding rule. - **T7, guest network.** An https fetch from the guest succeeds, DNS included; a published port is reachable from the host. +- **T8, snap e2e.** CI builds the snap and runs `ecrou run -q -e + DEBIAN_FRONTEND=noninteractive ubuntu -- "apt update && apt install + -y fastfetch && fastfetch"` inside it: strict confinement, KVM + through the plug, the staged e2fsprogs, apt across the TSI proxy, + and the payload's exit code back through the control file. A boot + of alpine (`uname -r` differing from the host's) runs before it so + a broken environment fails fast. The apt wall time is the standing + re-measurement of the ln driver's throughput. ## Snap packaging