Skip to content

build(deps): Bump the dev-dependencies group with 2 updates #157

build(deps): Bump the dev-dependencies group with 2 updates

build(deps): Bump the dev-dependencies group with 2 updates #157

Workflow file for this run

name: CI
on:
# Manual on-demand runs (e.g. to re-trigger the browser-SDK SonarQube scan
# against a chosen ref without pushing a commit): gh workflow run ci.yml --ref main
workflow_dispatch:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Set up JDK 21
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: '21'
distribution: 'temurin'
# Verify gradle-wrapper.jar matches a known-good Gradle release checksum before it
# is executed — guards against a tampered wrapper jar (a classic build-time backdoor).
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@5e2ebd065dc2488b7a6ad670704656cbbe1e8f60 # v6
- name: Set up Gradle
uses: gradle/actions/setup-gradle@5e2ebd065dc2488b7a6ad670704656cbbe1e8f60 # v6
# The persistence integration suites self-skip when PKAUTH_SKIP_TESTCONTAINERS=1. The CI
# gate must exercise them against real Postgres/DynamoDB Local, so fail loudly if that
# escape hatch leaks into the gating pipeline (otherwise the build can go green with zero
# persistence and concurrency coverage).
- name: Guard against skipped integration tests
run: |
if [ "${PKAUTH_SKIP_TESTCONTAINERS:-}" = "1" ]; then
echo "PKAUTH_SKIP_TESTCONTAINERS=1 must not be set in the CI gate — it would silently skip all persistence integration tests." >&2
exit 1
fi
- name: Build and test
run: ./gradlew clean build test --stacktrace
- name: Upload JaCoCo reports
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: jacoco-reports
path: '**/build/reports/jacoco/**'
if-no-files-found: ignore
# Run mutation tests and submit results to the Stryker Dashboard (stryker-mutator.io),
# which tracks mutation score over time with a badge. Requires STRYKER_DASHBOARD_TOKEN
# set as a repo secret.
browser-mutation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '20'
- name: Install dependencies
run: npm ci --ignore-scripts
working-directory: clients/passkeys-browser
- name: Run tests with coverage
run: npx vitest run --coverage
working-directory: clients/passkeys-browser
- name: SonarQube scan
# JavaScript/browser-SDK static analysis only. SonarQube was dropped for the JVM modules
# (ADR 0018, native JaCoCo gates) but retained here for the TypeScript SDK.
# SONAR_TOKEN is unavailable to PRs from forks; skip there to avoid a hard failure.
# Manual (workflow_dispatch) and push runs always have the secret available.
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
uses: sonarsource/sonarqube-scan-action@713881670b6b3676cda39549040e2d88c70d582e # v8.2.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
projectBaseDir: clients/passkeys-browser
- name: Run Stryker mutation tests
run: npm exec --no-install -- stryker run
working-directory: clients/passkeys-browser
env:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_TOKEN }}
- name: Annotate surviving mutants
if: always()
working-directory: clients/passkeys-browser
run: |
node -e "
const fs = require('fs');
if (!fs.existsSync('reports/mutation/mutation.json')) process.exit(0);
const report = JSON.parse(fs.readFileSync('reports/mutation/mutation.json', 'utf8'));
for (const [file, data] of Object.entries(report.files || {})) {
for (const mutant of data.mutants || []) {
if (mutant.status !== 'Survived' && mutant.status !== 'NoCoverage') continue;
const {start, end} = mutant.location;
const title = mutant.status === 'NoCoverage' ? 'No Coverage' : 'Surviving Mutant';
const msg = (mutant.mutatorName + ': ' + (mutant.replacement || '(removed)'))
.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
const path = 'clients/passkeys-browser/' + file;
process.stdout.write('::warning file=' + path + ',line=' + start.line + ',col=' + start.column + ',endLine=' + end.line + ',endColumn=' + end.column + ',title=' + title + '::' + msg + '\n');
}
}
"
- name: Upload mutation report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: mutation-report
path: clients/passkeys-browser/reports/mutation/
if-no-files-found: ignore
# Block PRs that introduce dependencies with known vulnerabilities or incompatible
# licenses, before they merge. Uses the GitHub dependency graph; PR-only.
dependency-review:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Dependency review
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
fail-on-severity: high