Skip to content

Layered EdgeZero deploy actions + Fastly staging lifecycle (design + impl, supersedes #303) #714

Layered EdgeZero deploy actions + Fastly staging lifecycle (design + impl, supersedes #303)

Layered EdgeZero deploy actions + Fastly staging lifecycle (design + impl, supersedes #303) #714

Workflow file for this run

name: "Run Tests"
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: cargo test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Cache Cargo dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-test-
- name: Retrieve Rust version
id: rust-version
run: echo "rust-version=$(grep '^rust ' .tool-versions | awk '{print $2}')" >> $GITHUB_OUTPUT
shell: bash
- name: Set up Rust tool chain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ steps.rust-version.outputs.rust-version }}
- name: Add wasm targets
run: rustup target add wasm32-wasip1 wasm32-wasip2 wasm32-unknown-unknown
- name: Fetch dependencies (locked)
run: cargo fetch --locked
- name: No placeholder pins
run: ./scripts/check_no_placeholder_pins.sh
- name: No legacy typed reads
run: ./scripts/check_no_legacy_typed_reads.sh
- name: Nested AppConfig audit
run: cargo run -q --bin check_no_nested_app_config --features nested-app-config-check -- examples/app-demo crates/edgezero-cli/src/templates
# The checker's own unit tests live behind `required-features =
# ["nested-app-config-check"]`, so the unfeatured
# `cargo test --workspace` step below does not compile or run them.
# Exercise them explicitly to keep the coverage closure enforced by CI.
- name: Nested AppConfig checker tests
run: cargo test -p edgezero-cli --features nested-app-config-check --bin check_no_nested_app_config
- name: Run workspace tests
run: cargo test --workspace --all-targets
# The adapter CLI dispatch (build/deploy/stage/healthcheck/rollback) and
# its tests live behind the `cli` feature, which the unfeatured
# `cargo test --workspace` step above does not enable — so none of those
# tests compile or run there. Exercise them explicitly.
- name: Adapter CLI dispatch tests
run: cargo test -p edgezero-adapter-fastly --all-targets --features cli
- name: Check feature compilation
run: cargo check --workspace --all-targets --features "fastly cloudflare spin"
- name: Verify a generated project compiles
run: cargo test -p edgezero-cli --test generated_project_builds -- --ignored
# `examples/app-demo` is excluded from the root workspace, so
# `cargo test --workspace` above does not cover it. Run its own
# workspace tests separately. An end-to-end push →
# AxumConfigStore → handler roundtrip in
# `app-demo-cli/tests/config_flow.rs` exists to be exercised by
# THIS step — without it, a regression in the JSON-file contract
# between `config push --adapter axum` and
# `AxumConfigStore::from_path` would not be caught by CI.
# Axum-only path, no live external calls — intentionally kept
# off the wasm matrix.
- name: Run app-demo workspace tests
working-directory: examples/app-demo
run: cargo test --workspace --all-targets
adapter-wasm-tests:
name: ${{ matrix.adapter }} wasm tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- adapter: cloudflare
target: wasm32-unknown-unknown
runner_env: CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER
runner_value: wasm-bindgen-test-runner
- adapter: fastly
target: wasm32-wasip1
runner_env: CARGO_TARGET_WASM32_WASIP1_RUNNER
runner_value: viceroy run
- adapter: spin
target: wasm32-wasip2
runner_env: CARGO_TARGET_WASM32_WASIP2_RUNNER
runner_value: wasmtime run
steps:
- uses: actions/checkout@v6
- name: Cache Cargo dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
~/.wasmtime/bin/
target/
key: ${{ runner.os }}-cargo-${{ matrix.adapter }}-${{ hashFiles('**/Cargo.lock', '.tool-versions') }}
restore-keys: |
${{ runner.os }}-cargo-${{ matrix.adapter }}-
- name: Retrieve Rust version
id: rust-version
run: echo "rust-version=$(grep '^rust ' .tool-versions | awk '{print $2}')" >> $GITHUB_OUTPUT
shell: bash
- name: Set up Rust tool chain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ steps.rust-version.outputs.rust-version }}
- name: Add wasm target
run: rustup target add ${{ matrix.target }}
- name: Resolve wasm-bindgen CLI version
if: matrix.adapter == 'cloudflare'
id: wasm-bindgen-version
shell: bash
run: |
version="$(
awk '
$1 == "name" && $3 == "\"wasm-bindgen\"" { in_pkg=1; next }
in_pkg && $1 == "version" {
gsub(/"/, "", $3)
print $3
exit
}
' Cargo.lock
)"
test -n "$version"
echo "version=$version" >> "$GITHUB_OUTPUT"
# `--force` is required because the cargo cache may restore an existing
# `~/.cargo/bin/<binary>` from a prior run, which `cargo install` rejects
# by default. Force-overwriting is safe — `--locked` pins the version.
- name: Install wasm-bindgen test runner
if: matrix.adapter == 'cloudflare'
run: cargo install wasm-bindgen-cli --version "${{ steps.wasm-bindgen-version.outputs.version }}" --locked --force
- name: Resolve Viceroy version
if: matrix.adapter == 'fastly'
id: viceroy-version
shell: bash
run: echo "version=$(grep '^viceroy ' .tool-versions | awk '{print $2}')" >> "$GITHUB_OUTPUT"
- name: Setup Viceroy
if: matrix.adapter == 'fastly'
# Version comes from .tool-versions (single source of truth shared with
# local dev).
run: cargo install viceroy --version "${{ steps.viceroy-version.outputs.version }}" --locked --force
- name: Resolve Wasmtime version
if: matrix.adapter == 'spin'
id: wasmtime-version
shell: bash
run: echo "version=$(grep '^wasmtime ' .tool-versions | awk '{print $2}')" >> "$GITHUB_OUTPUT"
- name: Setup Wasmtime
if: matrix.adapter == 'spin'
# Direct GitHub-release tarball install. The official
# `https://wasmtime.dev/install.sh` script broke as of
# 2026-05-19 (interpolation failure: tried to download
# version literal `{`), so we pin via .tool-versions and
# land the binary in `~/.wasmtime/bin/` so the cache step
# above actually short-circuits the download on subsequent
# runs.
#
# The cache key now hashes `.tool-versions` too, so a
# version bump invalidates the cached binary. We also
# explicitly compare `wasmtime --version` against the pin
# — without that a runner-provided wasmtime or a stale
# cache hit would silently shadow the pinned version.
run: |
install_dir="$HOME/.wasmtime/bin"
echo "$install_dir" >> "$GITHUB_PATH"
export PATH="$install_dir:$PATH"
version="${{ steps.wasmtime-version.outputs.version }}"
# Compare exact versions so a pin like `44.0.1` does not silently
# accept `wasmtime 44.0.10` from a stale cache or runner-provided
# binary.
actual="$(wasmtime --version 2>/dev/null | awk '{print $2}' || true)"
if [ "$actual" != "$version" ]; then
tag="v${version}"
archive="wasmtime-${tag}-x86_64-linux"
mkdir -p "$install_dir"
curl -fL "https://github.com/bytecodealliance/wasmtime/releases/download/${tag}/${archive}.tar.xz" -o /tmp/wasmtime.tar.xz
tar -xJf /tmp/wasmtime.tar.xz -C /tmp
install -m 0755 "/tmp/${archive}/wasmtime" "$install_dir/wasmtime"
fi
actual="$(wasmtime --version | awk '{print $2}')"
test "$actual" = "$version"
wasmtime --version
- name: Fetch dependencies (locked)
run: cargo fetch --locked
- name: Run ${{ matrix.adapter }} wasm tests
env:
${{ matrix.runner_env }}: ${{ matrix.runner_value }}
run: cargo test -p edgezero-adapter-${{ matrix.adapter }} --features ${{ matrix.adapter }} --target ${{ matrix.target }} --test contract
- name: Check ${{ matrix.adapter }} wasm target
run: cargo check -p edgezero-adapter-${{ matrix.adapter }} --features ${{ matrix.adapter }} --target ${{ matrix.target }}