name: "🔀 Gemini Dispatch"
on:
pull_request_review_comment:
types:
- "created"
pull_request_review:
types:
- "submitted"
pull_request_target:
types:
- "opened"
issue_comment:
types:
- "created"
defaults:
run:
shell: "bash"
jobs:
debugger:
if: |-
${{ fromJSON(vars.GEMINI_DEBUG || vars.ACTIONS_STEP_DEBUG || false) }}
runs-on: "ubuntu-latest"
permissions:
contents: "read"
steps:
- name: "Print context for debugging"
env:
DEBUG_event_name: "${{ github.event_name }}"
DEBUG_event__action: "${{ github.event.action }}"
DEBUG_event__comment__author_association: "${{ github.event.comment.author_association }}"
DEBUG_event__issue__author_association: "${{ github.event.issue.author_association }}"
DEBUG_event__pull_request__author_association: "${{ github.event.pull_request.author_association }}"
DEBUG_event__review__author_association: "${{ github.event.review.author_association }}"
DEBUG_event: "${{ toJSON(github.event) }}"
run: |-
env | grep '^DEBUG_'
dispatch:
# For PRs: pull_request_target runs workflow from base branch (security)
# For comments: only if user types @gemini-cli and is OWNER/MEMBER/COLLABORATOR
if: |-
(
github.event_name == 'pull_request_target' &&
github.event.pull_request.head.repo.fork == false
) || (
github.event.sender.type == 'User' &&
startsWith(github.event.comment.body || github.event.review.body || github.event.issue.body, '@gemini-cli') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association || github.event.issue.author_association)
)
runs-on: "ubuntu-latest"
permissions:
contents: "read"
issues: "write"
pull-requests: "write"
outputs:
command: "${{ steps.extract_command.outputs.command }}"
request: "${{ steps.extract_command.outputs.request }}"
additional_context: "${{ steps.extract_command.outputs.additional_context }}"
checkout_ref: "${{ steps.extract_command.outputs.checkout_ref }}"
issue_number: "${{ github.event.pull_request.number || github.event.issue.number }}"
steps:
- name: "Mint identity token"
id: "mint_identity_token"
if: |-
${{ vars.APP_ID }}
uses: "actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b" # ratchet:actions/create-github-app-token@v2
with:
app-id: "${{ vars.APP_ID }}"
private-key: "${{ secrets.APP_PRIVATE_KEY }}"
permission-contents: "read"
permission-issues: "write"
permission-pull-requests: "write"
- name: "Extract command"
id: "extract_command"
uses: "actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea" # ratchet:actions/github-script@v7
env:
EVENT_TYPE: "${{ github.event_name }}.${{ github.event.action }}"
REQUEST: "${{ github.event.comment.body || github.event.review.body || github.event.issue.body }}"
with:
script: |
const eventType = process.env.EVENT_TYPE;
const request = process.env.REQUEST || "";
core.setOutput('request', request);
let checkoutRef;
if (context.payload.pull_request) {
const pr = context.payload.pull_request;
checkoutRef = pr.head.repo.fork
? `refs/pull/${pr.number}/merge`
: pr.head.sha;
} else if (context.payload.issue?.pull_request && request.startsWith("@gemini-cli")) {
const { owner, repo } = context.repo;
const pull_number = context.issue.number;
const pr = await github.rest.pulls.get({ owner, repo, pull_number });
checkoutRef = pr.data.head.repo.fork
? `refs/pull/${pr.data.number}/merge`
: pr.data.head.sha;
}
if (checkoutRef) {
core.setOutput('checkout_ref', checkoutRef);
}
if (eventType === 'pull_request_target.opened') {
core.setOutput('command', 'review');
} else if (request.startsWith("@gemini-cli /review")) {
core.setOutput('command', 'review');
const additionalContext = request.replace(/^@gemini-cli \/review/, '').trim();
core.setOutput('additional_context', additionalContext);
} else if (request.startsWith("@gemini-cli")) {
const additionalContext = request.replace(/^@gemini-cli/, '').trim();
core.setOutput('command', 'invoke');
core.setOutput('additional_context', additionalContext);
} else {
core.setOutput('command', 'fallthrough');
}
- name: "Acknowledge request"
env:
GITHUB_TOKEN: "${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}"
ISSUE_NUMBER: "${{ github.event.pull_request.number || github.event.issue.number }}"
MESSAGE: |-
🤖 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.
REPOSITORY: "${{ github.repository }}"
run: |-
gh issue comment "${ISSUE_NUMBER}" \
--body "${MESSAGE}" \
--repo "${REPOSITORY}"
review:
needs: "dispatch"
if: |-
${{ needs.dispatch.outputs.command == 'review' }}
uses: "./.github/workflows/gemini-review.yml"
permissions:
contents: "read"
id-token: "write"
issues: "write"
pull-requests: "write"
with:
additional_context: "${{ needs.dispatch.outputs.additional_context }}"
checkout_ref: "${{ needs.dispatch.outputs.checkout_ref }}"
secrets: "inherit"
invoke:
needs: "dispatch"
if: |-
${{ needs.dispatch.outputs.command == 'invoke' }}
uses: "./.github/workflows/gemini-invoke.yml"
permissions:
contents: "read"
id-token: "write"
issues: "write"
pull-requests: "write"
with:
additional_context: "${{ needs.dispatch.outputs.additional_context }}"
checkout_ref: "${{ needs.dispatch.outputs.checkout_ref }}"
secrets: "inherit"
fallthrough:
needs:
- "dispatch"
- "review"
- "invoke"
if: |-
${{ always() && !cancelled() && (failure() || needs.dispatch.outputs.command == 'fallthrough') }}
runs-on: "ubuntu-latest"
permissions:
contents: "read"
issues: "write"
pull-requests: "write"
steps:
- name: "Mint identity token"
id: "mint_identity_token"
if: |-
${{ vars.APP_ID }}
uses: "actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b" # ratchet:actions/create-github-app-token@v2
with:
app-id: "${{ vars.APP_ID }}"
private-key: "${{ secrets.APP_PRIVATE_KEY }}"
permission-contents: "read"
permission-issues: "write"
permission-pull-requests: "write"
- name: "Send failure comment"
env:
GITHUB_TOKEN: "${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}"
ISSUE_NUMBER: "${{ github.event.pull_request.number || github.event.issue.number }}"
MESSAGE: |-
🤖 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.
REPOSITORY: "${{ github.repository }}"
run: |-
gh issue comment "${ISSUE_NUMBER}" \
--body "${MESSAGE}" \
--repo "${REPOSITORY}"