### Summary - Configures `gemini-manual.yml` to run on self-hosted runner `eliza` (`runs-on: [self-hosted, eliza]`). - Containerizes the job with `node:20-bookworm` and `--add-host host.docker.internal:host-gateway`. - Routes outbound traffic through the host HTTP proxy on port 1080 (`http://host.docker.internal:1080`) to bypass Antigravity location eligibility blocks. - Installs `gh` CLI in container startup and adds git `safe.directory`. --- Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.
301 lines
13 KiB
YAML
301 lines
13 KiB
YAML
name: gemini - manual
|
|
|
|
on:
|
|
issue_comment:
|
|
types: [created]
|
|
pull_request_review_comment:
|
|
types: [created]
|
|
|
|
concurrency:
|
|
group: agent-issue-${{ github.event.issue.number || github.event.pull_request.number }}
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: write
|
|
issues: write
|
|
pull-requests: write
|
|
actions: read
|
|
|
|
jobs:
|
|
agent-dispatch:
|
|
name: Agent / Dispatch
|
|
if: >
|
|
(github.event.comment.author_association == 'OWNER' ||
|
|
github.event.comment.author_association == 'MEMBER' ||
|
|
github.event.comment.author_association == 'COLLABORATOR') &&
|
|
(contains(github.event.comment.body, '/plan') ||
|
|
contains(github.event.comment.body, '/implement') ||
|
|
contains(github.event.comment.body, '/fix'))
|
|
runs-on: [self-hosted, eliza]
|
|
container:
|
|
image: node:20-bookworm
|
|
options: --add-host host.docker.internal:host-gateway
|
|
env:
|
|
HTTP_PROXY: http://host.docker.internal:1080
|
|
HTTPS_PROXY: http://host.docker.internal:1080
|
|
http_proxy: http://host.docker.internal:1080
|
|
https_proxy: http://host.docker.internal:1080
|
|
ALL_PROXY: http://host.docker.internal:1080
|
|
all_proxy: http://host.docker.internal:1080
|
|
NO_PROXY: localhost,127.0.0.1
|
|
no_proxy: localhost,127.0.0.1
|
|
timeout-minutes: 30
|
|
|
|
steps:
|
|
- name: Verify Collaborator Authorization
|
|
id: auth-check
|
|
run: |
|
|
AUTHOR_ASSOC="${{ github.event.comment.author_association }}"
|
|
echo "Author association: $AUTHOR_ASSOC"
|
|
if [[ "$AUTHOR_ASSOC" != "OWNER" && "$AUTHOR_ASSOC" != "MEMBER" && "$AUTHOR_ASSOC" != "COLLABORATOR" ]]; then
|
|
echo "::error::Unauthorized trigger by user with association '$AUTHOR_ASSOC'."
|
|
exit 1
|
|
fi
|
|
|
|
- name: Ensure GitHub CLI is Installed
|
|
run: |
|
|
if ! command -v gh &> /dev/null; then
|
|
echo "Installing GitHub CLI..."
|
|
curl -fsSL https://github.com/cli/cli/releases/download/v2.67.0/gh_2.67.0_linux_amd64.tar.gz | tar -xz -C /usr/local --strip-components=1
|
|
fi
|
|
|
|
- name: Acknowledge Command (Add Eyes Reaction)
|
|
if: success()
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
COMMENT_ID: ${{ github.event.comment.id }}
|
|
run: |
|
|
gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}/reactions" -f content=eyes || true
|
|
|
|
- name: Checkout Codebase
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v4
|
|
with:
|
|
version: 9.12.3
|
|
|
|
- name: Setup Node.js with pnpm cache
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 20
|
|
cache: 'pnpm'
|
|
|
|
- name: Install Dependencies & Build Workspace Packages
|
|
run: |
|
|
pnpm install --frozen-lockfile
|
|
pnpm build:deps
|
|
|
|
- name: Restore Agent Conversation Context
|
|
uses: actions/cache@v4
|
|
id: agent-context-cache
|
|
with:
|
|
path: |
|
|
~/.gemini/antigravity-cli/conversations
|
|
~/.gemini/antigravity-cli/brain
|
|
key: agent-context-issue-${{ github.event.issue.number }}-${{ github.run_id }}
|
|
restore-keys: |
|
|
agent-context-issue-${{ github.event.issue.number }}-
|
|
|
|
- name: Setup Antigravity CLI & Credentials
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
AGY_AUTH_TOKEN: ${{ secrets.AGY_AUTH_TOKEN }}
|
|
run: |
|
|
# 1. Download official Antigravity CLI binary from google-antigravity/antigravity-cli
|
|
mkdir -p "$HOME/.local/bin"
|
|
if ! command -v agy &> /dev/null; then
|
|
echo "Fetching Antigravity CLI from google-antigravity/antigravity-cli..."
|
|
gh release download --repo google-antigravity/antigravity-cli -p "agy_cli_linux_x64.tar.gz" -O - | tar -xz -C "$HOME/.local/bin"
|
|
if [ -f "$HOME/.local/bin/antigravity" ] && [ ! -f "$HOME/.local/bin/agy" ]; then
|
|
mv "$HOME/.local/bin/antigravity" "$HOME/.local/bin/agy"
|
|
fi
|
|
ln -sf "$HOME/.local/bin/agy" "$HOME/.local/bin/antigravity"
|
|
chmod +x "$HOME/.local/bin/agy" "$HOME/.local/bin/antigravity"
|
|
fi
|
|
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
echo "$HOME/.gemini/antigravity-cli/bin" >> $GITHUB_PATH
|
|
export PATH="$HOME/.local/bin:$HOME/.gemini/antigravity-cli/bin:$PATH"
|
|
|
|
# 2. Inject OAuth Token
|
|
mkdir -p ~/.gemini/antigravity-cli
|
|
if [ -n "$AGY_AUTH_TOKEN" ]; then
|
|
if echo "$AGY_AUTH_TOKEN" | base64 --decode >/dev/null 2>&1; then
|
|
echo "$AGY_AUTH_TOKEN" | base64 --decode > ~/.gemini/antigravity-cli/antigravity-oauth-token
|
|
else
|
|
echo "$AGY_AUTH_TOKEN" > ~/.gemini/antigravity-cli/antigravity-oauth-token
|
|
fi
|
|
chmod 600 ~/.gemini/antigravity-cli/antigravity-oauth-token
|
|
else
|
|
echo "::warning::AGY_AUTH_TOKEN secret is not set."
|
|
fi
|
|
|
|
- name: Configure Git Bot Identity
|
|
run: |
|
|
git config --global user.name "Adam Jensen [bot]"
|
|
git config --global user.email "adam@ermnvldmr.com"
|
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
|
|
# --- COMMAND: /plan ---
|
|
- name: Handle /plan (Issue Planning)
|
|
if: contains(github.event.comment.body, '/plan') && github.event.issue.pull_request == null
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
COMMENT_BODY: ${{ github.event.comment.body }}
|
|
run: |
|
|
echo "Generating plan for Issue #${ISSUE_NUMBER}..."
|
|
ISSUE_DATA=$(gh issue view "$ISSUE_NUMBER" --comments --json title,body,comments)
|
|
|
|
CONTINUE_FLAG=""
|
|
if [ -d "$HOME/.gemini/antigravity-cli/conversations" ] && [ "$(ls -A $HOME/.gemini/antigravity-cli/conversations 2>/dev/null)" ]; then
|
|
CONTINUE_FLAG="--continue"
|
|
fi
|
|
|
|
PROMPT="You are operating via GitHub Actions on Issue #${ISSUE_NUMBER}.\n\nIssue Context:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nPlease generate/update a detailed technical implementation plan adhering to project GEMINI.md guidelines."
|
|
|
|
PLAN_OUTPUT=$(agy $CONTINUE_FLAG --mode plan -p "$PROMPT" || echo "Agent encountered an error generating the plan.")
|
|
|
|
DISCLOSURE="\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
|
gh issue comment "$ISSUE_NUMBER" --body "${PLAN_OUTPUT}${DISCLOSURE}"
|
|
|
|
# --- COMMAND: /implement ---
|
|
- name: Handle /implement (Issue Implementation & PR)
|
|
if: contains(github.event.comment.body, '/implement') && github.event.issue.pull_request == null
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
COMMENT_BODY: ${{ github.event.comment.body }}
|
|
run: |
|
|
BRANCH_NAME="agent/issue-${ISSUE_NUMBER}"
|
|
git checkout -b "$BRANCH_NAME"
|
|
|
|
ISSUE_DATA=$(gh issue view "$ISSUE_NUMBER" --comments --json title,body,comments)
|
|
|
|
CONTINUE_FLAG=""
|
|
if [ -d "$HOME/.gemini/antigravity-cli/conversations" ] && [ "$(ls -A $HOME/.gemini/antigravity-cli/conversations 2>/dev/null)" ]; then
|
|
CONTINUE_FLAG="--continue"
|
|
fi
|
|
|
|
PROMPT="You are operating via GitHub Actions to implement Issue #${ISSUE_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nImplement the changes cleanly in the repository according to GEMINI.md rules."
|
|
agy $CONTINUE_FLAG --dangerously-skip-permissions -p "$PROMPT"
|
|
|
|
echo "Running repository verification gates..."
|
|
pnpm typecheck
|
|
pnpm lint
|
|
pnpm test
|
|
|
|
ISSUE_TITLE=$(gh issue view "$ISSUE_NUMBER" --json title -q .title)
|
|
git add -A
|
|
if git diff --staged --quiet; then
|
|
echo "No changes produced by agent."
|
|
gh issue comment "$ISSUE_NUMBER" --body "No changes were produced for implementation.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
|
exit 0
|
|
fi
|
|
|
|
git commit -m "feat: implement issue #${ISSUE_NUMBER} (${ISSUE_TITLE})"
|
|
git push -u origin "$BRANCH_NAME" --force
|
|
|
|
PR_BODY="Resolves #${ISSUE_NUMBER}\n\nAutomated implementation generated via \`/implement\`.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
|
gh pr create \
|
|
--title "feat: ${ISSUE_TITLE}" \
|
|
--body "$PR_BODY" \
|
|
--base next \
|
|
--head "$BRANCH_NAME"
|
|
|
|
# --- COMMAND: /fix ---
|
|
- name: Handle /fix (PR Review Adjustments & CI Failure Debugging)
|
|
if: contains(github.event.comment.body, '/fix')
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
ISSUE_OR_PR_NUMBER: ${{ github.event.issue.number }}
|
|
COMMENT_BODY: ${{ github.event.comment.body }}
|
|
run: |
|
|
IS_PR="${{ github.event.issue.pull_request != null }}"
|
|
if [ "$IS_PR" = "true" ]; then
|
|
# Verify PR is not from an untrusted cross-repository fork
|
|
IS_CROSS_REPO=$(gh pr view "$ISSUE_OR_PR_NUMBER" --json isCrossRepository -q .isCrossRepository)
|
|
if [ "$IS_CROSS_REPO" = "true" ]; then
|
|
echo "::error::Cross-repository fork PRs cannot be automatically processed in privileged context."
|
|
exit 1
|
|
fi
|
|
|
|
gh pr checkout "$ISSUE_OR_PR_NUMBER"
|
|
BRANCH_NAME=$(git branch --show-current)
|
|
PR_DIFF=$(gh pr diff "$ISSUE_OR_PR_NUMBER" || true)
|
|
|
|
FAILED_RUN_ID=$(gh run list --branch "$BRANCH_NAME" --status failure --limit 1 --json databaseId -q '.[0].databaseId' || true)
|
|
CI_LOGS=""
|
|
if [ -n "$FAILED_RUN_ID" ] && [ "$FAILED_RUN_ID" != "null" ]; then
|
|
echo "Found failed CI run: #$FAILED_RUN_ID. Fetching failure logs..."
|
|
CI_LOGS=$(gh run view "$FAILED_RUN_ID" --log-failed | tail -n 200 || true)
|
|
fi
|
|
|
|
CONTINUE_FLAG=""
|
|
if [ -d "$HOME/.gemini/antigravity-cli/conversations" ] && [ "$(ls -A $HOME/.gemini/antigravity-cli/conversations 2>/dev/null)" ]; then
|
|
CONTINUE_FLAG="--continue"
|
|
fi
|
|
|
|
PROMPT="You are operating via GitHub Actions to fix/adjust PR #${ISSUE_OR_PR_NUMBER} on branch ${BRANCH_NAME}.\n\nFeedback / Comment:\n${COMMENT_BODY}\n\nPR Diff:\n${PR_DIFF}\n\nFailed CI Logs (if any):\n${CI_LOGS}\n\nApply the necessary fixes, making sure all lint, typecheck, and test checks pass."
|
|
agy $CONTINUE_FLAG --dangerously-skip-permissions -p "$PROMPT"
|
|
|
|
echo "Running repository verification gates..."
|
|
pnpm typecheck
|
|
pnpm lint
|
|
pnpm test
|
|
|
|
git add -A
|
|
if git diff --staged --quiet; then
|
|
echo "No additional changes were needed."
|
|
gh pr comment "$ISSUE_OR_PR_NUMBER" --body "Analyzed the request; no additional changes were needed.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
|
exit 0
|
|
fi
|
|
|
|
git commit -m "fix: apply review adjustments and CI fixes"
|
|
git push origin "$BRANCH_NAME"
|
|
|
|
gh pr comment "$ISSUE_OR_PR_NUMBER" --body "Applied adjustments and verified build/test suite.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
|
else
|
|
echo "Handling /fix on Issue #${ISSUE_OR_PR_NUMBER}..."
|
|
BRANCH_NAME="agent/fix-issue-${ISSUE_OR_PR_NUMBER}"
|
|
git checkout -b "$BRANCH_NAME"
|
|
|
|
ISSUE_DATA=$(gh issue view "$ISSUE_OR_PR_NUMBER" --comments --json title,body,comments)
|
|
PROMPT="Fix issue #${ISSUE_OR_PR_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nInstruction:\n${COMMENT_BODY}"
|
|
agy --dangerously-skip-permissions -p "$PROMPT"
|
|
|
|
pnpm typecheck
|
|
pnpm lint
|
|
pnpm test
|
|
|
|
git add -A
|
|
git commit -m "fix: resolve issue #${ISSUE_OR_PR_NUMBER}"
|
|
git push -u origin "$BRANCH_NAME" --force
|
|
|
|
gh pr create \
|
|
--title "fix: resolve issue #${ISSUE_OR_PR_NUMBER}" \
|
|
--body "Resolves #${ISSUE_OR_PR_NUMBER}\n\nFix applied via \`/fix\`.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" \
|
|
--base next \
|
|
--head "$BRANCH_NAME"
|
|
fi
|
|
|
|
- name: Complete Command (Add Rocket Reaction)
|
|
if: success()
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
COMMENT_ID: ${{ github.event.comment.id }}
|
|
run: |
|
|
gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}/reactions" -f content=rocket || true
|
|
|
|
- name: Report Failure on Comment
|
|
if: failure()
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
run: |
|
|
gh issue comment "$ISSUE_NUMBER" --body "⚠️ Workflow failed during execution. View run logs: [Action Run #${{ github.run_id }}](${RUN_URL})\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" || true
|