Skip to content

Commit fd8b492

Browse files
DeanChensjcopybara-github
authored andcommitted
feat(ci): add Gemini auto review and invoke workflows
Merge #5679 Same config as in adk-python-community COPYBARA_INTEGRATE_REVIEW=#5679 from DeanChensj:main d33c368 PiperOrigin-RevId: 914634367
1 parent 327c45f commit fd8b492

3 files changed

Lines changed: 410 additions & 0 deletions

File tree

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
name: '🔀 Gemini Dispatch'
2+
3+
on:
4+
pull_request_review_comment:
5+
types:
6+
- 'created'
7+
pull_request_review:
8+
types:
9+
- 'submitted'
10+
pull_request:
11+
types:
12+
- 'opened'
13+
- 'ready_for_review'
14+
issues:
15+
types:
16+
- 'opened'
17+
- 'reopened'
18+
issue_comment:
19+
types:
20+
- 'created'
21+
22+
defaults:
23+
run:
24+
shell: 'bash'
25+
26+
jobs:
27+
debugger:
28+
if: |-
29+
${{ fromJSON(vars.GEMINI_DEBUG || vars.ACTIONS_STEP_DEBUG || false) }}
30+
runs-on: 'ubuntu-latest'
31+
permissions:
32+
contents: 'read'
33+
steps:
34+
- name: 'Print context for debugging'
35+
env:
36+
DEBUG_event_name: '${{ github.event_name }}'
37+
DEBUG_event__action: '${{ github.event.action }}'
38+
DEBUG_event__comment__author_association: '${{ github.event.comment.author_association }}'
39+
DEBUG_event__issue__author_association: '${{ github.event.issue.author_association }}'
40+
DEBUG_event__pull_request__author_association: '${{ github.event.pull_request.author_association }}'
41+
DEBUG_event__review__author_association: '${{ github.event.review.author_association }}'
42+
DEBUG_event: '${{ toJSON(github.event) }}'
43+
run: |-
44+
env | grep '^DEBUG_'
45+
46+
dispatch:
47+
# For PRs: only if not from a fork
48+
# For issues: only on open/reopen
49+
# For comments: only if user types @gemini-cli and is OWNER/MEMBER/COLLABORATOR
50+
if: |-
51+
(
52+
github.event_name == 'pull_request' &&
53+
github.event.pull_request.head.repo.fork == false &&
54+
github.event.pull_request.draft == false
55+
) || (
56+
github.event.sender.type == 'User' &&
57+
startsWith(github.event.comment.body || github.event.review.body || github.event.issue.body, '@gemini-cli') &&
58+
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association || github.event.issue.author_association)
59+
)
60+
runs-on: 'ubuntu-latest'
61+
permissions:
62+
contents: 'read'
63+
issues: 'write'
64+
pull-requests: 'write'
65+
outputs:
66+
command: '${{ steps.extract_command.outputs.command }}'
67+
request: '${{ steps.extract_command.outputs.request }}'
68+
additional_context: '${{ steps.extract_command.outputs.additional_context }}'
69+
issue_number: '${{ github.event.pull_request.number || github.event.issue.number }}'
70+
steps:
71+
- name: 'Mint identity token'
72+
id: 'mint_identity_token'
73+
if: |-
74+
${{ vars.APP_ID }}
75+
uses: 'actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf' # ratchet:actions/create-github-app-token@v2
76+
with:
77+
app-id: '${{ vars.APP_ID }}'
78+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
79+
permission-contents: 'read'
80+
permission-issues: 'write'
81+
permission-pull-requests: 'write'
82+
83+
- name: 'Extract command'
84+
id: 'extract_command'
85+
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7
86+
env:
87+
EVENT_TYPE: '${{ github.event_name }}.${{ github.event.action }}'
88+
REQUEST: '${{ github.event.comment.body || github.event.review.body || github.event.issue.body }}'
89+
with:
90+
script: |
91+
const eventType = process.env.EVENT_TYPE;
92+
const request = process.env.REQUEST;
93+
core.setOutput('request', request);
94+
95+
if (eventType === 'pull_request.opened' || eventType === 'pull_request.ready_for_review') {
96+
core.setOutput('command', 'review');
97+
} else if (request.startsWith("@gemini-cli /review")) {
98+
core.setOutput('command', 'review');
99+
const additionalContext = request.replace(/^@gemini-cli \/review/, '').trim();
100+
core.setOutput('additional_context', additionalContext);
101+
} else if (request.startsWith("@gemini-cli")) {
102+
const additionalContext = request.replace(/^@gemini-cli/, '').trim();
103+
core.setOutput('command', 'invoke');
104+
core.setOutput('additional_context', additionalContext);
105+
} else {
106+
core.setOutput('command', 'fallthrough');
107+
}
108+
109+
- name: 'Acknowledge request'
110+
env:
111+
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}'
112+
ISSUE_NUMBER: '${{ github.event.pull_request.number || github.event.issue.number }}'
113+
MESSAGE: |-
114+
🤖 Hi @${{ github.actor }}, I've received your request, and I'm working on it now! You can track my progress [in the logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details.
115+
REPOSITORY: '${{ github.repository }}'
116+
run: |-
117+
gh issue comment "${ISSUE_NUMBER}" \
118+
--body "${MESSAGE}" \
119+
--repo "${REPOSITORY}"
120+
121+
review:
122+
needs: 'dispatch'
123+
if: |-
124+
${{ needs.dispatch.outputs.command == 'review' }}
125+
uses: './.github/workflows/gemini-review.yml'
126+
permissions:
127+
contents: 'read'
128+
id-token: 'write'
129+
issues: 'write'
130+
pull-requests: 'write'
131+
with:
132+
additional_context: '${{ needs.dispatch.outputs.additional_context }}'
133+
secrets: 'inherit'
134+
135+
invoke:
136+
needs: 'dispatch'
137+
if: |-
138+
${{ needs.dispatch.outputs.command == 'invoke' }}
139+
uses: './.github/workflows/gemini-invoke.yml'
140+
permissions:
141+
contents: 'read'
142+
id-token: 'write'
143+
issues: 'write'
144+
pull-requests: 'write'
145+
with:
146+
additional_context: '${{ needs.dispatch.outputs.additional_context }}'
147+
secrets: 'inherit'
148+
149+
fallthrough:
150+
needs:
151+
- 'dispatch'
152+
- 'review'
153+
- 'invoke'
154+
if: |-
155+
${{ always() && !cancelled() && (failure() || needs.dispatch.outputs.command == 'fallthrough') }}
156+
runs-on: 'ubuntu-latest'
157+
permissions:
158+
contents: 'read'
159+
issues: 'write'
160+
pull-requests: 'write'
161+
steps:
162+
- name: 'Mint identity token'
163+
id: 'mint_identity_token'
164+
if: |-
165+
${{ vars.APP_ID }}
166+
uses: 'actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf' # ratchet:actions/create-github-app-token@v2
167+
with:
168+
app-id: '${{ vars.APP_ID }}'
169+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
170+
permission-contents: 'read'
171+
permission-issues: 'write'
172+
permission-pull-requests: 'write'
173+
174+
- name: 'Send failure comment'
175+
env:
176+
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}'
177+
ISSUE_NUMBER: '${{ github.event.pull_request.number || github.event.issue.number }}'
178+
MESSAGE: |-
179+
🤖 I'm sorry @${{ github.actor }}, but I was unable to process your request. Please [see the logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details.
180+
REPOSITORY: '${{ github.repository }}'
181+
run: |-
182+
gh issue comment "${ISSUE_NUMBER}" \
183+
--body "${MESSAGE}" \
184+
--repo "${REPOSITORY}"
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: '▶️ Gemini Invoke'
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
additional_context:
7+
type: 'string'
8+
description: 'Any additional context from the request'
9+
required: false
10+
11+
concurrency:
12+
group: '${{ github.workflow }}-invoke-${{ github.event_name }}-${{ github.event.pull_request.number || github.event.issue.number }}'
13+
cancel-in-progress: false
14+
15+
defaults:
16+
run:
17+
shell: 'bash'
18+
19+
jobs:
20+
invoke:
21+
runs-on: 'ubuntu-latest'
22+
permissions:
23+
contents: 'read'
24+
id-token: 'write'
25+
issues: 'write'
26+
pull-requests: 'write'
27+
steps:
28+
- name: 'Mint identity token'
29+
id: 'mint_identity_token'
30+
if: |-
31+
${{ vars.APP_ID }}
32+
uses: 'actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf' # ratchet:actions/create-github-app-token@v2
33+
with:
34+
app-id: '${{ vars.APP_ID }}'
35+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
36+
permission-contents: 'read'
37+
permission-issues: 'write'
38+
permission-pull-requests: 'write'
39+
40+
- name: 'Checkout Code'
41+
uses: 'actions/checkout@v4' # ratchet:exclude
42+
43+
- name: 'Run Gemini CLI'
44+
id: 'run_gemini'
45+
uses: 'google-github-actions/run-gemini-cli@v0' # ratchet:exclude
46+
env:
47+
TITLE: '${{ github.event.pull_request.title || github.event.issue.title }}'
48+
DESCRIPTION: '${{ github.event.pull_request.body || github.event.issue.body }}'
49+
EVENT_NAME: '${{ github.event_name }}'
50+
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}'
51+
IS_PULL_REQUEST: '${{ !!github.event.pull_request }}'
52+
ISSUE_NUMBER: '${{ github.event.pull_request.number || github.event.issue.number }}'
53+
REPOSITORY: '${{ github.repository }}'
54+
ADDITIONAL_CONTEXT: '${{ inputs.additional_context }}'
55+
with:
56+
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
57+
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
58+
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
59+
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
60+
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
61+
gemini_cli_version: '${{ vars.GEMINI_CLI_VERSION }}'
62+
gemini_debug: '${{ fromJSON(vars.GEMINI_DEBUG || vars.ACTIONS_STEP_DEBUG || false) }}'
63+
gemini_model: '${{ vars.GEMINI_MODEL }}'
64+
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
65+
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
66+
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
67+
upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}'
68+
workflow_name: 'gemini-invoke'
69+
# Assistant workflows can be triggered by comments on either Issues or PRs.
70+
# We explicitly map both fields so the CLI can correctly categorize the interaction.
71+
github_pr_number: '${{ github.event.pull_request.number }}'
72+
github_issue_number: '${{ github.event.issue.number }}'
73+
settings: |-
74+
{
75+
"model": {
76+
"maxSessionTurns": 25
77+
},
78+
"telemetry": {
79+
"enabled": true,
80+
"target": "local",
81+
"outfile": ".gemini/telemetry.log"
82+
},
83+
"mcpServers": {
84+
"github": {
85+
"command": "docker",
86+
"args": [
87+
"run",
88+
"-i",
89+
"--rm",
90+
"-e",
91+
"GITHUB_PERSONAL_ACCESS_TOKEN",
92+
"ghcr.io/github/github-mcp-server:v0.27.0"
93+
],
94+
"includeTools": [
95+
"add_issue_comment",
96+
"issue_read",
97+
"list_issues",
98+
"search_issues",
99+
"pull_request_read",
100+
"list_pull_requests",
101+
"search_pull_requests",
102+
"get_commit",
103+
"get_file_contents",
104+
"list_commits",
105+
"search_code"
106+
],
107+
"env": {
108+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}"
109+
}
110+
}
111+
},
112+
"tools": {
113+
"core": [
114+
"run_shell_command(cat)",
115+
"run_shell_command(echo)",
116+
"run_shell_command(grep)",
117+
"run_shell_command(head)",
118+
"run_shell_command(tail)"
119+
]
120+
}
121+
}
122+
prompt: '/gemini-invoke'

0 commit comments

Comments
 (0)