Skip to content

Add real-stack Playwright e2e smoke suite #1808

Add real-stack Playwright e2e smoke suite

Add real-stack Playwright e2e smoke suite #1808

Workflow file for this run

name: Build
# For more information on this YAML file, please reference blog: https://agramont.net/blog/devops-intro-deploy-net-aspire-azure-github-actions
on:
workflow_dispatch:
push:
# Run when commits are pushed to mainline branch (main or master)
# Set this to the mainline branch you are using
branches:
- master
- main
pull_request:
branches: ["dev", "master", "main"]
permissions:
contents: read
# Based from https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-net
jobs:
changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
backend: ${{ steps.filter.outputs.backend || 'true' }}
openapi: ${{ steps.filter.outputs.openapi || 'true' }}
frontend: ${{ steps.filter.outputs.frontend || 'true' }}
e2e: ${{ steps.filter.outputs.e2e || 'true' }}
steps:
- name: Checkout
if: github.event_name == 'pull_request'
uses: actions/checkout@v7
- name: Check for file changes
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
id: filter
with:
filters: |
backend:
- 'backend/**'
- '.github/workflows/main.yml'
openapi:
- 'backend/**'
- 'ui/**'
- 'open-api/**'
- '.github/workflows/main.yml'
frontend:
- 'ui/**'
- 'open-api/**'
- '.github/workflows/main.yml'
e2e:
- 'backend/**'
- 'ui/**'
- 'open-api/**'
- '.github/workflows/main.yml'
dependency-review:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Dependency Review
uses: actions/dependency-review-action@v5
backend-build:
name: Create OpenAPI spec
needs: changes
if: |
github.event_name != 'pull_request' ||
needs.changes.outputs.openapi == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
actions: write
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup dotnet 10.x
uses: actions/setup-dotnet@v6
with:
dotnet-version: "10.0.x"
- name: Restore
run: dotnet restore MenuApi.sln
working-directory: ./backend
- name: Build solution (generate OpenAPI)
run: dotnet build MenuApi.sln --configuration Release --no-restore
working-directory: ./backend
- name: Upload OpenAPI document
uses: actions/upload-artifact@v7
with:
name: openapi-spec
path: open-api/menu-api.json
if-no-files-found: error
backend-tests:
name: Backend tests
needs: changes
if: |
github.event_name != 'pull_request' ||
needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup dotnet 10.x
uses: actions/setup-dotnet@v6
with:
dotnet-version: "10.0.x"
- name: Restore
run: dotnet restore MenuApi.sln
working-directory: ./backend
- name: Build solution (generate OpenAPI)
run: dotnet build MenuApi.sln --configuration Release --no-restore
working-directory: ./backend
- name: Test with the dotnet CLI
run: |
Get-ChildItem -Recurse -Filter "*.Tests.csproj" | Where-Object { $_.FullName -notlike "*Integration*" } | ForEach-Object {
dotnet test $_.FullName --configuration Release --no-build
}
shell: pwsh
working-directory: ./backend
backend-integration-tests:
name: Backend integration tests
needs: changes
if: |
github.event_name != 'pull_request' ||
needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup dotnet 10.x
uses: actions/setup-dotnet@v6
with:
dotnet-version: "10.0.x"
- name: Restore
run: dotnet restore MenuApi.sln
working-directory: ./backend
- name: Build solution (generate OpenAPI)
run: dotnet build MenuApi.sln --configuration Release --no-restore
working-directory: ./backend
- name: clean ssl cert
run: dotnet dev-certs https --clean
- name: trust ssl cert
run: |
dotnet dev-certs https --trust || true
echo "SSL_CERT_DIR=$HOME/.aspnet/dev-certs/trust:${SSL_CERT_DIR:-/usr/lib/ssl/certs}" >> "$GITHUB_ENV"
- name: Test with the dotnet CLI
run: dotnet test --project MenuApi.Integration.Tests/MenuApi.Integration.Tests.csproj --configuration Release --no-build
working-directory: ./backend
env:
parameters__Auth0TestClientId: ${{ vars.AUTH0_CLIENT_ID }}
parameters__Auth0TestClientSecret: ${{ secrets.AUTH0_CLIENT_SECRET }}
parameters__Auth0Domain: ${{ vars.AUTH0_DOMAIN }}
parameters__Auth0Audience: http://localhost:65273
frontend:
name: Frontend validation
runs-on: ubuntu-latest
needs: [changes, backend-build]
if: |
!cancelled() &&
(
github.event_name != 'pull_request' ||
needs.changes.outputs.openapi == 'true' ||
needs.changes.outputs.frontend == 'true'
) &&
(needs.backend-build.result == 'success' || needs.backend-build.result == 'skipped')
permissions:
contents: read
actions: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Download OpenAPI document
if: needs.backend-build.result == 'success'
uses: actions/download-artifact@v8
with:
name: openapi-spec
path: open-api
merge-multiple: true
- name: Use Node.js 22.x
uses: actions/setup-node@v7
with:
node-version: 22.x
- name: Install latest pnpm
run: npm install -g pnpm@latest
- name: Get pnpm store directory
id: pnpm-cache
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
working-directory: ./ui/menu-website
- name: Cache pnpm store
uses: actions/cache@v6
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('ui/menu-website/pnpm-lock.yaml', 'ui/menu-website/package.json') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile
working-directory: ./ui/menu-website
- name: Generate OpenAPI types
run: pnpm run generate-openapi
working-directory: ./ui/menu-website
- name: Lint frontend
run: pnpm run lint
working-directory: ./ui/menu-website
- name: Build frontend
run: pnpm run build
working-directory: ./ui/menu-website
- name: Get installed Playwright version
id: playwright-version
run: |
PLAYWRIGHT_VERSION=$(node -p "require('playwright/package.json').version")
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> "$GITHUB_OUTPUT"
working-directory: ./ui/menu-website
- name: Cache Playwright browsers
uses: actions/cache@v6
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.PLAYWRIGHT_VERSION }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm exec playwright install --with-deps
working-directory: ./ui/menu-website
- name: Run frontend tests
run: pnpm run test
working-directory: ./ui/menu-website
frontend-e2e:
name: Frontend E2E (shard ${{ matrix.shard }})
needs: [changes, backend-build]
if: |
!cancelled() &&
(
github.event_name != 'pull_request' ||
(
needs.changes.outputs.e2e == 'true' &&
github.event.pull_request.head.repo.full_name == github.repository
)
)
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3]
timeout-minutes: 30
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Download OpenAPI document
if: needs.backend-build.result == 'success'
uses: actions/download-artifact@v8
with:
name: openapi-spec
path: open-api
merge-multiple: true
- name: Setup dotnet 10.x
uses: actions/setup-dotnet@v6
with:
dotnet-version: "10.0.x"
- name: Restore backend
run: dotnet restore MenuApi.sln
working-directory: ./backend
- name: Install Aspire CLI
run: |
dotnet tool install --global Aspire.Cli
export PATH="$HOME/.dotnet/tools:$PATH"
echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH"
aspire --version
- name: Use Node.js 22.x
uses: actions/setup-node@v7
with:
node-version: 22.x
- name: Install latest pnpm
run: npm install -g pnpm@latest
- name: Get pnpm store directory
id: pnpm-cache
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
working-directory: ./ui/menu-website
- name: Cache pnpm store
uses: actions/cache@v6
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('ui/menu-website/pnpm-lock.yaml', 'ui/menu-website/package.json') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile
working-directory: ./ui/menu-website
- name: Generate OpenAPI types
run: pnpm run generate-openapi
working-directory: ./ui/menu-website
- name: Get installed Playwright version
id: playwright-version
run: |
PLAYWRIGHT_VERSION=$(node -p "require('playwright/package.json').version")
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> "$GITHUB_OUTPUT"
working-directory: ./ui/menu-website
- name: Cache Playwright browsers
uses: actions/cache@v6
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.PLAYWRIGHT_VERSION }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm exec playwright install --with-deps
working-directory: ./ui/menu-website
- name: Run Playwright shard
run: pnpm run test:e2e -- --shard=${{ matrix.shard }}/${{ strategy.job-total }} --reporter=blob
working-directory: ./ui/menu-website
env:
CI: true
parameters__Auth0Domain: ${{ vars.AUTH0_DOMAIN }}
parameters__Auth0Audience: http://localhost:65273
E2E_AUTH0_USERNAME: ${{ secrets.E2E_AUTH0_USERNAME }}
E2E_AUTH0_PASSWORD: ${{ secrets.E2E_AUTH0_PASSWORD }}
- name: Upload Playwright blob report
if: always()
uses: actions/upload-artifact@v7
with:
name: playwright-blob-${{ matrix.shard }}
path: ui/menu-website/blob-report
if-no-files-found: ignore
retention-days: 14
- name: Upload Playwright failure artifacts
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-failures-${{ matrix.shard }}
path: |
ui/menu-website/test-results
ui/menu-website/playwright-report
if-no-files-found: ignore
retention-days: 14
frontend-e2e-fork-skip:
name: Frontend E2E skipped (fork PR)
needs: changes
if: github.event_name == 'pull_request' && needs.changes.outputs.e2e == 'true' && github.event.pull_request.head.repo.full_name != github.repository
runs-on: ubuntu-latest
steps:
- name: Explain skipped E2E run
run: echo "Frontend E2E is skipped for fork pull requests because CI secrets are unavailable."
merge-e2e-reports:
name: Merge frontend E2E reports
needs: frontend-e2e
if: always() && (needs.frontend-e2e.result == 'success' || needs.frontend-e2e.result == 'failure')
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup Node.js 22.x
uses: actions/setup-node@v7
with:
node-version: 22.x
- name: Install pnpm
run: npm install -g pnpm@latest
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
working-directory: ./ui/menu-website
- name: Download shard reports
uses: actions/download-artifact@v8
with:
pattern: playwright-blob-*
path: ui/menu-website/all-blob-reports
- name: Merge reports into HTML
run: pnpm exec playwright merge-reports --reporter html ./all-blob-reports
working-directory: ./ui/menu-website
- name: Upload merged Playwright report
if: always()
uses: actions/upload-artifact@v7
with:
name: playwright-report
path: ui/menu-website/playwright-report
if-no-files-found: ignore
retention-days: 14