-
Notifications
You must be signed in to change notification settings - Fork 11
150 lines (136 loc) · 6.99 KB
/
Copy pathvalidate-deps.yml
File metadata and controls
150 lines (136 loc) · 6.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
name: Validate Dependencies
on:
pull_request:
paths:
- '**/package.json'
- 'pnpm-lock.yaml'
- '.changeset/config.json'
- 'pnpm-workspace.yaml'
- 'scripts/check-changeset-fixed.mjs'
- 'scripts/check-override-consistency.mjs'
# The consumer-resolution half of the same question (#16186) — an edit to
# the gate must be exercised on the PR that makes it.
- 'scripts/check-vendor-export-contract.mjs'
# The OSV exemption ledger and its check: a PR that touches either must
# run this workflow, or an exemption could be added without the gate
# that governs it ever running on the PR that adds it.
- 'osv-scanner.toml'
- 'scripts/check-osv-exemptions.mjs'
# Re-run when the workflow itself changes, so edits to these gates are
# exercised on the PR that introduces them.
- '.github/workflows/validate-deps.yml'
schedule:
# Run daily at 03:00 UTC — narrows the discovery window for a new OSV
# advisory from up to six days (weekly) to one, so the scheduled scan
# is more likely to surface a red before an unrelated PR's blocking
# trigger collides with it (#14645).
- cron: '0 3 * * *'
workflow_dispatch:
jobs:
validate:
name: Validate Package Dependencies
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '22'
- name: Setup pnpm
uses: ./.github/actions/setup-pnpm
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache
uses: actions/cache@v6
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-v3-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-v3-
- name: Verify lockfile is up to date
run: |
pnpm install --frozen-lockfile --prefer-offline
- name: Verify Changesets "fixed" group covers every public package
run: node scripts/check-changeset-fixed.mjs
# pnpm overrides pin what THIS workspace resolves, but they do not ship
# with published packages — downstream installs see only the declared
# ranges. If an override target isn't reachable from a publishable
# package's declared range, we test one dependency graph and publish
# another (the 15.1.0 quickstart shipped exactly that: plugin-auth
# declared better-auth ^1.6.23 while CI ran the 1.7.0-rc.1 override,
# and every fresh project 500'd on auth).
#
# The same run also prints two informational censuses (#6046): overrides
# nothing in the dependency tree consumes, and selectors whose upper
# bound excludes their own target (#4961 / #5032). Both are REPORTS and
# never fail the job — an unconsumed override is a legitimate posture
# (#5835 ruling A). `--self-test` proves the check in both directions,
# so run the `check:override-consistency` chain rather than the bare
# script: a self-test nothing invokes is a phantom check.
- name: Verify overrides are reflected in published manifests
run: pnpm check:override-consistency
# The half check-override-consistency structurally cannot cover (#16186).
# It asks whether the override TARGET is reachable from the declared
# range; `^1.7.2` and `^1.7.2` agreed perfectly while both floated onto
# `@better-auth/core@1.7.3`, a PATCH that deleted the export plugin-auth
# imports statically. Three published releases could not load on a fresh
# install and nothing here went red, because pnpm-lock.yaml held 1.7.2.
#
# `--resolve` deliberately ignores the lockfile: for every version the
# DECLARED range admits on the registry -- the way a downstream project
# resolves -- it installs that version outside this workspace and checks
# the export surface. It fails if ANY admitted version is missing a symbol
# we import. With the ranges pinned exact that is one small install per
# vendor; under a caret it is one per published version, which is the cost
# of the risk being taken.
#
# It lives HERE rather than in the lint farm because it needs the network,
# which this job already has, and because the daily schedule is what turns
# "a vendor published something today" into a red in this repo instead of
# in a customer's install. An unreachable registry exits 3
# (PREREQUISITE NOT MET), never a green.
- name: Verify the declared ranges cannot resolve past our import surface
run: pnpm check:vendor-export-contract-resolve
# Fail the workflow if known vulnerabilities are found — enforces
# security compliance before merging.
#
# Previously this ran `pnpm audit --audit-level=high`, but npm retired the
# audit endpoint (HTTP 410, "This endpoint is being retired. Use the bulk
# advisory endpoint instead.") and pnpm has not migrated, so `pnpm audit`
# now fails unconditionally on every branch (see issue #2974). OSV-Scanner
# reads pnpm-lock.yaml directly against the OSV database and exits non-zero
# when any advisory matches, restoring a working blocking gate.
#
# Note: OSV-Scanner blocks on any severity, not just high/critical. When
# the advisory has a fixed version you take the fix. The ONLY escape
# hatch, for an advisory with no fix available, is an `[[IgnoredVulns]]`
# entry in `osv-scanner.toml` at the repo root — never lowering the gate.
#
# That escape hatch is governed by three conventions (#4965), stated in
# full in the header of osv-scanner.toml: `ignoreUntil` mandatory
# (default 30 days, ceiling 90), `reason` mandatory with an advisory link
# plus a sentence on why it cannot be fixed, and exemptions land in their
# own `osv-exemption`-labelled PR. The scanner enforces none of that — it
# reads a missing `ignoreUntil` as "ignore forever", silently — so the
# step below runs first and fails on any exemption that is missing,
# quoted, expired, over the ceiling, or unexplained. `--self-test` proves
# the check in both directions.
- name: Verify OSV exemptions carry an expiry and a reason
run: |
node scripts/check-osv-exemptions.mjs --self-test
node scripts/check-osv-exemptions.mjs
- name: Audit dependencies for known vulnerabilities (OSV-Scanner)
uses: google/osv-scanner-action/osv-scanner-action@f4cfcc01edc9c8b756a9b873b7a623ca674da51e # v2.3.8
with:
scan-args: |-
--lockfile=pnpm-lock.yaml
- name: List outdated packages
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
run: |
pnpm outdated --recursive || true