skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
fellowship-dev/dogfooded-skills121 installs

post-merge

Use when triggering a post-merge deployment after a PR is merged (stage 1 of the post-merge pipeline).

How do I install this agent skill?

npx skills add https://github.com/fellowship-dev/dogfooded-skills --skill post-merge
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The skill automates post-merge deployment tasks including PR analysis and job dispatching. It accesses local configuration files and executes commands based on external project files, which introduces typical DevOps surface risks such as local data exposure and potential indirect prompt injection from PR metadata.

  • Socketwarn

    1 alert: gptAnomaly

  • Snykwarn

    Risk: MEDIUM · 1 issue

What does this agent skill do?

post-merge

Stage 1 of the autonomous deployment pipeline. Runs after a PR merges: reads the diff, determines whether the deploy is automatic or manual, optionally performs the manual deploy, then dispatches a deployment-checker job to poll until live.

When to Use

  • Triggered automatically by event-rules when a PR merges to the default branch
  • Manual: /post-merge PR_NUMBER org/repo

Invocation

/post-merge 42 fellowship-dev/pylot

Arguments

PR_NUMBER=$1    # PR number
REPO=$2         # org/repo

Runbook

Step 0: Dedup Gate

PR=$1
REPO=$2

# Check if deployment-checker job already dispatched for this PR
EXISTING=$(ls ${PYLOT_DISPATCH_DIR:-$HOME/.local/share/pylot/missions}/pending/ \
  ${PYLOT_DISPATCH_DIR:-$HOME/.local/share/pylot/missions}/running/ 2>/dev/null \
  | grep "deploy-check-${PR}-" || true)
if [ -n "$EXISTING" ]; then
  echo "[post-merge] outcome=\"already dispatched — deploy-checker job exists\" status=success"
  exit 0
fi

Step 1: Gather PR Context

# Fetch PR metadata
PR_DATA=$(gh pr view $PR --repo $REPO --json number,title,mergedAt,baseRefName,headRefName,files,url,mergeCommit)
PR_TITLE=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['title'])")
PR_SHA=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('mergeCommit',{}).get('oid','') or '')" 2>/dev/null || true)
CHANGED_FILES=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print('\n'.join(f['path'] for f in d['files']))")
BASE_BRANCH=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['baseRefName'])")

echo "PR: $PR — $PR_TITLE"
echo "SHA: $PR_SHA"
echo "Base: $BASE_BRANCH"
echo "Files changed:"
echo "$CHANGED_FILES"

Step 2: Read Team Deploy Configuration

Read the team's CLAUDE.md to determine the deploy method configured for this repo. Look for a deploy: section:

# Example in crew/infra/CLAUDE.md or team CLAUDE.md:
deploy:
  method: auto-pull          # auto-pull | github-actions | manual
  health_url: "http://localhost:1337/_health"
  timeout_minutes: 5
  checker_script: "scripts/deployment-checker-pylot.sh"
  expected_sha_field: "sha"  # JSON field in health response containing deployed sha

Deploy method decision tree:

MethodAction
auto-pullDeploy is automatic. Skip Step 3 and Step 4 (auto-deploy.sh handles deploy-check).
github-actionsDeploy triggered by merge. Wait ~2 min, then Step 4.
manualCTO runs deploy command now (Step 3), then Step 4.

If no deploy config found, emit a warning and exit — do not guess.

Step 3: Manual Deploy (if method = manual)

Only execute when method: manual. Read the deploy command from team config:

# Example: manual deploy for a Fly.io app
cd /path/to/repo && fly deploy --remote-only

# Example: manual ECR push
aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URI
docker build -t $IMAGE . && docker push $IMAGE

Document the command executed and its output.

Step 4: Dispatch deployment-checker Job

Skip this step if method: auto-pull. Auto-pull repos have their deploy-check dispatched by auto-deploy.sh after the executor restarts — dispatching here would create a chicken-and-egg deadlock (deploy-checker blocks the queue, which blocks the deploy it's waiting for).

For other deploy methods (github-actions, manual), dispatch a new job:

if [ "$DEPLOY_METHOD" != "auto-pull" ]; then
  PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
  curl -sS -X POST \
    -H "Authorization: Bearer $(grep '^PYLOT_DISPATCH_TOKEN=' $HOME/projects/fellowship-dev/claude-buddy/.env | cut -d= -f2)" \
    -H "Content-Type: application/json" \
    -d "$(python3 -c "import json; print(json.dumps({'agent':'${TEAM}.intern','task':'Check deployment for $REPO#$PR — $PR_TITLE','repo':'$REPO','context':'SHA: $PR_SHA. Health URL: $HEALTH_URL. Timeout: ${TIMEOUT_MINUTES:-5} minutes. Checker script: ${CHECKER_SCRIPT}. Run /deployment-checker $PR $REPO.'}))")" \
    "http://127.0.0.1:3000/dispatch"
else
  echo "[post-merge] Skipping deploy-check dispatch — auto-pull deploys are checked by auto-deploy.sh"
fi

Step 5: Post Comment on PR

gh pr comment $PR --repo $REPO --body "$(cat <<'EOF'
**Post-merge pipeline started** 🚀

| Field | Value |
|-------|-------|
| Deploy method | \`$DEPLOY_METHOD\` |
| Health endpoint | \`$HEALTH_URL\` |
| Timeout | ${TIMEOUT_MINUTES:-5} min |
| Expected SHA | \`${PR_SHA:-unknown}\` |

Deployment checker dispatched. Will apply \`deployed\` or \`deploy-failed\` label when complete.
EOF
)"

Step 6: Write Report

PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
REPORT="$PYLOT_DIR/reports/$(date +%Y-%m-%d)-post-merge-$(echo $REPO | tr '/' '-')-pr${PR}.md"
cat > "$REPORT" <<EOF
# Post-Merge: $REPO PR #$PR — $PR_TITLE

**Date**: $(date +%Y-%m-%d)
**PR**: [$REPO#$PR]($PR_URL)
**SHA**: $PR_SHA
**Deploy method**: $DEPLOY_METHOD
**Deploy-checker job**: dispatched

## Changed Files
$CHANGED_FILES

## Outcome
Deploy-checker dispatched. Awaiting health confirmation.
EOF

Team Configuration Reference

Each team's CLAUDE.md should contain a deploy: section. Generic examples:

Pylot (auto-pull)

deploy:
  method: auto-pull
  health_url: "http://localhost:1337/_health"
  timeout_minutes: 5
  checker_script: "scripts/deployment-checker-pylot.sh"
  expected_sha_field: "sha"

Lexgo (GitHub Actions → Fly.io)

deploy:
  method: github-actions
  health_url: "https://api.lexgo.cl/_health"
  timeout_minutes: 30
  checker_script: "scripts/deployment-checker-lexgo.sh"

Booster-pack (branch-push → Fly + Vercel)

deploy:
  method: auto-pull
  health_url: "https://api.booster-pack.dev/health"
  timeout_minutes: 10

Notes

  • No team config = no action. Don't guess deploy methods — missing config is a signal to configure.
  • SHA comparison is best-effort. If health endpoint doesn't expose a sha field, fall back to timestamp comparison.
  • Post-merge fires per-PR. Each merged PR gets its own deploy-checker job.
  • Monorepo: if the repo has multiple deploy targets (e.g., backend + frontend), dispatch one checker per target. The checker_script determines which target to poll.

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/fellowship-dev/dogfooded-skills/post-merge">View post-merge on skillZs</a>