Repair: pygal for violin-basic (attempt 3) #1182
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: "Impl: Repair" | |
| run-name: "Repair: ${{ inputs.library }} for ${{ inputs.specification_id }} (attempt ${{ inputs.attempt }})" | |
| # Repairs a rejected implementation based on AI feedback | |
| # Triggered by impl-review.yml when ai-rejected label is added | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: "PR number to repair" | |
| required: true | |
| type: string | |
| specification_id: | |
| description: "The specification ID" | |
| required: true | |
| type: string | |
| library: | |
| description: "The library to repair" | |
| required: true | |
| type: string | |
| attempt: | |
| description: "Current attempt number (1, 2, or 3)" | |
| required: true | |
| type: string | |
| env: | |
| DEPS_matplotlib: "matplotlib>=3.9.0 numpy>=1.26.0" | |
| DEPS_seaborn: "seaborn>=0.13.0 matplotlib>=3.9.0 numpy>=1.26.0" | |
| DEPS_plotly: "plotly>=5.18.0 kaleido>=0.2.1 numpy>=1.26.0" | |
| DEPS_bokeh: "bokeh>=3.4.0 numpy>=1.26.0 selenium>=4.15.0 webdriver-manager>=4.0.0" | |
| DEPS_altair: "altair>=5.2.0 vl-convert-python>=1.3.0 numpy>=1.26.0" | |
| DEPS_plotnine: "plotnine>=0.13.0 numpy>=1.26.0" | |
| DEPS_pygal: "pygal>=3.0.0 cairosvg>=2.7.0" | |
| DEPS_highcharts: "highcharts-core>=1.10.0 numpy>=1.26.0 selenium>=4.15.0 webdriver-manager>=4.0.0" | |
| DEPS_letsplot: "lets-plot>=4.5.0" | |
| jobs: | |
| repair: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| actions: write | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Checkout PR branch | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| BRANCH=$(gh pr view ${{ inputs.pr_number }} --json headRefName -q '.headRefName') | |
| echo "branch=$BRANCH" >> $GITHUB_ENV | |
| git fetch origin "$BRANCH" | |
| git checkout "$BRANCH" | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.14' | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Get library dependencies | |
| id: deps | |
| run: | | |
| DEPS_VAR="DEPS_${{ inputs.library }}" | |
| DEPS="${!DEPS_VAR}" | |
| echo "deps=$DEPS" >> $GITHUB_OUTPUT | |
| - name: Install dependencies | |
| run: | | |
| uv venv .venv | |
| source .venv/bin/activate | |
| uv pip install ${{ steps.deps.outputs.deps }} pandas>=2.2.0 ruff Pillow>=10.0.0 | |
| - name: Setup Chrome for Highcharts | |
| if: inputs.library == 'highcharts' | |
| uses: browser-actions/setup-chrome@v2 | |
| with: | |
| chrome-version: stable | |
| - name: Extract AI feedback from PR | |
| id: feedback | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| FEEDBACK=$(gh pr view ${{ inputs.pr_number }} --json comments -q ' | |
| [.comments[] | select(.body | contains("AI Review"))] | last | .body | |
| ' 2>/dev/null || echo "") | |
| if [ -z "$FEEDBACK" ]; then | |
| FEEDBACK="No specific feedback available. Review the implementation against the spec." | |
| fi | |
| echo "$FEEDBACK" > /tmp/ai_feedback.md | |
| - name: Remove ai-rejected label | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh pr edit ${{ inputs.pr_number }} --remove-label "ai-rejected" 2>/dev/null || true | |
| - name: Run Claude Code to repair implementation | |
| id: claude | |
| continue-on-error: true | |
| timeout-minutes: 45 | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| claude_args: "--model opus" | |
| allowed_bots: '*' | |
| prompt: | | |
| Read `prompts/workflow-prompts/impl-repair-claude.md` and follow those instructions. | |
| Variables for this run: | |
| - LIBRARY: ${{ inputs.library }} | |
| - SPEC_ID: ${{ inputs.specification_id }} | |
| - ATTEMPT: ${{ inputs.attempt }} | |
| - BRANCH: ${{ env.branch }} | |
| - name: Retry Claude (on failure) | |
| if: steps.claude.outcome == 'failure' | |
| id: claude_retry | |
| timeout-minutes: 45 | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| claude_args: "--model opus" | |
| allowed_bots: '*' | |
| prompt: | | |
| Read `prompts/workflow-prompts/impl-repair-claude.md` and follow those instructions. | |
| Variables for this run: | |
| - LIBRARY: ${{ inputs.library }} | |
| - SPEC_ID: ${{ inputs.specification_id }} | |
| - ATTEMPT: ${{ inputs.attempt }} | |
| - BRANCH: ${{ env.branch }} | |
| - name: Process repaired image | |
| if: success() | |
| env: | |
| SPEC_ID: ${{ inputs.specification_id }} | |
| LIBRARY: ${{ inputs.library }} | |
| run: | | |
| IMPL_DIR="plots/${SPEC_ID}/implementations" | |
| if [ ! -f "$IMPL_DIR/plot.png" ]; then | |
| echo "::warning::No plot.png found after repair" | |
| exit 0 | |
| fi | |
| source .venv/bin/activate | |
| # Process PNG: optimize and create thumbnail | |
| python -m core.images process \ | |
| "$IMPL_DIR/plot.png" \ | |
| "$IMPL_DIR/plot.png" \ | |
| "$IMPL_DIR/plot_thumb.png" | |
| echo "::notice::Processed images: optimized + thumbnail created" | |
| ls -la "$IMPL_DIR/" | |
| - name: Upload repaired plot to GCS staging | |
| if: success() | |
| env: | |
| GCS_CREDENTIALS: ${{ secrets.GCS_CREDENTIALS }} | |
| SPEC_ID: ${{ inputs.specification_id }} | |
| LIBRARY: ${{ inputs.library }} | |
| run: | | |
| IMPL_DIR="plots/${SPEC_ID}/implementations" | |
| STAGING_PATH="gs://pyplots-images/staging/${SPEC_ID}/${LIBRARY}" | |
| if [ -z "$GCS_CREDENTIALS" ]; then | |
| echo "::warning::GCS_CREDENTIALS not configured" | |
| exit 0 | |
| fi | |
| echo "$GCS_CREDENTIALS" > /tmp/gcs-key.json | |
| gcloud auth activate-service-account --key-file=/tmp/gcs-key.json | |
| if [ -f "$IMPL_DIR/plot.png" ]; then | |
| gsutil cp "$IMPL_DIR/plot.png" "${STAGING_PATH}/plot.png" | |
| gsutil acl ch -u AllUsers:R "${STAGING_PATH}/plot.png" 2>/dev/null || true | |
| fi | |
| if [ -f "$IMPL_DIR/plot_thumb.png" ]; then | |
| gsutil cp "$IMPL_DIR/plot_thumb.png" "${STAGING_PATH}/plot_thumb.png" | |
| gsutil acl ch -u AllUsers:R "${STAGING_PATH}/plot_thumb.png" 2>/dev/null || true | |
| fi | |
| if [ -f "$IMPL_DIR/plot.html" ]; then | |
| gsutil cp "$IMPL_DIR/plot.html" "${STAGING_PATH}/plot.html" | |
| gsutil acl ch -u AllUsers:R "${STAGING_PATH}/plot.html" 2>/dev/null || true | |
| fi | |
| rm -f /tmp/gcs-key.json | |
| - name: Post repair status | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh pr comment ${{ inputs.pr_number }} --body "## :wrench: Repair Attempt ${{ inputs.attempt }}/3 | |
| Applied fixes based on AI review feedback. | |
| **Status:** Repair completed, re-triggering review... | |
| --- | |
| :robot: *[impl-repair](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})*" | |
| - name: Re-trigger review | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUM: ${{ inputs.pr_number }} | |
| run: | | |
| # Use repository_dispatch as workaround for workflow_dispatch caching issue | |
| gh api repos/${{ github.repository }}/dispatches \ | |
| -f event_type=review-pr \ | |
| -f "client_payload[pr_number]=$PR_NUM" | |
| echo "::notice::Triggered impl-review.yml via repository_dispatch for PR #$PR_NUM" |