@@ -54,15 +54,31 @@ jobs:
5454 app-id : ' ${{ vars.APP_ID }}'
5555 private-key : ' ${{ secrets.APP_PRIVATE_KEY }}'
5656
57- - name : ' Run Gemini Issue Triage'
57+ - name : ' Get Repository Labels'
58+ id : ' get_labels'
59+ uses : ' actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
60+ with :
61+ github-token : ' ${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
62+ script : |-
63+ const { data: labels } = await github.rest.issues.listLabelsForRepo({
64+ owner: context.repo.owner,
65+ repo: context.repo.repo,
66+ });
67+ const labelNames = labels.map(label => label.name);
68+ core.setOutput('available_labels', labelNames.join(','));
69+ core.info(`Found ${labelNames.length} labels: ${labelNames.join(', ')}`);
70+ return labelNames;
71+
72+ - name : ' Run Gemini Issue Analysis'
5873 uses : ' ./'
59- id : ' gemini_issue_triage '
74+ id : ' gemini_issue_analysis '
6075 env :
61- GITHUB_TOKEN : ' ${{ steps.generate_token.outputs. token || secrets.GITHUB_TOKEN }} '
76+ GITHUB_TOKEN : ' ' # Do not pass any auth token here since this runs on untrusted inputs
6277 ISSUE_TITLE : ' ${{ github.event.issue.title }}'
6378 ISSUE_BODY : ' ${{ github.event.issue.body }}'
6479 ISSUE_NUMBER : ' ${{ github.event.issue.number }}'
6580 REPOSITORY : ' ${{ github.repository }}'
81+ AVAILABLE_LABELS : ' ${{ steps.get_labels.outputs.available_labels }}'
6682 with :
6783 gemini_cli_version : ' ${{ vars.GEMINI_CLI_VERSION }}'
6884 gcp_workload_identity_provider : ' ${{ vars.GCP_WIF_PROVIDER }}'
7793 "debug": ${{ fromJSON(env.DEBUG || env.ACTIONS_STEP_DEBUG || false) }},
7894 "maxSessionTurns": 25,
7995 "coreTools": [
80- "run_shell_command(echo)",
81- "run_shell_command(gh label list)",
82- "run_shell_command(gh issue edit)"
96+ "run_shell_command(echo)"
8397 ],
8498 "telemetry": {
8599 "enabled": true,
@@ -90,41 +104,88 @@ jobs:
90104 ## Role
91105
92106 You are an issue triage assistant. Analyze the current GitHub issue
93- and apply the most appropriate existing labels. Use the available
107+ and identify the most appropriate existing labels. Use the available
94108 tools to gather information; do not ask for information to be
95109 provided.
96110
97111 ## Steps
98112
99- 1. Run: `gh label list` to get all available labels .
113+ 1. Review the available labels in the environment variable: "${AVAILABLE_LABELS}" .
100114 2. Review the issue title and body provided in the environment
101115 variables: "${ISSUE_TITLE}" and "${ISSUE_BODY}".
102- 3. Classify issues by their kind (bug, enhancement, documentation,
103- cleanup, etc) and their priority (p0, p1, p2, p3). Set the
104- labels accoridng to the format `kind/*` and `priority/*` patterns.
105- 4. Apply the selected labels to this issue using:
106- `gh issue edit "${ISSUE_NUMBER}" --add-label "label1,label2"`
107- 5. If the "status/needs-triage" label is present, remove it using:
108- `gh issue edit "${ISSUE_NUMBER}" --remove-label "status/needs-triage"`
116+ 3. Classify the issue by the appropriate labels from the available labels.
117+ 4. Output the appropriate labels for this issue in JSON format with explanation, for example:
118+ ```
119+ {"labels_to_set": ["kind/bug", "priority/p0"], "explanation": "This is a critical bug report affecting main functionality"}
120+ ```
121+ 5. If the issue cannot be classified using the available labels, output:
122+ ```
123+ {"labels_to_set": [], "explanation": "Unable to classify this issue with available labels"}
124+ ```
109125
110126 ## Guidelines
111127
112128 - Only use labels that already exist in the repository
113- - Do not add comments or modify the issue content
114- - Triage only the current issue
115129 - Assign all applicable labels based on the issue content
116130 - Reference all shell variables as "${VAR}" (with quotes and braces)
131+ - Output only valid JSON format
132+ - Do not include any explanation or additional text, just the JSON
133+
134+ - name : ' Apply Labels to Issue'
135+ if : |-
136+ ${{ steps.gemini_issue_analysis.outputs.summary != '' }}
137+ env :
138+ REPOSITORY : ' ${{ github.repository }}'
139+ ISSUE_NUMBER : ' ${{ github.event.issue.number }}'
140+ LABELS_OUTPUT : ' ${{ steps.gemini_issue_analysis.outputs.summary }}'
141+ uses : ' actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
142+ with :
143+ github-token : ' ${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
144+ script : |-
145+ // Strip code block markers if present
146+ const rawLabels = process.env.LABELS_OUTPUT;
147+ core.info(`Raw labels JSON: ${rawLabels}`);
148+ let parsedLabels;
149+ try {
150+ const trimmedLabels = rawLabels.replace(/^```(?:json)?\s*/, '').replace(/\s*```$/, '').trim();
151+ parsedLabels = JSON.parse(trimmedLabels);
152+ core.info(`Parsed labels JSON: ${JSON.stringify(parsedLabels)}`);
153+ } catch (err) {
154+ core.setFailed(`Failed to parse labels JSON from Gemini output: ${err.message}\nRaw output: ${rawLabels}`);
155+ return;
156+ }
117157
118- - name : ' Post Issue Triage Failure Comment'
158+ const issueNumber = parseInt(process.env.ISSUE_NUMBER);
159+
160+ // Set labels based on triage result
161+ if (parsedLabels.labels_to_set && parsedLabels.labels_to_set.length > 0) {
162+ await github.rest.issues.setLabels({
163+ owner: context.repo.owner,
164+ repo: context.repo.repo,
165+ issue_number: issueNumber,
166+ labels: parsedLabels.labels_to_set
167+ });
168+ const explanation = parsedLabels.explanation ? ` - ${parsedLabels.explanation}` : '';
169+ core.info(`Successfully set labels for #${issueNumber}: ${parsedLabels.labels_to_set.join(', ')}${explanation}`);
170+ } else {
171+ // If no labels to set, leave the issue as is
172+ const explanation = parsedLabels.explanation ? ` - ${parsedLabels.explanation}` : '';
173+ core.info(`No labels to set for #${issueNumber}, leaving as is${explanation}`);
174+ }
175+
176+ - name : ' Post Issue Analysis Failure Comment'
119177 if : |-
120- ${{ failure() && steps.gemini_issue_triage.outcome == 'failure' }}
178+ ${{ failure() && steps.gemini_issue_analysis.outcome == 'failure' }}
179+ env :
180+ ISSUE_NUMBER : ' ${{ github.event.issue.number }}'
181+ RUN_URL : ' ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
121182 uses : ' actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
122183 with :
123184 github-token : ' ${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
124185 script : |-
125186 github.rest.issues.createComment({
126- owner: '${{ github.repository }}'.split('/')[0] ,
127- repo: '${{ github.repository }}'.split('/')[1] ,
128- issue_number: '${{ github.event.issue.number }}' ,
129- body: 'There is a problem with the Gemini CLI issue triaging. Please check the [action logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id } }) for details.'
187+ owner: context.repo.owner ,
188+ repo: context.repo.repo ,
189+ issue_number: parseInt(process.env.ISSUE_NUMBER) ,
190+ body: 'There is a problem with the Gemini CLI issue triaging. Please check the [action logs](${process.env.RUN_URL }) for details.'
130191 })
0 commit comments