@@ -54,15 +54,31 @@ jobs:
54
54
app-id : ' ${{ vars.APP_ID }}'
55
55
private-key : ' ${{ secrets.APP_PRIVATE_KEY }}'
56
56
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'
58
73
uses : ' ./'
59
- id : ' gemini_issue_triage '
74
+ id : ' gemini_issue_analysis '
60
75
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
62
77
ISSUE_TITLE : ' ${{ github.event.issue.title }}'
63
78
ISSUE_BODY : ' ${{ github.event.issue.body }}'
64
79
ISSUE_NUMBER : ' ${{ github.event.issue.number }}'
65
80
REPOSITORY : ' ${{ github.repository }}'
81
+ AVAILABLE_LABELS : ' ${{ steps.get_labels.outputs.available_labels }}'
66
82
with :
67
83
gemini_cli_version : ' ${{ vars.GEMINI_CLI_VERSION }}'
68
84
gcp_workload_identity_provider : ' ${{ vars.GCP_WIF_PROVIDER }}'
77
93
"debug": ${{ fromJSON(env.DEBUG || env.ACTIONS_STEP_DEBUG || false) }},
78
94
"maxSessionTurns": 25,
79
95
"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)"
83
97
],
84
98
"telemetry": {
85
99
"enabled": true,
@@ -90,41 +104,88 @@ jobs:
90
104
## Role
91
105
92
106
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
94
108
tools to gather information; do not ask for information to be
95
109
provided.
96
110
97
111
## Steps
98
112
99
- 1. Run: `gh label list` to get all available labels .
113
+ 1. Review the available labels in the environment variable: "${AVAILABLE_LABELS}" .
100
114
2. Review the issue title and body provided in the environment
101
115
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
+ ```
109
125
110
126
## Guidelines
111
127
112
128
- 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
115
129
- Assign all applicable labels based on the issue content
116
130
- 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
+ }
117
157
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'
119
177
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 }}'
121
182
uses : ' actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
122
183
with :
123
184
github-token : ' ${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
124
185
script : |-
125
186
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.'
130
191
})
0 commit comments