Files
gstack/setup-deploy/SKILL.md.tmpl
T
50d020ad9d v1.91.85.0 fix(cso,deploy): /cso on Windows Git 2.56 and macOS Docker, zsh-safe loops, honest deploy stops (Wave 9 Lane D) (#3134)
/cso sets GIT_CONFIG_GLOBAL=/dev/null on every platform (Git for Windows 2.56
rejects NUL), shared by childEnvironment and the eval and producer Git
environments, with a Windows-safe test that `git config --global --list` is
empty. On macOS the local Docker socket resolves without opening it when Bun's
realpathSync throws EOPNOTSUPP; Linux admission and the local-Unix-only rule
are unchanged. /test-audit and /ship loop over file lists zsh does not
word-split, with a static test against `for x in $VAR` in generated bash.
/setup-deploy stops and writes nothing when nothing is deployed yet;
/land-and-deploy runs a recorded command trigger only with explicit approval
before claiming revision proof. TODOS.md records the open P2/P3 bugs by area,
the Wave 9 parked items and the feature themes.

Closes #3082. Adopts #3094, #3095, #3096 and #3109.

Co-authored-by: marcode <244097767+vilano93@users.noreply.github.com>
Co-authored-by: Nathan <196341+nathanshox@users.noreply.github.com>
Co-authored-by: mikehasa <91774998+mikehasa@users.noreply.github.com>
Co-authored-by: Andrey <95643518+Alfabit7@users.noreply.github.com>
2026-10-11 15:43:33 +00:00

251 lines
10 KiB
Cheetah

---
name: setup-deploy
preamble-tier: 2
version: 1.0.0
description: |
Configure deployment settings for /land-and-deploy. Detects your deploy
platform (Fly.io, Render, Vercel, Netlify, Heroku, GitHub Actions, custom),
production URL, health check endpoints, and deploy status commands. Writes
the configuration to CLAUDE.md so all future deploys are automatic.
Use when: "setup deploy", "configure deployment", "set up land-and-deploy",
"how do I deploy with gstack", "add deploy config".
triggers:
- configure deploy
- setup deployment
- set deploy platform
allowed-tools:
- Bash
- Read
- Write
- Edit
- Glob
- Grep
- AskUserQuestion
---
{{PREAMBLE}}
{{THIRD_PARTY_ACTIONS}}
# /setup-deploy — Configure Deployment for gstack
You are helping the user configure their deployment so `/land-and-deploy` works
automatically. Your job is to detect the deploy platform, production URL, health
checks, and deploy status commands — then persist everything to CLAUDE.md.
After this runs once, `/land-and-deploy` reads CLAUDE.md and skips detection entirely.
## Instructions
### Step 1: Check existing configuration
```bash
grep -A 20 "## Deploy Configuration" CLAUDE.md 2>/dev/null || echo "NO_CONFIG"
```
If configuration already exists, show it and ask:
- **Context:** Deploy configuration already exists in CLAUDE.md.
- **RECOMMENDATION:** Choose A to update if your setup changed.
- A) Reconfigure from scratch (overwrite existing)
- B) Edit specific fields (show current config, let me change one thing)
- C) Done — configuration looks correct
If the user picks C, stop.
### Step 2: Detect platform
Run the platform detection from the deploy bootstrap:
```bash
# Platform config files
[ -f fly.toml ] && echo "PLATFORM:fly" && cat fly.toml
[ -f render.yaml ] && echo "PLATFORM:render" && cat render.yaml
{ [ -f vercel.json ] || [ -d .vercel ]; } && echo "PLATFORM:vercel"
[ -f netlify.toml ] && echo "PLATFORM:netlify" && cat netlify.toml
[ -f Procfile ] && echo "PLATFORM:heroku"
{ [ -f railway.json ] || [ -f railway.toml ]; } && echo "PLATFORM:railway"
# GitHub Actions 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|staging" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f"
done
# Project type
[ -f package.json ] && grep -q '"bin"' package.json 2>/dev/null && echo "PROJECT_TYPE:cli"
find . -maxdepth 1 -name '*.gemspec' 2>/dev/null | grep -q . && echo "PROJECT_TYPE:library"
```
### Step 3: Platform-specific setup
Based on what was detected, guide the user through platform-specific configuration.
If several platforms are detected, ask which one serves this project's production target before proceeding. Detection is a hint, not a selection. Confirm whether the project is a web app, API, CLI, or library; use detected CLI/library markers as defaults.
#### Fly.io
If `fly.toml` detected:
1. Extract app name: `grep -m1 "^app" fly.toml | sed 's/app = "\(.*\)"/\1/'`
2. Check if `fly` CLI is installed: `which fly 2>/dev/null`
3. If installed, verify: `fly status --app {app} 2>/dev/null`
4. Infer URL: `https://{app}.fly.dev`
5. Set deploy status command: `fly status --app {app}`
6. Set health check: run `curl -s -o /dev/null -w "%{http_code}" https://{app}.fly.dev/health`; use `https://{app}.fly.dev/health` when it returns 2xx, otherwise `https://{app}.fly.dev`
Ask the user to confirm the production URL. Some Fly apps use custom domains.
#### Render
If `render.yaml` detected:
1. Extract service name and type from render.yaml
2. Check only whether the Render API key is set. Never print any key bytes, including a prefix:
```bash
if [ -n "${RENDER_API_KEY:-}" ]; then
echo "RENDER_API_KEY: set"
else
echo "RENDER_API_KEY: not set"
fi
```
3. Infer URL: `https://{service-name}.onrender.com`
4. Render deploys automatically on push to the connected branch — no deploy workflow needed
5. Set health check: the inferred URL
Ask the user to confirm. Render uses auto-deploy from the connected git branch — after
merge to the default branch, Render picks it up automatically. The "deploy wait" in /land-and-deploy
should poll the Render URL until it responds with the new version.
#### Vercel
If vercel.json or .vercel detected:
1. Check for `vercel` CLI: `which vercel 2>/dev/null`
2. If installed: `vercel ls --prod 2>/dev/null | head -3`
3. Vercel deploys automatically on push — preview on PR, production on merge to the default branch — only when the Vercel project is connected to this Git repository. For a CLI-only project, ask how production deploys run and record that command as the deploy trigger
4. Set health check: the production URL from vercel project settings
Ask for the production URL if not available from the CLI, then confirm it before writing.
#### Netlify
If netlify.toml detected:
1. Extract site info from netlify.toml
2. Netlify deploys automatically on push
3. Set health check: the production URL
Ask for and confirm the production URL; do not infer it from a repository name.
#### Heroku / Railway
These markers do not identify the production app or service reliably. Keep the detected platform as a suggestion and use the Custom / Manual questions below to collect the production URL, trigger, and status check.
#### GitHub Actions only
If deploy workflows detected but no platform config:
1. Read the workflow file to understand what it does
2. Extract the deploy target (if mentioned)
3. Ask the user for the production URL
4. Set deploy status command: `gh run list --workflow {workflow file name} --limit 1 --json headSha,status,conclusion`
#### Custom / Manual
If nothing detected:
A project deployed only with the Vercel CLI has no `vercel.json` or `.vercel/`; `vercel link` creates `.vercel/`, so a re-run detects it.
Use AskUserQuestion to gather the information:
1. **How are deploys triggered?**
- A) Automatically on push to the default branch (Fly, Render, Vercel, Netlify, etc.)
- B) Via GitHub Actions workflow
- C) Via a deploy script or CLI command (describe it)
- D) Manually (SSH, dashboard, etc.)
- E) Nothing is deployed yet (the first production deploy is still to come)
- F) This project never deploys (library, CLI, tool)
On E, stop here and write nothing: there is no production URL and no deploy trigger to record yet. Tell the user that this skill configures how `/land-and-deploy` verifies a deploy, and the first bring-up is its own step, done with the platform's own CLI or whatever bring-up tool they choose. Bring the project up first, then re-run `/setup-deploy` after the first production deploy exists. On F, Step 4 writes the `none` configuration.
2. **What's the production URL?** (Free text — the URL where the app runs)
3. **How can gstack check if a deploy succeeded?**
- A) HTTP health check at a specific URL (e.g., /health, /api/status)
- B) CLI command (e.g., `fly status`, `kubectl rollout status`)
- C) Check the GitHub Actions workflow status
- D) No automated way — just check the URL loads
4. **Any pre-merge or post-merge hooks?**
- Commands to run before merging (e.g., `bun run build`)
- Commands to run after merge but before deploy verification
### Step 4: Write configuration
Before writing, collect fields not already confirmed (a field is confirmed only when the user confirmed it or a platform section above set it; Fly, Heroku/Railway and GitHub Actions leave the deploy trigger unset): merge method (squash/merge/rebase, offering only the methods `gh repo view --json squashMergeAllowed,mergeCommitAllowed,rebaseMergeAllowed` reports as allowed), pre-merge command or none, deploy trigger, and status/health checks. Ask only for missing values, across every platform path. If the project does not deploy, set platform/URL/workflow/status/health/trigger to `none`, retain its CLI/library project type, and skip deploy verification. Show the complete proposed configuration and obtain confirmation.
Read CLAUDE.md (or create it). Find and replace the `## Deploy Configuration` section
if it exists, or append it at the end.
```markdown
## Deploy Configuration (configured by /setup-deploy)
- Platform: {platform}
- Production URL: {url}
- Deploy workflow: {workflow file or "auto-deploy on push"}
- Deploy status command: {command or "HTTP health check"}
- Merge method: {squash/merge/rebase}
- Project type: {web app / API / CLI / library}
- Post-deploy health check: {health check URL or command}
### Custom deploy hooks
- Pre-merge: {command or "none"}
- Deploy trigger: {command or "automatic on push to <default branch>"}
- Deploy status: {command or "poll production URL"}
- Health check: {URL or command}
```
Resolve `<default branch>` with `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`. The hooks block repeats the exact commands /land-and-deploy runs: `Deploy status` is the same value as `Deploy status command`, and `Health check` the same as `Post-deploy health check`. Write each value in both places.
### Step 5: Verify
After writing, verify the configuration works:
1. If a health check URL was configured, try it:
```bash
curl -sf "{health-check-url}" -o /dev/null -w "%{http_code}" 2>/dev/null || echo "UNREACHABLE"
```
2. If a deploy status command was configured, try it:
```bash
_OUT=$({deploy-status-command} 2>&1); _RC=$?
printf '%s\n' "$_OUT" | head -5
[ "$_RC" -eq 0 ] || echo "COMMAND_FAILED (exit $_RC)"
```
Report results. If anything failed, note it but don't block — the config is still
useful even if the health check is temporarily unreachable.
### Step 6: Summary
```
DEPLOY CONFIGURATION — COMPLETE
════════════════════════════════
Platform: {platform}
URL: {url}
Health check: {health check}
Status cmd: {status command}
Merge method: {merge method}
Saved to CLAUDE.md. /land-and-deploy will use these settings automatically.
Next steps:
- Run /land-and-deploy to merge and deploy your current PR
- Edit the "## Deploy Configuration" section in CLAUDE.md to change settings
- Run /setup-deploy again to reconfigure
```
## Important Rules
- **Never expose secrets.** Don't print full API keys, tokens, or passwords.
- **Confirm with the user.** Always show the detected config and ask for confirmation before writing.
- **CLAUDE.md is the source of truth.** All configuration lives there — not in a separate config file.
- **Idempotent.** Running /setup-deploy multiple times overwrites the previous config cleanly.
- **Platform CLIs are optional.** If `fly` or `vercel` CLI isn't installed, fall back to URL-based health checks.