diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index a892ddbe13..76752388a7 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -1,12 +1,16 @@ name: '📋 Gemini Scheduled Issue Triage' on: + issues: + types: + - 'opened' + - 'reopened' schedule: - cron: '0 * * * *' # Runs every hour workflow_dispatch: concurrency: - group: '${{ github.workflow }}' + group: '${{ github.workflow }}-${{ github.event.number || github.run_id }}' cancel-in-progress: true defaults: @@ -35,7 +39,17 @@ jobs: private-key: '${{ secrets.PRIVATE_KEY }}' permission-issues: 'write' + - name: 'Get issue from event' + if: github.event_name == 'issues' + id: 'get_issue_from_event' + run: | + set -euo pipefail + ISSUE_JSON=$(jq -n --argjson issue "$${{ toJSON(github.event.issue) }}" '[{number: $issue.number, title: $issue.title, body: $issue.body}]') + echo "issues_to_triage=${ISSUE_JSON}" >> "${GITHUB_OUTPUT}" + echo "✅ Found issue #${{ github.event.issue.number }} from event to triage! 🎯" + - name: 'Find untriaged issues' + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' id: 'find_issues' env: GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}' @@ -76,13 +90,12 @@ jobs: return labelNames; - name: 'Run Gemini Issue Analysis' - if: |- - ${{ steps.find_issues.outputs.issues_to_triage != '[]' }} + if: steps.get_issue_from_event.outputs.issues_to_triage != '[]' || steps.find_issues.outputs.issues_to_triage != '[]' uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0 id: 'gemini_issue_analysis' env: GITHUB_TOKEN: '' # Do not pass any auth token here since this runs on untrusted inputs - ISSUES_TO_TRIAGE: '${{ steps.find_issues.outputs.issues_to_triage }}' + ISSUES_TO_TRIAGE: "${{ steps.get_issue_from_event.outputs.issues_to_triage || steps.find_issues.outputs.issues_to_triage }}" REPOSITORY: '${{ github.repository }}' AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}' with: @@ -284,4 +297,4 @@ jobs: if ((!entry.labels_to_add || entry.labels_to_add.length === 0) && (!entry.labels_to_remove || entry.labels_to_remove.length === 0)) { core.info(`No labels to add or remove for #${issueNumber}, leaving as is`); } - } + } \ No newline at end of file diff --git a/scripts/batch_triage.sh b/scripts/batch_triage.sh new file mode 100755 index 0000000000..c6f1982491 --- /dev/null +++ b/scripts/batch_triage.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# scripts/batch_triage.sh +# Usage: ./scripts/batch_triage.sh [repository] +# Example: ./scripts/batch_triage.sh google-gemini/maintainers-gemini-cli + +set -e + +REPO="${1:-google-gemini/gemini-cli}" +WORKFLOW="gemini-automated-issue-triage.yml" + +echo "🔍 Searching for open issues in '$REPO' that need triage (missing 'area/' label)..." + +# Fetch open issues with number, title, and labels +# We fetch up to 1000 issues. +ISSUES_JSON=$(gh issue list --repo "$REPO" --state open --limit 1000 --json number,title,labels) + +# Filter issues that DO NOT have a label starting with 'area/' +TARGET_ISSUES=$(echo "$ISSUES_JSON" | jq '[.[] | select(.labels | map(.name) | any(startswith("area/")) | not)]') + +COUNT=$(echo "$TARGET_ISSUES" | jq '. | length') + +if [ "$COUNT" -eq 0 ]; then + echo "✅ No issues found needing triage in '$REPO'." + exit 0 +fi + +echo "🚀 Found $COUNT issues to triage." + +# Loop through and trigger workflow +echo "$TARGET_ISSUES" | jq -r '.[] | "\(.number)|\(.title)"' | while IFS="|" read -r number title; do + echo "▶️ Triggering triage for #$number: $title" + + # Trigger the workflow dispatch event + gh workflow run "$WORKFLOW" --repo "$REPO" -f issue_number="$number" + + # Sleep briefly to be nice to the API + sleep 1 +done + +echo "🎉 All triage workflows triggered!"