diff --git a/.github/workflows/impl-generate.yml b/.github/workflows/impl-generate.yml index 14d0b2aab9..d5ef54718b 100644 --- a/.github/workflows/impl-generate.yml +++ b/.github/workflows/impl-generate.yml @@ -342,7 +342,15 @@ jobs: # Sync with remote (Claude already pushed the code) git fetch origin - git checkout -B "$BRANCH" "origin/$BRANCH" + + # Check if remote branch exists before checkout (fixes branch-not-found error) + if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then + git checkout -B "$BRANCH" "origin/$BRANCH" + else + # Branch doesn't exist on remote - create fresh from main + echo "::warning::Remote branch $BRANCH not found, creating fresh from main" + git checkout -B "$BRANCH" origin/main + fi # Restore plot files after git operations cp "/tmp/plot.png" "plots/${SPEC_ID}/implementations/plot.png" 2>/dev/null || true @@ -613,3 +621,57 @@ jobs: else echo "success=false" >> $GITHUB_OUTPUT fi + + # ======================================================================== + # Failure handling: Track failures and clean up labels + # ======================================================================== + - name: Handle generation failure + if: failure() && steps.inputs.outputs.issue_number != '' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SPEC_ID: ${{ steps.inputs.outputs.specification_id }} + LIBRARY: ${{ steps.inputs.outputs.library }} + ISSUE: ${{ steps.inputs.outputs.issue_number }} + run: | + echo "::notice::Handling generation failure for $LIBRARY/$SPEC_ID" + + # Count previous failed generation runs for this spec/library + # Filter by both library AND spec ID to avoid counting unrelated failures + FAILURE_COUNT=$(gh run list \ + --workflow=impl-generate.yml \ + --limit 20 \ + --json conclusion,displayTitle,createdAt \ + -q "[.[] | select(.conclusion == \"failure\") | select(.displayTitle | (contains(\"$LIBRARY\") and contains(\"$SPEC_ID\")))] | length" \ + 2>/dev/null || echo "0") + + echo "::notice::Previous failures: $FAILURE_COUNT" + + # After 3 failures, mark as failed (current run is the 3rd) + if [ "$FAILURE_COUNT" -ge 2 ]; then + echo "::warning::Marking $LIBRARY as failed after multiple generation failures" + + # Create failed label if needed + gh label create "impl:${LIBRARY}:failed" --color "d73a4a" \ + --description "${LIBRARY} implementation failed" 2>/dev/null || true + + # Remove stale labels and add failed (Fix #2: clean up duplicates) + gh issue edit "$ISSUE" \ + --remove-label "generate:${LIBRARY},impl:${LIBRARY}:pending" \ + --add-label "impl:${LIBRARY}:failed" 2>/dev/null || true + + # Post failure comment + gh issue comment "$ISSUE" --body "## :x: ${LIBRARY} Failed + + The **${LIBRARY}** implementation for \`${SPEC_ID}\` failed after multiple attempts. + + This may indicate that the library cannot implement this plot type natively. + + --- + :robot: *[impl-generate](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})*" + + else + # Not enough failures yet - just clean up stale generate label + # Keep pending label for retry + gh issue edit "$ISSUE" --remove-label "generate:${LIBRARY}" 2>/dev/null || true + echo "::notice::Cleaned up generate label, keeping pending for retry" + fi diff --git a/.github/workflows/impl-merge.yml b/.github/workflows/impl-merge.yml index bc507011a8..49883b0ac2 100644 --- a/.github/workflows/impl-merge.yml +++ b/.github/workflows/impl-merge.yml @@ -245,39 +245,56 @@ jobs: # Get current labels on the issue LABELS=$(gh issue view "$ISSUE" --json labels -q '.labels[].name' 2>/dev/null || echo "") - # Count done implementations + # Count done and failed implementations DONE_COUNT=0 + FAILED_COUNT=0 + DONE_LIBS="" + FAILED_LIBS="" + for lib in $LIBRARIES; do if echo "$LABELS" | grep -q "^impl:${lib}:done$"; then DONE_COUNT=$((DONE_COUNT + 1)) + DONE_LIBS="$DONE_LIBS $lib" + elif echo "$LABELS" | grep -q "^impl:${lib}:failed$"; then + FAILED_COUNT=$((FAILED_COUNT + 1)) + FAILED_LIBS="$FAILED_LIBS $lib" fi done - echo "::notice::Libraries done: $DONE_COUNT/9" + TOTAL=$((DONE_COUNT + FAILED_COUNT)) + echo "::notice::Libraries: $DONE_COUNT done, $FAILED_COUNT failed, $TOTAL/9 total" + + # Close issue if all 9 libraries are done OR done+failed=9 + if [ "$TOTAL" -eq 9 ]; then + # Build status table + TABLE="| Library | Status |\n|---------|--------|" + for lib in $LIBRARIES; do + if echo "$DONE_LIBS" | grep -w -q "$lib"; then + TABLE="$TABLE\n| $lib | :white_check_mark: |" + elif echo "$FAILED_LIBS" | grep -w -q "$lib"; then + TABLE="$TABLE\n| $lib | :x: (not supported) |" + fi + done + + if [ "$FAILED_COUNT" -eq 0 ]; then + TITLE=":tada: All Implementations Complete!" + SUMMARY="All 9 library implementations for \`${SPEC_ID}\` have been successfully merged." + else + TITLE=":white_check_mark: Implementations Complete" + SUMMARY="${DONE_COUNT}/9 implementations merged, ${FAILED_COUNT} libraries could not implement this plot type." + fi - # Close issue if all 9 libraries are done - if [ "$DONE_COUNT" -eq 9 ]; then - gh issue comment "$ISSUE" --body "## :tada: All Implementations Complete! + gh issue comment "$ISSUE" --body "## ${TITLE} - All 9 library implementations for \`${SPEC_ID}\` have been successfully merged. + ${SUMMARY} - | Library | Status | - |---------|--------| - | matplotlib | :white_check_mark: | - | seaborn | :white_check_mark: | - | plotly | :white_check_mark: | - | bokeh | :white_check_mark: | - | altair | :white_check_mark: | - | plotnine | :white_check_mark: | - | pygal | :white_check_mark: | - | highcharts | :white_check_mark: | - | letsplot | :white_check_mark: | + $(echo -e "$TABLE") --- :robot: *[impl-merge](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})*" gh issue close "$ISSUE" - echo "::notice::Closed issue #$ISSUE - all implementations complete" + echo "::notice::Closed issue #$ISSUE - all implementations complete ($DONE_COUNT done, $FAILED_COUNT failed)" fi - name: Trigger database sync