GitHub Actions Deployment
<instructions>Manage GitHub Actions — workflows, releases, GHCR, CI/CD with safety gates and persistent config.
Robustness Rules (MANDATORY — apply to ALL phases)
Fail-Fast
| Rule | Applies to |
|---|---|
Every Bash call MUST end with && echo "OK ..." || echo "FAILED ..." | ALL scripts |
On FAILED — stop current phase, report error to user, DO NOT retry same command blindly | ALL phases |
| Max 2 retries per failed operation. After 2nd failure — report and stop | ALL phases |
| If a script exits non-zero — read its stderr, diagnose, fix root cause, then retry ONCE | Scripts |
Loop Protection
| Rule | Limit |
|---|---|
gh auth attempts — max 2, then ask user | 2 auth |
gh commands per phase — max 5 | 5 per phase |
| AskUserQuestion — max 3 questions per phase | 3 per phase |
| update-agent mode — max 5 workflows per run | 5 workflows |
Timeouts
| Operation | Timeout | Action on timeout |
|---|---|---|
gh CLI commands | 30s (timeout 30 gh ...) | Report "gh timed out", stop |
gh run watch | 5min (timeout 300 gh run watch ...) | Report "Watch timed out", switch to polling |
| Entire skill invocation | Do not exceed 15 gh calls total | Stop, report progress, suggest manual |
Fallback Strategy
If a script fails and cannot be fixed:
- Report the exact error to user: script name, exit code, stderr
- Attempt the same operation manually (inline Bash) — scripts are helpers, not gatekeepers
- If manual fallback also fails — report both attempts and ask user what to do
- NEVER silently swallow errors or continue with stale/missing data
Manual fallback examples:
| Failed script | Manual alternative |
|---|---|
| detect-mode.sh | Parse $ARGUMENTS yourself — keyword matching is simple |
| gh-env-check.sh | Run gh auth status, gh repo view --json name, gh secret list |
| workflow-discover.sh | Run ls .github/workflows/, gh workflow list, gh run list -L 5 |
| deploy-local-ops.sh | Read/write CLAUDE.local.md directly with Read/Edit tools |
Error Reporting (MANDATORY)
On ANY failure — before stopping or asking user — output:
SCRIPT_ERROR: <script-name>
EXIT_CODE: <code>
STDERR: <error message>
PHASE: <current phase>
ACTION: <what was attempted>
FALLBACK: <what will be tried next OR "asking user">
This is non-negotiable. Silent failures are bugs.
Phase 0: Mode Detection (MANDATORY FIRST STEP)
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/detect-mode.sh" "$ARGUMENTS"
Output format:
ARGS: [arguments received]
MODE: [detected mode]
Use the MODE value and GOTO that mode section below.
Mode Reference
| Keyword in args | MODE |
|---|---|
| setup, check, prerequisites, init | setup |
| create, new workflow, add workflow | create |
| release, bump, version, tag, publish | release |
| deploy, trigger, dispatch, run workflow | deploy |
| monitor, watch, status, check runs, logs | monitor |
| update agent, refresh, rescan | update-agent |
| (empty, no GitHub config) | setup |
| (empty, GitHub config exists) | monitor |
Phase 1: Environment & Config Check
Runs for ALL modes before branching.
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/gh-env-check.sh" && echo "OK env-check" || echo "FAILED env-check"
STOP if FAILED -- fix GitHub environment before continuing.
Parse output key=value pairs. Note gh CLI version, auth status, repo info, secrets count.
Load Existing Config
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/deploy-local-ops.sh" list 2>/dev/null || echo "NO_CONFIG"
Read CLAUDE.local.md if it exists — check for ## GitHub Config and ## Workflows: sections.
Branching logic:
| Condition | Action |
|---|---|
NO_CONFIG AND mode=setup | GOTO Phase 2: Setup |
NO_CONFIG AND mode=create/release/deploy | GOTO Phase 2 (need config first) |
Config exists AND mode=setup | Report existing config, ask if re-setup |
Config exists AND mode=create | GOTO Phase 3: Create Workflow |
Config exists AND mode=release | GOTO Phase 4: Release |
Config exists AND mode=deploy | GOTO Phase 5: Deploy |
Config exists AND mode=monitor | GOTO Phase 6: Monitor |
mode=update-agent | GOTO Mode: update-agent |
Phase 2: Setup
Step 1: Verify gh Auth
EXECUTE using Bash tool:
gh auth status 2>&1 && echo "OK auth" || echo "FAILED auth"
If FAILED — instruct user: gh auth login
Step 2: Detect Repo
EXECUTE using Bash tool:
gh repo view --json owner,name,url,defaultBranchRef,visibility 2>/dev/null && echo "OK repo" || echo "FAILED repo"
Step 3: Check Secrets
EXECUTE using Bash tool:
gh secret list 2>/dev/null && echo "OK secrets" || echo "FAILED secrets"
Step 4: Check SSH Integration
Check if CLAUDE.local.md has SSH server config (for deploy workflows):
EXECUTE using Bash tool:
grep -q "^## SSH Servers" CLAUDE.local.md 2>/dev/null && echo "SSH_SERVERS=exists" || echo "SSH_SERVERS=missing"
Step 5: Discover Workflows
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/workflow-discover.sh" && echo "OK discovery" || echo "FAILED discovery"
Step 6: Persist Config
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/deploy-local-ops.sh" add-github "OWNER" "REPO" "ghcr.io" && echo "OK add-github" || echo "FAILED add-github"
Replace OWNER and REPO with detected values from Step 2.
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/deploy-local-ops.sh" add-workflows && echo "OK add-workflows" || echo "FAILED add-workflows"
Step 7: Gitignore
EXECUTE using Bash tool:
grep -q "CLAUDE.local.md" .gitignore 2>/dev/null && echo "EXISTS" || (echo "CLAUDE.local.md" >> .gitignore && echo "ADDED")
Step 8: Generate deploy-admin Agent
Read the agent template:
EXECUTE using Bash tool:
cat "${CLAUDE_SKILL_DIR}/templates/deploy-admin-agent.md.template"
Replace placeholders in template:
{{GITHUB_CONFIG}}-- GitHub Config table from CLAUDE.local.md{{WORKFLOW_INVENTORY}}-- Workflows table from CLAUDE.local.md{{SERVER_TARGETS}}-- SSH Servers table from CLAUDE.local.md (if exists) or "No SSH servers configured"{{SECRETS_LIST}}-- secret names fromgh secret list{{LAST_UPDATED}}-- current ISO timestamp
Write result to .claude/agents/deploy-admin.md in the project using Write tool.
Phase 3: Create Workflow
Step 1: Load Templates
Read references/workflow-templates.md from skill directory for workflow patterns.
Step 2: Determine Type
Use AskUserQuestion:
header: "Workflow Type"
question: "What type of GitHub Actions workflow do you need?"
options:
- label: "Build + Push to GHCR"
description: "Build Docker image and push to GitHub Container Registry"
- label: "Deploy to VPS"
description: "Deploy via SSH to a remote server"
- label: "Release"
description: "Create GitHub Release from tag push"
- label: "Security Scan"
description: "Dependency/code scanning with SARIF"
- label: "Custom"
description: "Describe your workflow needs"
Step 3: Generate YAML
Based on selected template and user input:
- Generate workflow YAML with project-specific values
- Write to
.github/workflows/<name>.yml - Validate YAML structure
EXECUTE using Bash tool:
mkdir -p .github/workflows && echo "OK dir" || echo "FAILED dir"
Write workflow file using Write tool.
Step 4: Update Config
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/deploy-local-ops.sh" update-workflows && echo "OK update" || echo "FAILED update"