* chore(#2828): add canary release workflow (dev builds on push to main) Publishes get-shit-done-cc@canary and @gsd-build/sdk@canary on every push to main. Version format: {base}-canary.{N} where base strips any pre-release suffix from package.json (1.39.0-rc.4 → 1.39.0-canary.1). Sequential canary number is auto-detected from existing git tags so reruns never collide. Concurrency group cancels stale in-flight canary runs when commits land quickly. Mirrors the structure and steps of release.yml: same checkout pins, Node 24, npm-publish environment, build:sdk, tarball verification, dry-run publish gate, and publish verification with sleep 10. Closes #2828 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#2828): address CodeRabbit review findings on canary.yml - cancel-in-progress: false — was true, allowing a newer push to cancel a run mid-publish (after tag push but before SDK publish), leaving a partial release state that's unrecoverable since npm versions are immutable - Guard tag/publish/verify steps with github.ref == 'refs/heads/main' so a manual workflow_dispatch from a feature branch (dry_run defaults false) cannot accidentally publish unmerged code under the shared canary dist-tag - Replace fixed sleep 10 with exponential backoff retry loop (delays: 5 10 20 30 45s); fixed sleep is flaky against normal npm CDN replication lag and a false failure forces a new canary number since the tag already exists Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(plan-phase): expose --mvp flag in command frontmatter Adds --mvp to argument-hint and Flags doc. Workflow handler in next commit. * chore(#2828): remove push:main trigger from canary workflow Submission rate to main is too high to auto-publish a canary on every merge. Restrict the workflow to manual workflow_dispatch only. Closes #2828 --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
144
.github/workflows/canary.yml
vendored
Normal file
144
.github/workflows/canary.yml
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
name: Canary
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Dry run (skip npm publish, tagging, and push)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: canary
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
NODE_VERSION: 24
|
||||
|
||||
jobs:
|
||||
canary:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
environment: npm-publish
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Determine canary version
|
||||
id: canary
|
||||
run: |
|
||||
# Strip any pre-release suffix from package.json version to get base (e.g. 1.39.0-rc.4 → 1.39.0)
|
||||
RAW=$(node -p "require('./package.json').version")
|
||||
BASE=$(echo "$RAW" | sed 's/-.*//')
|
||||
# Find next sequential canary number from existing tags
|
||||
N=1
|
||||
while git tag -l "v${BASE}-canary.${N}" | grep -q .; do
|
||||
N=$((N + 1))
|
||||
done
|
||||
CANARY_VERSION="${BASE}-canary.${N}"
|
||||
echo "canary_version=$CANARY_VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Configure git identity
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Bump to canary version
|
||||
env:
|
||||
CANARY_VERSION: ${{ steps.canary.outputs.canary_version }}
|
||||
run: |
|
||||
npm version "$CANARY_VERSION" --no-git-tag-version
|
||||
cd sdk && npm version "$CANARY_VERSION" --no-git-tag-version && cd ..
|
||||
|
||||
- name: Install and test
|
||||
run: |
|
||||
npm ci
|
||||
npm test
|
||||
|
||||
- name: Build SDK dist for tarball
|
||||
run: npm run build:sdk
|
||||
|
||||
- name: Verify tarball ships sdk/dist/cli.js (bug #2647)
|
||||
run: bash scripts/verify-tarball-sdk-dist.sh
|
||||
|
||||
- name: Dry-run publish validation
|
||||
run: |
|
||||
npm publish --dry-run --tag canary
|
||||
cd sdk && npm publish --dry-run --tag canary
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Tag and push
|
||||
if: ${{ github.ref == 'refs/heads/main' && !inputs.dry_run }}
|
||||
env:
|
||||
CANARY_VERSION: ${{ steps.canary.outputs.canary_version }}
|
||||
run: |
|
||||
git tag "v${CANARY_VERSION}"
|
||||
git push origin "v${CANARY_VERSION}"
|
||||
|
||||
- name: Publish to npm (canary)
|
||||
if: ${{ github.ref == 'refs/heads/main' && !inputs.dry_run }}
|
||||
run: npm publish --provenance --access public --tag canary
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Publish SDK to npm (canary)
|
||||
if: ${{ github.ref == 'refs/heads/main' && !inputs.dry_run }}
|
||||
run: cd sdk && npm publish --provenance --access public --tag canary
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Verify publish
|
||||
if: ${{ github.ref == 'refs/heads/main' && !inputs.dry_run }}
|
||||
env:
|
||||
CANARY_VERSION: ${{ steps.canary.outputs.canary_version }}
|
||||
run: |
|
||||
PUBLISHED="NOT_FOUND"
|
||||
SDK_PUBLISHED="NOT_FOUND"
|
||||
for delay in 5 10 20 30 45; do
|
||||
PUBLISHED=$(npm view get-shit-done-cc@"$CANARY_VERSION" version 2>/dev/null || echo "NOT_FOUND")
|
||||
SDK_PUBLISHED=$(npm view @gsd-build/sdk@"$CANARY_VERSION" version 2>/dev/null || echo "NOT_FOUND")
|
||||
if [ "$PUBLISHED" = "$CANARY_VERSION" ] && [ "$SDK_PUBLISHED" = "$CANARY_VERSION" ]; then
|
||||
break
|
||||
fi
|
||||
echo "Not yet live (sleeping ${delay}s)..."
|
||||
sleep "$delay"
|
||||
done
|
||||
if [ "$PUBLISHED" != "$CANARY_VERSION" ]; then
|
||||
echo "::error::Published version verification failed. Expected $CANARY_VERSION, got $PUBLISHED"
|
||||
exit 1
|
||||
fi
|
||||
echo "Verified: get-shit-done-cc@$CANARY_VERSION is live on npm"
|
||||
if [ "$SDK_PUBLISHED" != "$CANARY_VERSION" ]; then
|
||||
echo "::error::SDK version verification failed. Expected $CANARY_VERSION, got $SDK_PUBLISHED"
|
||||
exit 1
|
||||
fi
|
||||
echo "Verified: @gsd-build/sdk@$CANARY_VERSION is live on npm"
|
||||
CANARY_TAG=$(npm dist-tag ls get-shit-done-cc 2>/dev/null | grep "canary:" | awk '{print $2}')
|
||||
echo "canary dist-tag points to: $CANARY_TAG"
|
||||
|
||||
- name: Summary
|
||||
env:
|
||||
CANARY_VERSION: ${{ steps.canary.outputs.canary_version }}
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
echo "## Canary v${CANARY_VERSION}" >> "$GITHUB_STEP_SUMMARY"
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "**DRY RUN** — npm publish, tagging, and push skipped" >> "$GITHUB_STEP_SUMMARY"
|
||||
else
|
||||
echo "- Published to npm as \`canary\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "- SDK also published: \`@gsd-build/sdk@${CANARY_VERSION}\` on \`canary\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "- Tagged \`v${CANARY_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "- Install: \`npx get-shit-done-cc@canary\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
fi
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:plan-phase
|
||||
description: Create detailed phase plan (PLAN.md) with verification loop
|
||||
argument-hint: "[phase] [--auto] [--research] [--skip-research] [--gaps] [--skip-verify] [--prd <file>] [--reviews] [--text] [--tdd]"
|
||||
argument-hint: "[phase] [--auto] [--research] [--skip-research] [--gaps] [--skip-verify] [--prd <file>] [--reviews] [--text] [--tdd] [--mvp]"
|
||||
agent: gsd-planner
|
||||
allowed-tools:
|
||||
- Read
|
||||
@@ -42,6 +42,7 @@ Phase number: $ARGUMENTS (optional — auto-detects next unplanned phase if omit
|
||||
- `--prd <file>` — Use a PRD/acceptance criteria file instead of discuss-phase. Parses requirements into CONTEXT.md automatically. Skips discuss-phase entirely.
|
||||
- `--reviews` — Replan incorporating cross-AI review feedback from REVIEWS.md (produced by `/gsd-review`)
|
||||
- `--text` — Use plain-text numbered lists instead of TUI menus (required for `/rc` remote sessions)
|
||||
- `--mvp` — Vertical MVP mode. Planner organizes tasks as feature slices (UI→API→DB) instead of horizontal layers. On Phase 1 of a new project, also emits `SKELETON.md` (Walking Skeleton). Can be persisted on a phase via `**Mode:** mvp` in ROADMAP.md.
|
||||
|
||||
Normalize phase input in step 2 before any directory lookups.
|
||||
</context>
|
||||
|
||||
Reference in New Issue
Block a user