Skip to content

build: Fallout 10.4 across the repo group, pinned exactly #148

build: Fallout 10.4 across the repo group, pinned exactly

build: Fallout 10.4 across the repo group, pinned exactly #148

Workflow file for this run

name: UI tests
# Label-gated Playwright runs for PRs (#128). Heavy: a chromium install +
# `--with-deps` apt-get is ~150MB plus host-package churn, so we don't run
# UI tests on every push. Add the `run-ui-tests` label to a PR to opt in.
#
# Trigger fires on label add (so adding the label kicks the workflow), on
# new pushes to the PR (so subsequent commits re-run while the label is
# present), and on opened/reopened (so a PR opened with the label already
# attached runs immediately).
on:
pull_request:
branches: [main]
types: [opened, reopened, synchronize, labeled]
workflow_dispatch:
permissions:
contents: read
checks: write # publish-unit-test-result-action
pull-requests: write # auto-label job needs this (currently disabled)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
concurrency:
group: ui-tests-${{ github.ref }}
cancel-in-progress: true
jobs:
# ---------------------------------------------------------------------------
# Decide whether to run. Two signals:
# 1. `run-ui-tests` label present on the PR → manual opt-in.
# 2. Web paths changed (src/Presentation/Web/**, test/Presentation/Web/**) → auto-detected.
# Either signal flips `run=true`. The path check is wired now even though
# the auto-add-label job below is disabled, so a path-touching PR still
# gets UI coverage if the human forgets the label.
# ---------------------------------------------------------------------------
decide:
name: Decide
runs-on: ubuntu-latest
timeout-minutes: 2
outputs:
run: ${{ steps.gate.outputs.run }}
label-present: ${{ steps.gate.outputs.label-present }}
paths-changed: ${{ steps.filter.outputs.web }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect web paths
id: filter
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@v3
with:
# Explicit positive patterns ONLY. dorny/paths-filter's `!`
# syntax does NOT subtract from prior patterns the way the
# README implies — under the default `some` quantifier each
# `!` line is an independent positive match for "file does
# NOT match this glob", which OR-combines with the others and
# ends up matching almost everything (e.g. an ADR .md outside
# any src/ path matched the previous `!**/Dockerfile` line
# because it isn't a Dockerfile). Lesson: enumerate the
# extensions that actually move pixels.
filters: |
web:
- 'src/Presentation/Web/Satisfactory.Presentation.Web/**/*.{cs,razor,razor.css,css,js,html,json}'
- 'src/Presentation/Web/Satisfactory.Presentation.Web/wwwroot/**'
- 'src/Presentation/Web/CaptainOfIndustry.Presentation.Web/**/*.{cs,razor,razor.css,css,js,html,json}'
- 'src/Presentation/Web/CaptainOfIndustry.Presentation.Web/wwwroot/**'
- 'src/Presentation/Web/Erp.Presentation.Web.Common/**/*.{cs,razor,razor.css,css,js,html}'
- 'test/Presentation/Web/**'
- name: Compute gate
id: gate
env:
LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
PATHS_CHANGED: ${{ steps.filter.outputs.web }}
EVENT: ${{ github.event_name }}
run: |
label_present=false
if echo "$LABELS" | grep -q '"run-ui-tests"'; then
label_present=true
fi
echo "label-present=$label_present" >> "$GITHUB_OUTPUT"
if [ "$EVENT" = "workflow_dispatch" ]; then
echo "run=true" >> "$GITHUB_OUTPUT"
elif [ "$label_present" = "true" ] || [ "$PATHS_CHANGED" = "true" ]; then
echo "run=true" >> "$GITHUB_OUTPUT"
else
echo "run=false" >> "$GITHUB_OUTPUT"
fi
# ---------------------------------------------------------------------------
# Auto-add the `run-ui-tests` label when web paths change on a PR that
# doesn't already carry it. **Disabled for now** — flip `if: false` to
# `if: needs.decide.outputs.paths-changed == 'true' && needs.decide.outputs.label-present == 'false' && github.event_name == 'pull_request'`
# when ready. The tests still run from the path-changed signal alone, so
# disabling this is purely cosmetic — it just means the label won't
# auto-appear on the PR.
# ---------------------------------------------------------------------------
auto-label:
name: Auto-add run-ui-tests label
needs: decide
if: false
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Add label
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: gh pr edit "$PR_NUMBER" --add-label run-ui-tests
# ---------------------------------------------------------------------------
# The actual Playwright run. Mirrors the existing `build-and-test` job
# structure (checkout + submodule + NuGet cache + setup-dotnet) and then
# calls the new `TestUi` Nuke target, which depends on
# `InstallPlaywrightBrowsers` (Nuke handles the `playwright.ps1 install
# --with-deps chromium` invocation).
# ---------------------------------------------------------------------------
ui-tests:
name: UI tests (Playwright)
needs: decide
if: needs.decide.outputs.run == 'true'
runs-on: ubuntu-latest
# 30 min was tight on a cold ubuntu-latest runner — NuGet restore + Playwright
# browser install + Aspire-orchestrated test suite was hitting the limit before
# `dotnet test` finished (TRX uploaded with the tests that did run all green,
# job itself killed at the timeout). 45 min gives breathing room without
# being absurd.
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # NB.GV needs full history for version-height calc
- name: Initialize vendored SatisfactorySaveNet submodule
run: git -c submodule.vendor/SatisfactorySaveNet.update=checkout submodule update --init --recursive
- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ubuntu-latest-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }}
restore-keys: ubuntu-latest-nuget-
- name: Setup .NET
uses: actions/setup-dotnet@v4
env:
DOTNET_INSTALL_DIR: /home/runner/.dotnet
with:
dotnet-version: 8.0.x
global-json-file: global.json
# Aspire AppHost's WithHttpHealthCheck("/health") probe hits the
# apiservice / webfrontend over HTTPS. The .NET dev cert isn't in the
# Linux runner's CA bundle by default, so HttpClient inside the
# AppHost rejects the cert with UntrustedRoot, /health is never
# reached, webfrontend stays Unhealthy forever, and the test fixture
# hangs in WaitForResourceHealthyAsync until the job timeout.
#
# `dotnet dev-certs https` generates the cert; `--trust` is a no-op
# for the system trust store on Linux, so we additionally export the
# cert as PEM and drop it into /usr/local/share/ca-certificates/.
# update-ca-certificates then rebuilds the system bundle that
# OpenSSL (and HttpClient via SslStream) consult.
- name: Trust ASP.NET Core HTTPS dev cert
run: |
dotnet dev-certs https
dotnet dev-certs https --export-path /tmp/aspnet-https.pem --format Pem --no-password
sudo cp /tmp/aspnet-https.pem /usr/local/share/ca-certificates/aspnet-https-dev.crt
sudo update-ca-certificates
- name: Run UI tests
run: ./build.sh TestUi
- name: Upload TRX test results
if: always()
uses: actions/upload-artifact@v4
with:
name: ui-test-results
path: artifacts/test-results/*.trx
if-no-files-found: warn
- name: Upload Playwright traces / videos (on failure)
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-traces
path: |
test/Presentation/Web/Satisfactory.Presentation.Web.UiTests/bin/**/playwright-traces/**
test/Presentation/Web/Satisfactory.Presentation.Web.UiTests/bin/**/test-results/**
if-no-files-found: ignore
# ---------------------------------------------------------------------------
# Publish — same shape as the main CI workflow's publish-test-results job,
# scoped to the UI run.
# ---------------------------------------------------------------------------
publish-results:
name: Publish UI test results
needs: [decide, ui-tests]
if: always() && needs.decide.outputs.run == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
pull-requests: write
steps:
- name: Download TRX artifacts
uses: actions/download-artifact@v4
with:
path: test-results
pattern: ui-test-results
merge-multiple: false
- name: Publish results to commit check
uses: EnricoMi/publish-unit-test-result-action/linux@v2
with:
files: test-results/**/*.trx
check_name: UI test results
comment_mode: changes in failures