Research-Stack/4-Infrastructure/servo-fetch/.github/workflows/test-smoke.yml

160 lines
5.5 KiB
YAML

name: Smoke test
on:
workflow_dispatch:
inputs:
ref:
description: "Branch or tag to validate"
required: true
default: "main"
permissions:
contents: read
jobs:
validate:
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-24.04
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
- target: aarch64-apple-darwin
os: macos-latest
- target: x86_64-apple-darwin
os: macos-15-intel
- target: x86_64-pc-windows-msvc
os: windows-2022
env:
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
ref: ${{ inputs.ref }}
- uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
with:
toolchain: "1.95.0"
targets: ${{ matrix.target }}
- uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- name: Configure sccache
shell: bash
run: |
{
echo "SCCACHE_GHA_ENABLED=true"
echo "RUSTC_WRAPPER=sccache"
echo "CCACHE=sccache"
} >> "$GITHUB_ENV"
- name: Install system dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y cmake clang llvm pkg-config libfontconfig-dev libfreetype-dev \
libssl-dev libglib2.0-dev libegl1-mesa-dev \
xvfb libegl1 libgles2 libgl1-mesa-dri mesa-utils \
libfontconfig1 libfreetype6 libharfbuzz0b libx11-6 libxcb1 libxcb-render0 libxcb-shape0 libxcb-xfixes0
- name: Set LIBCLANG_PATH (Windows)
if: runner.os == 'Windows'
shell: bash
run: printf 'LIBCLANG_PATH=C:\\Program Files\\LLVM\\bin\n' >> "$GITHUB_ENV"
- name: Build release binary
run: cargo build --release --locked --target ${{ matrix.target }}
- name: Bundle Windows ANGLE DLLs
if: runner.os == 'Windows'
shell: bash
run: |
set -eu
shopt -s failglob
BIN_DIR="target/${TARGET}/release"
cp "$BIN_DIR"/build/mozangle-*/out/libEGL.dll "$BIN_DIR"/
cp "$BIN_DIR"/build/mozangle-*/out/libGLESv2.dll "$BIN_DIR"/
- name: Smoke (L1 — CLI, deterministic, no network)
shell: bash
env:
RUNNER_OS_NAME: ${{ runner.os }}
run: |
set -euo pipefail
BIN="target/${TARGET}/release/servo-fetch"
[[ "$RUNNER_OS_NAME" == "Windows" ]] && BIN="$BIN.exe"
ERR="$RUNNER_TEMP/err.log"
"$BIN" --version | grep -q '^servo-fetch '
"$BIN" --help >/dev/null
# Each URL must be rejected *with a specific validation message* — not a crash.
# Messages mirror src/net.rs::validate_url exactly.
check() {
local url=$1 want=$2
if "$BIN" "$url" 2>"$ERR"; then
echo "FAIL: $url was accepted" >&2; cat "$ERR" >&2; exit 1
fi
grep -qE "$want" "$ERR" || {
echo "FAIL: $url rejected without expected message: $want" >&2
cat "$ERR" >&2; exit 1
}
}
check 'file:///etc/passwd' "scheme 'file' not allowed"
check 'http://127.0.0.1' 'access to private/local addresses is not allowed: 127\.0\.0\.1'
check 'http://169.254.169.254/latest/meta-data/' 'access to private/local addresses is not allowed: 169\.254\.169\.254'
- name: Smoke (L2 — network, in-shell retry)
shell: bash
env:
RUNNER_OS_NAME: ${{ runner.os }}
run: |
set -eux -o pipefail
BIN="target/${TARGET}/release/servo-fetch"
[[ "$RUNNER_OS_NAME" == "Windows" ]] && BIN="$BIN.exe"
if [[ "$RUNNER_OS_NAME" == "Linux" ]]; then
XVFB=(xvfb-run --auto-servernum --server-args="-screen 0 1280x800x24")
else
XVFB=()
fi
for i in 1 2 3; do
"${XVFB[@]+"${XVFB[@]}"}" "$BIN" 'https://example.com' | grep -q 'Example Domain' && exit 0
echo "attempt $i failed; sleeping 15s" >&2
sleep 15
done
exit 1
- name: Smoke (L3 — full scenarios, non-blocking)
continue-on-error: true
shell: bash
env:
RUNNER_OS_NAME: ${{ runner.os }}
run: |
set -eux -o pipefail
BIN="target/${TARGET}/release/servo-fetch"
[[ "$RUNNER_OS_NAME" == "Windows" ]] && BIN="$BIN.exe"
if [[ "$RUNNER_OS_NAME" == "Linux" ]]; then
XVFB=(xvfb-run --auto-servernum --server-args="-screen 0 1280x800x24")
else
XVFB=()
fi
SHOT="$RUNNER_TEMP/shot.png"
"${XVFB[@]+"${XVFB[@]}"}" "$BIN" --json 'https://example.com' \
| python3 -c 'import json,sys; json.load(sys.stdin)'
sleep 2
"${XVFB[@]+"${XVFB[@]}"}" "$BIN" --screenshot "$SHOT" 'https://example.com'
head -c 8 "$SHOT" | cmp -s - <(printf '\x89PNG\r\n\x1a\n')
sleep 2
"${XVFB[@]+"${XVFB[@]}"}" "$BIN" --js 'document.title' 'https://example.com' \
| grep -q 'Example Domain'