From b17b14e7cca7092718d553c1879a7b57356a2765 Mon Sep 17 00:00:00 2001 From: Arun Kumar Thiagarajan Date: Wed, 1 Apr 2026 11:26:01 +0530 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20add=20/speckit.ship=20command=20?= =?UTF-8?q?=E2=80=94=20release=20engineering=20automation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new core command that automates the full release pipeline: 1. Pre-flight readiness checks (tasks, review, QA, working tree) 2. Branch synchronization with target branch 3. Changelog generation from spec + tasks + git commits 4. CI pipeline verification 5. PR creation with full traceability to .specify/ artifacts 6. Release artifact archival Supports GitHub CLI (gh) for automated PR creation with fallback to manual flow. Inspired by GStack's /ship command. --- templates/commands/ship.md | 248 +++++++++++++++++++++++++++++++++++++ templates/ship-template.md | 97 +++++++++++++++ 2 files changed, 345 insertions(+) create mode 100644 templates/commands/ship.md create mode 100644 templates/ship-template.md diff --git a/templates/commands/ship.md b/templates/commands/ship.md new file mode 100644 index 0000000000..6a9e61134a --- /dev/null +++ b/templates/commands/ship.md @@ -0,0 +1,248 @@ +--- +description: Automate the release pipeline including pre-flight checks, branch sync, changelog generation, CI verification, and pull request creation. +scripts: + sh: scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks + ps: scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks +--- + +## User Input + +```text +$ARGUMENTS +``` + +You **MUST** consider the user input before proceeding (if not empty). + +## Pre-Execution Checks + +**Check for extension hooks (before ship)**: +- Check if `.specify/extensions.yml` exists in the project root. +- If it exists, read it and look for entries under the `hooks.before_ship` key +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation +- For each executable hook, output the following based on its `optional` flag: + - **Optional hook** (`optional: true`): + ``` + ## Extension Hooks + + **Optional Pre-Hook**: {extension} + Command: `/{command}` + Description: {description} + + Prompt: {prompt} + To execute: `/{command}` + ``` + - **Mandatory hook** (`optional: false`): + ``` + ## Extension Hooks + + **Automatic Pre-Hook**: {extension} + Executing: `/{command}` + EXECUTE_COMMAND: {command} + + Wait for the result of the hook command before proceeding to the Outline. + ``` +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently + +## Goal + +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. + +## Operating Constraints + +**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. + +**TRACEABILITY**: The PR description and changelog must link back to spec, plan, tasks, review, and QA artifacts for full audit trail. + +## Outline + +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"). + +2. **Pre-Flight Readiness Checks**: + Run a comprehensive readiness assessment before proceeding: + + **Task Completion**: + - Read `tasks.md` and count total tasks vs. completed tasks (marked `[X]` or `[x]`) + - If any tasks are incomplete: **STOP** and warn. Ask user to confirm proceeding or run `/speckit.implement` first. + + **Review Status** (if FEATURE_DIR/reviews/ exists): + - Read the most recent review report + - If verdict is ❌ CHANGES REQUIRED: **STOP** and warn. Recommend running `/speckit.review` after fixes. + - If verdict is ⚠️ APPROVED WITH CONDITIONS: Warn but allow proceeding with confirmation. + + **QA Status** (if FEATURE_DIR/qa/ exists): + - Read the most recent QA report + - If verdict is ❌ QA FAILED: **STOP** and warn. Recommend running `/speckit.qa` after fixes. + - If verdict is ⚠️ QA PASSED WITH NOTES: Warn but allow proceeding with confirmation. + + **Working Tree**: + - Run `git status` to check for uncommitted changes + - If uncommitted changes exist: prompt user to commit or stash before proceeding + + Display a readiness summary: + ``` + Ship Readiness Check: + ✅ Tasks: 12/12 complete + ✅ Review: APPROVED + ⚠️ QA: PASSED WITH NOTES (2 non-critical items) + ✅ Working tree: Clean + + Overall: READY TO SHIP (with notes) + Proceed? (yes/no) + ``` + +3. **Determine Shipping Configuration**: + - Detect the current feature branch: `git branch --show-current` + - Determine the target branch (default: `main`; override via user input or `.specify/config.yml`) + - Detect remote name (default: `origin`; check `git remote -v`) + - Check if GitHub CLI (`gh`) is available for PR creation + - If `gh` is not available, generate the PR description as a markdown file for manual creation + +4. **Branch Synchronization**: + - Fetch latest from remote: `git fetch origin` + - Check if feature branch is behind target branch: + ```bash + git rev-list --count HEAD..origin/{target_branch} + ``` + - If behind, offer to rebase or merge: + - **Rebase** (recommended for clean history): `git rebase origin/{target_branch}` + - **Merge**: `git merge origin/{target_branch}` + - If conflicts arise: **STOP** and provide conflict resolution guidance + - After sync, push the updated feature branch: `git push origin {feature_branch}` + +5. **Changelog Generation**: + - Collect changelog inputs: + - Feature summary from `spec.md` (overview section) + - Implementation highlights from completed tasks in `tasks.md` + - Git commit messages: `git log origin/{target_branch}..HEAD --oneline` + - Generate a structured changelog entry: + ```markdown + ## [Feature Name] - {date} + + ### Added + - [List of new features/capabilities from spec] + + ### Changed + - [List of modifications to existing behavior] + + ### Fixed + - [List of bug fixes discovered during implementation] + + ### Technical Notes + - [Key architecture decisions from plan.md] + ``` + - If a CHANGELOG.md exists at repo root: prepend the new entry (ask for confirmation) + - If no CHANGELOG.md exists: create one with the entry + +6. **CI Verification**: + - If GitHub CLI (`gh`) is available: + - Check CI status: `gh run list --branch {feature_branch} --limit 5` + - If CI is running: wait and report status + - If CI failed: **STOP** and display failure details. Recommend fixing before shipping. + - If CI passed: record the passing run ID for the PR + - If `gh` is not available: + - Remind the user to verify CI status manually before merging + - Check for local test commands and run them: `npm test`, `pytest`, `go test ./...`, etc. + +7. **Generate PR Description**: + Compose a comprehensive PR description from `.specify/` artifacts: + + ```markdown + ## Summary + [One-paragraph summary from spec.md overview] + + ## Specification + [Link to or summary of key requirements from spec.md] + + ## Implementation + [Key implementation decisions from plan.md] + [Summary of completed tasks from tasks.md] + + ## Testing + [QA results summary if qa/ reports exist] + [Test coverage information] + + ## Review Notes + [Summary of review findings if reviews/ reports exist] + [Any conditions or known limitations] + + ## Checklist + - [ ] All tasks completed + - [ ] Code review passed + - [ ] QA testing passed + - [ ] CI pipeline green + - [ ] Changelog updated + - [ ] Documentation updated (if applicable) + + --- + *Generated by `/speckit.ship` from spec-driven development artifacts.* + ``` + +8. **Create Pull Request**: + - If GitHub CLI (`gh`) is available: + ```bash + gh pr create --base {target_branch} --head {feature_branch} --title "{PR title}" --body-file {pr_description_file} + ``` + - If `gh` is not available: + - Save the PR description to `FEATURE_DIR/releases/pr-description-{timestamp}.md` + - Provide instructions for manual PR creation + - Output the PR title and description for copy-paste + + **PR Title Format**: `feat: {feature_name} — {one-line summary from spec}` + +9. **Archive Release Artifacts**: + - Create `FEATURE_DIR/releases/release-{timestamp}.md` with: + - PR URL (if created via `gh`) + - Changelog entry + - Readiness check results + - Links to review and QA reports + - Git commit range: `{base_sha}..{head_sha}` + +10. **Post-Ship Summary**: + Display a completion summary: + ``` + 🚀 Ship Complete! + + PR: #{pr_number} - {pr_title} ({pr_url}) + Branch: {feature_branch} → {target_branch} + Commits: {commit_count} + Files changed: {files_changed} + Changelog: Updated + + Next steps: + - Review the PR at {pr_url} + - After merge, run `/speckit.retro` for a retrospective + ``` + +**Check for extension hooks (after ship)**: +- Check if `.specify/extensions.yml` exists in the project root. +- If it exists, read it and look for entries under the `hooks.after_ship` key +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation +- For each executable hook, output the following based on its `optional` flag: + - **Optional hook** (`optional: true`): + ``` + ## Extension Hooks + + **Optional Hook**: {extension} + Command: `/{command}` + Description: {description} + + Prompt: {prompt} + To execute: `/{command}` + ``` + - **Mandatory hook** (`optional: false`): + ``` + ## Extension Hooks + + **Automatic Hook**: {extension} + Executing: `/{command}` + EXECUTE_COMMAND: {command} + ``` +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently diff --git a/templates/ship-template.md b/templates/ship-template.md new file mode 100644 index 0000000000..e765371a89 --- /dev/null +++ b/templates/ship-template.md @@ -0,0 +1,97 @@ +# Release: [FEATURE NAME] + +**Date**: [DATE] +**Branch**: [feature_branch] → [target_branch] +**PR**: [#number — title](URL) +**Status**: [🚀 Shipped / ⏳ Pending Review / ❌ Blocked] + +--- + +## Summary + +[One-paragraph summary of the shipped feature, derived from spec.md overview.] + +--- + +## Changelog Entry + +### Added +- [New feature or capability from spec] + +### Changed +- [Modification to existing behavior] + +### Fixed +- [Bug fix discovered during implementation] + +### Technical Notes +- [Key architecture decisions from plan.md] + +--- + +## Readiness Check Results + +| Check | Status | Details | +|-------|--------|---------| +| Tasks complete | ✅/❌ | [X]/[Y] tasks completed | +| Code review | ✅/⚠️/❌ | [Review verdict] | +| QA testing | ✅/⚠️/❌ | [QA verdict] | +| CI pipeline | ✅/❌ | [CI run ID or status] | +| Working tree | ✅/❌ | [Clean/dirty] | + +--- + +## PR Description + +### Summary +[Feature summary from spec.md] + +### Specification +[Key requirements summary] + +### Implementation +[Architecture decisions and completed tasks summary] + +### Testing +[QA and test coverage summary] + +### Review Notes +[Review findings summary and conditions] + +### Checklist +- [ ] All tasks completed +- [ ] Code review passed +- [ ] QA testing passed +- [ ] CI pipeline green +- [ ] Changelog updated +- [ ] Documentation updated (if applicable) + +--- + +## Artifacts + +| Artifact | Path | +|----------|------| +| Specification | [FEATURE_DIR/spec.md] | +| Plan | [FEATURE_DIR/plan.md] | +| Tasks | [FEATURE_DIR/tasks.md] | +| Review | [FEATURE_DIR/reviews/review-{timestamp}.md] | +| QA Report | [FEATURE_DIR/qa/qa-{timestamp}.md] | +| This Release | [FEATURE_DIR/releases/release-{timestamp}.md] | + +--- + +## Git Info + +| Property | Value | +|----------|-------| +| Feature branch | [branch name] | +| Target branch | [main/develop] | +| Commit range | [base_sha..head_sha] | +| Commits | [count] | +| Files changed | [count] | +| Lines | +[additions] / -[deletions] | + +--- + +*Generated by `/speckit.ship` — Release automation for spec-driven development.* From 9c80ce5f02ae45ce456e902c1dd87141d8433ab8 Mon Sep 17 00:00:00 2001 From: Arun Kumar Thiagarajan Date: Wed, 1 Apr 2026 17:56:35 +0530 Subject: [PATCH 2/3] fix: address PR review comments for ship command - Use {remote_name} consistently instead of hard-coded 'origin' - Add explicit user confirmation before rebase/merge operations - Add explicit user confirmation before push operations - Add explicit user confirmation before PR creation --- templates/commands/ship.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/templates/commands/ship.md b/templates/commands/ship.md index 6a9e61134a..4b4461230a 100644 --- a/templates/commands/ship.md +++ b/templates/commands/ship.md @@ -53,7 +53,10 @@ Automate the complete release engineering workflow: verify readiness, synchroniz ## Operating Constraints -**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. +**SAFE BY DEFAULT**: Every destructive or potentially destructive operation (e.g., rebase/merge during branch sync, push/force push, branch delete, PR creation) requires explicit user confirmation. +- For the branch sync flow, add a required confirmation prompt **immediately before** performing any rebase/merge, with the default answer set to **no**. +- Add a separate required confirmation prompt **immediately before** performing any push (including force push) to the remote, with the default answer set to **no**. +- Default to dry-run mode for destructive git operations wherever possible. **TRACEABILITY**: The PR description and changelog must link back to spec, plan, tasks, review, and QA artifacts for full audit trail. @@ -102,22 +105,24 @@ Automate the complete release engineering workflow: verify readiness, synchroniz - If `gh` is not available, generate the PR description as a markdown file for manual creation 4. **Branch Synchronization**: - - Fetch latest from remote: `git fetch origin` + - Fetch latest from remote: `git fetch {remote_name}` - Check if feature branch is behind target branch: ```bash - git rev-list --count HEAD..origin/{target_branch} + git rev-list --count HEAD..{remote_name}/{target_branch} ``` - If behind, offer to rebase or merge: - - **Rebase** (recommended for clean history): `git rebase origin/{target_branch}` - - **Merge**: `git merge origin/{target_branch}` + - Prompt the user for explicit confirmation **before** performing the rebase/merge (default **no**) + - **Rebase** (recommended for clean history): `git rebase {remote_name}/{target_branch}` + - **Merge**: `git merge {remote_name}/{target_branch}` - If conflicts arise: **STOP** and provide conflict resolution guidance - - After sync, push the updated feature branch: `git push origin {feature_branch}` + - After sync, prompt the user for explicit confirmation **before** pushing (default **no**): + `git push {remote_name} {feature_branch}` 5. **Changelog Generation**: - Collect changelog inputs: - Feature summary from `spec.md` (overview section) - Implementation highlights from completed tasks in `tasks.md` - - Git commit messages: `git log origin/{target_branch}..HEAD --oneline` + - Git commit messages: `git log {remote_name}/{target_branch}..HEAD --oneline` - Generate a structured changelog entry: ```markdown ## [Feature Name] - {date} @@ -183,10 +188,12 @@ Automate the complete release engineering workflow: verify readiness, synchroniz 8. **Create Pull Request**: - If GitHub CLI (`gh`) is available: + - Prompt the user for explicit confirmation **right before** creating the PR (default **no**): ```bash gh pr create --base {target_branch} --head {feature_branch} --title "{PR title}" --body-file {pr_description_file} ``` - If `gh` is not available: + - Prompt the user for explicit confirmation **before** writing the PR description file (default **no**) - Save the PR description to `FEATURE_DIR/releases/pr-description-{timestamp}.md` - Provide instructions for manual PR creation - Output the PR title and description for copy-paste From 313df69d94d232a192c36735fb24eba863542d82 Mon Sep 17 00:00:00 2001 From: Arun Kumar Thiagarajan Date: Wed, 1 Apr 2026 19:28:28 +0530 Subject: [PATCH 3/3] fix: address additional PR review comments for ship command - Remove misleading .specify/config.yml reference for target branch - Gate /speckit.review, /speckit.qa, /speckit.retro references with (if available) - Always write PR description to FEATURE_DIR/releases/ before gh pr create - Align QA verdict terminology with qa command (PARTIAL PASS/FAILURES FOUND) --- templates/commands/ship.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/templates/commands/ship.md b/templates/commands/ship.md index 4b4461230a..b05422efcf 100644 --- a/templates/commands/ship.md +++ b/templates/commands/ship.md @@ -73,13 +73,13 @@ Automate the complete release engineering workflow: verify readiness, synchroniz **Review Status** (if FEATURE_DIR/reviews/ exists): - Read the most recent review report - - If verdict is ❌ CHANGES REQUIRED: **STOP** and warn. Recommend running `/speckit.review` after fixes. + - If verdict is ❌ CHANGES REQUIRED: **STOP** and warn. Recommend running `/speckit.review` after fixes (if available). - If verdict is ⚠️ APPROVED WITH CONDITIONS: Warn but allow proceeding with confirmation. **QA Status** (if FEATURE_DIR/qa/ exists): - Read the most recent QA report - - If verdict is ❌ QA FAILED: **STOP** and warn. Recommend running `/speckit.qa` after fixes. - - If verdict is ⚠️ QA PASSED WITH NOTES: Warn but allow proceeding with confirmation. + - If verdict is ❌ FAILURES FOUND: **STOP** and warn. Recommend running `/speckit.qa` after fixes (if available). + - If verdict is ⚠️ PARTIAL PASS: Warn but allow proceeding with confirmation. **Working Tree**: - Run `git status` to check for uncommitted changes @@ -90,7 +90,7 @@ Automate the complete release engineering workflow: verify readiness, synchroniz Ship Readiness Check: ✅ Tasks: 12/12 complete ✅ Review: APPROVED - ⚠️ QA: PASSED WITH NOTES (2 non-critical items) + ⚠️ QA: PARTIAL PASS (2 non-critical items) ✅ Working tree: Clean Overall: READY TO SHIP (with notes) @@ -99,7 +99,7 @@ Automate the complete release engineering workflow: verify readiness, synchroniz 3. **Determine Shipping Configuration**: - Detect the current feature branch: `git branch --show-current` - - Determine the target branch (default: `main`; override via user input or `.specify/config.yml`) + - Determine the target branch (default: `main`; allow override via user input/prompt) - Detect remote name (default: `origin`; check `git remote -v`) - Check if GitHub CLI (`gh`) is available for PR creation - If `gh` is not available, generate the PR description as a markdown file for manual creation @@ -187,14 +187,13 @@ Automate the complete release engineering workflow: verify readiness, synchroniz ``` 8. **Create Pull Request**: + - Write the PR description to `FEATURE_DIR/releases/pr-description-{timestamp}.md` - If GitHub CLI (`gh`) is available: - Prompt the user for explicit confirmation **right before** creating the PR (default **no**): ```bash - gh pr create --base {target_branch} --head {feature_branch} --title "{PR title}" --body-file {pr_description_file} + gh pr create --base {target_branch} --head {feature_branch} --title "{PR title}" --body-file FEATURE_DIR/releases/pr-description-{timestamp}.md ``` - If `gh` is not available: - - Prompt the user for explicit confirmation **before** writing the PR description file (default **no**) - - Save the PR description to `FEATURE_DIR/releases/pr-description-{timestamp}.md` - Provide instructions for manual PR creation - Output the PR title and description for copy-paste @@ -221,7 +220,7 @@ Automate the complete release engineering workflow: verify readiness, synchroniz Next steps: - Review the PR at {pr_url} - - After merge, run `/speckit.retro` for a retrospective + - After merge, consider running `/speckit.retro` for a retrospective (if available) ``` **Check for extension hooks (after ship)**: