## 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: {{DEPLOY_BOOTSTRAP}} 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 {{SLUG_EVAL}} 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." ---