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 <rotimi-best@users.noreply.github.com>
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
@@ -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
permissions:
contents: none
issues: read
pull-requests: write
jobs:
label_on_pr:
runs-on: ubuntu-latest
permissions:
contents: none
issues: read
pull-requests: write
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