diff --git a/.github/workflows/gemini-automated-issue-triage.yml b/.github/workflows/gemini-automated-issue-triage.yml index b1251fee66..47801fcb9b 100644 --- a/.github/workflows/gemini-automated-issue-triage.yml +++ b/.github/workflows/gemini-automated-issue-triage.yml @@ -93,7 +93,9 @@ jobs: - name: 'Generate GitHub App Token' id: 'generate_token' - if: ${{ secrets.APP_ID != '' }} + env: + APP_ID: '${{ secrets.APP_ID }}' + if: "${{ env.APP_ID != '' }}" uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2 with: app-id: '${{ secrets.APP_ID }}' diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 76752388a7..6c3fbb7c63 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -40,16 +40,18 @@ jobs: permission-issues: 'write' - name: 'Get issue from event' - if: github.event_name == 'issues' + if: "github.event_name == 'issues'" id: 'get_issue_from_event' + env: + ISSUE_EVENT: '${{ toJSON(github.event.issue) }}' run: | set -euo pipefail - ISSUE_JSON=$(jq -n --argjson issue "$${{ toJSON(github.event.issue) }}" '[{number: $issue.number, title: $issue.title, body: $issue.body}]') + ISSUE_JSON=$(echo "$ISSUE_EVENT" | jq -c '[{number: .number, title: .title, body: .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' + if: "github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'" id: 'find_issues' env: GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}' @@ -90,12 +92,14 @@ jobs: return labelNames; - name: 'Run Gemini Issue Analysis' - if: steps.get_issue_from_event.outputs.issues_to_triage != '[]' || steps.find_issues.outputs.issues_to_triage != '[]' + if: |- + (steps.get_issue_from_event.outputs.issues_to_triage != '' && steps.get_issue_from_event.outputs.issues_to_triage != '[]') || + (steps.find_issues.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.get_issue_from_event.outputs.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: @@ -234,16 +238,23 @@ jobs: core.info(`Raw labels JSON: ${rawLabels}`); let parsedLabels; try { + // First, try to parse the raw output as JSON. + parsedLabels = JSON.parse(rawLabels.trim()); + } catch (jsonError) { + // If that fails, check for a markdown code block. + core.info(`Direct JSON parsing failed: ${jsonError.message}. Trying to extract from a markdown block.`); const jsonMatch = rawLabels.match(/```json\s*([\s\S]*?)\s*```/); - if (!jsonMatch || !jsonMatch[1]) { - throw new Error("Could not find a ```json ... ``` block in the output."); + if (jsonMatch && jsonMatch[1]) { + try { + parsedLabels = JSON.parse(jsonMatch[1].trim()); + } catch (markdownError) { + core.setFailed(`Failed to parse JSON even after extracting from markdown block: ${markdownError.message}\nRaw output: ${rawLabels}`); + return; + } + } else { + core.setFailed(`Output is not valid JSON and does not contain a JSON markdown block.\nRaw output: ${rawLabels}`); + return; } - const jsonString = jsonMatch[1].trim(); - parsedLabels = JSON.parse(jsonString); - core.info(`Parsed labels JSON: ${JSON.stringify(parsedLabels)}`); - } catch (err) { - core.setFailed(`Failed to parse labels JSON from Gemini output: ${err.message}\nRaw output: ${rawLabels}`); - return; } for (const entry of parsedLabels) { @@ -297,4 +308,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 + }