From 67c5f0e700b0e181f69bba321f33e4739cc40c49 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:53:12 +0100 Subject: [PATCH 1/2] fix(workflows): improve robustness of impl-generate and impl-merge - Fix #1: Handle missing remote branches in impl-generate.yml - Check if branch exists before checkout to avoid 'not a commit' errors - Fall back to creating fresh branch from main if remote doesn't exist - Fix #2: Clean up duplicate labels on failure - Remove both 'generate:X' and 'impl:X:pending' when marking as failed - Prevents label accumulation (e.g., both pending and failed) - Fix #3: Auto-close issues when done + failed = 9 - Previously only closed when all 9 were 'done' - Now closes when total (done + failed) reaches 9 - Shows which libraries failed in closing comment - Fix #4: Track generation failures and auto-mark as failed - Count previous failed runs for same spec/library - After 3 failures, mark as 'impl:X:failed' automatically - Posts failure comment explaining the library may not support this plot type --- .github/workflows/impl-generate.yml | 64 ++++++++++++++++++++++++++++- .github/workflows/impl-merge.yml | 53 ++++++++++++++++-------- 2 files changed, 98 insertions(+), 19 deletions(-) diff --git a/.github/workflows/impl-generate.yml b/.github/workflows/impl-generate.yml index 14d0b2aab9..9f0d469a1a 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 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 + # Look at workflow runs from the last 24 hours + FAILURE_COUNT=$(gh run list \ + --workflow=impl-generate.yml \ + --limit 20 \ + --json conclusion,displayTitle,createdAt \ + -q "[.[] | select(.conclusion == \"failure\") | select(.displayTitle | contains(\"$LIBRARY\"))] | 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..cb1416ab53 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 -q "$lib"; then + TABLE="$TABLE\n| $lib | :white_check_mark: |" + elif echo "$FAILED_LIBS" | grep -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 From 132042c8af3a64f32359a11c7792f05a8065f99a Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:26:38 +0100 Subject: [PATCH 2/2] fix: address Copilot review feedback - Use --heads flag for git ls-remote (more precise branch check) - Filter failure count by both LIBRARY and SPEC_ID (avoid false counts) - Use grep -w for word-boundary matching (prevent false positives) --- .github/workflows/impl-generate.yml | 6 +++--- .github/workflows/impl-merge.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/impl-generate.yml b/.github/workflows/impl-generate.yml index 9f0d469a1a..d5ef54718b 100644 --- a/.github/workflows/impl-generate.yml +++ b/.github/workflows/impl-generate.yml @@ -344,7 +344,7 @@ jobs: git fetch origin # Check if remote branch exists before checkout (fixes branch-not-found error) - if git ls-remote --exit-code origin "$BRANCH" >/dev/null 2>&1; then + 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 @@ -636,12 +636,12 @@ jobs: echo "::notice::Handling generation failure for $LIBRARY/$SPEC_ID" # Count previous failed generation runs for this spec/library - # Look at workflow runs from the last 24 hours + # 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\"))] | length" \ + -q "[.[] | select(.conclusion == \"failure\") | select(.displayTitle | (contains(\"$LIBRARY\") and contains(\"$SPEC_ID\")))] | length" \ 2>/dev/null || echo "0") echo "::notice::Previous failures: $FAILURE_COUNT" diff --git a/.github/workflows/impl-merge.yml b/.github/workflows/impl-merge.yml index cb1416ab53..49883b0ac2 100644 --- a/.github/workflows/impl-merge.yml +++ b/.github/workflows/impl-merge.yml @@ -269,9 +269,9 @@ jobs: # Build status table TABLE="| Library | Status |\n|---------|--------|" for lib in $LIBRARIES; do - if echo "$DONE_LIBS" | grep -q "$lib"; then + if echo "$DONE_LIBS" | grep -w -q "$lib"; then TABLE="$TABLE\n| $lib | :white_check_mark: |" - elif echo "$FAILED_LIBS" | grep -q "$lib"; then + elif echo "$FAILED_LIBS" | grep -w -q "$lib"; then TABLE="$TABLE\n| $lib | :x: (not supported) |" fi done