Skip to content

Commit 3c7f943

Browse files
jeropsethvargo
andauthored
feat: Initial implementation of the Gemini CLI GitHub Action (#1)
This commit introduces the core implementation of the Gemini CLI GitHub Action, establishing its primary features and structure. Key features: - **Composite Action:** The action is built as a composite action, directly installing and running the Gemini CLI for efficiency and simplicity. - **Workflows:** Includes example workflows for key use cases: - Automated and scheduled issue triage. - Pull request reviews. - **Documentation:** Comprehensive documentation is added for: - Configuration and setup. - Authentication using GitHub Apps and Google Cloud Workload Identity Federation. - Observability with OpenTelemetry. - **Scripts:** Helper scripts are provided to facilitate the setup of Workload Identity and OpenTelemetry. - **Project Files:** - `action.yml` is configured with inputs for the CLI. - `README.md`, `CONTRIBUTING.md`, and `GEMINI.md` provide usage and contribution guidelines. --------- Co-authored-by: Seth Vargo <seth@sethvargo.com>
1 parent dac2fd4 commit 3c7f943

28 files changed

+2649
-2675
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: '🏷️ Gemini Automated Issue Triage'
2+
3+
on:
4+
issues:
5+
types:
6+
- 'opened'
7+
- 'reopened'
8+
9+
concurrency:
10+
group: '${{ github.workflow }}-${{ github.event.issue.number }}'
11+
cancel-in-progress: true
12+
13+
defaults:
14+
run:
15+
shell: 'bash'
16+
17+
permissions:
18+
contents: 'read'
19+
id-token: 'write'
20+
issues: 'write'
21+
statuses: 'write'
22+
23+
jobs:
24+
triage-issue:
25+
timeout-minutes: 5
26+
runs-on: 'ubuntu-latest'
27+
28+
steps:
29+
- name: 'Checkout repository'
30+
uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
31+
32+
- name: 'Generate GitHub App Token'
33+
id: 'generate_token'
34+
if: |-
35+
${{ vars.APP_ID }}
36+
uses: 'actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e' # ratchet:actions/create-github-app-token@v2
37+
with:
38+
app-id: '${{ vars.APP_ID }}'
39+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
40+
41+
- name: 'Run Gemini Issue Triage'
42+
uses: './'
43+
env:
44+
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
45+
ISSUE_TITLE: '${{ github.event.issue.title }}'
46+
ISSUE_BODY: '${{ github.event.issue.body }}'
47+
ISSUE_NUMBER: '${{ github.event.issue.number }}'
48+
REPOSITORY: '${{ github.repository }}'
49+
GEMINI_CLI_VERSION: '${{ vars.GEMINI_CLI_VERSION }}'
50+
OTLP_GOOGLE_CLOUD_PROJECT: '${{ vars.OTLP_GOOGLE_CLOUD_PROJECT }}'
51+
OTLP_GCP_WIF_PROVIDER: '${{ vars.OTLP_GCP_WIF_PROVIDER }}'
52+
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
53+
with:
54+
settings_json: |-
55+
{
56+
"coreTools": [
57+
"run_shell_command(gh label list)",
58+
"run_shell_command(gh issue edit)"
59+
],
60+
"telemetry": {
61+
"enabled": true,
62+
"target": "gcp"
63+
},
64+
"sandbox": false
65+
}
66+
prompt: |-
67+
## Role
68+
69+
You are an issue triage assistant. Analyze the current GitHub issue
70+
and apply the most appropriate existing labels. Use the available
71+
tools to gather information; do not ask for information to be
72+
provided.
73+
74+
## Steps
75+
76+
1. Run: `gh label list` to get all available labels.
77+
2. Review the issue title and body provided in the environment
78+
variables: "${ISSUE_TITLE}" and "${ISSUE_BODY}".
79+
3. Select the most relevant labels from the existing labels. If
80+
available, set labels that follow the `kind/*`, `area/*`, and
81+
`priority/*` patterns.
82+
4. Apply the selected labels to this issue using:
83+
`gh issue edit "${ISSUE_NUMBER}" --add-label "label1,label2"`
84+
5. If the "status/needs-triage" label is present, remove it using:
85+
`gh issue edit "${ISSUE_NUMBER}" --remove-label "status/needs-triage"`
86+
87+
## Guidelines
88+
89+
- Only use labels that already exist in the repository
90+
- Do not add comments or modify the issue content
91+
- Triage only the current issue
92+
- Assign all applicable labels based on the issue content
93+
- Reference all shell variables as "${VAR}" (with quotes and braces)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: '📋 Gemini Scheduled Issue Triage'
2+
3+
on:
4+
schedule:
5+
- cron: '0 * * * *' # Runs every hour
6+
workflow_dispatch:
7+
8+
concurrency:
9+
group: '${{ github.workflow }}'
10+
cancel-in-progress: true
11+
12+
defaults:
13+
run:
14+
shell: 'bash'
15+
16+
permissions:
17+
contents: 'read'
18+
id-token: 'write'
19+
issues: 'write'
20+
statuses: 'write'
21+
22+
jobs:
23+
triage-issues:
24+
timeout-minutes: 10
25+
runs-on: 'ubuntu-latest'
26+
27+
steps:
28+
- name: 'Checkout repository'
29+
uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
30+
31+
- name: 'Generate GitHub App Token'
32+
id: 'generate_token'
33+
if: |-
34+
${{ vars.APP_ID }}
35+
uses: 'actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e' # ratchet:actions/create-github-app-token@v2
36+
with:
37+
app-id: '${{ vars.APP_ID }}'
38+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
39+
40+
- name: 'Find untriaged issues'
41+
id: 'find_issues'
42+
env:
43+
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
44+
GITHUB_REPOSITORY: '${{ github.repository }}'
45+
GITHUB_OUTPUT: '${{ github.output }}'
46+
run: |-
47+
set -euo pipefail
48+
49+
echo '🔍 Finding issues without labels...'
50+
NO_LABEL_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
51+
--search 'is:open is:issue no:label' --json number,title,body)"
52+
53+
echo '🏷️ Finding issues that need triage...'
54+
NEED_TRIAGE_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
55+
--search 'is:open is:issue label:"status/needs-triage"' --json number,title,body)"
56+
57+
echo '🔄 Merging and deduplicating issues...'
58+
ISSUES="$(echo "${NO_LABEL_ISSUES}" "${NEED_TRIAGE_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
59+
60+
echo '📝 Setting output for GitHub Actions...'
61+
echo "issues_to_triage=${ISSUES}" >> "${GITHUB_OUTPUT}"
62+
63+
ISSUE_COUNT="$(echo "${ISSUES}" | jq 'length')"
64+
echo "✅ Found ${ISSUE_COUNT} issues to triage! 🎯"
65+
66+
- name: 'Run Gemini Issue Triage'
67+
if: |-
68+
${{ steps.find_issues.outputs.issues_to_triage != '[]' }}
69+
uses: './'
70+
env:
71+
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}'
72+
ISSUES_TO_TRIAGE: '${{ steps.find_issues.outputs.issues_to_triage }}'
73+
REPOSITORY: '${{ github.repository }}'
74+
GEMINI_CLI_VERSION: '${{ vars.GEMINI_CLI_VERSION }}'
75+
OTLP_GOOGLE_CLOUD_PROJECT: '${{ vars.OTLP_GOOGLE_CLOUD_PROJECT }}'
76+
OTLP_GCP_WIF_PROVIDER: '${{ vars.OTLP_GCP_WIF_PROVIDER }}'
77+
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
78+
with:
79+
settings_json: |-
80+
{
81+
"coreTools": [
82+
"run_shell_command(echo)",
83+
"run_shell_command(gh label list)",
84+
"run_shell_command(gh issue edit)",
85+
"run_shell_command(gh issue list)"
86+
],
87+
"telemetry": {
88+
"enabled": true,
89+
"target": "gcp"
90+
},
91+
"sandbox": false
92+
}
93+
prompt: |-
94+
## Role
95+
96+
You are an issue triage assistant. Analyze issues and apply
97+
appropriate labels. Use the available tools to gather information;
98+
do not ask for information to be provided.
99+
100+
## Steps
101+
102+
1. Run: `gh label list`
103+
2. Check environment variable: "${ISSUES_TO_TRIAGE}" (JSON array
104+
of issues)
105+
3. For each issue, apply labels:
106+
`gh issue edit "${ISSUE_NUMBER}" --add-label "label1,label2"`.
107+
If available, set labels that follow the `kind/*`, `area/*`,
108+
and `priority/*` patterns.
109+
4. For each issue, if the `status/needs-triage` label is present,
110+
remove it using:
111+
`gh issue edit "${ISSUE_NUMBER}" --remove-label "status/needs-triage"`
112+
113+
## Guidelines
114+
115+
- Only use existing repository labels
116+
- Do not add comments
117+
- Triage each issue independently
118+
- Reference all shell variables as "${VAR}" (with quotes and braces)

0 commit comments

Comments
 (0)