Skip to content

Commit 34890ca

Browse files
authored
feat(actions): use the dispatcher pattern to separate concerns (#212)
This introduces a new top-level workflow "gemini-dispatch" that listens for a series of events. Based on the trigger or contents, it calls another workflow (using `workflow_call`). This helps keep each workflow separate and allows us to re-use workflows in the future. The generic "invoke" command still needs a lot of work, but this is progress. /cc @jerop
1 parent 796d219 commit 34890ca

8 files changed

Lines changed: 714 additions & 835 deletions
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
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+
issues:
14+
types:
15+
- 'opened'
16+
- 'reopened'
17+
issue_comment:
18+
types:
19+
- 'created'
20+
21+
defaults:
22+
run:
23+
shell: 'bash'
24+
25+
jobs:
26+
dispatch:
27+
if: |-
28+
(
29+
github.event_name == 'pull_request' &&
30+
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.pull_request.author_association)
31+
) || (
32+
github.event.sender.type == 'User' &&
33+
startsWith(github.event.comment.body || github.event.review.body || github.event.issue.body, '@gemini-cli') &&
34+
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association || github.event.issue.author_association)
35+
) || (
36+
github.event_name == 'issues' &&
37+
contains(fromJSON('["opened", "reopened"]'), github.event.action)
38+
)
39+
runs-on: 'ubuntu-latest'
40+
permissions:
41+
contents: 'read'
42+
issues: 'write'
43+
pull-requests: 'write'
44+
outputs:
45+
command: '${{ steps.extract_command.outputs.command }}'
46+
request: '${{ steps.extract_command.outputs.request }}'
47+
additional_context: '${{ steps.extract_command.outputs.additional_context }}'
48+
issue_number: '${{ github.event.pull_request.number || github.event.issue.number }}'
49+
steps:
50+
- name: 'Mint identity token'
51+
id: 'mint_identity_token'
52+
if: |-
53+
${{ vars.APP_ID }}
54+
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
55+
with:
56+
app-id: '${{ vars.APP_ID }}'
57+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
58+
permission-contents: 'read'
59+
permission-issues: 'write'
60+
permission-pull-requests: 'write'
61+
62+
- name: 'Extract command'
63+
id: 'extract_command'
64+
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7
65+
env:
66+
EVENT_TYPE: '${{ github.event_name }}.${{ github.event.action }}'
67+
REQUEST: '${{ github.event.comment.body || github.event.review.body || github.event.issue.body }}'
68+
with:
69+
script: |
70+
const request = process.env.REQUEST;
71+
const eventType = process.env.EVENT_TYPE
72+
core.setOutput('request', request);
73+
74+
if (request.startsWith("@gemini-cli /review")) {
75+
core.setOutput('command', 'review');
76+
const additionalContext = request.replace(/^@gemini-cli \/review/, '').trim();
77+
core.setOutput('additional_context', additionalContext);
78+
} else if (request.startsWith("@gemini-cli /triage")) {
79+
core.setOutput('command', 'triage');
80+
} else if (request.startsWith("@gemini-cli")) {
81+
core.setOutput('command', 'invoke');
82+
const additionalContext = request.replace(/^@gemini-cli/, '').trim();
83+
core.setOutput('additional_context', additionalContext);
84+
} else if (eventType === 'pull_request.opened') {
85+
core.setOutput('command', 'review');
86+
} else if (['issues.opened', 'issues.reopened'].includes(eventType)) {
87+
core.setOutput('command', 'triage');
88+
} else {
89+
core.setOutput('command', 'fallthrough');
90+
}
91+
92+
- name: 'Acknowledge request'
93+
env:
94+
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}'
95+
ISSUE_NUMBER: '${{ github.event.pull_request.number || github.event.issue.number }}'
96+
MESSAGE: |-
97+
🤖 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.
98+
REPOSITORY: '${{ github.repository }}'
99+
run: |-
100+
gh issue comment "${ISSUE_NUMBER}" \
101+
--body "${MESSAGE}" \
102+
--repo "${REPOSITORY}"
103+
104+
review:
105+
needs: 'dispatch'
106+
if: |-
107+
${{ needs.dispatch.outputs.command == 'review' }}
108+
uses: './.github/workflows/gemini-review.yml'
109+
permissions:
110+
contents: 'read'
111+
pull-requests: 'write'
112+
issues: 'write'
113+
with:
114+
additional_context: '${{ needs.dispatch.outputs.additional_context }}'
115+
secrets: 'inherit'
116+
117+
triage:
118+
needs: 'dispatch'
119+
if: |-
120+
${{ needs.dispatch.outputs.command == 'triage' }}
121+
uses: './.github/workflows/gemini-triage.yml'
122+
permissions:
123+
contents: 'read'
124+
issues: 'write'
125+
pull-requests: 'write'
126+
with:
127+
additional_context: '${{ needs.dispatch.outputs.additional_context }}'
128+
secrets: 'inherit'
129+
130+
invoke:
131+
needs: 'dispatch'
132+
if: |-
133+
${{ needs.dispatch.outputs.command == 'invoke' }}
134+
uses: './.github/workflows/gemini-invoke.yml'
135+
permissions:
136+
contents: 'read'
137+
issues: 'write'
138+
pull-requests: 'write'
139+
with:
140+
additional_context: '${{ needs.dispatch.outputs.additional_context }}'
141+
secrets: 'inherit'
142+
143+
fallthrough:
144+
needs:
145+
- 'dispatch'
146+
- 'review'
147+
- 'triage'
148+
- 'invoke'
149+
if: |-
150+
${{ always() && !cancelled() && (failure() || needs.dispatch.outputs.command == 'fallthrough') }}
151+
runs-on: 'ubuntu-latest'
152+
permissions:
153+
contents: 'read'
154+
issues: 'write'
155+
pull-requests: 'write'
156+
steps:
157+
- name: 'Mint identity token'
158+
id: 'mint_identity_token'
159+
if: |-
160+
${{ vars.APP_ID }}
161+
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
162+
with:
163+
app-id: '${{ vars.APP_ID }}'
164+
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
165+
permission-contents: 'read'
166+
permission-issues: 'write'
167+
permission-pull-requests: 'write'
168+
169+
- name: 'Send failure comment'
170+
env:
171+
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}'
172+
ISSUE_NUMBER: '${{ github.event.pull_request.number || github.event.issue.number }}'
173+
MESSAGE: |-
174+
🤖 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.
175+
REPOSITORY: '${{ github.repository }}'
176+
run: |-
177+
gh issue comment "${ISSUE_NUMBER}" \
178+
--body "${MESSAGE}" \
179+
--repo "${REPOSITORY}"

0 commit comments

Comments
 (0)