mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-17 18:32:19 +02:00
feat(land-and-deploy): carve first-run validation, readiness gate, and merge/deploy into sections
The once-per-repo dry-run validation, the pre-merge readiness gate, and the
merge + deploy-strategy steps (37.8KB) load on demand: skeleton 91.1KB ->
55.7KB. Step 1.5 keeps its detection bash as the dispatch; the first-run
section's fingerprint-save block gained {{SLUG_EVAL}} so it is self-contained.
Zero content lost (line-coverage checked against HEAD).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
87589961a4
commit
b4fda5f484
@@ -0,0 +1,203 @@
|
||||
<!-- AUTO-GENERATED from first-run-validation.md.tmpl — do not edit directly -->
|
||||
<!-- Regenerate: bun run gen:skill-docs -->
|
||||
## Step 1.5 (dry-run flow): First-run / config-changed validation
|
||||
|
||||
You are here because the Step 1.5 detection in the skeleton printed `FIRST_RUN`
|
||||
or `CONFIG_CHANGED` (a `CONFIRMED` run never reads this section). Nothing has
|
||||
been merged or deployed yet.
|
||||
|
||||
**If CONFIG_CHANGED:** The deploy configuration has changed since the last confirmed deploy.
|
||||
Re-trigger the dry run. Tell the user:
|
||||
|
||||
"I've deployed this project before, but your deploy configuration has changed since the last
|
||||
time. That could mean a new platform, a different workflow, or updated URLs. I'm going to
|
||||
do a quick dry run to make sure I still understand how your project deploys."
|
||||
|
||||
Then proceed to the FIRST_RUN flow below (steps 1.5a through 1.5e).
|
||||
|
||||
**If FIRST_RUN:** This is the first time `/land-and-deploy` is running for this project. Before doing anything irreversible, show the user exactly what will happen. This is a dry run — explain, validate, and confirm.
|
||||
|
||||
Tell the user:
|
||||
|
||||
"This is the first time I'm deploying this project, so I'm going to do a dry run first.
|
||||
|
||||
Here's what that means: I'll detect your deploy infrastructure, test that my commands actually work, and show you exactly what will happen — step by step — before I touch anything. Deploys are irreversible once they hit production, so I want to earn your trust before I start merging.
|
||||
|
||||
Let me take a look at your setup."
|
||||
|
||||
### 1.5a: Deploy infrastructure detection
|
||||
|
||||
Run the deploy configuration bootstrap to detect the platform and settings:
|
||||
|
||||
```bash
|
||||
# Check for persisted deploy config in CLAUDE.md
|
||||
DEPLOY_CONFIG=$(grep -A 20 "## Deploy Configuration" CLAUDE.md 2>/dev/null || echo "NO_CONFIG")
|
||||
echo "$DEPLOY_CONFIG"
|
||||
|
||||
# If config exists, parse it
|
||||
if [ "$DEPLOY_CONFIG" != "NO_CONFIG" ]; then
|
||||
# Cut at the FIRST ": ", not the last. A greedy 's/.*: *//' ate the scheme of
|
||||
# any URL: "Production URL: https://x.com" became "//x.com", because the last
|
||||
# ":" belongs to "https:".
|
||||
PROD_URL=$(echo "$DEPLOY_CONFIG" | grep -i "production.*url" | head -1 | sed 's/^[^:]*: *//')
|
||||
PLATFORM=$(echo "$DEPLOY_CONFIG" | grep -i "platform" | head -1 | sed 's/^[^:]*: *//')
|
||||
echo "PERSISTED_PLATFORM:$PLATFORM"
|
||||
echo "PERSISTED_URL:$PROD_URL"
|
||||
fi
|
||||
|
||||
# Auto-detect platform from config files
|
||||
[ -f fly.toml ] && echo "PLATFORM:fly"
|
||||
[ -f render.yaml ] && echo "PLATFORM:render"
|
||||
([ -f vercel.json ] || [ -d .vercel ]) && echo "PLATFORM:vercel"
|
||||
[ -f netlify.toml ] && echo "PLATFORM:netlify"
|
||||
[ -f Procfile ] && echo "PLATFORM:heroku"
|
||||
([ -f railway.json ] || [ -f railway.toml ]) && echo "PLATFORM:railway"
|
||||
|
||||
# Detect deploy workflows
|
||||
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null); do
|
||||
[ -f "$f" ] && grep -qiE "deploy|release|production|cd" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f"
|
||||
[ -f "$f" ] && grep -qiE "staging" "$f" 2>/dev/null && echo "STAGING_WORKFLOW:$f"
|
||||
done
|
||||
```
|
||||
|
||||
If `PERSISTED_PLATFORM` and `PERSISTED_URL` were found in CLAUDE.md, use them directly
|
||||
and skip manual detection. If no persisted config exists, use the auto-detected platform
|
||||
to guide deploy verification. If nothing is detected, ask the user via AskUserQuestion
|
||||
in the decision tree below.
|
||||
|
||||
If you want to persist deploy settings for future runs, suggest the user run `/setup-deploy`.
|
||||
|
||||
Parse the output and record: the detected platform, production URL, deploy workflow (if any),
|
||||
and any persisted config from CLAUDE.md.
|
||||
|
||||
### 1.5b: Command validation
|
||||
|
||||
Test each detected command to verify the detection is accurate. Build a validation table:
|
||||
|
||||
```bash
|
||||
# Test gh auth (already passed in Step 1, but confirm)
|
||||
gh auth status 2>&1 | head -3
|
||||
|
||||
# Test platform CLI if detected
|
||||
# Fly.io: fly status --app {app} 2>/dev/null
|
||||
# Heroku: heroku releases --app {app} -n 1 2>/dev/null
|
||||
# Vercel: vercel ls 2>/dev/null | head -3
|
||||
|
||||
# Test production URL reachability
|
||||
# curl -sf {production-url} -o /dev/null -w "%{http_code}" 2>/dev/null
|
||||
```
|
||||
|
||||
Run whichever commands are relevant based on the detected platform. Build the results into this table:
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ DEPLOY INFRASTRUCTURE VALIDATION ║
|
||||
╠══════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ Platform: {platform} (from {source}) ║
|
||||
║ App: {app name or "N/A"} ║
|
||||
║ Prod URL: {url or "not configured"} ║
|
||||
║ ║
|
||||
║ COMMAND VALIDATION ║
|
||||
║ ├─ gh auth status: ✓ PASS ║
|
||||
║ ├─ {platform CLI}: ✓ PASS / ⚠ NOT INSTALLED / ✗ FAIL ║
|
||||
║ ├─ curl prod URL: ✓ PASS (200 OK) / ⚠ UNREACHABLE ║
|
||||
║ └─ deploy workflow: {file or "none detected"} ║
|
||||
║ ║
|
||||
║ STAGING DETECTION ║
|
||||
║ ├─ Staging URL: {url or "not configured"} ║
|
||||
║ ├─ Staging workflow: {file or "not found"} ║
|
||||
║ └─ Preview deploys: {detected or "not detected"} ║
|
||||
║ ║
|
||||
║ WHAT WILL HAPPEN ║
|
||||
║ 1. Run pre-merge readiness checks (reviews, tests, docs) ║
|
||||
║ 2. Wait for CI if pending ║
|
||||
║ 3. Merge PR via {merge method} ║
|
||||
║ 4. {Wait for deploy workflow / Wait 60s / Skip} ║
|
||||
║ 5. {Run canary verification / Skip (no URL)} ║
|
||||
║ ║
|
||||
║ MERGE METHOD: {squash/merge/rebase} (from repo settings) ║
|
||||
║ MERGE QUEUE: {detected / not detected} ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
**Validation failures are WARNINGs, not BLOCKERs** (except `gh auth status` which already
|
||||
failed at Step 1). If `curl` fails, note "I couldn't reach that URL — might be a network
|
||||
issue, VPN requirement, or incorrect address. I'll still be able to deploy, but I won't
|
||||
be able to verify the site is healthy afterward."
|
||||
If platform CLI is not installed, note "The {platform} CLI isn't installed on this machine.
|
||||
I can still deploy through GitHub, but I'll use HTTP health checks instead of the platform
|
||||
CLI to verify the deploy worked."
|
||||
|
||||
### 1.5c: Staging detection
|
||||
|
||||
Check for staging environments in this order:
|
||||
|
||||
1. **CLAUDE.md persisted config:** Check for a staging URL in the Deploy Configuration section:
|
||||
```bash
|
||||
grep -i "staging" CLAUDE.md 2>/dev/null | head -3
|
||||
```
|
||||
|
||||
2. **GitHub Actions staging workflow:** Check for workflow files with "staging" in the name or content:
|
||||
```bash
|
||||
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null); do
|
||||
[ -f "$f" ] && grep -qiE "staging" "$f" 2>/dev/null && echo "STAGING_WORKFLOW:$f"
|
||||
done
|
||||
```
|
||||
|
||||
3. **Vercel/Netlify preview deploys:** Check PR status checks for preview URLs:
|
||||
```bash
|
||||
gh pr checks --json name,targetUrl 2>/dev/null | head -20
|
||||
```
|
||||
Look for check names containing "vercel", "netlify", or "preview" and extract the target URL.
|
||||
|
||||
Record any staging targets found. These will be offered in Step 5.
|
||||
|
||||
### 1.5d: Readiness preview
|
||||
|
||||
Tell the user: "Before I merge any PR, I run a series of readiness checks — code reviews, tests, documentation, PR accuracy. Let me show you what that looks like for this project."
|
||||
|
||||
Preview the readiness checks that will run at Step 3.5 (without re-running tests):
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-review-read 2>/dev/null
|
||||
```
|
||||
|
||||
Show a summary of review status: which reviews have been run, how stale they are.
|
||||
Also check if CHANGELOG.md and VERSION have been updated.
|
||||
|
||||
Explain in plain English: "When I merge, I'll check: has the code been reviewed recently? Do the tests pass? Is the CHANGELOG updated? Is the PR description accurate? If anything looks off, I'll flag it before merging."
|
||||
|
||||
### 1.5e: Dry-run confirmation
|
||||
|
||||
Tell the user: "That's everything I detected. Take a look at the table above — does this match how your project actually deploys?"
|
||||
|
||||
Present the full dry-run results to the user via AskUserQuestion:
|
||||
|
||||
- **Re-ground:** "First deploy dry-run for [project] on branch [branch]. Above is what I detected about your deploy infrastructure. Nothing has been merged or deployed yet — this is just my understanding of your setup."
|
||||
- Show the infrastructure validation table from 1.5b above.
|
||||
- List any warnings from command validation, with plain-English explanations.
|
||||
- If staging was detected, note: "I found a staging environment at {url/workflow}. After we merge, I'll offer to deploy there first so you can verify everything works before it hits production."
|
||||
- If no staging was detected, note: "I didn't find a staging environment. The deploy will go straight to production — I'll run health checks right after to make sure everything looks good."
|
||||
- **RECOMMENDATION:** Choose A if all validations passed. Choose B if there are issues to fix. Choose C to run /setup-deploy for a more thorough configuration.
|
||||
- A) That's right — this is how my project deploys. Let's go. (Completeness: 10/10)
|
||||
- B) Something's off — let me tell you what's wrong (Completeness: 10/10)
|
||||
- C) I want to configure this more carefully first (runs /setup-deploy) (Completeness: 10/10)
|
||||
|
||||
**If A:** Tell the user: "Great — I've saved this configuration. Next time you run `/land-and-deploy`, I'll skip the dry run and go straight to readiness checks. If your deploy setup changes (new platform, different workflows, updated URLs), I'll automatically re-run the dry run to make sure I still have it right."
|
||||
|
||||
Save the deploy config fingerprint so we can detect future changes:
|
||||
```bash
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
|
||||
mkdir -p ~/.gstack/projects/$SLUG
|
||||
CURRENT_HASH=$(sed -n '/## Deploy Configuration/,/^## /p' CLAUDE.md 2>/dev/null | shasum -a 256 | cut -d' ' -f1)
|
||||
WORKFLOW_HASH=$(find .github/workflows -maxdepth 1 \( -name '*deploy*' -o -name '*cd*' \) 2>/dev/null | xargs cat 2>/dev/null | shasum -a 256 | cut -d' ' -f1)
|
||||
echo "${CURRENT_HASH}-${WORKFLOW_HASH}" > ~/.gstack/projects/$SLUG/land-deploy-confirmed
|
||||
```
|
||||
Continue to Step 2.
|
||||
|
||||
**If B:** **STOP.** "Tell me what's different about your setup and I'll adjust. You can also run `/setup-deploy` to walk through the full configuration."
|
||||
|
||||
**If C:** **STOP.** "Running `/setup-deploy` will walk through your deploy platform, production URL, and health checks in detail. It saves everything to CLAUDE.md so I'll know exactly what to do next time. Run `/land-and-deploy` again when that's done."
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user