Files
openwork/.github/workflows/warden.yml
T

135 lines
5.3 KiB
YAML

name: Warden
# Trigger types must stay aligned with the warden.toml trigger actions:
# an event that runs this workflow but matches no warden trigger would
# produce findings_count=0 without analysis and wrongly grant clearance.
# (ready_for_review is deliberately absent — warden does not support it;
# draft-to-ready PRs get analyzed on their next push.)
on:
pull_request:
types: [opened, synchronize, reopened]
branches: [dev]
permissions:
# contents:write is required by GitHub to resolve review threads via
# GraphQL; Warden auto-resolves its own findings once fixed, which the
# ruleset's required_review_thread_resolution depends on.
contents: write
pull-requests: write
checks: write
concurrency:
group: warden-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
slow-proof:
# Keep PR-controlled matching code isolated from Warden credentials.
if: >-
!github.event.pull_request.draft &&
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 10
steps:
- name: Checkout pull request
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
fetch-depth: 0
persist-credentials: false
- name: Match slow proof
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
node evals/scripts/spec-impact.mjs \
--base "$BASE_SHA" \
--head "$HEAD_SHA" \
--summary "$GITHUB_STEP_SUMMARY"
warden:
# Skip drafts and fork PRs: forks have no secrets, so analysis cannot
# run (and clearance is fork-blocked in warden-clearance.yml anyway).
if: >-
!github.event.pull_request.draft &&
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 30
env:
WARDEN_MODEL: ${{ secrets.WARDEN_MODEL }}
WARDEN_OPENAI_API_KEY: ${{ secrets.WARDEN_OPENAI_API_KEY }}
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Analyze
id: analyze
uses: getsentry/warden@8759014a14130cd2b82e59d3fb450a7385721221 # v0
with:
mode: analyze
- name: Report
uses: getsentry/warden@8759014a14130cd2b82e59d3fb450a7385721221 # v0
with:
mode: report
findings-file: ${{ steps.analyze.outputs.findings-file }}
# Consumed by warden-clearance.yml (workflow_run). blocking_count excludes
# advisory desktop↔den sync findings so they notify without withholding
# clearance. The clearance workflow refuses to act on PRs that touch review
# machinery, so this artifact cannot be forged without tripping that guard.
- name: Write clearance summary
env:
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
FINDINGS_COUNT: ${{ steps.analyze.outputs.findings-count }}
HIGH_COUNT: ${{ steps.analyze.outputs.high-count }}
FINDINGS_FILE: ${{ steps.analyze.outputs.findings-file }}
run: |
set -euo pipefail
if [ -n "$FINDINGS_FILE" ] && [ -f "$FINDINGS_FILE" ] && counts="$(jq -ce '
{
security_count: ([.skills[] | select(.name == "diff-security-review") | .findings | length] | add // 0),
sync_blocking_count: ([.skills[] | select(.name == "desktop-den-sync-review") | .findings[] | select(.severity != "medium" and .severity != "low")] | length),
sync_advisory_count: ([.skills[] | select(.name == "desktop-den-sync-review") | .findings[] | select(.severity == "medium" or .severity == "low")] | length)
}
' "$FINDINGS_FILE" 2>/dev/null)"; then
security_count="$(jq -r '.security_count' <<< "$counts")"
sync_blocking_count="$(jq -r '.sync_blocking_count' <<< "$counts")"
sync_advisory_count="$(jq -r '.sync_advisory_count' <<< "$counts")"
blocking_count="$((security_count + sync_blocking_count))"
else
security_count="$FINDINGS_COUNT"
sync_blocking_count=0
sync_advisory_count=0
blocking_count="$FINDINGS_COUNT"
fi
jq -n \
--arg sha "$HEAD_SHA" \
--arg count "$FINDINGS_COUNT" \
--arg high "$HIGH_COUNT" \
--arg blocking "$blocking_count" \
--arg security "$security_count" \
--arg sync_blocking "$sync_blocking_count" \
--arg sync_advisory "$sync_advisory_count" \
'{
head_sha: $sha,
findings_count: ($count | tonumber),
high_count: ($high | tonumber),
blocking_count: ($blocking | tonumber),
security_count: ($security | tonumber),
sync_blocking_count: ($sync_blocking | tonumber),
sync_advisory_count: ($sync_advisory | tonumber)
}' \
> warden-summary.json
cat warden-summary.json
- name: Upload clearance summary
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: warden-summary
path: warden-summary.json