|
| 1 | +--- |
| 2 | +description: Automate the release pipeline including pre-flight checks, branch sync, changelog generation, CI verification, and pull request creation. |
| 3 | +scripts: |
| 4 | + sh: scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks |
| 5 | + ps: scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks |
| 6 | +--- |
| 7 | + |
| 8 | +## User Input |
| 9 | + |
| 10 | +```text |
| 11 | +$ARGUMENTS |
| 12 | +``` |
| 13 | + |
| 14 | +You **MUST** consider the user input before proceeding (if not empty). |
| 15 | + |
| 16 | +## Pre-Execution Checks |
| 17 | + |
| 18 | +**Check for extension hooks (before ship)**: |
| 19 | +- Check if `.specify/extensions.yml` exists in the project root. |
| 20 | +- If it exists, read it and look for entries under the `hooks.before_ship` key |
| 21 | +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally |
| 22 | +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. |
| 23 | +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: |
| 24 | + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable |
| 25 | + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation |
| 26 | +- For each executable hook, output the following based on its `optional` flag: |
| 27 | + - **Optional hook** (`optional: true`): |
| 28 | + ``` |
| 29 | + ## Extension Hooks |
| 30 | +
|
| 31 | + **Optional Pre-Hook**: {extension} |
| 32 | + Command: `/{command}` |
| 33 | + Description: {description} |
| 34 | +
|
| 35 | + Prompt: {prompt} |
| 36 | + To execute: `/{command}` |
| 37 | + ``` |
| 38 | + - **Mandatory hook** (`optional: false`): |
| 39 | + ``` |
| 40 | + ## Extension Hooks |
| 41 | +
|
| 42 | + **Automatic Pre-Hook**: {extension} |
| 43 | + Executing: `/{command}` |
| 44 | + EXECUTE_COMMAND: {command} |
| 45 | +
|
| 46 | + Wait for the result of the hook command before proceeding to the Outline. |
| 47 | + ``` |
| 48 | +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently |
| 49 | +
|
| 50 | +## Goal |
| 51 | +
|
| 52 | +Automate the complete release engineering workflow: verify readiness, synchronize branches, generate a changelog, verify CI status, create a well-structured pull request, and archive release artifacts. This command transforms the implemented feature into a shippable, reviewable PR with full traceability back to the original specification. |
| 53 | +
|
| 54 | +## Operating Constraints |
| 55 | +
|
| 56 | +**SAFE BY DEFAULT**: Every destructive operation (force push, branch delete, PR creation) requires explicit user confirmation. Default to dry-run mode for destructive git operations. |
| 57 | +
|
| 58 | +**TRACEABILITY**: The PR description and changelog must link back to spec, plan, tasks, review, and QA artifacts for full audit trail. |
| 59 | +
|
| 60 | +## Outline |
| 61 | +
|
| 62 | +1. Run `{SCRIPT}` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot"). |
| 63 | +
|
| 64 | +2. **Pre-Flight Readiness Checks**: |
| 65 | + Run a comprehensive readiness assessment before proceeding: |
| 66 | +
|
| 67 | + **Task Completion**: |
| 68 | + - Read `tasks.md` and count total tasks vs. completed tasks (marked `[X]` or `[x]`) |
| 69 | + - If any tasks are incomplete: **STOP** and warn. Ask user to confirm proceeding or run `/speckit.implement` first. |
| 70 | +
|
| 71 | + **Review Status** (if FEATURE_DIR/reviews/ exists): |
| 72 | + - Read the most recent review report |
| 73 | + - If verdict is ❌ CHANGES REQUIRED: **STOP** and warn. Recommend running `/speckit.review` after fixes. |
| 74 | + - If verdict is ⚠️ APPROVED WITH CONDITIONS: Warn but allow proceeding with confirmation. |
| 75 | +
|
| 76 | + **QA Status** (if FEATURE_DIR/qa/ exists): |
| 77 | + - Read the most recent QA report |
| 78 | + - If verdict is ❌ QA FAILED: **STOP** and warn. Recommend running `/speckit.qa` after fixes. |
| 79 | + - If verdict is ⚠️ QA PASSED WITH NOTES: Warn but allow proceeding with confirmation. |
| 80 | +
|
| 81 | + **Working Tree**: |
| 82 | + - Run `git status` to check for uncommitted changes |
| 83 | + - If uncommitted changes exist: prompt user to commit or stash before proceeding |
| 84 | +
|
| 85 | + Display a readiness summary: |
| 86 | + ``` |
| 87 | + Ship Readiness Check: |
| 88 | + ✅ Tasks: 12/12 complete |
| 89 | + ✅ Review: APPROVED |
| 90 | + ⚠️ QA: PASSED WITH NOTES (2 non-critical items) |
| 91 | + ✅ Working tree: Clean |
| 92 | + |
| 93 | + Overall: READY TO SHIP (with notes) |
| 94 | + Proceed? (yes/no) |
| 95 | + ``` |
| 96 | +
|
| 97 | +3. **Determine Shipping Configuration**: |
| 98 | + - Detect the current feature branch: `git branch --show-current` |
| 99 | + - Determine the target branch (default: `main`; override via user input or `.specify/config.yml`) |
| 100 | + - Detect remote name (default: `origin`; check `git remote -v`) |
| 101 | + - Check if GitHub CLI (`gh`) is available for PR creation |
| 102 | + - If `gh` is not available, generate the PR description as a markdown file for manual creation |
| 103 | +
|
| 104 | +4. **Branch Synchronization**: |
| 105 | + - Fetch latest from remote: `git fetch origin` |
| 106 | + - Check if feature branch is behind target branch: |
| 107 | + ```bash |
| 108 | + git rev-list --count HEAD..origin/{target_branch} |
| 109 | + ``` |
| 110 | + - If behind, offer to rebase or merge: |
| 111 | + - **Rebase** (recommended for clean history): `git rebase origin/{target_branch}` |
| 112 | + - **Merge**: `git merge origin/{target_branch}` |
| 113 | + - If conflicts arise: **STOP** and provide conflict resolution guidance |
| 114 | + - After sync, push the updated feature branch: `git push origin {feature_branch}` |
| 115 | +
|
| 116 | +5. **Changelog Generation**: |
| 117 | + - Collect changelog inputs: |
| 118 | + - Feature summary from `spec.md` (overview section) |
| 119 | + - Implementation highlights from completed tasks in `tasks.md` |
| 120 | + - Git commit messages: `git log origin/{target_branch}..HEAD --oneline` |
| 121 | + - Generate a structured changelog entry: |
| 122 | + ```markdown |
| 123 | + ## [Feature Name] - {date} |
| 124 | + |
| 125 | + ### Added |
| 126 | + - [List of new features/capabilities from spec] |
| 127 | + |
| 128 | + ### Changed |
| 129 | + - [List of modifications to existing behavior] |
| 130 | + |
| 131 | + ### Fixed |
| 132 | + - [List of bug fixes discovered during implementation] |
| 133 | + |
| 134 | + ### Technical Notes |
| 135 | + - [Key architecture decisions from plan.md] |
| 136 | + ``` |
| 137 | + - If a CHANGELOG.md exists at repo root: prepend the new entry (ask for confirmation) |
| 138 | + - If no CHANGELOG.md exists: create one with the entry |
| 139 | +
|
| 140 | +6. **CI Verification**: |
| 141 | + - If GitHub CLI (`gh`) is available: |
| 142 | + - Check CI status: `gh run list --branch {feature_branch} --limit 5` |
| 143 | + - If CI is running: wait and report status |
| 144 | + - If CI failed: **STOP** and display failure details. Recommend fixing before shipping. |
| 145 | + - If CI passed: record the passing run ID for the PR |
| 146 | + - If `gh` is not available: |
| 147 | + - Remind the user to verify CI status manually before merging |
| 148 | + - Check for local test commands and run them: `npm test`, `pytest`, `go test ./...`, etc. |
| 149 | +
|
| 150 | +7. **Generate PR Description**: |
| 151 | + Compose a comprehensive PR description from `.specify/` artifacts: |
| 152 | +
|
| 153 | + ```markdown |
| 154 | + ## Summary |
| 155 | + [One-paragraph summary from spec.md overview] |
| 156 | +
|
| 157 | + ## Specification |
| 158 | + [Link to or summary of key requirements from spec.md] |
| 159 | +
|
| 160 | + ## Implementation |
| 161 | + [Key implementation decisions from plan.md] |
| 162 | + [Summary of completed tasks from tasks.md] |
| 163 | +
|
| 164 | + ## Testing |
| 165 | + [QA results summary if qa/ reports exist] |
| 166 | + [Test coverage information] |
| 167 | +
|
| 168 | + ## Review Notes |
| 169 | + [Summary of review findings if reviews/ reports exist] |
| 170 | + [Any conditions or known limitations] |
| 171 | +
|
| 172 | + ## Checklist |
| 173 | + - [ ] All tasks completed |
| 174 | + - [ ] Code review passed |
| 175 | + - [ ] QA testing passed |
| 176 | + - [ ] CI pipeline green |
| 177 | + - [ ] Changelog updated |
| 178 | + - [ ] Documentation updated (if applicable) |
| 179 | +
|
| 180 | + --- |
| 181 | + *Generated by `/speckit.ship` from spec-driven development artifacts.* |
| 182 | + ``` |
| 183 | + |
| 184 | +8. **Create Pull Request**: |
| 185 | + - If GitHub CLI (`gh`) is available: |
| 186 | + ```bash |
| 187 | + gh pr create --base {target_branch} --head {feature_branch} --title "{PR title}" --body-file {pr_description_file} |
| 188 | + ``` |
| 189 | + - If `gh` is not available: |
| 190 | + - Save the PR description to `FEATURE_DIR/releases/pr-description-{timestamp}.md` |
| 191 | + - Provide instructions for manual PR creation |
| 192 | + - Output the PR title and description for copy-paste |
| 193 | + |
| 194 | + **PR Title Format**: `feat: {feature_name} — {one-line summary from spec}` |
| 195 | + |
| 196 | +9. **Archive Release Artifacts**: |
| 197 | + - Create `FEATURE_DIR/releases/release-{timestamp}.md` with: |
| 198 | + - PR URL (if created via `gh`) |
| 199 | + - Changelog entry |
| 200 | + - Readiness check results |
| 201 | + - Links to review and QA reports |
| 202 | + - Git commit range: `{base_sha}..{head_sha}` |
| 203 | + |
| 204 | +10. **Post-Ship Summary**: |
| 205 | + Display a completion summary: |
| 206 | + ``` |
| 207 | + 🚀 Ship Complete! |
| 208 | + |
| 209 | + PR: #{pr_number} - {pr_title} ({pr_url}) |
| 210 | + Branch: {feature_branch} → {target_branch} |
| 211 | + Commits: {commit_count} |
| 212 | + Files changed: {files_changed} |
| 213 | + Changelog: Updated |
| 214 | + |
| 215 | + Next steps: |
| 216 | + - Review the PR at {pr_url} |
| 217 | + - After merge, run `/speckit.retro` for a retrospective |
| 218 | + ``` |
| 219 | + |
| 220 | +**Check for extension hooks (after ship)**: |
| 221 | +- Check if `.specify/extensions.yml` exists in the project root. |
| 222 | +- If it exists, read it and look for entries under the `hooks.after_ship` key |
| 223 | +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally |
| 224 | +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. |
| 225 | +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: |
| 226 | + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable |
| 227 | + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation |
| 228 | +- For each executable hook, output the following based on its `optional` flag: |
| 229 | + - **Optional hook** (`optional: true`): |
| 230 | + ``` |
| 231 | + ## Extension Hooks |
| 232 | +
|
| 233 | + **Optional Hook**: {extension} |
| 234 | + Command: `/{command}` |
| 235 | + Description: {description} |
| 236 | +
|
| 237 | + Prompt: {prompt} |
| 238 | + To execute: `/{command}` |
| 239 | + ``` |
| 240 | + - **Mandatory hook** (`optional: false`): |
| 241 | + ``` |
| 242 | + ## Extension Hooks |
| 243 | +
|
| 244 | + **Automatic Hook**: {extension} |
| 245 | + Executing: `/{command}` |
| 246 | + EXECUTE_COMMAND: {command} |
| 247 | + ``` |
| 248 | +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently |
0 commit comments