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

post-deploy

Use when running post-deploy file-match actions after a merge (stage 3 of the post-merge pipeline).

How do I install this agent skill?

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

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The skill automates post-deployment actions by matching changed files in a GitHub PR to specific tasks defined in the repository configuration. While it is a legitimate development tool, it executes scripts directly from the repository and processes untrusted PR metadata like titles and file paths without sanitization, creating a surface for command interference and indirect prompt injection.

  • Socketwarn

    1 alert: gptAnomaly

  • Snykwarn

    Risk: MEDIUM · 1 issue

What does this agent skill do?

post-deploy

Stage 3 of the autonomous deployment pipeline. Triggered by the deployed label. Reads the PR's changed files, matches them against configured patterns, and runs targeted actions: ECR image rebuilds, config reload verification, smoke tests, or custom scripts.

When to Use

  • Triggered by deployed label via event-rules (after deployment-checker confirms live deploy)
  • Manual: /post-deploy PR_NUMBER org/repo

Invocation

/post-deploy 42 fellowship-dev/pylot

Runbook

Step 0: Dedup Gate

PR=$1
REPO=$2

# Check if post-deploy already ran (look for a post-deploy comment)
EXISTING=$(gh pr view $PR --repo $REPO --json comments \
  --jq '.comments[].body' | grep "Post-deploy actions" || true)
if [ -n "$EXISTING" ]; then
  echo "[post-deploy] outcome=\"already complete — post-deploy comment found\" status=success"
  exit 0
fi

Step 1: Read PR Context

PR_DATA=$(gh pr view $PR --repo $REPO --json number,title,url,files,mergeCommit,baseRefName)
PR_TITLE=$(echo "$PR_DATA" | python3 -c "import json,sys; print(json.load(sys.stdin)['title'])")
PR_URL=$(echo "$PR_DATA" | python3 -c "import json,sys; print(json.load(sys.stdin)['url'])")
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']))
")

echo "PR: $PR — $PR_TITLE"
echo "Changed files:"
echo "$CHANGED_FILES"

Step 2: Read Team Post-Deploy Configuration

Read the team's CLAUDE.md for post_deploy: rules. Each rule maps a file glob pattern to an action:

# Example in team CLAUDE.md:
post_deploy:
  - match: "Dockerfile*"
    action: ecr-rebuild
    description: "Rebuild and push ECR image"
  - match: "docker-entrypoint.sh"
    action: ecr-rebuild
  - match: "crew.yml"
    action: config-reload-verify
    description: "Verify gateway reloaded updated config"
  - match: "scripts/*.sh"
    action: executor-verify
    description: "Spot-check executor behavior"
  - match: "event-rules.yml"
    action: config-reload-verify
  - match: "**"
    action: smoke-test
    optional: true
    description: "Optional smoke test for any PR"

Action types:

ActionDescription
ecr-rebuildRebuild Docker image and push to ECR
config-reload-verifyVerify the process/gateway has reloaded the updated config
executor-verifySpot-check executor or script behavior
smoke-testRun team-defined smoke test
customRun command field as shell command

Step 3: Match Files to Actions

# Pseudocode — implement in bash with Python for glob matching
import fnmatch

changed = CHANGED_FILES.splitlines()
triggered_actions = []

for rule in post_deploy_rules:
    pattern = rule['match']
    matching = [f for f in changed if fnmatch.fnmatch(f, pattern)]
    if matching:
        triggered_actions.append({
            'action': rule['action'],
            'description': rule.get('description', rule['action']),
            'matched_files': matching,
            'optional': rule.get('optional', False)
        })

Step 4: Execute Actions

Run each triggered action. Document result for each.

Action: ecr-rebuild

# Rebuild and push ECR image
PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
ECR_URI="${ECR_URI:-$(grep 'fargate_ecr_uri' $PYLOT_DIR/crew.yml | awk '{print $2}')}"

cd "$PYLOT_DIR"
bash scripts/build-worker-image.sh 2>&1
ECR_EXIT=$?
[ $ECR_EXIT -eq 0 ] && echo "ecr-rebuild: success" || echo "ecr-rebuild: failed exit=$ECR_EXIT"

Action: config-reload-verify

# Verify the executor/gateway has reloaded the updated config
# For Pylot: check that crew.yml timestamp matches what executor loaded
PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"

# Check if executor is running and has loaded recent config
CREW_MTIME=$(stat -c %Y "$PYLOT_DIR/crew.yml" 2>/dev/null || stat -f %m "$PYLOT_DIR/crew.yml" 2>/dev/null)
EXECUTOR_PID=$(pgrep -f "executor.sh" || true)

if [ -n "$EXECUTOR_PID" ]; then
  echo "config-reload-verify: executor running (pid=$EXECUTOR_PID). crew.yml mtime=$CREW_MTIME."
  echo "config-reload-verify: success — executor will pick up config on next poll cycle"
else
  echo "config-reload-verify: WARNING — executor not running. Config will load on restart."
fi

Action: executor-verify

# Spot-check executor behavior — run a quick test
PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"

# Syntax-check the modified scripts
for script in $MATCHED_SCRIPTS; do
  bash -n "$PYLOT_DIR/$script" && echo "executor-verify: $script syntax OK" || echo "executor-verify: $script SYNTAX ERROR"
done

Action: smoke-test

Run the team's configured smoke test. Optional by default.

# Team-specific smoke test — read from CLAUDE.md smoke_test.command
# Example for Pylot: run a dry-run event dispatch
PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
bash "$PYLOT_DIR/event-router.sh" --dry-run 2>&1 | head -20
echo "smoke-test: event-router dry-run complete"

Step 5: Post Summary Comment

# Build table rows before heredoc (<<'EOF' prevents expansion — pre-build instead)
ACTION_TABLE=""
for action_entry in $TRIGGERED_ACTION_ENTRIES; do
  ACTION_NAME=$(echo "$action_entry" | cut -d: -f1)
  ACTION_FILES=$(echo "$action_entry" | cut -d: -f2)
  ACTION_RESULT=$(echo "$action_entry" | cut -d: -f3)
  ACTION_TABLE="${ACTION_TABLE}| ${ACTION_NAME} | ${ACTION_FILES} | ${ACTION_RESULT} |\n"
done
[ -z "$ACTION_TABLE" ] && ACTION_TABLE="_No file-match rules triggered for this PR's changed files._\n"

gh pr comment $PR --repo $REPO --body "$(printf '%s' "## Post-deploy actions

| Action | Matched Files | Result |
|--------|--------------|--------|
$(printf '%b' "$ACTION_TABLE")
**Pipeline complete.** This PR is live and verified.")"

Step 6: Write Report

PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
REPORT="$PYLOT_DIR/reports/$(date +%Y-%m-%d)-post-deploy-$(echo $REPO | tr '/' '-')-pr${PR}.md"

cat > "$REPORT" <<EOF
# Post-Deploy: $REPO PR #$PR — $PR_TITLE

**Date**: $(date +%Y-%m-%d)
**PR**: [$REPO#$PR]($PR_URL)

## Changed Files
$CHANGED_FILES

## Actions Triggered
$TRIGGERED_ACTIONS_SUMMARY

## Results
$ACTIONS_RESULTS
EOF

Default File-Match Rules (Pylot)

PatternActionWhen
Dockerfile*ecr-rebuildDocker image changed
docker-entrypoint.shecr-rebuildEntrypoint script changed
crew.ymlconfig-reload-verifyCrew config changed
event-rules.ymlconfig-reload-verifyEvent routing changed
scripts/*.shexecutor-verifyShell scripts changed
dispatch.shexecutor-verifyDispatch logic changed
executor.shexecutor-verifyExecutor logic changed

Notes

  • No matched rules = no actions. A PR touching only Markdown files does nothing. This is correct behavior.
  • Optional actions (smoke-test) run but do not affect the summary verdict.
  • ecr-rebuild failure should be surfaced as a comment but does not re-apply deploy-failed — the deploy itself was verified. File a follow-up issue instead.
  • Team config is the authority. Generic skill + team CLAUDE.md = full configurability without modifying the skill.
  • Monorepo: match files against per-target rules if the team has multiple deploy targets.

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-deploy">View post-deploy on skillZs</a>