Security Review (Manual) #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security Review (Manual) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| servers: | |
| description: "Comma-separated list of local server names to audit (leave blank for all)." | |
| required: false | |
| default: "" | |
| agent: | |
| description: "Optional reviewer agent (claude or codex)." | |
| required: false | |
| default: "" | |
| model: | |
| description: "Optional reviewer model override." | |
| required: false | |
| default: "" | |
| timeout_secs: | |
| description: "Optional reviewer timeout in seconds (defaults to 1800)." | |
| required: false | |
| default: "" | |
| concurrency: | |
| group: security-review-manual-${{ github.run_id }} | |
| cancel-in-progress: false | |
| jobs: | |
| full-audit: | |
| name: Execute Full Audit | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Install Task | |
| uses: arduino/setup-task@v2 | |
| with: | |
| version: 3.x | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Collect audit targets | |
| id: collect | |
| run: | | |
| set -euo pipefail | |
| task ci -- collect-full-audit \ | |
| --workspace "${{ github.workspace }}" \ | |
| --servers "${{ github.event.inputs.servers }}" \ | |
| --output-json audit-targets.json | |
| if jq -e '. | length > 0' audit-targets.json >/dev/null; then | |
| echo "has_targets=true" >> "$GITHUB_OUTPUT" | |
| echo "targets=audit-targets.json" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No audit targets identified; exiting." >&2 | |
| echo "has_targets=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Run security reviews | |
| if: steps.collect.outputs.has_targets == 'true' | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| REVIEW_AGENT_INPUT: ${{ github.event.inputs.agent }} | |
| REVIEW_MODEL_INPUT: ${{ github.event.inputs.model }} | |
| REVIEW_TIMEOUT_INPUT: ${{ github.event.inputs.timeout_secs }} | |
| run: | | |
| set -uo pipefail | |
| agent="${REVIEW_AGENT_INPUT:-}" | |
| if [ -z "$agent" ]; then | |
| agent="claude" | |
| fi | |
| model="${REVIEW_MODEL_INPUT:-}" | |
| timeout_secs="${REVIEW_TIMEOUT_INPUT:-1800}" | |
| mkdir -p reports | |
| while read -r target; do | |
| server=$(echo "$target" | jq -r '.server') | |
| project=$(echo "$target" | jq -r '.project') | |
| head_commit=$(echo "$target" | jq -r '.commit') | |
| if [ -z "$project" ] || [ "$project" = "null" ]; then | |
| echo "Skipping $server: missing project URL." >&2 | |
| continue | |
| fi | |
| if [ -z "$head_commit" ] || [ "$head_commit" = "null" ]; then | |
| echo "Skipping $server: missing commit information." >&2 | |
| continue | |
| fi | |
| report_path="reports/${server}.md" | |
| labels_path="reports/${server}-labels.txt" | |
| cmd=(task security-reviewer -- \ | |
| --agent "$agent" \ | |
| --repo "$project" \ | |
| --head "$head_commit" \ | |
| --target-label "$server" \ | |
| --output "$report_path" \ | |
| --labels-output "$labels_path" \ | |
| --timeout "$timeout_secs") | |
| if [ -n "$model" ]; then | |
| cmd+=(--model "$model") | |
| fi | |
| if ! "${cmd[@]}"; then | |
| echo "::error::Security review failed for $server" | |
| fi | |
| done < <(jq -c '.[]' "${{ steps.collect.outputs.targets }}") | |
| - name: Upload security reports | |
| if: steps.collect.outputs.has_targets == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: security-reports | |
| path: reports/ | |
| if-no-files-found: warn |