Files
ermnvldmr.com/.github/workflows/gemini-manual.yml
T
deytenit cd656691e8 fix(ci): increase agy print timeout, set actions write permission, and sharpen headless prompt (#60)
### Summary of Changes
- Grant `actions: write` workflow permission so that `actions/cache@v4`
can save conversation context keys on self-hosted runners.
- Set `--print-timeout 25m` (and `20m` for plan) on all `agy` CLI
invocations to avoid premature cancellation during initial workspace
verification checks.
- Sharpen the headless mode prompt in `/implement` and `/fix` steps to
instruct the agent not to exit before applying edits directly to the
source code.

Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.
2026-09-13 18:54:16 +03:00

320 lines
15 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: write
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
ALL_PROXY: http://host.docker.internal:1080
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. Patch location eligibility check (open-antigravity-patcher CLI_GATE_X64)
node -e '
const fs = require("fs");
const file = process.env.HOME + "/.local/bin/agy";
if (!fs.existsSync(file)) process.exit(0);
const buf = fs.readFileSync(file);
let count = 0;
for (let i = 0; i < buf.length - 18; i++) {
if (buf[i] === 0x48 && buf[i+1] === 0x85 && buf[i+2] === 0xc0 && buf[i+3] === 0x0f && buf[i+4] === 0x84 &&
buf[i+9] === 0x80 && buf[i+10] === 0x78 && buf[i+11] === 0x08 && buf[i+12] === 0x00 &&
buf[i+13] === 0x0f && buf[i+14] === 0x85) {
buf[i+9] = 0x48; buf[i+10] = 0x85; buf[i+11] = 0xc0; buf[i+12] = 0x90;
count++;
}
}
if (count > 0) {
fs.writeFileSync(file, buf);
console.log(`Applied open-antigravity-patcher: ${count} gates patched.`);
} else {
console.log("Antigravity CLI is already patched or signature not found.");
}
'
# 3. 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 in non-interactive headless mode 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 --print-timeout 20m -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 in non-interactive headless mode to implement Issue #${ISSUE_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nTask: Inspect relevant files, implement the necessary code changes directly in the workspace adhering to GEMINI.md rules, and verify them. Do not exit or stop before applying edits to the source code."
agy $CONTINUE_FLAG --dangerously-skip-permissions --print-timeout 25m -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 in non-interactive headless mode 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\nTask: Apply the necessary fixes directly to the files, ensuring all lint, typecheck, and test checks pass. Do not exit without applying the changes."
agy $CONTINUE_FLAG --dangerously-skip-permissions --print-timeout 25m -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="You are operating via GitHub Actions in non-interactive headless mode to fix issue #${ISSUE_OR_PR_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nInstruction:\n${COMMENT_BODY}\n\nTask: Apply the necessary fixes directly to the files adhering to GEMINI.md rules."
agy --dangerously-skip-permissions --print-timeout 25m -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