Skip to content

Commit d447faa

Browse files
Sbussisoclaude
andcommitted
ci: weekly dependency-refresh workflow (uv lock --upgrade + npm update -> PR)
Stay ahead of newly-disclosed advisories instead of discovering them when the pip-audit/npm-audit deploy gate goes red (pyjwt, react-router, and pip have each done this recently). A scheduled Monday job refreshes both locks within their semver ranges, runs the same gates deploy.yml runs (pip-audit + pytest; npm audit + vitest + build), and opens a single PR only if everything's green — a red run means an upgrade needs a human. deploy.yml runs for real on merge. PR is bot-authored, so close-external-prs.yml leaves it alone. Requires the repo's 'Allow GitHub Actions to create and approve pull requests' setting. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 23db5ae commit d447faa

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Weekly dependency refresh
2+
3+
# Proactively refresh the dependency locks within their existing semver
4+
# ranges, so a newly-disclosed CVE doesn't turn the Test & Deploy
5+
# pip-audit / npm-audit gate red out of nowhere. It has happened more than
6+
# once — see the [tool.uv] constraint comments in backend/pyproject.toml.
7+
#
8+
# This runs the SAME gates the deploy pipeline runs, then opens ONE PR with
9+
# the refreshed locks. deploy.yml only triggers on push-to-master, so the
10+
# verification has to happen here: a green run means the PR is safe to merge,
11+
# and merging it triggers the normal Test & Deploy. If a gate fails (an
12+
# upgrade breaks a test, or a CVE has no fix yet) the run goes red and NO PR
13+
# is opened — that red run is the signal to look manually.
14+
#
15+
# Scope is lock-only and within-range: `uv lock --upgrade` respects the
16+
# floors in pyproject.toml and `npm update` stays inside the package.json
17+
# semver ranges. Major-version bumps stay deliberate and manual.
18+
#
19+
# One-time setup: Settings → Actions → General → Workflow permissions →
20+
# enable "Allow GitHub Actions to create and approve pull requests", or the
21+
# final PR step fails with a 403.
22+
23+
on:
24+
schedule:
25+
# Mondays 06:00 UTC — a fresh PR waiting at the start of the week.
26+
- cron: "0 6 * * 1"
27+
workflow_dispatch: {}
28+
29+
permissions:
30+
contents: write
31+
pull-requests: write
32+
33+
concurrency:
34+
group: weekly-deps-refresh
35+
cancel-in-progress: true
36+
37+
jobs:
38+
refresh:
39+
name: Refresh + verify locks
40+
runs-on: ubuntu-latest
41+
steps:
42+
- uses: actions/checkout@v5
43+
44+
# ── Backend — uv lock --upgrade, then deploy.yml's backend gates ──
45+
- name: Install uv
46+
uses: astral-sh/setup-uv@v8.1.0
47+
- name: Set up Python
48+
run: uv python install 3.12
49+
- name: Upgrade backend lock (within pyproject constraints)
50+
working-directory: backend
51+
run: uv lock --upgrade
52+
- name: Install backend deps
53+
working-directory: backend
54+
run: uv sync --extra dev
55+
- name: Backend dependency scan (pip-audit --strict)
56+
working-directory: backend
57+
run: uv run pip-audit --strict
58+
- name: Backend tests
59+
working-directory: backend
60+
run: uv run pytest -q
61+
62+
# ── Frontend — npm update, then deploy.yml's frontend gates ──
63+
- uses: actions/setup-node@v6
64+
with:
65+
node-version: "20"
66+
cache: "npm"
67+
cache-dependency-path: frontend/package-lock.json
68+
- name: Install frontend deps from the current lock
69+
working-directory: frontend
70+
run: npm ci
71+
- name: Upgrade frontend lock (within package.json ranges)
72+
working-directory: frontend
73+
run: npm update
74+
- name: Frontend audit (production deps, high+critical)
75+
working-directory: frontend
76+
run: npm audit --audit-level=high --omit=dev
77+
- name: Frontend tests (vitest)
78+
working-directory: frontend
79+
run: npm test
80+
- name: Frontend production build
81+
working-directory: frontend
82+
run: npm run build
83+
84+
# ── Open / update one PR with the refreshed locks ──
85+
# No changes → no PR (the action also tidies up the stale branch).
86+
# The PR is authored by github-actions[bot] (user.type == 'Bot'),
87+
# which close-external-prs.yml explicitly exempts, so it survives.
88+
- name: Open dependency-refresh PR
89+
uses: peter-evans/create-pull-request@v7
90+
with:
91+
add-paths: |
92+
backend/uv.lock
93+
frontend/package-lock.json
94+
branch: deps/weekly-refresh
95+
delete-branch: true
96+
commit-message: "chore(deps): weekly lock refresh"
97+
title: "chore(deps): weekly dependency lock refresh"
98+
labels: dependencies
99+
body: |
100+
Automated weekly refresh of `backend/uv.lock` and
101+
`frontend/package-lock.json`, bounded to the existing semver
102+
ranges (`uv lock --upgrade` + `npm update`).
103+
104+
Every deploy gate passed in the refresh run **before** this PR
105+
was opened:
106+
107+
- `pip-audit --strict` — backend advisory scan
108+
- `pytest` — backend suite
109+
- `npm audit --audit-level=high --omit=dev` — frontend
110+
- `vitest` + production build — frontend
111+
112+
Merge to ship: the push to `master` triggers the normal
113+
Test & Deploy pipeline, which re-runs all of the above.

0 commit comments

Comments
 (0)