Files
orca/.github/workflows/dependency-security.yml
T
OrcaWinandOrcaWin 791502fae4 ci: move secondary, scheduled and contract workflows to GitHub-hosted runners (#34568)
* ci: move secondary, scheduled and contract workflows to GitHub-hosted runners

Public-repo standard hosted runners are free under Enterprise. Release, build,
benchmark, e2e and unit workflows stay on Blacksmith. ci-xterm-cache seeds both
cache stores since its PR consumer's pool is undecided.

* test(pi): resolve the smoke bundle's external packages from the repo

#34148 pulled zod into the commit-message planner graph; the bundle in the
OS temp dir could not resolve it on any runner.

* ci(unit): use four workers on the hosted four-core x64 runner

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 16:15:14 -07:00

179 lines
6.5 KiB
YAML

name: Dependency security
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
paths:
- '**/package.json'
- '**/pnpm-lock.yaml'
- '**/pnpm-workspace.yaml'
- '**/.npmrc'
- 'native/**/Cargo.toml'
- 'native/**/Cargo.lock'
- 'config/dependency-security-exceptions.json'
- 'config/cargo-deny.toml'
- 'config/scripts/*dependency-security*'
- 'config/scripts/pnpm-cli-invocation.mjs'
- 'config/pnpmfile.cjs'
- '**/patches/**'
- '.github/workflows/dependency-security.yml'
- '.github/workflows/release-cut.yml'
- '.github/actions/install-node-dependencies/**'
- '.github/actions/prepare-dependency-audit/**'
- 'src/packages/process-host/**'
workflow_call:
inputs:
ref:
description: Exact release tag to audit using the workflow commit's tooling
required: true
type: string
runner:
description: Runner override for GitHub-hosted signing provenance.
type: string
default: ubuntu-24.04
secrets:
SLACK_WEBHOOK_URL:
description: Existing orca-releases incoming webhook
required: false
workflow_dispatch:
permissions:
contents: read
concurrency:
group: dependency-security-${{ inputs.ref && github.run_id || github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
ORCA_BACKGROUND_LAUNCH: '1'
jobs:
javascript:
if: github.event_name != 'pull_request' || github.event.pull_request.draft != true
runs-on: ${{ inputs.runner || 'ubuntu-24.04' }}
timeout-minutes: 15
outputs:
audit_result: ${{ steps.audit.outcome }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.workflow_sha }}
persist-credentials: false
- uses: ./.github/actions/install-node-dependencies
- uses: ./.github/actions/prepare-dependency-audit
if: inputs.ref != ''
with:
ref: ${{ inputs.ref }}
- name: Audit JavaScript lockfiles
id: audit
continue-on-error: true
shell: bash
env:
RELEASE_REF: ${{ inputs.ref }}
run: |
if [ -n "$RELEASE_REF" ]; then
pnpm check:dependencies candidate . mobile
else
pnpm check:dependencies
fi
- uses: actions/upload-artifact@v7
if: always()
with:
name: dependency-security-javascript
path: tmp/dependency-security/*.json
if-no-files-found: error
rust:
if: github.event_name != 'pull_request' || github.event.pull_request.draft != true
runs-on: ${{ inputs.runner || 'ubuntu-24.04' }}
timeout-minutes: 20
outputs:
audit_result: ${{ steps.audit.outcome }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.workflow_sha }}
persist-credentials: false
- uses: actions/cache@v5
id: scanner
with:
path: ~/.cargo/bin/cargo-deny
key: cargo-deny-0.20.2-${{ runner.os }}-${{ runner.arch }}
- if: steps.scanner.outputs.cache-hit != 'true'
run: cargo install cargo-deny --locked --version 0.20.2
- uses: ./.github/actions/prepare-dependency-audit
if: inputs.ref != ''
with:
ref: ${{ inputs.ref }}
- name: Audit native Rust lockfiles
id: audit
continue-on-error: true
shell: bash
working-directory: ${{ inputs.ref != '' && 'candidate' || '.' }}
run: |
set -euo pipefail
report_dir="$GITHUB_WORKSPACE/tmp/dependency-security"
mkdir -p "$report_dir"
status=0
for manifest in native/*/Cargo.toml; do
name="$(basename "$(dirname "$manifest")")"
cargo deny --manifest-path "$manifest" --locked --config "$GITHUB_WORKSPACE/config/cargo-deny.toml" check advisories 2>&1 | tee "$report_dir/$name.log" || status=1
done
exit "$status"
- uses: actions/upload-artifact@v7
if: always()
with:
name: dependency-security-rust
path: tmp/dependency-security/*.log
if-no-files-found: error
notify:
needs: [javascript, rust]
if: >-
!cancelled() && github.repository == 'stablyai/orca' &&
(needs.javascript.outputs.audit_result == 'failure' ||
needs.rust.outputs.audit_result == 'failure' ||
needs.javascript.result == 'failure' || needs.rust.result == 'failure')
runs-on: ${{ inputs.runner || 'ubuntu-24.04' }}
timeout-minutes: 5
steps:
- name: Send dependency review to orca-releases
uses: actions/github-script@v8
continue-on-error: true
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
RELEASE_REF: ${{ inputs.ref }}
AUDIT_RESULTS: ${{ toJSON(needs) }}
with:
script: |
if (!process.env.SLACK_WEBHOOK_URL) {
core.notice('Slack notification unavailable for this run; see the dependency reports in Actions.')
return
}
const results = JSON.parse(process.env.AUDIT_RESULTS)
const checks = [['javascript', 'JavaScript'], ['rust', 'Rust']].map(([job, label]) => {
const result = results[job]
const status = result.result !== 'success' ? 'scan incomplete'
: result.outputs.audit_result === 'success' ? 'passed' : 'review suggested'
return `${label}: ${status}`
})
const target = context.payload.pull_request
? `PR #${context.payload.pull_request.number}`
: process.env.RELEASE_REF || context.ref
const runUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
const text = `Orca dependency review for ${target}\n${checks.join(' · ')}\nReports and logs: ${runUrl}`
let response
try {
response = await fetch(process.env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, mrkdwn: false, unfurl_links: false, unfurl_media: false }),
signal: AbortSignal.timeout(15000)
})
} catch {
throw new Error('Slack dependency review notification could not be sent')
}
if (!response.ok) {
throw new Error(`Slack dependency review notification returned HTTP ${response.status}`)
}