diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0af011f..dd26552 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,8 @@ name: CI on: + # Not on `labeled`: CI reads no label, and a label run cancelled before its jobs start hides Test. pull_request: - types: [opened, synchronize, reopened, labeled] branches: - main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f1a8999..ad365a4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,8 +11,9 @@ on: permissions: {} +# Each label run gets a group of its own, so labels added at once can't cancel the run that adds `preview`. concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.event.action == 'labeled' && github.run_id || github.ref }} cancel-in-progress: true jobs: @@ -70,7 +71,18 @@ jobs: # Runs PR code: never give this job the bot key. preview: name: Publish preview - if: ${{ github.event_name == 'pull_request' && (startsWith(github.head_ref, 'feat') || startsWith(github.head_ref, 'fix') || contains(github.event.pull_request.labels.*.name, 'preview')) }} + # One publish per commit: feat/fix pushes publish, and `preview` from the label run that adds it or a later push. + if: >- + ${{ github.event_name == 'pull_request' + && ((github.event.action != 'labeled' && (startsWith(github.head_ref, 'feat') || startsWith(github.head_ref, 'fix'))) + || (github.event.action == 'labeled' && github.event.label.name == 'preview' + && !(startsWith(github.head_ref, 'feat') || startsWith(github.head_ref, 'fix'))) + || ((github.event.action == 'synchronize' || github.event.action == 'reopened') + && contains(github.event.pull_request.labels.*.name, 'preview'))) }} + # One publish to `pr-` at a time: label runs don't share the workflow's group. + concurrency: + group: ${{ github.workflow }}-preview-${{ github.ref }} + cancel-in-progress: false runs-on: ubuntu-latest permissions: id-token: write # npm trusted publishing (OIDC) diff --git a/.github/workflows/workflow-audit.yml b/.github/workflows/workflow-audit.yml index eeb293e..54fed4d 100644 --- a/.github/workflows/workflow-audit.yml +++ b/.github/workflows/workflow-audit.yml @@ -1,8 +1,8 @@ name: Workflow audit on: + # Not on `labeled`: zizmor reads no label, and a label run cancelled before its jobs start hides Audit workflows. pull_request: - types: [opened, synchronize, reopened, labeled] branches: - main diff --git a/docs/development.md b/docs/development.md index f0f65d4..35c1dc7 100644 --- a/docs/development.md +++ b/docs/development.md @@ -27,6 +27,6 @@ The suite in `test/functional` runs in Vitest Browser Mode with Playwright. It c ## CI -- **On each pull request to `main`:** CI sets up mise 2026.10.19 and the locked tools, then runs `pnpm rr check`, `pnpm test` and the build with `pnpm rr pack`. Beside them, gitleaks scans the pull request's commits for secrets, and the required `Test` check passes when both do. Workflow audit runs zizmor on the workflows. +- **On each pull request to `main`:** CI sets up mise 2026.10.19 and the locked tools, then runs `pnpm rr check`, `pnpm test` and the build with `pnpm rr pack`. Beside them, gitleaks scans the pull request's commits for secrets, and the required `Test` check passes when both do. Workflow audit runs zizmor on the workflows. Adding a label runs neither: only Release runs on it, and it publishes a preview when the label is `preview` and the branch isn't `feat/` or `fix/`. - **Git hooks** ([lefthook](https://lefthook.dev)): `lefthook.yml` extends `lefthook/base.yml` from `@rrlab/cli`, whose jobs are listed in [its README](https://github.com/withvariablelab/dx/blob/main/run-run/cli/README.md#git-hooks), and its own `shared-hooks` job fails a commit, saying to run `pnpm install`, when that file is missing from `node_modules`. On commit, in parallel: Biome's fixes on the staged files, the type check when a TypeScript file or a tsconfig changes, and gitleaks on the staged changes. On push, the tests. - **Every Monday:** `pnpm audit` on the lockfile, which keeps an issue labeled `dependency-audit` open while it finds known vulnerabilities (Dependency audit).