feat(bokeh): implement line-basic #931
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: Sync Sub-Issue Status" | |
| # Syncs the status of all library sub-issues to the main issue's status table | |
| on: | |
| issues: | |
| types: [labeled, unlabeled, closed] | |
| pull_request: | |
| types: [labeled, closed] | |
| workflow_run: | |
| workflows: ["Gen: Library Implementation", "Bot: AI Review"] | |
| types: [completed] | |
| jobs: | |
| sync-status: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Determine parent issue | |
| id: parent | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Try to find parent issue from different trigger types | |
| if [ "${{ github.event_name }}" == "issues" ]; then | |
| ISSUE_NUM="${{ github.event.issue.number }}" | |
| LABELS="${{ join(github.event.issue.labels.*.name, ',') }}" | |
| # Check if this is a plot-request implementation issue | |
| if echo "$LABELS" | grep -q "plot-request:impl"; then | |
| # Find parent from issue body | |
| BODY=$(gh issue view $ISSUE_NUM --json body -q '.body') | |
| PARENT_NUM=$(echo "$BODY" | grep -oP '\*\*Parent Issue:\*\* #\K\d+' | head -1 || echo "") | |
| if [ -n "$PARENT_NUM" ]; then | |
| echo "parent_number=$PARENT_NUM" >> $GITHUB_OUTPUT | |
| echo "should_sync=true" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| fi | |
| # Check if this is the main issue with plot-request label | |
| if echo "$LABELS" | grep -q "plot-request"; then | |
| echo "parent_number=$ISSUE_NUM" >> $GITHUB_OUTPUT | |
| echo "should_sync=true" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| elif [ "${{ github.event_name }}" == "pull_request" ]; then | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| # Safely get PR body using gh CLI to avoid shell escaping issues with newlines | |
| PR_BODY=$(gh pr view "$PR_NUM" --json body -q '.body' 2>/dev/null || echo "") | |
| # Extract parent issue from PR body | |
| PARENT_NUM=$(echo "$PR_BODY" | grep -oP '\*\*Parent Issue:\*\* #\K\d+' | head -1 || echo "") | |
| if [ -n "$PARENT_NUM" ]; then | |
| echo "parent_number=$PARENT_NUM" >> $GITHUB_OUTPUT | |
| echo "should_sync=true" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| elif [ "${{ github.event_name }}" == "workflow_run" ]; then | |
| # For workflow_run, we need to extract from artifacts or run context | |
| # This is a fallback - the main triggers should handle most cases | |
| echo "should_sync=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "should_sync=false" >> $GITHUB_OUTPUT | |
| - name: Collect sub-issue statuses | |
| if: steps.parent.outputs.should_sync == 'true' | |
| id: collect | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PARENT_NUM: ${{ steps.parent.outputs.parent_number }} | |
| run: | | |
| # Get all sub-issues for this parent | |
| # Using GitHub's sub-issues API or searching for issues with "Parent Issue: #N" in body | |
| SUB_ISSUES=$(gh api graphql -f query=' | |
| query($owner: String!, $repo: String!, $parent: Int!) { | |
| repository(owner: $owner, name: $repo) { | |
| issue(number: $parent) { | |
| subIssues(first: 20) { | |
| nodes { | |
| number | |
| title | |
| labels(first: 10) { | |
| nodes { name } | |
| } | |
| state | |
| } | |
| } | |
| } | |
| } | |
| }' -f owner="${{ github.repository_owner }}" -f repo="${{ github.event.repository.name }}" -F parent="$PARENT_NUM" 2>/dev/null || echo '{"data":{"repository":{"issue":{"subIssues":{"nodes":[]}}}}}') | |
| # Fallback: search for issues with "Parent Issue: #N" in body | |
| if [ "$(echo "$SUB_ISSUES" | jq '.data.repository.issue.subIssues.nodes | length')" == "0" ]; then | |
| SUB_ISSUES_SEARCH=$(gh issue list --search "**Parent Issue:** #$PARENT_NUM in:body" --json number,title,labels,state) | |
| echo "$SUB_ISSUES_SEARCH" > /tmp/sub_issues.json | |
| else | |
| echo "$SUB_ISSUES" | jq '.data.repository.issue.subIssues.nodes' > /tmp/sub_issues.json | |
| fi | |
| echo "sub_issues_file=/tmp/sub_issues.json" >> $GITHUB_OUTPUT | |
| - name: Build status table | |
| if: steps.parent.outputs.should_sync == 'true' | |
| id: table | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PARENT_NUM: ${{ steps.parent.outputs.parent_number }} | |
| run: | | |
| # Define all libraries | |
| LIBRARIES="matplotlib seaborn plotly bokeh altair plotnine pygal highcharts" | |
| # Start building the table | |
| cat > /tmp/status_table.md << 'TABLEEOF' | |
| ## Implementation Status | |
| | Library | Status | Score | PR | Attempts | | |
| |---------|--------|-------|-----|----------| | |
| TABLEEOF | |
| for LIB in $LIBRARIES; do | |
| # Find sub-issue for this library | |
| SUB_ISSUE=$(jq -r --arg lib "$LIB" '.[] | select(.title | contains($lib)) | .number' /tmp/sub_issues.json 2>/dev/null | head -1 || echo "") | |
| if [ -z "$SUB_ISSUE" ]; then | |
| # No sub-issue yet | |
| echo "| $LIB | :hourglass: Pending | - | - | 0/3 |" >> /tmp/status_table.md | |
| continue | |
| fi | |
| # Get labels for status | |
| LABELS=$(jq -r --arg lib "$LIB" '.[] | select(.title | contains($lib)) | .labels | if type == "array" then .[].name else .nodes[].name end' /tmp/sub_issues.json 2>/dev/null | tr '\n' ',' || echo "") | |
| # Determine status emoji and text | |
| if echo "$LABELS" | grep -q "merged"; then | |
| STATUS=":white_check_mark: Merged" | |
| elif echo "$LABELS" | grep -q "ai-approved"; then | |
| STATUS=":ballot_box_with_check: Approved" | |
| elif echo "$LABELS" | grep -q "not-feasible"; then | |
| STATUS=":warning: Not Feasible" | |
| elif echo "$LABELS" | grep -q "ai-rejected"; then | |
| STATUS=":x: Rejected" | |
| elif echo "$LABELS" | grep -q "reviewing"; then | |
| STATUS=":mag: Reviewing" | |
| elif echo "$LABELS" | grep -q "testing"; then | |
| STATUS=":test_tube: Testing" | |
| elif echo "$LABELS" | grep -q "generating"; then | |
| STATUS=":gear: Generating" | |
| else | |
| STATUS=":hourglass: Pending" | |
| fi | |
| # Get quality score from sub-issue comments (format: | Claude | XX/100 | approve |) | |
| SCORE=$(gh api repos/${{ github.repository }}/issues/$SUB_ISSUE/comments \ | |
| --jq '[.[] | .body | capture("Claude \\| (?<score>\\d+)/100") | .score] | last // "-"' 2>/dev/null || echo "-") | |
| # Find PR for this library (search by library name in auto/ branches) | |
| PR_NUM=$(gh pr list --head "auto/" --search "$LIB" \ | |
| --json number,headRefName -q '.[] | select(.headRefName | contains("'"$LIB"'")) | .number' 2>/dev/null | head -1 || echo "") | |
| PR_LINK=$([[ -n "$PR_NUM" ]] && echo "#$PR_NUM" || echo "-") | |
| # Count attempts from sub-issue comments | |
| ATTEMPTS=$(gh api repos/${{ github.repository }}/issues/$SUB_ISSUE/comments \ | |
| --jq '[.[] | .body | select(startswith("## Attempt"))] | length' 2>/dev/null || echo "0") | |
| [[ -z "$ATTEMPTS" ]] && ATTEMPTS=0 | |
| echo "| $LIB | $STATUS | $SCORE | $PR_LINK | $ATTEMPTS/3 |" >> /tmp/status_table.md | |
| done | |
| echo "" >> /tmp/status_table.md | |
| echo "_Last updated: $(date -u +"%Y-%m-%d %H:%M UTC")_" >> /tmp/status_table.md | |
| cat /tmp/status_table.md | |
| - name: Update main issue body | |
| if: steps.parent.outputs.should_sync == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PARENT_NUM: ${{ steps.parent.outputs.parent_number }} | |
| run: | | |
| # Get current issue body | |
| CURRENT_BODY=$(gh issue view $PARENT_NUM --json body -q '.body') | |
| # Check if status table already exists | |
| if echo "$CURRENT_BODY" | grep -q "## Implementation Status"; then | |
| # Replace existing table | |
| # Find start and end markers | |
| NEW_BODY=$(echo "$CURRENT_BODY" | awk ' | |
| /^## Implementation Status/ { skip=1; next } | |
| /^## / && skip { skip=0 } | |
| !skip { print } | |
| ') | |
| # Append new table at the end | |
| echo "$NEW_BODY" > /tmp/new_body.md | |
| echo "" >> /tmp/new_body.md | |
| cat /tmp/status_table.md >> /tmp/new_body.md | |
| else | |
| # Append table to existing body | |
| echo "$CURRENT_BODY" > /tmp/new_body.md | |
| echo "" >> /tmp/new_body.md | |
| cat /tmp/status_table.md >> /tmp/new_body.md | |
| fi | |
| # Update issue | |
| gh issue edit $PARENT_NUM --body-file /tmp/new_body.md | |
| echo "::notice::Updated status table in issue #$PARENT_NUM" |