Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
name: "Integration Tests"

permissions:
contents: read

on:
push:
branches: [main]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Blocking — Workflow still triggers on push: main

Commit 5b00113 says "Trigger integration test on pull requests only" but this trigger is still here. Every merged PR runs the full Docker+WASM+Playwright suite twice (on the PR and on the push to main).

Remove the push trigger or make the duplication intentional with a comment explaining why.

pull_request:
pull_request_review:
types: [submitted]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌱 pull_request_review trigger means integration tests re-run on every review submission, even when no code changed. Combined with the pull_request trigger, an approval on an existing PR triggers a full redundant run. Consider removing this trigger or using workflow_dispatch for on-demand runs.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 (efficiency/cost): pull_request_review triggers will re-run the full integration + browser test suites on every review submission — even when there are no code changes. Consider removing this trigger and keeping just pull_request + workflow_dispatch for canonical/manual runs.

workflow_dispatch:

env:
ORIGIN_PORT: 8888

jobs:
integration-tests:
name: integration tests
runs-on: ubuntu-latest
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Blocking — No timeout-minutes on CI jobs

Neither integration-tests nor browser-tests has a timeout-minutes. If Viceroy hangs or a container stalls, jobs run until GitHub's default 6-hour timeout, silently burning CI minutes.

jobs:
  integration-tests:
    runs-on: ubuntu-latest
    timeout-minutes: 15

if: >-
github.event_name == 'push' ||
github.event_name == 'pull_request' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request_review' && github.event.review.state == 'approved')
steps:
- uses: actions/checkout@v4

- 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 toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ steps.rust-version.outputs.rust-version }}
target: wasm32-wasip1
cache-shared-key: cargo-${{ runner.os }}

- name: Get Viceroy cache key
id: viceroy-rev
run: echo "sha=$(git ls-remote https://github.com/fastly/Viceroy HEAD | cut -f1)" >> $GITHUB_OUTPUT

- name: Cache Viceroy binary
id: cache-viceroy
uses: actions/cache@v4
with:
path: ~/.cargo/bin/viceroy
key: viceroy-${{ runner.os }}-${{ steps.viceroy-rev.outputs.sha }}

- name: Install Viceroy
if: steps.cache-viceroy.outputs.cache-hit != 'true'
run: cargo install --git https://github.com/fastly/Viceroy viceroy

- name: Build WASM binary
run: cargo build --bin trusted-server-fastly --release --target wasm32-wasip1
env:
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL: "http://127.0.0.1:${{ env.ORIGIN_PORT }}"
TRUSTED_SERVER__PROXY__CERTIFICATE_CHECK: "false"

- name: Build WordPress test container
run: |
docker build -t test-wordpress:latest \
crates/integration-tests/fixtures/frameworks/wordpress/

- name: Build Next.js test container
run: |
docker build -t test-nextjs:latest \
crates/integration-tests/fixtures/frameworks/nextjs/

- name: Run integration tests
run: >-
cargo test
--manifest-path crates/integration-tests/Cargo.toml
--target x86_64-unknown-linux-gnu
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📌 Non-blocking — Hardcoded target triple

x86_64-unknown-linux-gnu is hardcoded here, while the local script (integration-tests.sh) auto-detects via rustc -vV. Fine today on ubuntu-latest, but inconsistent with the local script approach. Consider aligning them.

-- --include-ignored --test-threads=1
env:
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
RUST_LOG: info

browser-tests:
name: browser integration tests
runs-on: ubuntu-latest
if: >-
github.event_name == 'push' ||
github.event_name == 'pull_request' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request_review' && github.event.review.state == 'approved')
steps:
- uses: actions/checkout@v4

- 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 toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ steps.rust-version.outputs.rust-version }}
target: wasm32-wasip1
cache-shared-key: cargo-${{ runner.os }}

- name: Get Viceroy cache key
id: viceroy-rev
run: echo "sha=$(git ls-remote https://github.com/fastly/Viceroy HEAD | cut -f1)" >> $GITHUB_OUTPUT

- name: Cache Viceroy binary
id: cache-viceroy
uses: actions/cache@v4
with:
path: ~/.cargo/bin/viceroy
key: viceroy-${{ runner.os }}-${{ steps.viceroy-rev.outputs.sha }}

- name: Install Viceroy
if: steps.cache-viceroy.outputs.cache-hit != 'true'
run: cargo install --git https://github.com/fastly/Viceroy viceroy

- name: Build WASM binary
run: cargo build --bin trusted-server-fastly --release --target wasm32-wasip1
env:
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL: "http://127.0.0.1:${{ env.ORIGIN_PORT }}"
TRUSTED_SERVER__PROXY__CERTIFICATE_CHECK: "false"

- name: Build WordPress test container
run: |
docker build -t test-wordpress:latest \
crates/integration-tests/fixtures/frameworks/wordpress/

- name: Build Next.js test container
run: |
docker build -t test-nextjs:latest \
crates/integration-tests/fixtures/frameworks/nextjs/

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: lts/*

- name: Install Playwright
working-directory: crates/integration-tests/browser
run: |
npm ci
npx playwright install --with-deps chromium

- name: Run browser tests (Next.js)
working-directory: crates/integration-tests/browser
env:
WASM_BINARY_PATH: ${{ github.workspace }}/target/wasm32-wasip1/release/trusted-server-fastly.wasm
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
VICEROY_CONFIG_PATH: ${{ github.workspace }}/crates/integration-tests/fixtures/configs/viceroy-template.toml
TEST_FRAMEWORK: nextjs
run: npx playwright test

- name: Run browser tests (WordPress)
working-directory: crates/integration-tests/browser
env:
WASM_BINARY_PATH: ${{ github.workspace }}/target/wasm32-wasip1/release/trusted-server-fastly.wasm
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
VICEROY_CONFIG_PATH: ${{ github.workspace }}/crates/integration-tests/fixtures/configs/viceroy-template.toml
TEST_FRAMEWORK: wordpress
run: npx playwright test

- name: Upload Playwright HTML report
uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Non-blocking — Playwright report overwritten between framework runs

The Next.js run (line 68) writes to playwright-report/, then the WordPress run (line 77) overwrites it. This artifact upload only captures the WordPress report. If Next.js fails but WordPress passes, the failure report is lost.

Consider distinct artifact names per framework, or separate report output directories via PLAYWRIGHT_HTML_REPORT env var.

path: crates/integration-tests/browser/playwright-report/
retention-days: 7

- name: Upload Playwright traces and screenshots
uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-traces
path: crates/integration-tests/browser/test-results/
retention-days: 7
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
run: cargo install --git https://github.com/fastly/Viceroy viceroy

- name: Run tests
run: cargo test
run: cargo test --workspace

test-typescript:
name: vitest
Expand Down
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/bin
/pkg
/target
/crates/integration-tests/target

# env
.env*
Expand All @@ -28,4 +29,10 @@ src/*.html
*.pem

/guest-profiles
/benchmark-results/**
/benchmark-results/**

# Playwright browser tests
/crates/integration-tests/browser/node_modules/
/crates/integration-tests/browser/test-results/
/crates/integration-tests/browser/playwright-report/
/crates/integration-tests/browser/.browser-test-state.json
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
resolver = "2"
members = [
"crates/common",
"crates/fastly",
"crates/fastly",
"crates/js",
]
# integration-tests is intentionally excluded from workspace members because it
# requires a native target (testcontainers, reqwest) while the workspace default
# is wasm32-wasip1. Run it via: ./scripts/integration-tests.sh
exclude = [
"crates/integration-tests",
]

# Build defaults exclude the web-only tsjs crate, which is compiled via wasm-pack.
default-members = [
"crates/common",
"crates/fastly",
Expand Down
10 changes: 8 additions & 2 deletions crates/fastly/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ async fn route_request(

// Match known routes and handle them
let result = match (method, path.as_str()) {
// Health check endpoint for integration tests and monitoring.
// Namespaced to avoid shadowing publisher routes.
(Method::GET, "/__trusted-server/health") => {
Ok(Response::from_status(200).with_body_text_plain("ok"))
}

// Serve the tsjs library
(Method::GET, path) if path.starts_with("/static/tsjs=") => {
handle_tsjs_dynamic(&req, integration_registry)
Expand Down Expand Up @@ -176,7 +182,7 @@ fn init_logger() {
.echo_stdout(true)
.max_level(log::LevelFilter::Debug)
.build()
.expect("Failed to build Logger");
.expect("should build Logger");

fern::Dispatch::new()
.format(|out, message, record| {
Expand All @@ -194,5 +200,5 @@ fn init_logger() {
})
.chain(Box::new(logger) as Box<dyn log::Log>)
.apply()
.expect("Failed to initialize logger");
.expect("should initialize logger");
}
6 changes: 6 additions & 0 deletions crates/integration-tests/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
target/
*.rs
Cargo.toml
Cargo.lock
tests/
README.md
Loading