Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: 2

# Third-party actions are pinned to immutable commit SHAs. SHAs never move on
# their own, so this entry is what keeps them current — without it the pins rot.
#
# Only the github-actions ecosystem is enabled. npm version-update PRs are
# deliberately off: `npm ci` installs strictly from the lockfile and `.npmrc`
# blocks dependency install scripts, so drift is already contained, and a PR
# per release is noise nobody reads. Dependabot *alerts* are enabled in repo
# settings and are the signal layer we do want; automated *security-update* PRs
# are off for the same reason — advisories get triaged against real exposure,
# not auto-patched.
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
# One PR for all action bumps instead of one per action.
groups:
actions:
patterns:
- "*"
commit-message:
prefix: "ci"
19 changes: 16 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npx tsc --noEmit
- run: npx biome check .
- run: npx vitest --run
# Blocking. Every installed dependency must carry a valid npm registry
# signature, so a tampered or unsigned tarball fails the build.
- run: npm audit signatures
# Blocking. This tree has no known advisories in its production
# dependencies today, so keep it that way: fix, replace, or drop the
# dependency rather than loosening the gate.
- run: npm audit --omit=dev
# `--no-install` keeps these on the binaries `npm ci` just installed and
# verified. Without it, npx silently fetches an unpinned package from the
# registry whenever a tool is missing from the lockfile, which lands
# unreviewed code in the job right after the gates above cleared it.
- run: npx --no-install tsc --noEmit
- run: npx --no-install vitest --run
# No lint step: the Biome CLI is not a declared dependency here, so
# invoking it would download an unreviewed binary on every run. Wiring up
# @biomejs/biome, and fixing what it reports, is a separate change.
15 changes: 13 additions & 2 deletions .github/workflows/claude-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,23 @@ jobs:
- uses: actions/checkout@v4

- name: Install OpenProse skill
# Pinned to a commit rather than tracking the default branch. This skill
# becomes the instructions Claude follows in a job that holds an API key
# and can write to pull requests, so a commit pushed to that repository
# would otherwise change behaviour here with nothing reviewed on this
# side. Bump deliberately.
env:
PROSE_REF: f7fa6770c4bf46d8af23215734ac5f16e5c3ee96
run: |
git clone --depth 1 https://github.com/openprose/prose.git /tmp/prose
set -euo pipefail
git init --quiet /tmp/prose
git -C /tmp/prose fetch --depth 1 --quiet \
https://github.com/openprose/prose.git "${PROSE_REF}"
git -C /tmp/prose checkout --quiet FETCH_HEAD
mkdir -p .claude/skills
cp -r /tmp/prose/skills/open-prose .claude/skills/open-prose

- uses: anthropics/claude-code-action@v1
- uses: anthropics/claude-code-action@c038e4dcdedfbbca18dfb17df35a17e40ded4ddc # v1.0.186
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "prose run pr-review.prose"
Expand Down
48 changes: 41 additions & 7 deletions .github/workflows/press-eval-full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ on:
workflow_dispatch:
inputs:
tier:
description: "Eval tier: quick (3 cheap), standard (6 default), full (all)"
description: "Eval tier"
required: false
default: "standard"
type: choice
options: [quick, standard, full]
model:
description: "Override model for all evals"
description: "Override model for all evals (provider/name form)"
required: false
concurrency:
description: "Max parallel evals"
description: "Max parallel evals (1-10)"
required: false
default: "3"

Expand All @@ -26,6 +28,12 @@ jobs:
- uses: actions/checkout@v4
with:
repository: openprose/prose
# Pinned: without a ref this tracks that repository's default branch,
# so a commit made there would change what runs in this job — which
# holds a provider key — with no change reviewed here. Bump
# deliberately.
ref: f7fa6770c4bf46d8af23215734ac5f16e5c3ee96
persist-credentials: false
path: prose

- uses: actions/setup-node@v4
Expand All @@ -36,13 +44,39 @@ jobs:
- run: npm ci

- name: Run Press evals
# Dispatch inputs travel through the environment and are validated before
# use. Interpolating them straight into this script would let a dispatch
# value containing shell syntax execute as code, in a job that holds a
# provider key. `--no-install` keeps tsx on the lockfile's copy.
run: |
npx tsx src/eval-pipeline.ts \
--tier ${{ inputs.tier || 'standard' }} \
--concurrency ${{ inputs.concurrency || '3' }} \
${{ inputs.model && format('--model {0}', inputs.model) || '' }}
set -euo pipefail

case "${TIER}" in
quick|standard|full) ;;
*) echo "::error::Invalid tier: ${TIER}" >&2; exit 1 ;;
esac

if ! printf '%s' "${CONCURRENCY}" | grep -qE '^([1-9]|10)$'; then
echo "::error::concurrency must be an integer from 1 to 10" >&2
exit 1
fi

args=(--tier "${TIER}" --concurrency "${CONCURRENCY}")

if [ -n "${MODEL}" ]; then
if ! printf '%s' "${MODEL}" | grep -qE '^[A-Za-z0-9._-]+/[A-Za-z0-9._:-]+$'; then
echo "::error::model must look like provider/name" >&2
exit 1
fi
args+=(--model "${MODEL}")
fi

npx --no-install tsx src/eval-pipeline.ts "${args[@]}"
env:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
TIER: ${{ inputs.tier || 'standard' }}
CONCURRENCY: ${{ inputs.concurrency || '3' }}
MODEL: ${{ inputs.model }}
timeout-minutes: 25

- name: Upload eval results
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/press-eval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ jobs:
- run: npm ci

- name: Run Press evals (quick tier)
run: npx tsx src/eval-pipeline.ts --tier quick --concurrency 3
# `--no-install` so this runs the lockfile's tsx rather than fetching an
# unpinned one from the registry into a job holding a provider key.
run: npx --no-install tsx src/eval-pipeline.ts --tier quick --concurrency 3
env:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
timeout-minutes: 8
Expand Down
30 changes: 26 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,30 @@ on:
branches: [main]

permissions:
contents: write
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Nothing here writes to the repository, so leave no git credential on
# disk for the build and test steps to reach.
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx tsc --noEmit
- run: npx biome check .
- run: npx vitest --run
# Blocking, and repeated from pull-request CI on purpose: this workflow
# runs on push, so it is the only check a change merged without a pull
# request ever sees.
- run: npm audit signatures
- run: npm audit --omit=dev
# See ci.yml for why these carry `--no-install` and why there is no lint step.
- run: npx --no-install tsc --noEmit
- run: npx --no-install vitest --run

- name: Get version
id: version
Expand All @@ -33,8 +42,21 @@ jobs:
# NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# # To enable: add NPM_TOKEN to repository secrets,
# # and add `registry-url: https://registry.npmjs.org` to setup-node above.
# #
# # Heads up: .npmrc sets `ignore-scripts=true` so no dependency install
# # script ever runs. That setting is not limited to dependencies — it also
# # suppresses this package's own `prepublishOnly` hook
# # (`npm run clean && npm run build`), so `npm publish` will NOT build
# # dist/ for you. The explicit `npm run build` step above is what produces
# # the artifact; keep it before any publish step (or run
# # `npm run clean && npm run build` here) so a stale or empty dist/ is
# # never published.

# - name: Create GitHub Release
# run: gh release create "v${{ steps.version.outputs.version }}" --generate-notes
# env:
# GH_TOKEN: ${{ github.token }}
# # To enable: this needs `contents: write`, which the workflow no longer
# # grants. Give it to a separate release job rather than widening the
# # build job — the build runs the whole dev dependency graph, and the
# # release step needs nothing from it but the finished dist/.
8 changes: 8 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Supply-chain hardening: never run a dependency's install lifecycle scripts.
# npm has no allow-list model (pnpm's onlyBuiltDependencies), so this is the
# blunt equivalent — it applies to CI (`npm ci`) and developer laptops alike.
#
# Caveat: this also suppresses THIS project's own lifecycle scripts, including
# `prepublishOnly` (clean + build). Any publish path must build explicitly
# first — see the note in .github/workflows/release.yml.
ignore-scripts=true
Loading
Loading