396 lines
21 KiB
YAML
396 lines
21 KiB
YAML
name: '📋 Gemini Scheduled Issue Triage'
|
|
|
|
on:
|
|
schedule:
|
|
- cron: '0 * * * *' # Runs every hour
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: '${{ github.workflow }}'
|
|
cancel-in-progress: true
|
|
|
|
defaults:
|
|
run:
|
|
shell: 'bash'
|
|
|
|
permissions:
|
|
contents: 'read'
|
|
id-token: 'write'
|
|
issues: 'write'
|
|
statuses: 'write'
|
|
packages: 'read'
|
|
|
|
jobs:
|
|
triage-issues:
|
|
timeout-minutes: 10
|
|
if: |-
|
|
${{ github.repository == 'google-gemini/gemini-cli' }}
|
|
runs-on: 'ubuntu-latest'
|
|
steps:
|
|
- name: 'Checkout'
|
|
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
|
|
|
- name: 'Generate GitHub App Token'
|
|
id: 'generate_token'
|
|
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
|
|
with:
|
|
app-id: '${{ secrets.APP_ID }}'
|
|
private-key: '${{ secrets.PRIVATE_KEY }}'
|
|
|
|
- name: 'Find untriaged issues'
|
|
id: 'find_issues'
|
|
env:
|
|
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
|
GITHUB_REPOSITORY: '${{ github.repository }}'
|
|
run: |-
|
|
set -euo pipefail
|
|
|
|
echo '🔍 Finding issues without labels...'
|
|
NO_LABEL_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
|
--search 'is:open is:issue no:label' --json number,title,body)"
|
|
|
|
echo '🏷️ Finding issues that need triage...'
|
|
NEED_TRIAGE_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
|
--search 'is:open is:issue label:"status/needs-triage"' --json number,title,body)"
|
|
|
|
echo '🔄 Merging and deduplicating issues...'
|
|
ISSUES="$(echo "${NO_LABEL_ISSUES}" "${NEED_TRIAGE_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
|
|
|
|
echo '📝 Setting output for GitHub Actions...'
|
|
echo "issues_to_triage=${ISSUES}" >> "${GITHUB_OUTPUT}"
|
|
|
|
ISSUE_COUNT="$(echo "${ISSUES}" | jq 'length')"
|
|
echo "✅ Found ${ISSUE_COUNT} issues to triage! 🎯"
|
|
|
|
- name: 'Get Repository Labels'
|
|
id: 'get_labels'
|
|
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
|
with:
|
|
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
|
script: |-
|
|
const { data: labels } = await github.rest.issues.listLabelsForRepo({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
});
|
|
const labelNames = labels.map(label => label.name);
|
|
core.setOutput('available_labels', labelNames.join(','));
|
|
core.info(`Found ${labelNames.length} labels: ${labelNames.join(', ')}`);
|
|
return labelNames;
|
|
|
|
- name: 'Run Gemini Issue Analysis'
|
|
if: |-
|
|
${{ steps.find_issues.outputs.issues_to_triage != '[]' }}
|
|
uses: 'google-github-actions/run-gemini-cli@06123c6a203eb7a964ce3be7c48479cc66059f23' # 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 }}'
|
|
REPOSITORY: '${{ github.repository }}'
|
|
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
|
|
with:
|
|
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
|
|
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
|
|
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
|
|
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
|
|
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
|
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
|
|
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
|
|
settings: |-
|
|
{
|
|
"maxSessionTurns": 25,
|
|
"coreTools": [
|
|
"run_shell_command(echo)",
|
|
],
|
|
"telemetry": {
|
|
"enabled": true,
|
|
"target": "gcp"
|
|
}
|
|
}
|
|
prompt: |-
|
|
## Role
|
|
|
|
You are an issue triage assistant. Analyze issues and identify
|
|
appropriate labels. Use the available tools to gather information;
|
|
do not ask for information to be provided.
|
|
|
|
## Steps
|
|
|
|
1. Review the available labels in the environment variable: "${AVAILABLE_LABELS}".
|
|
2. Check environment variable for issues to triage: $ISSUES_TO_TRIAGE (JSON array of issues)
|
|
3. Review the issue title, body and any comments provided in the environment variables.
|
|
4. Ignore any existing priorities or tags on the issue.
|
|
5. Identify the most relevant labels from the existing labels, focusing on kind/*, area/*, sub-area/* and priority/*.
|
|
6. Identify other applicable labels based on the issue content, such as status/*, help wanted, good first issue, etc.
|
|
7. For area/* and kind/* limit yourself to only the single most applicable label in each case.
|
|
8. Give me a single short explanation about why you are selecting each label in the process.
|
|
9. Output a JSON array of objects, each containing the issue number
|
|
and the labels to add and remove, along with an explanation. For example:
|
|
```
|
|
[
|
|
{
|
|
"issue_number": 123,
|
|
"labels_to_add": ["kind/bug", "priority/p2"],
|
|
"labels_to_remove": ["status/needs-triage"],
|
|
"explanation": "This issue is a bug that needs to be addressed with medium priority."
|
|
},
|
|
{
|
|
"issue_number": 456,
|
|
"labels_to_add": ["kind/enhancement"],
|
|
"labels_to_remove": [],
|
|
"explanation": "This issue is an enhancement request that could improve the user experience."
|
|
}
|
|
]
|
|
```
|
|
If an issue cannot be classified, do not include it in the output array.
|
|
10. For each issue please check if CLI version is present, this is usually in the output of the /about command and will look like 0.1.5
|
|
- Anything more than 6 versions older than the most recent should add the status/need-retesting label
|
|
11. If you see that the issue doesn't look like it has sufficient information recommend the status/need-information label
|
|
- After identifying appropriate labels to an issue, add "status/need-triage" label to labels_to_remove in the output.
|
|
|
|
## Guidelines
|
|
|
|
- Output only valid JSON format
|
|
- Do not include any explanation or additional text, just the JSON
|
|
- Only use labels that already exist in the repository.
|
|
- Do not add comments or modify the issue content.
|
|
- Do not remove labels titled help wanted or good first issue.
|
|
- Triage only the current issue.
|
|
- Identify only one area/ label
|
|
- Identify only one kind/ label (Do not apply kind/duplicate or kind/parent-issue)
|
|
- Identify all applicable sub-area/* and priority/* labels based on the issue content. It's ok to have multiple of these.
|
|
- Once you categorize the issue if it needs information bump down the priority by 1 eg.. a p0 would become a p1 a p1 would become a p2. P2 and P3 can stay as is in this scenario.
|
|
Categorization Guidelines:
|
|
P0: Critical / Blocker
|
|
- A P0 bug is a catastrophic failure that demands immediate attention. It represents a complete showstopper for a significant portion of users or for the development process itself.
|
|
Impact:
|
|
- Blocks development or testing for the entire team.
|
|
- Major security vulnerability that could compromise user data or system integrity.
|
|
- Causes data loss or corruption with no workaround.
|
|
- Crashes the application or makes a core feature completely unusable for all or most users in a production environment. Will it cause severe quality degration?
|
|
- Is it preventing contributors from contributing to the repository or is it a release blocker?
|
|
Qualifier: Is the main function of the software broken?
|
|
Example: The gemini auth login command fails with an unrecoverable error, preventing any user from authenticating and using the rest of the CLI.
|
|
P1: High
|
|
- A P1 bug is a serious issue that significantly degrades the user experience or impacts a core feature. While not a complete blocker, it's a major problem that needs a fast resolution.
|
|
- Feature requests are almost never P1.
|
|
Impact:
|
|
- A core feature is broken or behaving incorrectly for a large number of users or large number of use cases.
|
|
- Review the bug details and comments to try figure out if this issue affects a large set of use cases or if it's a narrow set of use cases.
|
|
- Severe performance degradation making the application frustratingly slow.
|
|
- No straightforward workaround exists, or the workaround is difficult and non-obvious.
|
|
Qualifier: Is a key feature unusable or giving very wrong results?
|
|
Example: The gemini -p "..." command consistently returns a malformed JSON response or an empty result, making the CLI's primary generation feature unreliable.
|
|
P2: Medium
|
|
- A P2 bug is a moderately impactful issue. It's a noticeable problem but doesn't prevent the use of the software's main functionality.
|
|
Impact:
|
|
- Affects a non-critical feature or a smaller, specific subset of users.
|
|
- An inconvenient but functional workaround is available and easy to execute.
|
|
- Noticeable UI/UX problems that don't break functionality but look unprofessional (e.g., elements are misaligned or overlapping).
|
|
Qualifier: Is it an annoying but non-blocking problem?
|
|
Example: An error message is unclear or contains a typo, causing user confusion but not halting their workflow.
|
|
P3: Low
|
|
- A P3 bug is a minor, low-impact issue that is trivial or cosmetic. It has little to no effect on the overall functionality of the application.
|
|
Impact:
|
|
- Minor cosmetic issues like color inconsistencies, typos in documentation, or slight alignment problems on a non-critical page.
|
|
- An edge-case bug that is very difficult to reproduce and affects a tiny fraction of users.
|
|
Qualifier: Is it a "nice-to-fix" issue?
|
|
Example: Spelling mistakes etc.
|
|
Additional Context:
|
|
- If users are talking about issues where the model gets downgraded from pro to flash then i want you to categorize that as a performance issue
|
|
- This product is designed to use different models eg.. using pro, downgrading to flash etc.
|
|
- When users report that they dont expect the model to change those would be categorized as feature requests.
|
|
Definition of Areas
|
|
area/ux:
|
|
- Issues concerning user-facing elements like command usability, interactive features, help docs, and perceived performance.
|
|
- I am seeing my screen flicker when using Gemini CLI
|
|
- I am seeing the output malformed
|
|
- Theme changes aren't taking effect
|
|
- My keyboard inputs arent' being recognzied
|
|
area/platform:
|
|
- Issues related to installation, packaging, OS compatibility (Windows, macOS, Linux), and the underlying CLI framework.
|
|
area/background: Issues related to long-running background tasks, daemons, and autonomous or proactive agent features.
|
|
area/models:
|
|
- i am not getting a response that is reasonable or expected. this can include things like
|
|
- I am calling a tool and the tool is not performing as expected.
|
|
- i am expecting a tool to be called and it is not getting called ,
|
|
- Including experience when using
|
|
- built-in tools (e.g., web search, code interpreter, read file, writefile, etc..),
|
|
- Function calling issues should be under this area
|
|
- i am getting responses from the model that are malformed.
|
|
- Issues concerning Gemini quality of response and inference,
|
|
- Issues talking about unnecessary token consumption.
|
|
- Issues talking about Model getting stuck in a loop be watchful as this could be the root cause for issues that otherwise seem like model performance issues.
|
|
- Memory compression
|
|
- unexpected responses,
|
|
- poor quality of generated code
|
|
area/tools:
|
|
- These are primarily issues related to Model Context Protocol
|
|
- These are issues that mention MCP support
|
|
- feature requests asking for support for new tools.
|
|
area/core:
|
|
- Issues with fundamental components like command parsing, configuration management, session state, and the main API client logic. Introducing multi-modality
|
|
area/contribution:
|
|
- Issues related to improving the developer contribution experience, such as CI/CD pipelines, build scripts, and test automation infrastructure.
|
|
area/authentication:
|
|
- Issues related to user identity, login flows, API key handling, credential storage, and access token management, unable to sign in selecting wrong authentication path etc..
|
|
area/security-privacy:
|
|
- Issues concerning vulnerability patching, dependency security, data sanitization, privacy controls, and preventing unauthorized data access.
|
|
area/extensibility:
|
|
- Issues related to the plugin system, extension APIs, or making the CLI's functionality available in other applications, github actions, ide support etc..
|
|
area/performance:
|
|
- Issues focused on model performance
|
|
- Issues with running out of capacity,
|
|
- 429 errors etc..
|
|
- could also pertain to latency,
|
|
- other general software performance like, memory usage, CPU consumption, and algorithmic efficiency.
|
|
- Switching models from one to the other unexpectedly.
|
|
|
|
- name: 'Apply Labels to Issues'
|
|
if: |-
|
|
${{ steps.gemini_issue_analysis.outcome == 'success' &&
|
|
steps.gemini_issue_analysis.outputs.summary != '[]' }}
|
|
env:
|
|
REPOSITORY: '${{ github.repository }}'
|
|
LABELS_OUTPUT: '${{ steps.gemini_issue_analysis.outputs.summary }}'
|
|
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
|
with:
|
|
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
|
script: |-
|
|
// Strip code block markers if present
|
|
const rawLabels = process.env.LABELS_OUTPUT;
|
|
core.info(`Raw labels JSON: ${rawLabels}`);
|
|
let parsedLabels;
|
|
try {
|
|
const trimmedLabels = rawLabels.replace(/^```(?:json)?\s*/, '').replace(/\s*```$/, '').trim();
|
|
parsedLabels = JSON.parse(trimmedLabels);
|
|
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) {
|
|
const issueNumber = entry.issue_number;
|
|
if (!issueNumber) {
|
|
core.info(`Skipping entry with no issue number: ${JSON.stringify(entry)}`);
|
|
continue;
|
|
}
|
|
|
|
// Set labels based on triage result
|
|
if (entry.labels_to_set && entry.labels_to_set.length > 0) {
|
|
await github.rest.issues.setLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
labels: entry.labels_to_set
|
|
});
|
|
const explanation = entry.explanation ? ` - ${entry.explanation}` : '';
|
|
core.info(`Successfully set labels for #${issueNumber}: ${entry.labels_to_set.join(', ')}${explanation}`);
|
|
} else {
|
|
// If no labels to set, leave the issue as is
|
|
core.info(`No labels to set for #${issueNumber}, leaving as is`);
|
|
}
|
|
}
|
|
|
|
refresh-embeddings:
|
|
if: |-
|
|
${{ vars.TRIAGE_DEDUPLICATE_ISSUES != '' && github.repository == 'google-gemini/gemini-cli' }}
|
|
timeout-minutes: 20
|
|
runs-on: 'ubuntu-latest'
|
|
steps:
|
|
- name: 'Checkout'
|
|
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
|
|
|
- name: 'Generate GitHub App Token'
|
|
id: 'generate_token'
|
|
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
|
|
with:
|
|
app-id: '${{ secrets.APP_ID }}'
|
|
private-key: '${{ secrets.PRIVATE_KEY }}'
|
|
|
|
- name: 'Log in to GitHub Container Registry'
|
|
uses: 'docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1' # ratchet:docker/login-action@v3
|
|
with:
|
|
registry: 'ghcr.io'
|
|
username: '${{ github.actor }}'
|
|
password: '${{ secrets.GITHUB_TOKEN }}'
|
|
|
|
- name: 'Run Gemini Issue Deduplication Refresh'
|
|
uses: 'google-github-actions/run-gemini-cli@06123c6a203eb7a964ce3be7c48479cc66059f23' # ratchet:google-github-actions/run-gemini-cli@v0
|
|
id: 'gemini_refresh_embeddings'
|
|
env:
|
|
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
|
ISSUE_TITLE: '${{ github.event.issue.title }}'
|
|
ISSUE_BODY: '${{ github.event.issue.body }}'
|
|
ISSUE_NUMBER: '${{ github.event.issue.number }}'
|
|
REPOSITORY: '${{ github.repository }}'
|
|
FIRESTORE_PROJECT: '${{ vars.FIRESTORE_PROJECT }}'
|
|
with:
|
|
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
|
|
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
|
|
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
|
|
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
|
|
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
|
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
|
|
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
|
|
settings: |-
|
|
{
|
|
"mcpServers": {
|
|
"issue_deduplication": {
|
|
"command": "docker",
|
|
"args": [
|
|
"run",
|
|
"-i",
|
|
"--rm",
|
|
"--network", "host",
|
|
"-e", "GITHUB_TOKEN",
|
|
"-e", "GEMINI_API_KEY",
|
|
"-e", "DATABASE_TYPE",
|
|
"-e", "FIRESTORE_DATABASE_ID",
|
|
"-e", "GCP_PROJECT",
|
|
"-e", "GOOGLE_APPLICATION_CREDENTIALS=/app/gcp-credentials.json",
|
|
"-v", "${GOOGLE_APPLICATION_CREDENTIALS}:/app/gcp-credentials.json",
|
|
"ghcr.io/google-gemini/gemini-cli-issue-triage@sha256:e3de1523f6c83aabb3c54b76d08940a2bf42febcb789dd2da6f95169641f94d3"
|
|
],
|
|
"env": {
|
|
"GITHUB_TOKEN": "${GITHUB_TOKEN}",
|
|
"GEMINI_API_KEY": "${{ secrets.GEMINI_API_KEY }}",
|
|
"DATABASE_TYPE":"firestore",
|
|
"GCP_PROJECT": "${FIRESTORE_PROJECT}",
|
|
"FIRESTORE_DATABASE_ID": "(default)",
|
|
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
|
|
},
|
|
"enabled": true,
|
|
"timeout": 600000
|
|
}
|
|
},
|
|
"maxSessionTurns": 25,
|
|
"coreTools": [
|
|
"run_shell_command(echo)"
|
|
],
|
|
"telemetry": {
|
|
"enabled": true,
|
|
"target": "gcp"
|
|
}
|
|
}
|
|
prompt: |-
|
|
## Role
|
|
|
|
You are a database maintenance assistant for a GitHub issue deduplication system.
|
|
|
|
## Goal
|
|
|
|
Your sole responsibility is to refresh the embeddings for all open issues in the repository to ensure the deduplication database is up-to-date.
|
|
|
|
## Steps
|
|
|
|
1. **Extract Repository Information:** The repository is ${{ github.repository }}.
|
|
2. **Refresh Embeddings:** Call the `refresh` tool with the correct `repo`. Do not use the `force` parameter.
|
|
3. **Log Output:** Print the JSON output from the `refresh` tool to the logs.
|
|
|
|
## Guidelines
|
|
|
|
- Only use the `refresh` tool.
|
|
- Do not attempt to find duplicates or modify any issues.
|
|
- Your only task is to call the `refresh` tool and log its output.
|