Skip to content

web-easy-smoke

web-easy-smoke #188

name: web-easy-smoke
on:
push:
paths:
- "lib/web-easy/**"
- ".github/workflows/web-easy-smoke.yml"
pull_request:
paths:
- "lib/web-easy/**"
- ".github/workflows/web-easy-smoke.yml"
schedule:
- cron: "0 2 * * *"
workflow_dispatch:
jobs:
smoke:
runs-on: ubuntu-latest
env:
WASM_TOOLS_VERSION: "1.225.0"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Racket
uses: Bogdanp/setup-racket@v1.11
with:
architecture: x64
distribution: full
version: stable
- name: Cache Racket user packages
uses: actions/cache@v4
with:
path: |
~/.local/share/racket
~/.cache/racket
key: ${{ runner.os }}-racket-user-${{ hashFiles('.github/workflows/web-easy-smoke.yml') }}
restore-keys: |
${{ runner.os }}-racket-user-
- name: Ensure raco static-web
run: |
raco pkg install --auto --skip-installed --no-docs raco-static-web
raco static-web --help >/dev/null
- name: Ensure nanopass
run: raco pkg install --auto --skip-installed --no-docs nanopass
- name: Cache wasm-tools binary
uses: actions/cache@v4
with:
path: ~/.local/bin/wasm-tools
key: ${{ runner.os }}-wasm-tools-${{ env.WASM_TOOLS_VERSION }}
- name: Add local bin to PATH
run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Install wasm-tools (prebuilt)
run: |
if [ ! -x "$HOME/.local/bin/wasm-tools" ]; then
mkdir -p "$HOME/.local/bin"
curl -L -o /tmp/wasm-tools.tar.gz \
"https://github.com/bytecodealliance/wasm-tools/releases/download/v${WASM_TOOLS_VERSION}/wasm-tools-${WASM_TOOLS_VERSION}-x86_64-linux.tar.gz"
tar -xzf /tmp/wasm-tools.tar.gz -C /tmp
cp "/tmp/wasm-tools-${WASM_TOOLS_VERSION}-x86_64-linux/wasm-tools" "$HOME/.local/bin/wasm-tools"
chmod +x "$HOME/.local/bin/wasm-tools"
fi
wasm-tools --version
- name: Setup Node (for webracket -r)
uses: actions/setup-node@v4
with:
node-version: 25.2.1
- name: Cache Playwright package
uses: actions/cache@v4
with:
path: .local-tools/node_modules
key: ${{ runner.os }}-playwright-node-modules-${{ hashFiles('.github/workflows/web-easy-smoke.yml') }}
restore-keys: |
${{ runner.os }}-playwright-node-modules-
- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-browsers-${{ hashFiles('.github/workflows/web-easy-smoke.yml') }}
restore-keys: |
${{ runner.os }}-playwright-browsers-
- name: Ensure Playwright Chromium
run: |
npm --prefix .local-tools install --save-dev playwright
npx --prefix .local-tools playwright install --with-deps chromium
- name: Link local webracket collection
run: raco link "$GITHUB_WORKSPACE"
- name: Headless verify preflight
run: |
cd lib/web-easy/smoke
SMOKE_LOCAL_TOOLS_DIR="$GITHUB_WORKSPACE/.local-tools" ./headless.sh verify
- name: Run web-easy smoke checks
run: |
cd lib/web-easy/smoke
echo "[1/3] core tests (real Racket)"
racket ../test/test-web-easy.rkt
echo "[2/5] keyword negative tests"
(cd ../test && ./test-define-key-negative.sh)
echo "[3/5] core tests (webracket -r)"
WEBRACKET_OUT="$(cd ../test && racket ../../../webracket.rkt -r test-web-easy-run.rkt)"
if [ -n "$WEBRACKET_OUT" ] && [ "$WEBRACKET_OUT" != "#<void>" ]; then
printf '%s\n' "$WEBRACKET_OUT"
fi
echo "web-easy webracket tests passed"
echo "[4/5] smoke compile"
./check-smoke.sh
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "[5/5] nightly deep headless CI (contract + theme + smoke + guard)"
SMOKE_TIMEOUT_MS=600000 SMOKE_WARN_MS=2000 SMOKE_SKIP_COMPILE=1 ./headless.sh ci
echo "nightly deep CI gate passed"
else
echo "[5/5] PR/push lean headless CI (smoke + key contracts; optional visual gate: make smoke-solar-sections-gate)"
SMOKE_TIMEOUT_MS=300000 SMOKE_WARN_MS=2000 SMOKE_SKIP_COMPILE=1 ./headless.sh ci-fast
echo "lean CI gate passed"
fi
- name: Publish headless timing summary
if: always()
run: |
files=(
/tmp/web-easy-contract-timings.tsv
/tmp/web-easy-smoke-timings.tsv
/tmp/web-easy-parity-timings.tsv
/tmp/web-easy-theme-timings.tsv
)
{
echo "web-easy headless timing summary"
for f in "${files[@]}"; do
if [ -f "$f" ]; then
echo
echo "$(basename "$f"):"
awk -F $'\t' 'NR > 1 { print $2 "\t" $1 }' "$f" | sort -nr | head -n 10 | awk -F $'\t' '{ printf(" %s ms %s\n", $1, $2) }'
else
echo
echo "$(basename "$f"): (missing)"
fi
done
} > /tmp/web-easy-headless-timing-summary.txt
{
echo "### web-easy headless timing summary"
for f in "${files[@]}"; do
if [ -f "$f" ]; then
echo
echo "#### $(basename "$f")"
echo
echo "| duration_ms | page |"
echo "| ---: | --- |"
awk -F $'\t' 'NR > 1 { print $2 "\t" $1 }' "$f" | sort -nr | head -n 10 | awk -F $'\t' '{ printf("| %s | %s |\n", $1, $2) }'
fi
done
} >> "$GITHUB_STEP_SUMMARY"
- name: Prepare smoke failure context
if: failure()
run: |
{
echo "web-easy smoke failure context"
echo "sha=${GITHUB_SHA}"
echo "ref=${GITHUB_REF}"
echo "run_id=${GITHUB_RUN_ID}"
echo "run_attempt=${GITHUB_RUN_ATTEMPT}"
echo "time_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo
echo "tail: /tmp/web-easy-smoke-headless.log"
if [ -f /tmp/web-easy-smoke-headless.log ]; then
tail -n 80 /tmp/web-easy-smoke-headless.log
else
echo "(missing)"
fi
echo
echo "tail: /tmp/web-easy-dashboard-guard.log"
if [ -f /tmp/web-easy-dashboard-guard.log ]; then
tail -n 80 /tmp/web-easy-dashboard-guard.log
else
echo "(missing)"
fi
} > /tmp/web-easy-smoke-failure-context.txt
- name: Upload smoke failure logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: web-easy-smoke-failure-logs
if-no-files-found: warn
path: |
/tmp/web-easy-smoke-headless.log
/tmp/web-easy-dashboard-guard.log
/tmp/web-easy-smoke-failure-context.txt
lib/web-easy/smoke/COMMANDS.tsv
- name: Upload headless timing artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: web-easy-headless-timings
if-no-files-found: warn
path: |
/tmp/web-easy-contract-timings.tsv
/tmp/web-easy-smoke-timings.tsv
/tmp/web-easy-parity-timings.tsv
/tmp/web-easy-theme-timings.tsv
/tmp/web-easy-style-timings.tsv
/tmp/web-easy-all-timings.tsv
/tmp/web-easy-headless-timing-summary.txt