Fix task 006 ground truth: remove --project-id flag, expand CLI refer… #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | ||
| # Triggers when VERSION file is updated on main (typically via a version bump PR) | ||
| on: | ||
| push: | ||
| branches: [main] | ||
| paths: | ||
| - 'VERSION' | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| env: | ||
| SYNC_PR_BRANCH: sync-main-to-experimental | ||
| EXPERIMENTAL_BRANCH: experimental | ||
| jobs: | ||
| sync-experimental: | ||
| name: Sync Experimental Branch | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| synced: ${{ steps.check-sync.outputs.synced }} | ||
| pr_number: ${{ steps.find-or-create-pr.outputs.pr_number }} | ||
| pr_url: ${{ steps.find-or-create-pr.outputs.pr_url }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Configure Git | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| - name: Check if experimental branch exists | ||
| id: check-experimental | ||
| run: | | ||
| if git ls-remote --heads origin ${{ env.EXPERIMENTAL_BRANCH }} | grep -q ${{ env.EXPERIMENTAL_BRANCH }}; then | ||
| echo "exists=true" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "exists=false" >> $GITHUB_OUTPUT | ||
| echo "::notice::Experimental branch does not exist yet. It will be created from main." | ||
| fi | ||
| - name: Create experimental branch if missing | ||
| if: steps.check-experimental.outputs.exists == 'false' | ||
| run: | | ||
| git checkout -b ${{ env.EXPERIMENTAL_BRANCH }} | ||
| git push origin ${{ env.EXPERIMENTAL_BRANCH }} | ||
| echo "::notice::Created '${{ env.EXPERIMENTAL_BRANCH }}' branch from main" | ||
| - name: Check if experimental is in sync with main | ||
| id: check-sync | ||
| if: steps.check-experimental.outputs.exists == 'true' | ||
| run: | | ||
| git fetch origin ${{ env.EXPERIMENTAL_BRANCH }} | ||
| # Check if main is ahead of experimental | ||
| BEHIND_COUNT=$(git rev-list --count origin/${{ env.EXPERIMENTAL_BRANCH }}..origin/main) | ||
| if [ "$BEHIND_COUNT" -eq 0 ]; then | ||
| echo "synced=true" >> $GITHUB_OUTPUT | ||
| echo "::notice::✅ Experimental branch is in sync with main" | ||
| else | ||
| echo "synced=false" >> $GITHUB_OUTPUT | ||
| echo "behind_count=$BEHIND_COUNT" >> $GITHUB_OUTPUT | ||
| echo "::warning::Experimental branch is $BEHIND_COUNT commit(s) behind main" | ||
| fi | ||
| - name: Find or create sync PR | ||
| id: find-or-create-pr | ||
| if: steps.check-sync.outputs.synced == 'false' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # Check for existing open PR | ||
| EXISTING_PR=$(gh pr list --head main --base ${{ env.EXPERIMENTAL_BRANCH }} --state open --json number,url --jq '.[0]') | ||
| if [ -n "$EXISTING_PR" ]; then | ||
| PR_NUMBER=$(echo "$EXISTING_PR" | jq -r '.number') | ||
| PR_URL=$(echo "$EXISTING_PR" | jq -r '.url') | ||
| echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT | ||
| echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT | ||
| echo "pr_existed=true" >> $GITHUB_OUTPUT | ||
| echo "::notice::Found existing sync PR #$PR_NUMBER" | ||
| else | ||
| # Create new PR | ||
| PR_URL=$(gh pr create \ | ||
| --title "🔄 Sync: merge main into experimental" \ | ||
| --body "## Auto-generated sync PR | ||
| This PR keeps the \`experimental\` branch up to date with \`main\`. | ||
| ### Why is this needed? | ||
| The experimental branch allows users to opt-in to early access features. It must stay in sync with main to ensure experimental users get all stable fixes and features. | ||
| ### What to do? | ||
| - **If this PR has no conflicts**: It will be auto-merged by the release workflow | ||
| - **If this PR has conflicts**: Please resolve them manually, then the next release attempt will succeed | ||
| --- | ||
| *This PR was automatically created by the release workflow.*" \ | ||
| --head main \ | ||
| --base ${{ env.EXPERIMENTAL_BRANCH }}) | ||
| PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') | ||
| echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT | ||
| echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT | ||
| echo "pr_existed=false" >> $GITHUB_OUTPUT | ||
| echo "::notice::Created sync PR #$PR_NUMBER: $PR_URL" | ||
| fi | ||
| - name: Check PR mergeability | ||
| id: check-mergeable | ||
| if: steps.check-sync.outputs.synced == 'false' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| PR_NUMBER="${{ steps.find-or-create-pr.outputs.pr_number }}" | ||
| # Wait a moment for GitHub to compute mergeability | ||
| sleep 5 | ||
| # Get PR mergeable state | ||
| MERGEABLE=$(gh pr view "$PR_NUMBER" --json mergeable --jq '.mergeable') | ||
| echo "mergeable=$MERGEABLE" >> $GITHUB_OUTPUT | ||
| if [ "$MERGEABLE" = "MERGEABLE" ]; then | ||
| echo "::notice::✅ Sync PR #$PR_NUMBER is mergeable (no conflicts)" | ||
| elif [ "$MERGEABLE" = "CONFLICTING" ]; then | ||
| echo "::error::❌ Sync PR #$PR_NUMBER has merge conflicts that must be resolved manually" | ||
| else | ||
| echo "::warning::⏳ Sync PR #$PR_NUMBER mergeability is unknown (state: $MERGEABLE)" | ||
| fi | ||
| - name: Auto-merge sync PR | ||
| id: auto-merge | ||
| if: steps.check-sync.outputs.synced == 'false' && steps.check-mergeable.outputs.mergeable == 'MERGEABLE' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| PR_NUMBER="${{ steps.find-or-create-pr.outputs.pr_number }}" | ||
| echo "Auto-merging sync PR #$PR_NUMBER..." | ||
| gh pr merge "$PR_NUMBER" --merge --admin -t "Sync main into experimental (auto-merge)" | ||
| echo "merged=true" >> $GITHUB_OUTPUT | ||
| echo "::notice::✅ Successfully merged sync PR #$PR_NUMBER" | ||
| - name: Fail if conflicts exist | ||
| if: steps.check-sync.outputs.synced == 'false' && steps.check-mergeable.outputs.mergeable == 'CONFLICTING' | ||
| run: | | ||
| PR_URL="${{ steps.find-or-create-pr.outputs.pr_url }}" | ||
| PR_NUMBER="${{ steps.find-or-create-pr.outputs.pr_number }}" | ||
| echo "" | ||
| echo "❌ RELEASE BLOCKED - Merge conflicts detected" | ||
| echo "" | ||
| echo "📋 Sync PR: $PR_URL" | ||
| echo "" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
| echo " HOW TO FIX" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
| echo "" | ||
| echo "Open Claude Code in the ai-dev-kit repo and paste this prompt:" | ||
| echo "" | ||
| cat << 'PROMPT' | ||
| ━━━━━━━━━━━━━━━━━━━━━ COPY BELOW THIS LINE ━━━━━━━━━━━━━━━━━━━━━ | ||
| Merge main into experimental and resolve any conflicts. | ||
| ## Step 1: Start the merge | ||
| Run: | ||
| git checkout experimental | ||
| git pull | ||
| git merge origin/main | ||
| ## Step 2: Understand what's in experimental (IMPORTANT - do this BEFORE resolving) | ||
| I need you to fully understand the experimental branch before touching any conflicts. | ||
| 1. List commits only in experimental: | ||
| git log main..experimental --oneline | ||
| 2. For each commit, read the actual changes (not just the message): | ||
| git show <commit-hash> --stat | ||
| Then read the key files if needed. | ||
| 3. Give me a detailed summary: | ||
| - What experimental features exist (describe each one) | ||
| - What files are experimental-only vs modified from main | ||
| - The intent/purpose of these experimental changes | ||
| Do NOT proceed to conflict resolution until you've given me this summary. | ||
| ## Step 3: Analyze each conflict | ||
| Run: git diff --name-only --diff-filter=U | ||
| For each conflicted file: | ||
| 1. Show me the conflict markers (the <<<<<<< ======= >>>>>>> sections) | ||
| 2. Explain what MAIN is changing (likely: bugfix, stable feature, refactor) | ||
| 3. Explain what EXPERIMENTAL is changing (likely: early-access feature) | ||
| 4. Explain if these changes are independent or overlapping | ||
| ## Step 4: Resolve conflicts | ||
| Apply these rules: | ||
| - **Independent changes** (different parts of file): Keep BOTH - main's updates AND experimental's features | ||
| - **Compatible changes** (e.g., main fixed a bug in code experimental also modified): Apply main's fix within experimental's version | ||
| - **Conflicting intent**: STOP and ask me. Based on your analysis from Step 2, explain the tradeoff and give me clear options to choose from. | ||
| ## Step 5: Complete the merge | ||
| After ALL conflicts are resolved, commit with a detailed message: | ||
| git add . | ||
| git commit -m "Merge main into experimental | ||
| Kept from main: | ||
| - [list bugfixes and features from main] | ||
| Preserved from experimental: | ||
| - [list experimental features preserved] | ||
| Resolutions: | ||
| - [list any non-trivial merge decisions] | ||
| " | ||
| git push origin experimental | ||
| ## Step 6: Confirm | ||
| Tell me when the merge is pushed so I can re-run the release workflow. | ||
| ━━━━━━━━━━━━━━━━━━━━━ COPY ABOVE THIS LINE ━━━━━━━━━━━━━━━━━━━━━ | ||
| PROMPT | ||
| echo "" | ||
| echo "After the merge is pushed, re-run this workflow." | ||
| echo "" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
| exit 1 | ||
| create-release: | ||
| name: Create Release | ||
| runs-on: ubuntu-latest | ||
| needs: sync-experimental | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Read version | ||
| id: version | ||
| run: | | ||
| VERSION=$(cat VERSION | tr -d '[:space:]') | ||
| echo "version=$VERSION" >> $GITHUB_OUTPUT | ||
| echo "::notice::Releasing version $VERSION" | ||
| - name: Check if tag already exists | ||
| id: check-tag | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.version }}" | ||
| if git rev-parse "v$VERSION" >/dev/null 2>&1; then | ||
| echo "exists=true" >> $GITHUB_OUTPUT | ||
| echo "::warning::Tag v$VERSION already exists, skipping release creation" | ||
| else | ||
| echo "exists=false" >> $GITHUB_OUTPUT | ||
| fi | ||
| - name: Create and push tag | ||
| if: steps.check-tag.outputs.exists == 'false' | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.version }}" | ||
| git tag "v$VERSION" | ||
| git push origin "v$VERSION" | ||
| echo "::notice::Created tag v$VERSION" | ||
| - name: Create GitHub Release | ||
| if: steps.check-tag.outputs.exists == 'false' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.version }}" | ||
| gh release create "v$VERSION" \ | ||
| --title "v$VERSION" \ | ||
| --generate-notes \ | ||
| --latest | ||
| echo "" | ||
| echo "╔══════════════════════════════════════════════════════════════════╗" | ||
| echo "║ ✅ RELEASE SUCCESSFUL ║" | ||
| echo "╠══════════════════════════════════════════════════════════════════╣" | ||
| echo "║ ║" | ||
| echo "║ Version: v$VERSION" | ||
| echo "║ ║" | ||
| echo "║ • GitHub Release created ║" | ||
| echo "║ • Experimental branch is in sync ║" | ||
| echo "║ ║" | ||
| echo "╚══════════════════════════════════════════════════════════════════╝" | ||