Merge pull request 'ci: fold the Tests workflow into SonarQube Analysis and delete it (#123)' (#127) from feature/123-consolidate-test-workflows into main
Reviewed-on: #127
This commit was merged in pull request #127.
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
name: SonarQube Analysis
|
name: SonarQube Analysis
|
||||||
|
|
||||||
|
# The only workflow that runs the test suites. tests.yml used to run the unit
|
||||||
|
# and end-to-end suites as well, on identical triggers, so every pull request
|
||||||
|
# installed, migrated, built, started the backend and ran the whole end-to-end
|
||||||
|
# suite twice. With one runner the second copy did not run in parallel, it
|
||||||
|
# queued. It was deleted and its two summarize steps folded in here. See #123.
|
||||||
|
#
|
||||||
|
# Note that the integration suite DOES run here, on every push and pull request,
|
||||||
|
# despite backend-integration.yml describing it as manual. That quarantine only
|
||||||
|
# ever applied to tests.yml. It is survivable here because test:integration:cov
|
||||||
|
# passes --forceExit, which papers over the post-run hang, and because of the
|
||||||
|
# timeout below.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
@@ -82,8 +94,13 @@ jobs:
|
|||||||
run: node migrate.js up
|
run: node migrate.js up
|
||||||
working-directory: backend
|
working-directory: backend
|
||||||
|
|
||||||
|
# --json/--outputFile appended rather than baked into the script: the
|
||||||
|
# coverage run and the results file are wanted together here, and nowhere
|
||||||
|
# else. summarize-jest.js below reads that file.
|
||||||
- name: Backend unit tests with coverage
|
- name: Backend unit tests with coverage
|
||||||
run: npm run test:unit:cov
|
id: unit
|
||||||
|
continue-on-error: true
|
||||||
|
run: npm run test:unit:cov -- --json --outputFile=unit-results.json
|
||||||
working-directory: backend
|
working-directory: backend
|
||||||
|
|
||||||
# Covers everything in src/routes, which the unit suite does not touch —
|
# Covers everything in src/routes, which the unit suite does not touch —
|
||||||
@@ -116,11 +133,21 @@ jobs:
|
|||||||
# Runs against an istanbul-instrumented dev server, which is what produces
|
# Runs against an istanbul-instrumented dev server, which is what produces
|
||||||
# window.__coverage__ for the fixture to collect.
|
# window.__coverage__ for the fixture to collect.
|
||||||
- name: Frontend end-to-end tests with coverage
|
- name: Frontend end-to-end tests with coverage
|
||||||
run: npm run test:e2e:cov
|
id: e2e
|
||||||
|
continue-on-error: true
|
||||||
|
env:
|
||||||
|
PLAYWRIGHT_JSON_OUTPUT_NAME: playwright-results.json
|
||||||
|
# list as well as json, so the log still shows which test failed rather
|
||||||
|
# than only a file nobody reads until the summary step.
|
||||||
|
run: npm run test:e2e:cov -- --reporter=list,json
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
|
|
||||||
|
# Keyed off the step outcome rather than failure(). continue-on-error above
|
||||||
|
# means the job is not in a failed state at this point, so failure() would
|
||||||
|
# never fire and the log that explains an end-to-end failure would go
|
||||||
|
# unprinted precisely when it is wanted.
|
||||||
- name: Backend log
|
- name: Backend log
|
||||||
if: failure()
|
if: steps.e2e.outcome == 'failure'
|
||||||
run: cat /tmp/backend.log
|
run: cat /tmp/backend.log
|
||||||
|
|
||||||
# Fails when nothing was collected rather than writing an empty report. An
|
# Fails when nothing was collected rather than writing an empty report. An
|
||||||
@@ -135,3 +162,22 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
|
||||||
|
# Readable pass and fail counts, which the raw jest and Playwright output
|
||||||
|
# does not give at a glance. Both run with if: always() so a failing suite
|
||||||
|
# is still summarised — which is the case they exist for.
|
||||||
|
- name: Summarize unit tests
|
||||||
|
if: always()
|
||||||
|
run: node scripts/summarize-jest.js backend/unit-results.json "Backend Unit Test"
|
||||||
|
|
||||||
|
- name: Summarize end-to-end tests
|
||||||
|
if: always()
|
||||||
|
run: node scripts/summarize-playwright.js frontend/playwright-results.json
|
||||||
|
|
||||||
|
# Last, so a failing suite still produces coverage, a scan and both
|
||||||
|
# summaries first. Without this step continue-on-error above would turn a
|
||||||
|
# failing suite into a passing job, which is the one way this change could
|
||||||
|
# do real damage.
|
||||||
|
- name: Fail if either suite failed
|
||||||
|
if: steps.unit.outcome == 'failure' || steps.e2e.outcome == 'failure'
|
||||||
|
run: exit 1
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
name: Tests
|
|
||||||
|
|
||||||
# backend-integration lives in its own manual workflow
|
|
||||||
# (.gitea/workflows/backend-integration.yml) rather than running here. It held
|
|
||||||
# the runner for 3h12m on 2026-08-18 — 87 seconds of tests followed by a hang
|
|
||||||
# after the run completed — and blocked frontend-e2e behind it for the same
|
|
||||||
# three hours. Run it from Actions before merging anything that touches the API
|
|
||||||
# or the database.
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
backend-unit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
|
|
||||||
- name: Install deps
|
|
||||||
run: npm install
|
|
||||||
working-directory: backend
|
|
||||||
|
|
||||||
- name: Run unit tests
|
|
||||||
id: unit
|
|
||||||
continue-on-error: true
|
|
||||||
run: npm run test:unit:json
|
|
||||||
working-directory: backend
|
|
||||||
|
|
||||||
- name: Summarize
|
|
||||||
if: always()
|
|
||||||
run: node scripts/summarize-jest.js backend/unit-results.json "Backend Unit Test"
|
|
||||||
|
|
||||||
- name: Fail job if tests failed
|
|
||||||
if: steps.unit.outcome == 'failure'
|
|
||||||
run: exit 1
|
|
||||||
|
|
||||||
frontend-e2e:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:16
|
|
||||||
env:
|
|
||||||
POSTGRES_USER: redefined_test
|
|
||||||
POSTGRES_PASSWORD: redefined_test
|
|
||||||
POSTGRES_DB: redefined_test
|
|
||||||
options: >-
|
|
||||||
--health-cmd "pg_isready -U redefined_test"
|
|
||||||
--health-interval 5s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 10
|
|
||||||
env:
|
|
||||||
PGHOST: postgres
|
|
||||||
PGPORT: 5432
|
|
||||||
PGUSER: redefined_test
|
|
||||||
PGPASSWORD: redefined_test
|
|
||||||
PGDATABASE: redefined_test
|
|
||||||
PORT: 3000
|
|
||||||
DEMO_MODE: 'true'
|
|
||||||
UPLOADS_DIR: /tmp/redefined-uploads
|
|
||||||
# NODE_ENV is deliberately unset: `npm install` omits devDependencies when
|
|
||||||
# NODE_ENV=production, which strips tsc/vite/@playwright/test and breaks the
|
|
||||||
# build. It would also flip the session cookie to Secure, which the e2e run
|
|
||||||
# serves over plain http.
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
|
|
||||||
- name: Install backend deps
|
|
||||||
run: npm install
|
|
||||||
working-directory: backend
|
|
||||||
|
|
||||||
- name: Run migrations
|
|
||||||
run: node migrate.js up
|
|
||||||
working-directory: backend
|
|
||||||
|
|
||||||
- name: Build backend
|
|
||||||
run: npm run build
|
|
||||||
working-directory: backend
|
|
||||||
|
|
||||||
- name: Start backend
|
|
||||||
run: |
|
|
||||||
mkdir -p /tmp/redefined-uploads
|
|
||||||
node dist/server.js > /tmp/backend.log 2>&1 &
|
|
||||||
for i in $(seq 1 30); do
|
|
||||||
if node -e "require('http').get('http://localhost:3000/api/config', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"; then
|
|
||||||
echo "Backend ready after ${i}s"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
echo "Backend did not become ready within 30s:"
|
|
||||||
cat /tmp/backend.log
|
|
||||||
exit 1
|
|
||||||
working-directory: backend
|
|
||||||
|
|
||||||
- name: Install frontend deps
|
|
||||||
run: npm install
|
|
||||||
working-directory: frontend
|
|
||||||
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: npx playwright install --with-deps chromium
|
|
||||||
working-directory: frontend
|
|
||||||
|
|
||||||
- name: Run Playwright tests
|
|
||||||
id: e2e
|
|
||||||
continue-on-error: true
|
|
||||||
env:
|
|
||||||
PLAYWRIGHT_JSON_OUTPUT_NAME: playwright-results.json
|
|
||||||
run: npx playwright test --reporter=json
|
|
||||||
working-directory: frontend
|
|
||||||
|
|
||||||
- name: Backend log
|
|
||||||
if: steps.e2e.outcome == 'failure'
|
|
||||||
run: cat /tmp/backend.log
|
|
||||||
|
|
||||||
- name: Summarize
|
|
||||||
if: always()
|
|
||||||
run: node scripts/summarize-playwright.js frontend/playwright-results.json
|
|
||||||
|
|
||||||
- name: Fail job if tests failed
|
|
||||||
if: steps.e2e.outcome == 'failure'
|
|
||||||
run: exit 1
|
|
||||||
@@ -14,3 +14,9 @@ test-results/
|
|||||||
.local/
|
.local/
|
||||||
.scannerwork/
|
.scannerwork/
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
|
|
||||||
|
# Test result JSON, written by the CI test steps for the summarize scripts and
|
||||||
|
# by anyone running the same commands locally. Regenerated every run.
|
||||||
|
backend/unit-results.json
|
||||||
|
backend/integration-results.json
|
||||||
|
frontend/playwright-results.json
|
||||||
|
|||||||
Reference in New Issue
Block a user