Skip to content

Harden test network cleanup and sweep orphaned iptables rules #1869

Harden test network cleanup and sweep orphaned iptables rules

Harden test network cleanup and sweep orphaned iptables rules #1869

Workflow file for this run

name: Test
on:
push: {}
jobs:
test:
runs-on: [self-hosted, linux, x64, kvm]
steps:
- uses: actions/checkout@v4
with:
clean: false
- name: Clean workspace (preserve binary caches)
run: |
git reset --hard HEAD
git clean -ffdx \
-e lib/vmm/binaries/ \
-e lib/hypervisor/firecracker/binaries/ \
-e lib/ingress/binaries/ \
-e bin/
- name: Set up Go
uses: actions/setup-go@v6
with:
# Not necessary to upload cache on self-hosted runner(s)
# ~/go/pkg/mod and ~/.cache/go-build stay on disk between runs automatically.
cache: false
go-version: '1.25.4'
- name: Check UFFD pager version
run: |
git fetch origin main --depth=1
bash scripts/check-uffd-version.sh origin/main
- name: Install dependencies
run: |
set -xe
apt_update_with_retry() {
local attempts=5
local sleep_seconds=30
local n=1
while [ "$n" -le "$attempts" ]; do
if timeout 120s sudo apt-get update; then
return 0
fi
if [ "$n" -eq "$attempts" ]; then
return 1
fi
echo "apt-get update failed (attempt ${n}/${attempts}); retrying in ${sleep_seconds}s..."
sleep "$sleep_seconds"
n=$((n + 1))
done
}
if ! command -v mkfs.erofs &> /dev/null || \
! command -v mkfs.ext4 &> /dev/null || \
! command -v iptables &> /dev/null || \
! command -v qemu-system-x86_64 &> /dev/null || \
! qemu-system-x86_64 --version >/dev/null 2>&1; then
apt_update_with_retry
timeout 300s sudo apt-get install -y erofs-utils e2fsprogs iptables qemu-system-x86 qemu-utils
fi
go mod download
- name: Verify Linux test toolchain
run: |
set -euo pipefail
TEST_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"
for bin in mkfs.erofs mkfs.ext4 iptables qemu-system-x86_64; do
if ! sudo env "PATH=$TEST_PATH" bash -lc "command -v '$bin' >/dev/null"; then
echo "missing required binary under sudo PATH: $bin"
exit 1
fi
sudo env "PATH=$TEST_PATH" bash -lc "command -v '$bin'"
done
# Avoids rate limits when running the tests
# Tests includes pulling, then converting to disk images
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Generate OpenAPI code
run: make oapi-generate
- name: Build
run: make build
- name: Install UFFD pager systemd template
run: |
sudo mkdir -p /run/hypeman/uffd
sudo tee /etc/systemd/system/hypeman-uffd@.service > /dev/null <<'EOF'
[Unit]
Description=Hypeman UFFD Pager (%i)
Documentation=https://github.com/kernel/hypeman
After=network.target
[Service]
Type=simple
Environment="HYPEMAN_UFFD_BINARY=/opt/hypeman/bin/hypeman-uffd-pager"
Environment="HYPEMAN_UFFD_DATA_DIR=/var/lib/hypeman"
Environment="HYPEMAN_UFFD_VERSION_KEY=%i"
Environment="HYPEMAN_UFFD_CACHE_MAX_BYTES=4294967296"
EnvironmentFile=-/run/hypeman/uffd/%i.env
ExecStart=/bin/sh -c 'exec "$HYPEMAN_UFFD_BINARY" --data-dir "$HYPEMAN_UFFD_DATA_DIR" --version-key "$HYPEMAN_UFFD_VERSION_KEY" --cache-max-bytes "$HYPEMAN_UFFD_CACHE_MAX_BYTES"'
Restart=on-failure
RestartSec=5
KillMode=process
EOF
sudo systemctl daemon-reload
- name: Prewarm test cache
env:
HYPEMAN_TEST_REGISTRY: 127.0.0.1:5001
run: |
export HYPEMAN_TEST_PREWARM_DIR="$HOME/.cache/hypeman-ci/linux-amd64"
go run ./cmd/test-prewarm
- name: Check gofmt
run: |
set -euo pipefail
go_files="$(git ls-files '*.go')"
if [ -z "$go_files" ]; then
exit 0
fi
unformatted="$(echo "$go_files" | xargs gofmt -l)"
if [ -n "$unformatted" ]; then
echo "The following files are not gofmt-formatted:"
echo "$unformatted"
exit 1
fi
- name: Run tests
env:
GO_TEST_TIMEOUT: 600s
# Docker auth for tests running as root (sudo)
DOCKER_CONFIG: /home/debianuser/.docker
# TLS/ACME testing (optional - tests will skip if not configured)
ACME_EMAIL: ${{ secrets.ACME_EMAIL }}
ACME_DNS_PROVIDER: "cloudflare"
ACME_CA: "https://acme-staging-v02.api.letsencrypt.org/directory"
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
TLS_TEST_DOMAIN: "test.hypeman-development.com"
TLS_ALLOWED_DOMAINS: '*.hypeman-development.com'
HYPEMAN_TEST_PREWARM_STRICT: "1"
HYPEMAN_TEST_REGISTRY: 127.0.0.1:5001
HYPEMAN_UFFD_PAGER_BINARY: ${{ runner.temp }}/hypeman-uffd-pager-${{ github.run_id }}-${{ github.run_attempt }}
HYPEMAN_UFFD_SYSTEMD_INSTANCE_PREFIX: ci-${{ github.run_id }}-${{ github.run_attempt }}
run: |
cp "$PWD/bin/hypeman-uffd-pager" "$HYPEMAN_UFFD_PAGER_BINARY"
chmod +x "$HYPEMAN_UFFD_PAGER_BINARY"
export HYPEMAN_TEST_PREWARM_DIR="$HOME/.cache/hypeman-ci/linux-amd64"
make test TEST_TIMEOUT=20m
- name: Cleanup
if: always()
run: |
units="$(systemctl list-units --all --full --plain 'hypeman-uffd@ci-${{ github.run_id }}-${{ github.run_attempt }}-*.service' --no-legend | awk '{print $1}' || true)"
if [ -n "$units" ]; then
echo "$units" | xargs -r sudo systemctl stop || true
echo "$units" | xargs -r sudo systemctl reset-failed || true
fi
sudo rm -f /run/hypeman/uffd/ci-${{ github.run_id }}-${{ github.run_attempt }}-*.env
rm -f "${{ runner.temp }}/hypeman-uffd-pager-${{ github.run_id }}-${{ github.run_attempt }}"
test-darwin:
runs-on: [self-hosted, macos, arm64]
concurrency:
group: macos-ci-test-${{ github.ref }}
cancel-in-progress: true
env:
DATA_DIR: /tmp/hypeman-ci-${{ github.run_id }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v6
with:
go-version: '1.25.4'
cache: false
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Install dependencies
run: |
brew list e2fsprogs &>/dev/null || brew install e2fsprogs
brew list erofs-utils &>/dev/null || brew install erofs-utils
go mod download
- name: Create run-scoped data directory
run: mkdir -p "$DATA_DIR"
- name: Generate OpenAPI code
run: make oapi-generate
- name: Build
run: make build
- name: Prewarm test cache
env:
HYPEMAN_TEST_REGISTRY: 127.0.0.1:5001
run: |
export HYPEMAN_TEST_PREWARM_DIR="$HOME/.cache/hypeman-ci/darwin-arm64"
go run ./cmd/test-prewarm
- name: Check gofmt
run: |
set -euo pipefail
go_files="$(git ls-files '*.go')"
if [ -z "$go_files" ]; then
exit 0
fi
unformatted="$(echo "$go_files" | xargs gofmt -l)"
if [ -n "$unformatted" ]; then
echo "The following files are not gofmt-formatted:"
echo "$unformatted"
exit 1
fi
- name: Run tests
env:
GO_TEST_TIMEOUT: 600s
DEFAULT_HYPERVISOR: vz
JWT_SECRET: ci-test-secret
HYPEMAN_TEST_PREWARM_STRICT: "1"
HYPEMAN_TEST_REGISTRY: 127.0.0.1:5001
run: |
export HYPEMAN_TEST_PREWARM_DIR="$HOME/.cache/hypeman-ci/darwin-arm64"
make test
- name: Cleanup
if: always()
run: |
pkill -f "vz-shim.*$DATA_DIR" || true
rm -rf "$DATA_DIR"
make clean
e2e-install:
runs-on: [self-hosted, macos, arm64]
needs: test-darwin
concurrency:
group: macos-ci-e2e-${{ github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v6
with:
go-version: '1.25.4'
cache: false
- name: Install dependencies
run: brew list caddy &>/dev/null || brew install caddy
- name: Run E2E install test
run: bash scripts/e2e-install-test.sh
- name: Cleanup on failure
if: failure()
run: bash scripts/uninstall.sh || true