Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ updates:
directory: "/"
schedule:
interval: weekly
# Group every github-actions SHA bump into a single weekly PR so
# the SHA-pinned `uses:` lines (Scorecard Pinned-Dependencies)
# don't generate ~10 PRs per release cycle.
groups:
github-actions:
patterns: ["*"]

# pip ecosystem for packages/eval moved to
# github.com/theagenticguy/opencodehub-testbed as part of the M2 split.
29 changes: 15 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- run: pnpm install --frozen-lockfile --ignore-scripts
- run: pnpm exec biome ci .

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- run: pnpm install --frozen-lockfile --ignore-scripts
- name: Build workspace .d.ts so cross-package types resolve
run: pnpm -r build
Expand All @@ -43,11 +43,12 @@ jobs:
env:
MISE_NODE_VERSION: ${{ matrix.node-version }}
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- name: Ensure node-gyp is available for native tree-sitter build
if: matrix.node-version == 22
run: npm i -g node-gyp
# Pin node-gyp version (Scorecard Pinned-Dependencies / npmCommand)
run: npm i -g node-gyp@12.3.0
# Node 22: let native tree-sitter grammars postinstall (scripts enabled)
# so the OCH_NATIVE_PARSER=1 test path has working N-API bindings.
# Node 24: skip postinstall — native grammars can't build against the
Expand All @@ -66,23 +67,23 @@ jobs:
sarif-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- run: pnpm install --frozen-lockfile --ignore-scripts
- run: pnpm -F @opencodehub/sarif build
- run: pnpm -F @opencodehub/sarif run validate-schema

banned-strings:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- run: bash scripts/check-banned-strings.sh

licenses:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- run: pnpm install --frozen-lockfile --ignore-scripts
- name: license allowlist
run: >
Expand All @@ -102,7 +103,7 @@ jobs:
contents: read
security-events: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install osv-scanner
run: |
curl -sL -o /tmp/osv-scanner \
Expand All @@ -114,7 +115,7 @@ jobs:
--lockfile=pnpm-lock.yaml \
--format=sarif \
--output=osv.sarif || true
- uses: github/codeql-action/upload-sarif@v4
- uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
if: always()
with:
sarif_file: osv.sarif
Expand Down
16 changes: 10 additions & 6 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,31 @@ on:
schedule:
- cron: "27 4 * * 3"

# Top-level least-privilege; the analyze job opts into the writes
# CodeQL needs (security-events) explicitly. (Scorecard Token-Permissions)
permissions:
actions: read
contents: read
security-events: write

jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [javascript-typescript, python]
steps:
- uses: actions/checkout@v6
- uses: github/codeql-action/init@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with:
languages: ${{ matrix.language }}
queries: security-and-quality
- uses: github/codeql-action/autobuild@v4
- uses: github/codeql-action/analyze@v4
- uses: github/codeql-action/autobuild@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
- uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with:
category: "/language:${{ matrix.language }}"
4 changes: 2 additions & 2 deletions .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- uses: jdx/mise-action@v4
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- run: pnpm install --frozen-lockfile --ignore-scripts
- name: Validate PR commit messages
run: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/och-self-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ jobs:
security-events: write
issues: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0

- uses: jdx/mise-action@v4
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4

- name: Install dependencies
run: pnpm install --frozen-lockfile
Expand Down Expand Up @@ -64,14 +64,14 @@ jobs:

- name: Upload SARIF artifact
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: och-self-scan-sarif
path: .codehub/scan.sarif

- name: Upload SARIF to code scanning
if: always()
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with:
sarif_file: .codehub/scan.sarif
category: opencodehub-self
4 changes: 2 additions & 2 deletions .github/workflows/osv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
contents: read
security-events: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install osv-scanner
run: |
curl -sL -o /tmp/osv-scanner \
Expand All @@ -36,7 +36,7 @@ jobs:
--lockfile=pnpm-lock.yaml \
--format=sarif \
--output=osv.sarif || true
- uses: github/codeql-action/upload-sarif@v4
- uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
if: always()
with:
sarif_file: osv.sarif
Expand Down
141 changes: 141 additions & 0 deletions .github/workflows/pre-release-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Pre-release gate.
#
# This workflow runs on the release-please PR (branches starting with
# `release-please--`) and adds tag-blocking checks ON TOP of the existing
# CI / CodeQL / Semgrep / OSV / OCH self-scan / Scorecard suite. The
# existing scans already attach to every PR via their own workflows; this
# file does NOT duplicate them. It runs the additional checks that only
# matter at release time:
#
# - npm-audit at high+ severity
# - pnpm lockfile integrity (frozen + no lifecycle scripts)
# - detect-secrets full sweep
# - license allowlist re-assertion
# - aggregate "all checks green" gate that blocks merge if anything failed
#
# The aggregator job is the required status check on the release branch.
# Configure branch protection on `main` to require this job's name (the
# job key, not the display name) before merging release PRs.
#
# Operator runbook: docs/RELEASE.md.

name: Pre-Release Gate

on:
pull_request:
types: [opened, synchronize, reopened]
branches: [main]

concurrency:
group: pre-release-gate-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
contents: read

jobs:
# The whole workflow only fires on release-please-authored PRs. We
# short-circuit on every other PR via the `if:` on each job so we don't
# waste runner minutes; the aggregator below treats "skipped" as pass.
npm-audit:
name: npm audit (high+)
if: startsWith(github.head_ref, 'release-please--')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: jdx/mise-action@c37c93293d6b742fc901e1406b8f764f6fb19dac # v2.4.4
- name: Run pnpm audit at high+ severity
run: pnpm audit --audit-level=high --prod

lockfile-integrity:
name: pnpm-lock integrity
if: startsWith(github.head_ref, 'release-please--')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: jdx/mise-action@c37c93293d6b742fc901e1406b8f764f6fb19dac # v2.4.4
# Frozen + ignore-scripts is the strictest install path: any lockfile
# drift, missing entry, or sneaky postinstall fails the job.
- name: Install with frozen lockfile and no lifecycle scripts
run: pnpm install --frozen-lockfile --ignore-scripts

detect-secrets:
name: detect-secrets full sweep
if: startsWith(github.head_ref, 'release-please--')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Install detect-secrets
run: pip install --user 'detect-secrets==1.5.0'
- name: Sweep tracked tree
run: |
set -euo pipefail
export PATH="$HOME/.local/bin:$PATH"
# The repo already ships .secrets.baseline (per Track B). The
# release gate re-asserts that no NEW secrets have crept in.
if [ -f .secrets.baseline ]; then
detect-secrets scan --baseline .secrets.baseline
else
detect-secrets scan --all-files > /tmp/scan.json
FOUND=$(python3 -c "import json,sys; d=json.load(open('/tmp/scan.json')); n=sum(len(v) for v in d.get('results',{}).values()); print(n)")
if [ "$FOUND" != "0" ]; then
echo "detect-secrets found $FOUND potential secrets" >&2
cat /tmp/scan.json
exit 1
fi
fi

licenses-reassert:
name: License allowlist re-assert
if: startsWith(github.head_ref, 'release-please--')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: jdx/mise-action@c37c93293d6b742fc901e1406b8f764f6fb19dac # v2.4.4
- run: pnpm install --frozen-lockfile --ignore-scripts
- name: license allowlist
run: >
pnpm exec license-checker-rseidelsohn
--onlyAllow 'Apache-2.0;MIT;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0;BlueOak-1.0.0;0BSD'
--excludePrivatePackages
--production

# ---------------------------------------------------------------------------
# Aggregator. ALWAYS runs (even on non-release PRs) so the required check
# name resolves uniformly. On non-release PRs every dependency is skipped
# and the aggregator is a no-op pass. On release PRs every dependency
# must succeed.
# ---------------------------------------------------------------------------
pre-release-gate:
name: Pre-release gate (aggregate)
needs:
- npm-audit
- lockfile-integrity
- detect-secrets
- licenses-reassert
if: always()
runs-on: ubuntu-latest
steps:
- name: Aggregate dependency results
env:
NEEDS: ${{ toJson(needs) }}
run: |
set -euo pipefail
echo "$NEEDS"
# Fail if any dependency was failure / cancelled. Skipped is
# treated as pass so non-release PRs do not get blocked.
FAILED=$(echo "$NEEDS" | python3 -c "import json,sys; d=json.load(sys.stdin); print(','.join(k for k,v in d.items() if v.get('result') in ('failure','cancelled')))")
if [ -n "$FAILED" ]; then
echo "pre-release gate FAILED: $FAILED" >&2
exit 1
fi
echo "pre-release gate OK"
Loading
Loading