Skip to content

fixed mobile ui (#74) #210

fixed mobile ui (#74)

fixed mobile ui (#74) #210

Workflow file for this run

name: Tests
on:
workflow_dispatch:
push:
branches: ['*'] # Run on all branches
pull_request:
branches: ['*'] # Run on PRs to all branches
concurrency:
group: tests-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
changes:
name: Detect relevant changes
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
e2e: ${{ steps.filter.outputs.e2e }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check changed paths
id: filter
uses: dorny/paths-filter@v4
with:
base: ${{ github.ref_name }}
filters: |
frontend:
- 'src/**'
- 'config/**'
- 'public/**'
- 'scripts/**'
- 'package.json'
- 'package-lock.json'
- 'index.html'
- 'tsconfig.json'
- '.eslintrc.cjs'
- '.prettierrc'
- 'codecov.yml'
- '.github/workflows/test.yml'
- '.github/scripts/**'
e2e:
- 'e2e/**'
- 'config/playwright.config.ts'
- '.github/workflows/test.yml'
- '.github/scripts/**'
- name: Write CI plan
run: |
{
echo "### CI Plan"
echo ""
echo "| Area | Changed | Action |"
echo "| ---- | ------- | ------ |"
echo "| Frontend, unit, build | ${{ steps.filter.outputs.frontend }} | $([ '${{ steps.filter.outputs.frontend }}' = 'true' ] && echo 'Run' || echo 'Skip unless manually triggered') |"
echo "| E2E | ${{ steps.filter.outputs.e2e }} | $([ '${{ steps.filter.outputs.frontend }}' = 'true' ] || [ '${{ steps.filter.outputs.e2e }}' = 'true' ] && echo 'Run' || echo 'Skip unless manually triggered') |"
} >> "$GITHUB_STEP_SUMMARY"
test:
name: Run Tests with Coverage
runs-on: ubuntu-latest
needs: changes
permissions:
contents: read
id-token: write
issues: write
pull-requests: write
steps:
- name: Skip app test suite
if: github.event_name != 'workflow_dispatch' && needs.changes.outputs.frontend != 'true' && needs.changes.outputs.e2e != 'true'
run: |
{
echo "### App Test Suite"
echo ""
echo "No frontend, E2E, package, or test workflow inputs changed. Skipping lint, build, unit tests, coverage, and Codecov."
} >> "$GITHUB_STEP_SUMMARY"
- name: Checkout code
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
uses: actions/checkout@v4
- name: Setup Node.js
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
run: npm ci
- name: Run linter
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
id: lint
run: |
set +e
npm run lint 2>&1 | tee lint-output.log
status=${PIPESTATUS[0]}
echo "status=${status}" >> "$GITHUB_OUTPUT"
.github/scripts/write-log-summary.sh "Lint" "${status}" lint-output.log "npm run lint" 120
exit "${status}"
continue-on-error: true
- name: Build application
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
id: build
run: |
set +e
npm run build 2>&1 | tee build-output.log
status=${PIPESTATUS[0]}
echo "status=${status}" >> "$GITHUB_OUTPUT"
.github/scripts/write-log-summary.sh "Build" "${status}" build-output.log "npm run build" 160
exit "${status}"
- name: Run tests with coverage
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
id: unit_tests
run: |
set +e
npm run test:coverage 2>&1 | tee vitest-output.log
status=${PIPESTATUS[0]}
echo "status=${status}" >> "$GITHUB_OUTPUT"
.github/scripts/write-log-summary.sh "Unit Tests" "${status}" vitest-output.log "npm run test:coverage" 220
exit 0
- name: Generate coverage summary
if: always() && steps.unit_tests.outputs.status != ''
run: |
if [ -f coverage/coverage-summary.json ]; then
LINES=$(node -e "console.log(require('./coverage/coverage-summary.json').total.lines.pct)")
STATEMENTS=$(node -e "console.log(require('./coverage/coverage-summary.json').total.statements.pct)")
BRANCHES=$(node -e "console.log(require('./coverage/coverage-summary.json').total.branches.pct)")
FUNCTIONS=$(node -e "console.log(require('./coverage/coverage-summary.json').total.functions.pct)")
{
echo "### Coverage Report"
echo ""
echo "| Metric | Coverage |"
echo "|--------|----------|"
echo "| Lines | ${LINES}% |"
echo "| Statements | ${STATEMENTS}% |"
echo "| Branches | ${BRANCHES}% |"
echo "| Functions | ${FUNCTIONS}% |"
} >> "$GITHUB_STEP_SUMMARY"
fi
- name: Upload coverage report
if: always() && steps.unit_tests.outputs.status != ''
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 30
- name: Coverage comment on PR
if: always() && github.event_name == 'pull_request' && steps.unit_tests.outputs.status != ''
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
if (fs.existsSync('coverage/coverage-summary.json')) {
const coverage = require('./coverage/coverage-summary.json');
const marker = '<!-- robo-boy-coverage-report -->';
const body = `${marker}
## Test Coverage Report
| Metric | Coverage |
|--------|----------|
| Lines | ${coverage.total.lines.pct}% |
| Statements | ${coverage.total.statements.pct}% |
| Branches | ${coverage.total.branches.pct}% |
| Functions | ${coverage.total.functions.pct}% |
[View workflow summary](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID})`;
const {data: comments} = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
const previous = comments.find(comment =>
comment.user.type === 'Bot' && comment.body.includes(marker)
);
if (previous) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: previous.id,
body
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body
});
}
}
- name: Upload coverage to Codecov
if: >-
steps.unit_tests.outputs.status == '0' &&
(github.event_name == 'pull_request' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/dev'))
uses: codecov/codecov-action@v5
with:
files: ./coverage/lcov.info
flags: unit
name: unit-tests
fail_ci_if_error: true
disable_search: true
use_oidc: true
- name: Fail if unit tests failed
if: steps.unit_tests.outputs.status != '' && steps.unit_tests.outputs.status != '0'
run: exit 1
e2e:
name: E2E Tests
runs-on: ubuntu-latest
needs: [changes, test] # Run after unit tests pass
steps:
- name: Skip E2E suite
if: github.event_name != 'workflow_dispatch' && needs.changes.outputs.frontend != 'true' && needs.changes.outputs.e2e != 'true'
run: |
{
echo "### E2E Suite"
echo ""
echo "No frontend, E2E, package, or test workflow inputs changed. Skipping Playwright."
} >> "$GITHUB_STEP_SUMMARY"
- name: Checkout code
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
uses: actions/checkout@v4
- name: Setup Node.js
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
run: npm ci
- name: Install Playwright browsers
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
run: npx playwright install --with-deps chromium
- name: Run E2E tests
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.e2e == 'true'
id: e2e_tests
run: |
set +e
npm run e2e 2>&1 | tee playwright-output.log
status=${PIPESTATUS[0]}
echo "status=${status}" >> "$GITHUB_OUTPUT"
.github/scripts/write-log-summary.sh "E2E Tests" "${status}" playwright-output.log "npm run e2e" 260
exit 0
- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always() && steps.e2e_tests.outputs.status != ''
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- name: Upload Playwright test results
uses: actions/upload-artifact@v4
if: always() && steps.e2e_tests.outputs.status != ''
with:
name: playwright-test-results
path: test-results/
retention-days: 30
- name: Fail if E2E tests failed
if: steps.e2e_tests.outputs.status != '' && steps.e2e_tests.outputs.status != '0'
run: exit 1