diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d9021b9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +# Weekly dependency / third-party security scanning on GitHub infrastructure +# (≈ zero Action minutes). Dependabot opens PRs when a new CVE affects a +# dependency you did not touch; those PRs then run the normal event-driven CI + +# dependency-review gate. No scheduled CI job needed. +version: 2 +updates: + - package-ecosystem: npm + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 10 + groups: + # One PR for all non-major dev/runtime bumps keeps the noise (and CI runs) low. + minor-and-patch: + update-types: [minor, patch] + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e4e299..4ac864e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,103 +1,95 @@ +# CI — thin caller of the org-wide reusable pipeline (bymaxone/.github). +# +# The generic library jobs (lint, typecheck, unit+coverage, mutation) run via +# node-lib-ci.yml so every repo shares one definition. This library's build + +# bundle-size budget, its Testcontainers Redis e2e, the in-repo example build, +# and a verified-secret scan stay here (repo-specific). Mutation runs only on a +# push to main / manual dispatch, never on PRs. name: CI on: + workflow_dispatch: push: branches: [main] pull_request: branches: [main] -permissions: - contents: read - concurrency: - group: ci-${{ github.workflow }}-${{ github.ref }} + group: ci-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: - build: - name: Lint, typecheck, test & build + ci: + uses: bymaxone/.github/.github/workflows/node-lib-ci.yml@v1 + with: + run-format-check: false # no format:check script; prettier runs via lint/pre-commit + run-build: false # build + size verified in the `verify` job below + unit-command: pnpm test:cov:all + run-mutation: true + mutation-source-globs: '^(src/)' + + verify: + name: Verify build + size + needs: ci runs-on: ubuntu-latest + timeout-minutes: 15 steps: - - name: Harden runner - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - fetch-depth: 0 - - - name: Setup pnpm - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - - - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 24 - cache: pnpm - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Typecheck - run: pnpm typecheck - - - name: Lint - run: pnpm lint - - - name: Test with coverage - run: pnpm test:cov:all - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false - - - name: Build + - uses: actions/checkout@v6 + - uses: bymaxone/.github/.github/actions/setup-node-pnpm@v1 + - name: Build all subpaths run: pnpm build - - - name: Check bundle size + - name: Bundle size budget run: pnpm size + e2e: + name: E2E (Testcontainers + Redis) + needs: ci + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v6 + - uses: bymaxone/.github/.github/actions/setup-node-pnpm@v1 + - name: Pre-pull pinned Redis image (cache for Testcontainers) + run: docker pull redis:7-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99 - name: E2E tests run: pnpm test:e2e - - name: Secret scan - uses: trufflesecurity/trufflehog@30d5bb91af1a771378349dbbb0c82129392acf70 # v3.95.6 - with: - extra_args: --only-verified - example: name: Build & lint example + needs: ci runs-on: ubuntu-latest + timeout-minutes: 15 steps: - - name: Harden runner - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - - name: Setup pnpm - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - - - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 24 - cache: pnpm - - - name: Install workspace dependencies - run: pnpm install --frozen-lockfile - + - uses: actions/checkout@v6 + - uses: bymaxone/.github/.github/actions/setup-node-pnpm@v1 - name: Build library run: pnpm build - - name: Build example run: pnpm --filter nest-queue-example build - - name: Lint example run: pnpm --filter nest-queue-example lint + + secret-scan: + name: Secret scan + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Scan for verified secrets + uses: trufflesecurity/trufflehog@30d5bb91af1a771378349dbbb0c82129392acf70 # v3.95.6 + with: + extra_args: --only-verified + + security: + # Dependency review needs the dependency graph (public repos, or private + GHAS). + # Gated on visibility so it starts running automatically once this repo is public. + if: github.event_name == 'pull_request' && github.event.repository.visibility == 'public' + uses: bymaxone/.github/.github/workflows/security.yml@v1 + with: + fail-on-severity: high diff --git a/CLAUDE.md b/CLAUDE.md index 876c6b2..846cd10 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,7 +43,7 @@ Before making any change, read these sections (use `Read` with `offset`/`limit` pnpm typecheck && pnpm lint && pnpm test:cov:all && pnpm build && pnpm size ``` -100% line/branch coverage on every implemented file is a hard gate. Mutation testing (`pnpm mutation`) is a pre-release gate only. +100% line/branch coverage on every implemented file is a hard gate. Mutation testing runs automatically post-merge on `main` via the shared reusable (`bymaxone/.github` → node-lib-ci) plus an optional manual `pnpm mutation`. ---