fix rf time scheduler problem #80
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: GPU Tests from PR Comment | |
| # Lets maintainers (admin / write access) run GPU tests on a PR by commenting: | |
| # /diffusers-bot pytest <args> | |
| # e.g. `/diffusers-bot pytest tests/models/test_modeling_common.py -k "some_test"`. | |
| on: | |
| issue_comment: | |
| types: [created] | |
| # Default to read-only; jobs that comment opt into `pull-requests: write` explicitly. | |
| permissions: | |
| contents: read | |
| concurrency: | |
| # A newer command on the same PR supersedes an in-flight one. | |
| group: diffusers-bot-${{ github.event.issue.number }} | |
| cancel-in-progress: true | |
| env: | |
| DIFFUSERS_IS_CI: yes | |
| OMP_NUM_THREADS: 8 | |
| MKL_NUM_THREADS: 8 | |
| HF_XET_HIGH_PERFORMANCE: 1 | |
| PYTEST_TIMEOUT: 600 | |
| # Force version overrides across every `uv pip install`: pin tokenizers and the | |
| # torch/torchvision/torchaudio set baked into the image so `-U` installs can't bump | |
| # torch and break torchvision's C++ ABI. Re-written into the file in the install step. | |
| UV_OVERRIDE: /tmp/uv-overrides.txt | |
| jobs: | |
| gate: | |
| name: Authorize & launch | |
| # Only react to `/diffusers-bot pytest …` comments on open PRs. | |
| if: | | |
| github.event.issue.pull_request && | |
| github.event.issue.state == 'open' && | |
| startsWith(github.event.comment.body, '/diffusers-bot pytest') | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| pull-requests: write | |
| outputs: | |
| pytest_args: ${{ steps.parse.outputs.pytest_args }} | |
| comment_id: ${{ steps.comment.outputs.comment_id }} | |
| steps: | |
| - name: Check commenter permission | |
| id: auth | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| run: | | |
| PERM=$(gh api "repos/${REPO}/collaborators/${COMMENTER}/permission" --jq '.permission' 2>/dev/null || echo "none") | |
| echo "Commenter @${COMMENTER} has permission: ${PERM}" | |
| if [[ "$PERM" == "admin" || "$PERM" == "write" ]]; then | |
| echo "authorized=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "authorized=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Reject unauthorized commenter | |
| if: steps.auth.outputs.authorized != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| PR: ${{ github.event.issue.number }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| run: | | |
| gh api -X POST "repos/${REPO}/issues/${PR}/comments" \ | |
| -f body="🚫 Sorry @${COMMENTER}, you're not authorized to run \`/diffusers-bot\`. Only maintainers with write or admin access can trigger GPU tests." >/dev/null | |
| echo "::error::Only maintainers with write/admin access can run /diffusers-bot." | |
| exit 1 | |
| - name: Acknowledge with 👀 | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| COMMENT_ID: ${{ github.event.comment.id }} | |
| run: | | |
| gh api -X POST "repos/${REPO}/issues/comments/${COMMENT_ID}/reactions" -f content="eyes" >/dev/null | |
| - name: Parse pytest args | |
| id: parse | |
| env: | |
| COMMENT_BODY: ${{ github.event.comment.body }} | |
| run: | | |
| # Use only the first line of the comment, strip the command prefix. | |
| FIRST_LINE=$(printf '%s' "$COMMENT_BODY" | head -n1) | |
| ARGS="${FIRST_LINE#/diffusers-bot pytest}" | |
| # Trim surrounding whitespace/CR. | |
| ARGS="$(printf '%s' "$ARGS" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" | |
| echo "pytest_args=${ARGS}" >> "$GITHUB_OUTPUT" | |
| - name: Post "running" comment | |
| id: comment | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| PR: ${{ github.event.issue.number }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| PYTEST_ARGS: ${{ steps.parse.outputs.pytest_args }} | |
| RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| run: | | |
| BODY="⏳ Running \`pytest ${PYTEST_ARGS}\` on a GPU runner — [view logs](${RUN_URL}). | |
| Triggered by @${COMMENTER}." | |
| CID=$(gh api -X POST "repos/${REPO}/issues/${PR}/comments" -f body="$BODY" --jq '.id') | |
| echo "comment_id=${CID}" >> "$GITHUB_OUTPUT" | |
| gpu_tests: | |
| name: Run pytest on GPU | |
| needs: gate | |
| runs-on: | |
| group: aws-g4dn-2xlarge | |
| container: | |
| image: diffusers/diffusers-pytorch-cuda | |
| options: --gpus all --shm-size "16gb" --ipc host | |
| # Least privilege: this job checks out and runs untrusted fork code, so it gets no | |
| # write token. Comment writes happen only in `gate`/`report`. | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Checkout PR head | |
| uses: actions/checkout@v6 | |
| with: | |
| # Works for forks too — no fork credentials needed. | |
| ref: refs/pull/${{ github.event.issue.number }}/head | |
| fetch-depth: 2 | |
| - name: NVIDIA-SMI | |
| run: nvidia-smi | |
| - name: Install dependencies | |
| run: | | |
| printf 'tokenizers<0.23.0\ntorch==2.10.0\ntorchvision==0.25.0\ntorchaudio==2.10.0\n' > "$UV_OVERRIDE" | |
| uv pip install -e ".[quality,training,test]" | |
| uv pip install peft@git+https://github.com/huggingface/peft.git | |
| uv pip uninstall accelerate && uv pip install -U accelerate@git+https://github.com/huggingface/accelerate.git | |
| uv pip uninstall transformers huggingface_hub && UV_PRERELEASE=allow uv pip install -U transformers@git+https://github.com/huggingface/transformers.git | |
| - name: Environment | |
| run: diffusers-cli env | |
| - name: Run pytest | |
| env: | |
| # No secrets here: this step runs untrusted fork code (pytest imports the PR's | |
| # conftest.py/plugins), so exposing a token would let a malicious PR exfiltrate | |
| # it. Public Hub models download without auth; gated-repo tests are unsupported. | |
| # https://pytorch.org/docs/stable/notes/randomness.html#avoiding-nondeterministic-algorithms | |
| CUBLAS_WORKSPACE_CONFIG: :16:8 | |
| # Forwarded via env (not interpolated into the script) to avoid breakage on | |
| # quotes/special characters in a legitimate command. | |
| PYTEST_ARGS: ${{ needs.gate.outputs.pytest_args }} | |
| run: | | |
| eval "pytest --make-reports=tests_bot_gpu $PYTEST_ARGS" | |
| - name: Failure short reports | |
| if: ${{ failure() }} | |
| run: | | |
| cat reports/tests_bot_gpu_stats.txt || true | |
| cat reports/tests_bot_gpu_failures_short.txt || true | |
| - name: Test suite reports artifacts | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: bot_gpu_test_reports | |
| path: reports | |
| report: | |
| name: Report status | |
| needs: [gate, gpu_tests] | |
| # Always run so the comment is updated on success, failure, or cancellation — | |
| # but only if `gate` actually posted a comment to update. | |
| if: ${{ always() && needs.gate.outputs.comment_id != '' }} | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: Update comment with final status | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| CID: ${{ needs.gate.outputs.comment_id }} | |
| RESULT: ${{ needs.gpu_tests.result }} | |
| PYTEST_ARGS: ${{ needs.gate.outputs.pytest_args }} | |
| RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| run: | | |
| case "$RESULT" in | |
| success) EMOJI="✅"; MSG="passed";; | |
| failure) EMOJI="❌"; MSG="failed";; | |
| cancelled) EMOJI="⚠️"; MSG="was cancelled";; | |
| *) EMOJI="⚠️"; MSG="did not run (${RESULT})";; | |
| esac | |
| BODY="${EMOJI} \`pytest ${PYTEST_ARGS}\` ${MSG} on GPU — [view logs](${RUN_URL})." | |
| gh api -X PATCH "repos/${REPO}/issues/comments/${CID}" -f body="$BODY" |