diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9ec23f..831fc0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,3 +23,16 @@ jobs: - run: npm run lint:pkg - run: npm run test:coverage - run: npm run test:mutation + # Durable mutation-score artifact: each package's Stryker run writes + # JSON + HTML to packages//reports/mutation/. Retain them as a + # downloadable run artifact so the per-package score is retrievable + # after the run, not just ephemeral stdout. if: always() captures the + # report even when the break:90 gate fails (the score is the evidence). + - name: Upload mutation reports + if: always() + uses: actions/upload-artifact@v7 + with: + name: mutation-reports + path: packages/*/reports/mutation/ + retention-days: 30 + if-no-files-found: warn diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 092a8e9..9774e54 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,8 +3,12 @@ name: Publish on: push: branches: [main] + # Narrowed from '**/package.json' to package manifests only: a real + # release signal is a version edit under packages//package.json. + # Root/devDep manifest churn (dependabot, tooling) must NOT start the + # OIDC-minting publish job. (Sapper M2 H1 / STALE-4.) paths: - - '**/package.json' + - 'packages/*/package.json' jobs: build: @@ -28,6 +32,11 @@ jobs: publish: needs: build runs-on: ubuntu-latest + # Environment gate: the OIDC mint (id-token: write) is fronted by the + # 'npm-publish' deployment environment, whose protection rule (required + # reviewer / wait timer) gates the token mint behind a human/policy + # checkpoint. (Sapper M2 H1 / STALE-4.) + environment: npm-publish permissions: contents: write id-token: write diff --git a/packages/adapter-store/stryker.config.mjs b/packages/adapter-store/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/adapter-store/stryker.config.mjs +++ b/packages/adapter-store/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/cached-adapter-store/stryker.config.mjs b/packages/cached-adapter-store/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/cached-adapter-store/stryker.config.mjs +++ b/packages/cached-adapter-store/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/dialog/stryker.config.mjs b/packages/dialog/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/dialog/stryker.config.mjs +++ b/packages/dialog/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/helpers/stryker.config.mjs b/packages/helpers/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/helpers/stryker.config.mjs +++ b/packages/helpers/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/http/stryker.config.mjs b/packages/http/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/http/stryker.config.mjs +++ b/packages/http/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/loading/stryker.config.mjs b/packages/loading/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/loading/stryker.config.mjs +++ b/packages/loading/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/router/stryker.config.mjs b/packages/router/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/router/stryker.config.mjs +++ b/packages/router/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/storage/stryker.config.mjs b/packages/storage/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/storage/stryker.config.mjs +++ b/packages/storage/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/theme/stryker.config.mjs b/packages/theme/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/theme/stryker.config.mjs +++ b/packages/theme/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/toast/stryker.config.mjs b/packages/toast/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/toast/stryker.config.mjs +++ b/packages/toast/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always', diff --git a/packages/translation/stryker.config.mjs b/packages/translation/stryker.config.mjs index cea608c..8617354 100644 --- a/packages/translation/stryker.config.mjs +++ b/packages/translation/stryker.config.mjs @@ -4,7 +4,9 @@ export default { vitest: {configFile: 'vitest.config.ts'}, mutate: ['src/**/*.ts', '!src/**/types.ts'], thresholds: {high: 95, low: 90, break: 90}, - reporters: ['clear-text', 'progress'], + reporters: ['clear-text', 'progress', 'json', 'html'], + jsonReporter: {fileName: 'reports/mutation/mutation.json'}, + htmlReporter: {fileName: 'reports/mutation/mutation.html'}, incremental: true, incrementalFile: '.stryker-incremental.json', cleanTempDir: 'always',