Auto-Merge: auto/area-basic/bokeh #53
Workflow file for this run
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: "Bot: Auto-Merge" | |
| run-name: "Auto-Merge: ${{ github.event.pull_request.head.ref }}" | |
| on: | |
| pull_request: | |
| types: [labeled, closed] | |
| jobs: | |
| # ============================================================================ | |
| # Job 1: Enable auto-merge when ai-approved label is added | |
| # ============================================================================ | |
| auto-merge: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| steps: | |
| - name: Check conditions | |
| id: check | |
| run: | | |
| ACTION="${{ github.event.action }}" | |
| LABEL="${{ github.event.label.name }}" | |
| BRANCH="${{ github.event.pull_request.head.ref }}" | |
| if [[ "$ACTION" != "labeled" ]]; then | |
| echo "::notice::Skipping: Action is '$ACTION', not 'labeled'" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| if [[ "$LABEL" != "ai-approved" ]]; then | |
| echo "::notice::Skipping: Label is '$LABEL', not 'ai-approved'" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| if [[ ! "$BRANCH" =~ ^auto/ ]]; then | |
| echo "::notice::Skipping: Branch '$BRANCH' is not auto/*" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "should_run=true" >> $GITHUB_OUTPUT | |
| - name: Checkout repository | |
| if: steps.check.outputs.should_run == 'true' | |
| uses: actions/checkout@v6 | |
| - name: Extract info from branch | |
| if: steps.check.outputs.should_run == 'true' | |
| id: extract | |
| run: | | |
| BRANCH="${{ github.event.pull_request.head.ref }}" | |
| # Format: auto/{spec-id}/{library} | |
| SPEC_ID=$(echo "$BRANCH" | cut -d'/' -f2) | |
| LIBRARY=$(echo "$BRANCH" | cut -d'/' -f3) | |
| echo "spec_id=$SPEC_ID" >> $GITHUB_OUTPUT | |
| echo "library=$LIBRARY" >> $GITHUB_OUTPUT | |
| - name: Get sub-issue from PR body | |
| if: steps.check.outputs.should_run == 'true' | |
| id: sub_issue | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| PR_BODY=$(gh pr view "$PR_NUM" --json body -q '.body' 2>/dev/null || echo "") | |
| SUB_ISSUE=$(echo "$PR_BODY" | grep -oP '\*\*Sub-Issue:\*\* #\K\d+' | head -1 || echo "") | |
| echo "number=$SUB_ISSUE" >> $GITHUB_OUTPUT | |
| - name: React with rocket emoji | |
| if: steps.check.outputs.should_run == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/reactions \ | |
| -f content=rocket | |
| - name: Update sub-issue label | |
| if: steps.check.outputs.should_run == 'true' && steps.sub_issue.outputs.number != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh issue edit ${{ steps.sub_issue.outputs.number }} \ | |
| --remove-label "reviewing" \ | |
| --remove-label "ai-rejected" \ | |
| --add-label "ai-approved" | |
| - name: Enable auto-merge | |
| if: steps.check.outputs.should_run == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh pr merge ${{ github.event.pull_request.number }} \ | |
| --repo ${{ github.repository }} \ | |
| --squash \ | |
| --auto | |
| # ============================================================================ | |
| # Job 2: Post-merge summary (per library) | |
| # ============================================================================ | |
| post-merge-summary: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: read | |
| steps: | |
| - name: Check conditions | |
| id: check | |
| run: | | |
| ACTION="${{ github.event.action }}" | |
| MERGED="${{ github.event.pull_request.merged }}" | |
| BRANCH="${{ github.event.pull_request.head.ref }}" | |
| if [[ "$ACTION" != "closed" ]]; then | |
| echo "::notice::Skipping: Action is '$ACTION', not 'closed'" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| if [[ "$MERGED" != "true" ]]; then | |
| echo "::notice::Skipping: PR was closed but not merged" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| if [[ ! "$BRANCH" =~ ^auto/ ]]; then | |
| echo "::notice::Skipping: Branch '$BRANCH' is not auto/*" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "should_run=true" >> $GITHUB_OUTPUT | |
| - name: Checkout code | |
| if: steps.check.outputs.should_run == 'true' | |
| uses: actions/checkout@v6 | |
| - name: Extract spec ID, library, and issues | |
| if: steps.check.outputs.should_run == 'true' | |
| id: extract | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| BRANCH="${{ github.event.pull_request.head.ref }}" | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| PR_BODY=$(gh pr view "$PR_NUM" --json body -q '.body' 2>/dev/null || echo "") | |
| # Format: auto/{spec-id}/{library} | |
| SPEC_ID=$(echo "$BRANCH" | cut -d'/' -f2) | |
| LIBRARY=$(echo "$BRANCH" | cut -d'/' -f3) | |
| # Extract issues from PR body | |
| SUB_ISSUE=$(echo "$PR_BODY" | grep -oP '\*\*Sub-Issue:\*\* #\K\d+' | head -1 || echo "") | |
| MAIN_ISSUE=$(echo "$PR_BODY" | grep -oP '\*\*Parent Issue:\*\* #\K\d+' | head -1 || echo "") | |
| # Fallback: search for main issue | |
| if [ -z "$MAIN_ISSUE" ]; then | |
| MAIN_ISSUE=$(gh issue list --label plot-request --search "$SPEC_ID in:title" --json number -q '.[0].number' || echo "") | |
| fi | |
| echo "spec_id=$SPEC_ID" >> $GITHUB_OUTPUT | |
| echo "library=$LIBRARY" >> $GITHUB_OUTPUT | |
| echo "sub_issue=$SUB_ISSUE" >> $GITHUB_OUTPUT | |
| echo "main_issue=$MAIN_ISSUE" >> $GITHUB_OUTPUT | |
| echo "Spec: $SPEC_ID, Library: $LIBRARY, Sub: #$SUB_ISSUE, Main: #$MAIN_ISSUE" | |
| - name: Find implementation file | |
| if: steps.check.outputs.should_run == 'true' | |
| id: files | |
| run: | | |
| SPEC_ID="${{ steps.extract.outputs.spec_id }}" | |
| LIBRARY="${{ steps.extract.outputs.library }}" | |
| # Find implementation file for this library | |
| IMPL_FILE=$(find plots/$LIBRARY -name "default.py" -path "*/$SPEC_ID/*" 2>/dev/null | head -1 || echo "") | |
| echo "impl_file=$IMPL_FILE" >> $GITHUB_OUTPUT | |
| - name: Update sub-issue to merged | |
| if: steps.check.outputs.should_run == 'true' && steps.extract.outputs.sub_issue != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| SUB_ISSUE="${{ steps.extract.outputs.sub_issue }}" | |
| LIBRARY="${{ steps.extract.outputs.library }}" | |
| SPEC_ID="${{ steps.extract.outputs.spec_id }}" | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}" | |
| SHORT_SHA=$(echo "$MERGE_COMMIT" | cut -c1-7) | |
| IMPL_FILE="${{ steps.files.outputs.impl_file }}" | |
| # Update labels | |
| gh issue edit $SUB_ISSUE \ | |
| --remove-label "ai-approved" \ | |
| --remove-label "reviewing" \ | |
| --remove-label "generating" \ | |
| --remove-label "testing" \ | |
| --add-label "merged" | |
| # Post completion comment | |
| gh issue comment $SUB_ISSUE --body "## Merged | |
| **$LIBRARY** implementation for \`$SPEC_ID\` has been merged to main! | |
| ### Details | |
| - **PR:** #$PR_NUM | |
| - **Commit:** [$SHORT_SHA](https://github.com/${{ github.repository }}/commit/$MERGE_COMMIT) | |
| - **File:** \`$IMPL_FILE\` | |
| --- | |
| :rocket: *Auto-merged by pyplots CI*" | |
| # Close sub-issue | |
| gh issue close $SUB_ISSUE --reason completed | |
| - name: Check if all libraries are done | |
| if: steps.check.outputs.should_run == 'true' | |
| id: check_complete | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| MAIN_ISSUE="${{ steps.extract.outputs.main_issue }}" | |
| if [ -z "$MAIN_ISSUE" ]; then | |
| echo "all_done=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| # Get all sub-issues for this main issue | |
| SUB_ISSUES=$(gh issue list --search "**Parent Issue:** #$MAIN_ISSUE in:body" --json number,labels -q '.') | |
| # Count statuses | |
| TOTAL=$(echo "$SUB_ISSUES" | jq 'length') | |
| MERGED=$(echo "$SUB_ISSUES" | jq '[.[] | select(.labels[].name == "merged")] | length') | |
| NOT_FEASIBLE=$(echo "$SUB_ISSUES" | jq '[.[] | select(.labels[].name == "not-feasible")] | length') | |
| DONE=$((MERGED + NOT_FEASIBLE)) | |
| echo "total=$TOTAL" >> $GITHUB_OUTPUT | |
| echo "merged=$MERGED" >> $GITHUB_OUTPUT | |
| echo "not_feasible=$NOT_FEASIBLE" >> $GITHUB_OUTPUT | |
| if [ "$DONE" -eq "$TOTAL" ] && [ "$TOTAL" -gt 0 ]; then | |
| echo "all_done=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "all_done=false" >> $GITHUB_OUTPUT | |
| fi | |
| echo "Progress: $DONE/$TOTAL complete ($MERGED merged, $NOT_FEASIBLE not feasible)" | |
| - name: Post progress to main issue | |
| if: steps.check.outputs.should_run == 'true' && steps.extract.outputs.main_issue != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| MAIN_ISSUE="${{ steps.extract.outputs.main_issue }}" | |
| LIBRARY="${{ steps.extract.outputs.library }}" | |
| SPEC_ID="${{ steps.extract.outputs.spec_id }}" | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| MERGED="${{ steps.check_complete.outputs.merged }}" | |
| NOT_FEASIBLE="${{ steps.check_complete.outputs.not_feasible }}" | |
| TOTAL="${{ steps.check_complete.outputs.total }}" | |
| gh issue comment $MAIN_ISSUE --body "## :white_check_mark: $LIBRARY Merged | |
| **$LIBRARY** implementation for \`$SPEC_ID\` has been merged! | |
| **Progress:** $MERGED merged, $NOT_FEASIBLE not feasible, $((TOTAL - MERGED - NOT_FEASIBLE)) pending | |
| --- | |
| :robot: *PR #$PR_NUM*" | |
| - name: Complete main issue if all done | |
| if: steps.check.outputs.should_run == 'true' && steps.check_complete.outputs.all_done == 'true' && steps.extract.outputs.main_issue != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| MAIN_ISSUE="${{ steps.extract.outputs.main_issue }}" | |
| SPEC_ID="${{ steps.extract.outputs.spec_id }}" | |
| MERGED="${{ steps.check_complete.outputs.merged }}" | |
| NOT_FEASIBLE="${{ steps.check_complete.outputs.not_feasible }}" | |
| # Post final summary | |
| gh issue comment $MAIN_ISSUE --body "## :tada: Implementation Complete! | |
| All library implementations for \`$SPEC_ID\` are now complete. | |
| ### Final Status | |
| - **Merged:** $MERGED libraries | |
| - **Not Feasible:** $NOT_FEASIBLE libraries | |
| Check the **Implementation Status** table in the issue body for details. | |
| --- | |
| :robot: *pyplots CI*" | |
| # Add completed label | |
| gh issue edit $MAIN_ISSUE --add-label "completed" | |
| # Close main issue | |
| gh issue close $MAIN_ISSUE --reason completed |