Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the pull request identity in the concurrency group

For pull requests from forks, github.head_ref contains only the source branch name, so unrelated contributors using a common name such as main or fix receive the same concurrency group. Starting CI for one of those PRs will therefore cancel the in-progress verify job for the other; use the PR number, github.ref, or include the head repository owner to make the group unique per PR.

Useful? React with 👍 / 👎.

cancel-in-progress: true

jobs:
# The same lint + test pair the publish workflow gates on, run before the
# merge rather than after the tag. Until now nothing checked a pull request,
# so a change could only fail once it was already on its way to npm.
#
# ubuntu-latest, not a Blacksmith runner: this repo is public, so these
# minutes are free, and the job is short enough that a faster runner would
# save nothing worth paying for.
verify:
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: 22
cache: npm

- run: npm ci

- run: npm run lint

- run: npm test
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nk-crew/plugin-toolkit",
"version": "0.5.1",
"version": "0.6.0",
"description": "Shared development tooling for the nk-crew WordPress plugins",
"license": "MIT",
"author": "nK <https://nkdev.info>",
Expand Down
14 changes: 12 additions & 2 deletions playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ function createPlaywrightConfig({
Number.parseInt(process.env.TIMEOUT || '', 10) ||
timeout ||
200_000,
reportSlowTests: null,
// Playwright's default is `{ max: 5, threshold: 15000 }`; `null` silenced
// it entirely. That hid a suite where a `beforeEach` was loading the whole
// of wp-admin before every test, for months. The cost of the report is a
// few lines at the end of a run.
reportSlowTests: { max: 5, threshold: 30_000 },
testDir,
globalSetup,
outputDir: path.join(process.cwd(), 'artifacts/test-results'),
Expand All @@ -91,7 +95,13 @@ function createPlaywrightConfig({
// per-test budget is gone, so a single stuck page load costs the
// full `timeout` (and the same again for every retry).
navigationTimeout: 30000,
trace: 'retain-on-failure',
// `retain-on-failure` records a trace for every test and throws it
// away when the test passes, so the whole suite pays for tracing to
// keep artefacts for the few tests that fail. `on-first-retry` moves
// that cost onto the retry, which `retries` above already guarantees
// for anything that fails under CI -- same artefacts where they are
// useful, none of the overhead where they are not.
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'on-first-retry',
},
Expand Down
28 changes: 28 additions & 0 deletions scripts/self-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,34 @@ check('navigations are bounded, not left to the per-test budget', () => {
);
});

check('tracing is not paid for on the happy path', () => {
const { use, retries } = buildPlaywrightConfig(true);

assert.equal(
use.trace,
'on-first-retry',
'`retain-on-failure` traces every test and discards it on success, so a green suite pays the tracing cost in full'
);
assert.ok(
retries > 0,
'on-first-retry only yields artefacts if a failing test is actually retried under CI'
);
});

check('slow tests are reported', () => {
const { reportSlowTests } = buildPlaywrightConfig(true);

assert.notEqual(
reportSlowTests,
null,
'null silences the one report that would surface an expensive beforeEach'
);
assert.ok(
reportSlowTests && reportSlowTests.threshold > 0,
'a threshold of 0 flags every test and so says nothing'
);
});

check('every runtime require is a declared dependency', () => {
const declared = new Set([
...Object.keys(pkg.dependencies || {}),
Expand Down