Gatekeep evals / eval-floor (push) Successful in 8s
Add .github/workflows/gatekeep-pr.yml with uses: ./ and OPENROUTER_API_KEY from secrets. Forge-agnostic API helper for Gitea.
127 lines
4.3 KiB
YAML
127 lines
4.3 KiB
YAML
name: Gatekeep
|
||
description: >
|
||
Parallel multi-model AI PR review across providers. Agreed findings become
|
||
inline comments; disagreements stay in the summary. Fail-closed risk tier.
|
||
Self-contained remote uses: git-url@ref. Provider secrets via free-form env names.
|
||
author: Gatekeep
|
||
|
||
inputs:
|
||
github-token:
|
||
description: Token with pull-requests + checks write
|
||
required: true
|
||
config-dir:
|
||
description: >
|
||
Optional consumer config directory (e.g. .github/gatekeep with providers.yaml).
|
||
Empty = Action defaults/providers.yaml.
|
||
required: false
|
||
default: ""
|
||
models:
|
||
description: >
|
||
Optional override of 2–3 models as comma-separated provider:model
|
||
(or bare names unique in config). Empty = providers.yaml lists.
|
||
required: false
|
||
default: ""
|
||
skip-draft:
|
||
description: Skip draft PRs
|
||
required: false
|
||
default: "true"
|
||
run-verify:
|
||
description: Discover + run verify/benchmarks layer
|
||
required: false
|
||
default: "true"
|
||
retain-artifacts:
|
||
description: Upload last-good style artifacts from verify
|
||
required: false
|
||
default: "true"
|
||
|
||
outputs:
|
||
risk_tier:
|
||
description: Final published risk tier
|
||
value: ${{ steps.review.outputs.risk_tier }}
|
||
security_blocking:
|
||
description: Whether security check should block
|
||
value: ${{ steps.review.outputs.security_blocking }}
|
||
agreed_count:
|
||
description: Count of multi-model agreed findings
|
||
value: ${{ steps.review.outputs.agreed_count }}
|
||
|
||
runs:
|
||
using: composite
|
||
steps:
|
||
- name: Setup Node (stdlib only)
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: "20"
|
||
|
||
- name: Install PyYAML (providers.yaml)
|
||
shell: bash
|
||
run: |
|
||
python3 -m pip install --user pyyaml -q
|
||
python3 -c "import yaml; print('pyyaml ok', yaml.__version__)"
|
||
|
||
- name: Discover entry points
|
||
id: discover
|
||
shell: bash
|
||
env:
|
||
GATEKEEP_ROOT: ${{ github.workspace }}
|
||
GATEKEEP_ACTION: ${{ github.action_path }}
|
||
CONFIG_DIR: ${{ inputs.config-dir }}
|
||
run: bash "${{ github.action_path }}/scripts/discover.sh"
|
||
|
||
- name: Policy floor + security scan
|
||
id: floor
|
||
shell: bash
|
||
env:
|
||
GITHUB_TOKEN: ${{ inputs.github-token }}
|
||
CONFIG_DIR: ${{ inputs.config-dir }}
|
||
GATEKEEP_ROOT: ${{ github.workspace }}
|
||
GATEKEEP_ACTION: ${{ github.action_path }}
|
||
run: bash "${{ github.action_path }}/scripts/policy-floor.sh"
|
||
|
||
- name: Parallel multi-model review
|
||
id: review
|
||
shell: bash
|
||
env:
|
||
GITHUB_TOKEN: ${{ inputs.github-token }}
|
||
CONFIG_DIR: ${{ inputs.config-dir }}
|
||
GATEKEEP_MODELS: ${{ inputs.models }}
|
||
SKIP_DRAFT: ${{ inputs.skip-draft }}
|
||
GATEKEEP_ROOT: ${{ github.workspace }}
|
||
GATEKEEP_ACTION: ${{ github.action_path }}
|
||
POLICY_FLOOR: ${{ steps.floor.outputs.floor }}
|
||
POLICY_REASONS: ${{ steps.floor.outputs.reasons }}
|
||
SCAN_HARD_FAIL: ${{ steps.floor.outputs.scan_hard_fail }}
|
||
DISCOVER_JSON: ${{ steps.discover.outputs.discover_json }}
|
||
# Provider API keys: set free-form names from providers.yaml `key`
|
||
# on this step's env (inherited from the workflow step). Example:
|
||
# env:
|
||
# OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
||
# MY_CUSTOM_KEY: ${{ secrets.MY_CUSTOM_KEY }}
|
||
run: |
|
||
export PATH="$HOME/.local/bin:$PATH"
|
||
# Ensure user-site packages (PyYAML) are importable
|
||
export PYTHONPATH="$(python3 -c 'import site; print(site.getusersitepackages())'):${PYTHONPATH:-}"
|
||
bash "${{ github.action_path }}/scripts/review.sh"
|
||
|
||
- name: Verify layer (benchmarks)
|
||
if: inputs.run-verify == 'true'
|
||
id: verify
|
||
shell: bash
|
||
env:
|
||
GATEKEEP_ROOT: ${{ github.workspace }}
|
||
CONFIG_DIR: ${{ inputs.config-dir }}
|
||
GATEKEEP_ACTION: ${{ github.action_path }}
|
||
DISCOVER_JSON: ${{ steps.discover.outputs.discover_json }}
|
||
run: bash "${{ github.action_path }}/scripts/verify-benchmarks.sh"
|
||
|
||
- name: Retain artifacts
|
||
if: inputs.retain-artifacts == 'true' && always()
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: gatekeep-last-good-${{ github.run_id }}
|
||
path: |
|
||
${{ github.workspace }}/.gatekeep/out/
|
||
${{ github.workspace }}/.gatekeep/verify/
|
||
if-no-files-found: ignore
|
||
retention-days: 14
|