Skip to content

Auto-Merge: auto/area-basic/bokeh #53

Auto-Merge: auto/area-basic/bokeh

Auto-Merge: auto/area-basic/bokeh #53

Workflow file for this run

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