name: Cross version tests on: pull_request: types: - opened - synchronize - reopened paths-ignore: - "docs/**" - "**.md" - "dev/clint/**" - ".github/workflows/docs.yml" - ".github/workflows/preview-docs.yml" - "mlflow/server/js/**" - ".github/workflows/js.yml" - ".claude/**" workflow_dispatch: inputs: repository: description: > [Optional] Repository name with owner. For example, mlflow/mlflow. Defaults to the repository that triggered a workflow. required: false default: "" ref: description: > [Optional] The branch, tag or SHA to checkout. When checking out the repository that triggered a workflow, this defaults to the reference or SHA for that event. Otherwise, uses the default branch. required: false default: "" flavors: description: "[Optional] Comma-separated string specifying which flavors to test (e.g. 'sklearn, xgboost'). If unspecified, all flavors are tested." required: false default: "" versions: description: "[Optional] Comma-separated string specifying which versions to test (e.g. '1.2.3, 4.5.6'). If unspecified, all versions are tested." required: false default: "" schedule: # Run this workflow daily at 13:00 UTC - cron: "0 13 * * *" concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true defaults: run: shell: bash env: MLFLOW_HOME: ${{ github.workspace }} PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu PIP_CONSTRAINT: ${{ github.workspace }}/requirements/constraints.txt permissions: {} jobs: set-matrix: runs-on: ubuntu-latest timeout-minutes: 10 if: github.event_name == 'workflow_dispatch' || (github.event_name == 'schedule' && github.repository == 'mlflow/dev') || (github.event_name == 'pull_request' && (github.event.pull_request.draft == false || github.event.pull_request.user.login == 'Copilot' && github.event.pull_request.user.type == 'Bot')) permissions: contents: read outputs: matrix1: ${{ steps.set-matrix.outputs.matrix1 }} matrix2: ${{ steps.set-matrix.outputs.matrix2 }} is_matrix1_empty: ${{ steps.set-matrix.outputs.is_matrix1_empty }} is_matrix2_empty: ${{ steps.set-matrix.outputs.is_matrix2_empty }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false repository: ${{ github.event_name == 'schedule' && 'mlflow/mlflow' || github.event.inputs.repository }} ref: ${{ github.event.inputs.ref }} - uses: ./.github/actions/untracked - uses: ./.github/actions/setup-python with: pin-micro-version: false - name: Install flavors run: | uv sync --package flavors - name: Check labels uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 id: check-labels with: retries: 3 script: | if (context.eventName !== "pull_request") { return { enable_dev_tests: true, only_latest: false, }; } const labelNames = context.payload.pull_request.labels.map(l => l.name); return { enable_dev_tests: labelNames.includes("enable-dev-tests"), only_latest: labelNames.includes("only-latest"), }; - name: Test flavors CLI run: | uv run --no-sync pytest --noconftest dev/flavors/tests - id: set-matrix name: Set matrix env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} EVENT_NAME: ${{ github.event_name }} REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} BASE_REF: ${{ github.base_ref }} ENABLE_DEV_TESTS: ${{ fromJson(steps.check-labels.outputs.result).enable_dev_tests }} ONLY_LATEST: ${{ fromJson(steps.check-labels.outputs.result).only_latest }} FLAVORS: ${{ github.event.inputs.flavors }} VERSIONS: ${{ github.event.inputs.versions }} run: | if [ "$EVENT_NAME" = "pull_request" ]; then REF_VERSIONS_YAML=/tmp/ref-versions.yml git fetch origin "$BASE_REF" --depth=1 git show "origin/$BASE_REF:mlflow/ml-package-versions.yml" > "$REF_VERSIONS_YAML" CHANGED_FILES=$(gh pr view "$PR_NUMBER" --json files --jq '.files[].path' | grep -v '^mlflow/server/js' || true) NO_DEV_FLAG=$([ "$ENABLE_DEV_TESTS" == "true" ] && echo "" || echo "--no-dev") ONLY_LATEST_FLAG=$([ "$ONLY_LATEST" == "true" ] && echo "--only-latest" || echo "") uv run --no-sync flavors matrix --ref-versions-yaml "$REF_VERSIONS_YAML" --changed-files "$CHANGED_FILES" $NO_DEV_FLAG $ONLY_LATEST_FLAG elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then uv run --no-sync flavors matrix --flavors "$FLAVORS" --versions "$VERSIONS" else uv run --no-sync flavors matrix fi test1: needs: set-matrix if: needs.set-matrix.outputs.is_matrix1_empty == 'false' runs-on: ${{ matrix.runs_on }} timeout-minutes: 120 permissions: contents: read strategy: fail-fast: false matrix: ${{ fromJson(needs.set-matrix.outputs.matrix1) }} steps: &test-steps - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false repository: ${{ github.event_name == 'schedule' && 'mlflow/mlflow' || github.event.inputs.repository }} ref: ${{ github.event.inputs.ref }} - uses: ./.github/actions/free-disk-space if: matrix.free_disk_space - uses: ./.github/actions/setup-python with: python-version: ${{ matrix.python }} - uses: ./.github/actions/setup-pyenv - uses: ./.github/actions/setup-java with: java-version: ${{ matrix.java }} - name: Remove constraints env: PACKAGE: ${{ matrix.package }} run: | # Remove any constraints for the current package to prevent installation conflicts sed -i '/^'"$PACKAGE"'/d' requirements/constraints.txt sed -i '/^constraint-dependencies = \[/,/^\]/{ /'"$PACKAGE"'/d }' pyproject.toml if ! git diff --exit-code requirements/constraints.txt pyproject.toml; then git diff git config user.name 'mlflow-app[bot]' git config user.email 'mlflow-app[bot]@users.noreply.github.com' git add requirements/constraints.txt pyproject.toml git commit -m "Remove constraints for testing" fi - name: Install mlflow & test dependencies env: MATRIX_CATEGORY: ${{ matrix.category }} run: | # setuptools 82.0.0 removed pkg_resources, this breaking change breaks some packages like transformers uv pip install --system -U wheel "setuptools<82" # For tracing SDK test, install the tracing package from the local path and minimal test dependencies if [[ "$MATRIX_CATEGORY" == "tracing-sdk" ]]; then uv pip install --system libs/tracing uv pip install --system pytest pytest-asyncio pytest-cov # Other two categories of tests (model/autologging) else uv pip install --system .[extras] uv pip install --system -r requirements/test-requirements.txt fi - name: Install ${{ matrix.package }} ${{ matrix.version }} env: MATRIX_INSTALL: ${{ matrix.install }} run: | eval "$MATRIX_INSTALL" - uses: ./.github/actions/show-versions - name: Pre-test if: matrix.pre_test env: MATRIX_PRE_TEST: ${{ matrix.pre_test }} run: | eval "$MATRIX_PRE_TEST" - name: Run tests env: MLFLOW_CONDA_HOME: /usr/share/miniconda SPARK_LOCAL_IP: localhost HF_HUB_ENABLE_HF_TRANSFER: 1 MATRIX_RUN: ${{ matrix.run }} run: | eval "$MATRIX_RUN" test2: needs: set-matrix if: needs.set-matrix.outputs.is_matrix2_empty == 'false' runs-on: ${{ matrix.runs_on }} timeout-minutes: 120 permissions: contents: read strategy: fail-fast: false matrix: ${{ fromJson(needs.set-matrix.outputs.matrix2) }} steps: *test-steps