Add standalone checkpoint evaluation for Puzzletron (#2177) #10459
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: Unit tests | |
| on: | |
| pull_request: | |
| branches: [main, release/*, feature/*] | |
| push: | |
| branches: [main, release/*, feature/*] | |
| paths: | |
| - ".github/workflows/unit_tests.yml" | |
| - "examples/puzzletron/**" | |
| - "modelopt/**" | |
| - "noxfile.py" | |
| - "pyproject.toml" | |
| - "puzzletron_orchestrator/**" | |
| - "puzzletron_setup/**" | |
| - "tests/_test_utils/torch/distributed/**" | |
| - "tests/unit/**" | |
| - "tools/launcher/**" | |
| - ".agents/skills/**" | |
| schedule: | |
| - cron: "0 0 * * *" # Nightly | |
| workflow_dispatch: | |
| # On-demand | |
| concurrency: | |
| # Cancel previous runs if new commit is pushed | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| jobs: | |
| check-dco: | |
| uses: ./.github/workflows/_wait_for_checks.yml | |
| permissions: | |
| checks: read | |
| secrets: inherit | |
| with: | |
| match_pattern: "^DCO$" | |
| check-file-changes: | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| runs-on: ubuntu-latest | |
| outputs: | |
| any_changed: ${{ steps.changed.outputs.any_modified || steps.non-pr.outputs.any_changed }} | |
| puzzletron_changed: >- | |
| ${{ steps.puzzletron_base.outputs.any_changed || | |
| steps.puzzletron_changed.outputs.any_modified || | |
| steps.puzzletron_non_pr.outputs.any_changed }} | |
| steps: | |
| - id: non-pr | |
| if: github.event_name != 'pull_request' | |
| run: echo "any_changed=true" >> "$GITHUB_OUTPUT" | |
| - id: puzzletron_non_pr | |
| if: >- | |
| github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'push' && github.ref == 'refs/heads/feature/puzzletron_v2') | |
| run: echo "any_changed=true" >> "$GITHUB_OUTPUT" | |
| - id: puzzletron_base | |
| if: github.event_name == 'pull_request' && github.base_ref == 'feature/puzzletron_v2' | |
| run: echo "any_changed=true" >> "$GITHUB_OUTPUT" | |
| - if: github.event_name == 'pull_request' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - if: github.event_name == 'pull_request' | |
| name: Check for changes in test-relevant paths | |
| id: changed | |
| uses: step-security/changed-files@v46.0.5 | |
| with: | |
| files: | | |
| .github/workflows/unit_tests.yml | |
| modelopt/** | |
| noxfile.py | |
| pyproject.toml | |
| tests/_test_utils/torch/distributed/** | |
| tests/unit/** | |
| tools/launcher/** | |
| .agents/skills/** | |
| - if: github.event_name == 'pull_request' | |
| name: Check for Puzzletron v2 changes | |
| id: puzzletron_changed | |
| uses: step-security/changed-files@v46.0.5 | |
| with: | |
| files: | | |
| .github/workflows/unit_tests.yml | |
| examples/puzzletron/**/*.html | |
| examples/puzzletron/**/*.json | |
| examples/puzzletron/**/*.md | |
| examples/puzzletron/**/*.py | |
| examples/puzzletron/**/*.sh | |
| examples/puzzletron/**/*.txt | |
| examples/puzzletron/**/*.yaml | |
| examples/puzzletron/**/*.yml | |
| modelopt/torch/** | |
| noxfile.py | |
| pyproject.toml | |
| puzzletron_orchestrator/** | |
| puzzletron_setup/** | |
| tests/_test_utils/torch/distributed/** | |
| tests/unit/torch/puzzletron/** | |
| puzzletron_v2: | |
| name: Puzzletron v2 CPU tests | |
| if: needs.check-file-changes.outputs.puzzletron_changed == 'true' | |
| needs: [check-dco, check-file-changes] | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - uses: ./.github/actions/ubuntu-setup | |
| with: | |
| python-version: "3.12" | |
| - name: Run the dedicated Puzzletron v2 CPU suite | |
| id: puzzletron_tests | |
| env: | |
| COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml | |
| COVERAGE_FILE: ${{ github.workspace }}/.coverage | |
| run: pip install nox uv && nox -s puzzletron_v2 | |
| - name: Publish Puzzletron v2 test summary | |
| if: ${{ always() }} | |
| env: | |
| TEST_RESULT: ${{ steps.puzzletron_tests.outcome }} | |
| run: | | |
| if [[ "$TEST_RESULT" == "success" ]]; then | |
| heading="Puzzletron v2 CPU CI passed" | |
| detail="The dedicated tests/unit/torch/puzzletron suite passed against the pinned runtime." | |
| else | |
| heading="Puzzletron v2 CPU CI did not pass" | |
| detail="The dedicated tests/unit/torch/puzzletron session needs attention." | |
| fi | |
| { | |
| echo "## $heading" | |
| echo | |
| echo "$detail" | |
| echo | |
| echo "This lane runs only \`tests/unit/torch/puzzletron\`; the regular unit matrix continues to run all other \`tests/unit\` tests." | |
| echo | |
| echo "The job also verifies dependency consistency and the exact versions recorded in \`examples/puzzletron/ci_environment.json\`." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| echo "::notice title=$heading::$detail" | |
| - name: Upload coverage reports to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| flags: puzzletron | |
| fail_ci_if_error: true | |
| skip_validation: true | |
| verbose: true | |
| puzzletron_v2_pr_required_check: | |
| name: Puzzletron v2 CI / required check | |
| if: ${{ github.event_name == 'pull_request' && always() }} | |
| needs: [check-file-changes, puzzletron_v2] | |
| permissions: {} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Publish required-check result | |
| env: | |
| CHANGE_DETECTION_RESULT: ${{ needs.check-file-changes.result }} | |
| PUZZLETRON_CHANGED: ${{ needs.check-file-changes.outputs.puzzletron_changed }} | |
| PUZZLETRON_TEST_RESULT: ${{ needs.puzzletron_v2.result }} | |
| run: | | |
| if [[ "$CHANGE_DETECTION_RESULT" != "success" ]]; then | |
| heading="Puzzletron v2 CI could not determine applicability" | |
| detail="Change detection did not succeed, so this check cannot safely pass." | |
| conclusion="failure" | |
| elif [[ "$PUZZLETRON_CHANGED" != "true" ]]; then | |
| heading="Puzzletron v2 CPU CI was not required" | |
| detail="This pull request neither targets feature/puzzletron_v2 nor changes a Puzzletron v2 CI dependency path." | |
| conclusion="success" | |
| elif [[ "$PUZZLETRON_TEST_RESULT" == "success" ]]; then | |
| heading="Puzzletron v2 CPU CI passed" | |
| detail="The dedicated tests/unit/torch/puzzletron suite passed against the pinned runtime." | |
| conclusion="success" | |
| else | |
| heading="Puzzletron v2 CPU CI failed" | |
| detail="The dedicated tests/unit/torch/puzzletron job concluded with: $PUZZLETRON_TEST_RESULT." | |
| conclusion="failure" | |
| fi | |
| { | |
| echo "## $heading" | |
| echo | |
| echo "$detail" | |
| echo | |
| echo "This stable check runs the dedicated Puzzletron v2 suite for every pull request into \`feature/puzzletron_v2\`; other branches retain path-aware applicability." | |
| echo "The regular unit matrix continues to cover all other unit tests." | |
| echo "The existing unit aggregate also observes this lane until branch protection explicitly adopts this standalone check." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| echo "::notice title=$heading::$detail" | |
| if [[ "$conclusion" == "failure" ]]; then | |
| exit 1 | |
| fi | |
| linux: | |
| needs: [check-dco] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/ubuntu-setup | |
| - name: Run unit tests | |
| env: | |
| COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml | |
| COVERAGE_FILE: ${{ github.workspace }}/.coverage | |
| run: pip install nox uv && nox -s "unit-3.12(torch_212, tf_latest)" | |
| - name: Upload coverage reports to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| flags: unit | |
| fail_ci_if_error: true | |
| # Skip GPG/SHASUM integrity check of the Codecov CLI: its key import | |
| # intermittently fails (codecov/codecov-action#1876), which would | |
| # otherwise hard-fail this required job on a transient infra blip. | |
| skip_validation: true | |
| verbose: true | |
| windows: | |
| if: needs.check-file-changes.outputs.any_changed == 'true' | |
| needs: [linux, check-file-changes] | |
| runs-on: windows-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Run unit tests (without coverage) | |
| run: pip install nox uv && nox -s "unit-3.12(torch_212, tf_latest)" | |
| multi-version: | |
| if: needs.check-file-changes.outputs.any_changed == 'true' | |
| needs: [linux, check-file-changes] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - {nox_session: "unit-3.10(torch_212, tf_latest)", python_version: "3.10"} | |
| - {nox_session: "unit-3.11(torch_212, tf_latest)", python_version: "3.11"} | |
| - {nox_session: "unit-3.13(torch_212, tf_latest)", python_version: "3.13"} | |
| - {nox_session: "unit-3.14(torch_212, tf_latest)", python_version: "3.14"} | |
| - {nox_session: "unit-3.12(torch_28, tf_latest)", python_version: "3.12"} | |
| - {nox_session: "unit-3.12(torch_29, tf_latest)", python_version: "3.12"} | |
| - {nox_session: "unit-3.12(torch_210, tf_latest)", python_version: "3.12"} | |
| - {nox_session: "unit-3.12(torch_211, tf_latest)", python_version: "3.12"} | |
| - {nox_session: "unit-3.12(torch_212, tf_min)", python_version: "3.12"} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/ubuntu-setup | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Run unit tests | |
| run: pip install nox uv && nox -s "${{ matrix.nox_session }}" | |
| partial-install: | |
| if: needs.check-file-changes.outputs.any_changed == 'true' | |
| needs: [linux, check-file-changes] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| test-env: [onnx, torch] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/ubuntu-setup | |
| - name: Run unit tests | |
| run: pip install nox uv && nox -s "partial_unit(subset='${{ matrix.test-env }}')" | |
| launcher: | |
| if: needs.check-file-changes.outputs.any_changed == 'true' | |
| needs: [linux, check-file-changes] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Run launcher tests | |
| working-directory: tools/launcher | |
| run: | | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| export PATH="$HOME/.local/bin:$PATH" | |
| uv venv .venv | |
| uv pip install -e . pytest | |
| uv run python3 -m pytest -v | |
| skills: | |
| if: needs.check-file-changes.outputs.any_changed == 'true' | |
| needs: [linux, check-file-changes] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Run skill gate tests | |
| # Skill gate tests are stdlib-only and hermetic (no GPU/cluster/network), | |
| # so they run in their own lightweight job rather than the main unit lane. | |
| # Override addopts to drop the repo's coverage/instafail plugins (not installed here). | |
| run: | | |
| pip install pytest | |
| python -m pytest .agents/skills/ -o addopts="" -p no:cacheprovider -v | |
| unit-pr-required-check: | |
| # Run even if some jobs are skipped | |
| if: ${{ github.event_name == 'pull_request' && always() }} | |
| needs: [check-file-changes, linux, windows, multi-version, partial-install, puzzletron_v2, launcher, skills] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Required unit tests did not succeed | |
| if: >- | |
| ${{ needs.check-file-changes.result != 'success' || | |
| needs.linux.result != 'success' || (needs.check-file-changes.outputs.any_changed == 'true' && ( | |
| needs.windows.result != 'success' || | |
| needs.multi-version.result != 'success' || | |
| needs.partial-install.result != 'success' || | |
| needs.launcher.result != 'success' || | |
| needs.skills.result != 'success' | |
| )) || (needs.check-file-changes.outputs.puzzletron_changed == 'true' && | |
| needs.puzzletron_v2.result != 'success') }} | |
| run: exit 1 |