chore(ci): harden supply-chain controls before reopening PRs

Isolate npm publish from PR CI, enforce frozen lockfiles and a 24h
minimumReleaseAge, and document safe pull_request_target usage so fork
PRs cannot reach publish credentials.

Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
Cursor Agent
2026-08-10 21:00:29 +01:00
committed by Rotimi Best
co-authored by Rotimi Best
parent bbf5eb24de
commit 9adc38bd8a
13 changed files with 100 additions and 24 deletions
+5
View File
@@ -0,0 +1,5 @@
# High-risk supply-chain paths — prefer maintainer review before merge.
/.github/workflows/ @rotimi-best
/pnpm-lock.yaml @rotimi-best
/pnpm-workspace.yaml @rotimi-best
/package.json @rotimi-best
+1
View File
@@ -39,6 +39,7 @@ Fixes # (place issue number here without bracket)
- [ ] Removed all `console.logs`
- [ ] Merged the latest changes from main onto my branch with `git pull origin main`
- [ ] My changes don't cause any responsiveness issues
- [ ] If this PR changes `pnpm-lock.yaml`, `.github/workflows/**`, or publish config: call that out in the PR description
### Appreciated
@@ -1,19 +1,23 @@
name: 'Apply issue labels to PR'
# pull_request_target is used so labeling works for fork PRs.
# SAFE ONLY because this workflow never checks out or executes PR code.
# Do not add actions/checkout, pnpm install, build, or cache steps here.
on:
pull_request_target:
types:
- opened
jobs:
label_on_pr:
runs-on: ubuntu-latest
permissions:
permissions:
contents: none
issues: read
pull-requests: write
jobs:
label_on_pr:
runs-on: ubuntu-latest
steps:
- name: Apply labels from linked issue to PR
uses: actions/github-script@v5
+5
View File
@@ -5,6 +5,11 @@ on:
types:
- created
- edited
permissions:
contents: read
issues: write
jobs:
take-issue:
name: Disable take issue
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm i
run: pnpm install --frozen-lockfile
- name: Build Storybook
run: |
@@ -0,0 +1,44 @@
name: MCP package build check
# Verifies @classroomio/mcp still builds on PRs/pushes that touch it.
# Intentionally separate from publish-mcp.yml so PR CI never sees NPM_TOKEN.
on:
pull_request:
paths:
- 'packages/mcp/**'
- 'packages/question-types/**'
- 'packages/utils/**'
- 'pnpm-lock.yaml'
- '.github/workflows/mcp-package-build-check.yml'
push:
paths:
- 'packages/mcp/**'
- 'packages/question-types/**'
- 'packages/utils/**'
- 'pnpm-lock.yaml'
- '.github/workflows/mcp-package-build-check.yml'
branches:
- main
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20.19.3
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build publishable MCP package
run: pnpm mcp:build
@@ -24,6 +24,9 @@ on:
- '.nvmrc'
- '.github/workflows/package-build-check.yml'
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
+11 -5
View File
@@ -1,15 +1,19 @@
name: Publish @classroomio/course-app to NPM
on: workflow_dispatch
# Publish-only via manual dispatch. Do not add pull_request triggers here.
on:
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
environment: production
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20.19.3
@@ -17,11 +21,13 @@ jobs:
- uses: pnpm/action-setup@v4
- name: Install, Build & Publish
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build & Publish
working-directory: packages/course-app
run: |
pnpm i
pnpm build
pnpm publish --no-git-checks
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+6 -13
View File
@@ -1,22 +1,16 @@
name: Publish @classroomio/mcp to NPM
# Publish-only. Never triggered by pull_request — keeps NPM_TOKEN off the PR trust boundary.
# PR/push build verification lives in mcp-package-build-check.yml.
on:
workflow_dispatch:
pull_request:
paths:
- "packages/mcp/**"
push:
paths:
- "packages/mcp/**"
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
environment: production
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v4
@@ -24,18 +18,17 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20.19.3
registry-url: "https://registry.npmjs.org"
registry-url: 'https://registry.npmjs.org'
- uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
run: pnpm install --frozen-lockfile
- name: Build publishable MCP package
run: pnpm mcp:build
- name: Publish package
if: github.event_name == 'workflow_dispatch'
run: pnpm --filter @classroomio/mcp publish --no-git-checks --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,5 +1,9 @@
name: 'Check PR'
# pull_request_target is used so title lint can comment on fork PRs.
# SAFE ONLY because this workflow never checks out or executes PR code.
# Do not add actions/checkout, pnpm install, build, or cache steps here.
on:
pull_request_target:
types:
@@ -9,6 +13,7 @@ on:
- synchronize
permissions:
contents: read
pull-requests: write
jobs:
+3
View File
@@ -12,6 +12,9 @@ on:
- 'packages/ui/**'
- '.github/workflows/ui-prefix-check.yml'
permissions:
contents: read
jobs:
ui-prefix:
runs-on: ubuntu-latest
+4
View File
@@ -22,6 +22,10 @@ Ready to dive into the code and make a real impact? Here's your path:
Would you prefer a chat before you dive into a lot of work? Our [Discord server](https://dub.sh/ciodiscord) is your harbor. Share your thoughts, and we'll meet you there with open arms. We're responsive and friendly, promise!
## Dependency and workflow changes
PRs that touch `pnpm-lock.yaml`, `.github/workflows/**`, or npm publish config get extra review. Prefer the smallest lockfile diff that matches your change, and do not add `pull_request_target` workflows that check out or build untrusted PR code.
## Features
If you spot a feature that isn't part of our official plan but could propel ClassroomIO forward, don't hesitate. Raise it as an enhancement issue, and let us know you're ready to take the lead. We'll be quick to respond.
+3
View File
@@ -6,6 +6,9 @@ packages:
onlyBuiltDependencies:
- esbuild
- '@tailwindcss/oxide'
# Block brand-new registry publishes for 24h (supply-chain cooldown).
# Locked versions in pnpm-lock.yaml stay installable; this gates adds/updates.
minimumReleaseAge: 1440
minimumReleaseAgeExclude:
- '@getworkbench/hono'
- '@getworkbench/core'