Skip to content

PR Discovery

PR Discovery #38

Workflow file for this run

# .github/workflows/pr-discovery.yml
name: PR Discovery
on:
schedule:
- cron: "17 4 * * *"
workflow_dispatch:
concurrency:
group: pr-discovery
cancel-in-progress: false
permissions:
contents: read
pull-requests: read
env:
IF_REPO_ROOT: ${{ github.workspace }}
jobs:
gate:
name: Autonomy gate
uses: ./.github/workflows/autonomy-check.yml
with:
requested_action: discovery-scan
discover:
name: Discover upstream PRs
needs: gate
if: needs.gate.outputs.proceed == 'true'
runs-on: ubuntu-latest
environment: bot-credentials
outputs:
batch_count: ${{ steps.run.outputs.batch_count }}
steps:
- name: Generate GH App token
id: app-token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
# NOTE: The actual Claude action wiring (anthropics/claude-code-action) is implemented
# in a separate bead. This step is a placeholder that calls the action in the same form
# as the rest of the pipeline; CI will skip/fail gracefully until the action is wired.
- name: Load pr-discovery prompt
id: load-prompt
shell: bash
run: |
{
echo 'prompt<<__EOF_PROMPT__'
cat .if-fork/prompts/pr-discovery.md
echo
echo '__EOF_PROMPT__'
} >> "$GITHUB_OUTPUT"
- name: Run discovery (Claude Haiku)
id: run
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: ${{ steps.load-prompt.outputs.prompt }}
claude_args: >-
--max-turns 8
--model claude-haiku-4-5
--allowedTools Bash,Read,Grep,mcp__github__list_pull_requests,mcp__github__search_pull_requests,mcp__github__issue_write
--disallowedTools Edit,Write
github_token: ${{ steps.app-token.outputs.token }}
env:
CONFIG_PATH: .if-fork/config.yaml
LEDGER_PATH: .if-fork/patch-ledger.jsonl
STATE_PATH: .if-fork/patch-state.json
BATCH_ISSUE_PATH: /tmp/batch-issue.md
- name: Upload discovered PRs artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: discovered-prs-${{ github.run_id }}
path: /tmp/discovered-batch.json
retention-days: 30
if-no-files-found: ignore
record:
name: Record discovered events in ledger
needs: [gate, discover]
if: needs.discover.result == 'success'
runs-on: ubuntu-latest
environment: bot-credentials
steps:
- name: Generate GH App token
id: app-token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Download discovered PRs artifact
uses: actions/download-artifact@v4
with:
name: discovered-prs-${{ github.run_id }}
path: /tmp/
continue-on-error: true
- name: Import bot GPG key
uses: ./.github/actions/import-bot-gpg
with:
gpg-private-key: ${{ secrets.GH_BOT_GPG_KEY }}
gpg-key-id: ${{ secrets.GH_BOT_GPG_KEY_ID }}
gpg-fingerprint: ${{ secrets.GH_BOT_GPG_FINGERPRINT }}
- name: Emit ledger events for discovered PRs
run: |
if [ -f /tmp/discovered-batch.json ]; then
python tools/ledger-event.py \
--event discovered \
--pr-number 0 \
--head-sha "${{ github.sha }}" \
--actor pr-discovery \
--details-json "{\"batch_date\": \"$(date -u +%Y-%m-%d)\", \"run_url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \
--push
else
echo "::notice::No discovered-batch.json artifact; nothing to record."
fi
env:
GIT_AUTHOR_NAME: "Claude (Initial Force WPF Bot)"
GIT_AUTHOR_EMAIL: "wpf-bot@initialforce.com"
GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Trigger review for discovered PRs if new batch found
if: fromJSON(needs.discover.outputs.batch_count || '0') > 0
run: |
gh api repos/${{ github.repository }}/dispatches \
--field event_type=pr-discovered \
--field "client_payload[batch_date]=$(date -u +%Y-%m-%d)"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}