This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch tvm-simplify-jenkins-pytest-sharding
in repository https://gitbox.apache.org/repos/asf/tvm.git

commit 09f7de617acdaf9c2576f37c89c1fc53342b8eb2
Author: Tianqi Chen <[email protected]>
AuthorDate: Sun Jul 5 02:14:27 2026 +0000

    [CI] Simplify Jenkins pytest execution
    
    Enable standard pytest-xdist automatic parallelism in the canonical 
launchers while removing external sharding, obsolete wrapper machinery, JUnit 
reporting, and its XML consumer. Repair broad-suite targets and failure 
propagation, and bound active nested MetaSchedule test parallelism without 
blanket serialization.
---
 ci/jenkins/generated/arm_jenkinsfile.groovy        |  11 +-
 ci/jenkins/generated/cpu_jenkinsfile.groovy        |  98 +-------
 ci/jenkins/generated/docker_jenkinsfile.groovy     |  11 +-
 ci/jenkins/generated/gpu_jenkinsfile.groovy        | 129 +---------
 ci/jenkins/generated/wasm_jenkinsfile.groovy       |  12 +-
 ci/jenkins/templates/cpu_jenkinsfile.groovy.j2     |   4 +-
 ci/jenkins/templates/gpu_jenkinsfile.groovy.j2     |  10 +-
 ci/jenkins/templates/utils/Build.groovy.j2         |   7 -
 ci/jenkins/templates/utils/base.groovy.j2          |   2 +-
 ci/jenkins/templates/utils/macros.j2               |  30 +--
 ci/jenkins/templates/wasm_jenkinsfile.groovy.j2    |   1 -
 ci/scripts/github/__init__.py                      |   2 +-
 ci/scripts/github/github_pr_comment.py             |   4 -
 ci/scripts/github/github_skipped_tests_comment.py  | 263 -------------------
 ci/scripts/jenkins/pytest_ids.py                   |  43 ----
 ci/scripts/jenkins/pytest_wrapper.py               | 137 ----------
 conftest.py                                        |  54 ----
 docker/install/ubuntu_install_python_package.sh    |   2 -
 docs/contribute/pull_request.rst                   |   2 +-
 python/tvm/testing/plugin.py                       |   9 -
 tests/python/ci/test_ci.py                         | 280 +--------------------
 .../meta_schedule/test_meta_schedule_cost_model.py |  11 +-
 .../test_meta_schedule_search_strategy.py          |   1 +
 .../test_meta_schedule_task_scheduler.py           |  13 +
 tests/python/testing/test_tvm_testing_features.py  |   3 +-
 tests/scripts/setup-pytest-env.sh                  |  98 --------
 tests/scripts/task_clear_pytest.sh                 |  24 --
 tests/scripts/task_python_docs.sh                  |   2 +-
 tests/scripts/task_python_integration.sh           |   2 +-
 tests/scripts/task_python_nightly.sh               |  33 ---
 tests/scripts/task_python_unittest.sh              |  29 ++-
 tests/scripts/task_python_unittest_gpuonly.sh      |  11 +-
 32 files changed, 85 insertions(+), 1253 deletions(-)

diff --git a/ci/jenkins/generated/arm_jenkinsfile.groovy 
b/ci/jenkins/generated/arm_jenkinsfile.groovy
index d6826878bf..3442caded7 100644
--- a/ci/jenkins/generated/arm_jenkinsfile.groovy
+++ b/ci/jenkins/generated/arm_jenkinsfile.groovy
@@ -60,7 +60,7 @@
 // 'python3 jenkins/generate.py'
 // Note: This timestamp is here to ensure that updates to the Jenkinsfile are
 // always rebased on main before merging:
-// Generated at 2026-06-23T03:28:14.520193
+// Generated at 2026-07-05T01:05:57.719405
 
 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
 // These are set at runtime from data in ci/jenkins/docker-images.yml, update
@@ -97,7 +97,7 @@ properties([
 upstream_revision = null
 
 // command to start a docker container
-docker_run = 'docker/bash.sh --env CI --env PLATFORM --env TVM_SHARD_INDEX 
--env TVM_NUM_SHARDS --env RUN_DISPLAY_URL --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
+docker_run = 'docker/bash.sh --env CI --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
 docker_build = 'docker/build.sh'
 // timeout in minutes
 max_time = 180
@@ -404,13 +404,6 @@ def prepare(node_type) {
     }
   }
 }
-def ci_setup(image) {
-  sh (
-    script: "${docker_run} ${image} ./tests/scripts/task_clear_pytest.sh",
-    label: 'Clean up old workspace',
-  )
-}
-
 def python_unittest(image) {
   sh (
     script: "${docker_run} ${image} ./tests/scripts/task_python_unittest.sh",
diff --git a/ci/jenkins/generated/cpu_jenkinsfile.groovy 
b/ci/jenkins/generated/cpu_jenkinsfile.groovy
index 879cd8b79f..0d3e408235 100644
--- a/ci/jenkins/generated/cpu_jenkinsfile.groovy
+++ b/ci/jenkins/generated/cpu_jenkinsfile.groovy
@@ -60,7 +60,7 @@
 // 'python3 jenkins/generate.py'
 // Note: This timestamp is here to ensure that updates to the Jenkinsfile are
 // always rebased on main before merging:
-// Generated at 2026-06-23T03:28:14.505504
+// Generated at 2026-07-05T01:05:57.741181
 
 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
 // These are set at runtime from data in ci/jenkins/docker-images.yml, update
@@ -97,7 +97,7 @@ properties([
 upstream_revision = null
 
 // command to start a docker container
-docker_run = 'docker/bash.sh --env CI --env PLATFORM --env TVM_SHARD_INDEX 
--env TVM_NUM_SHARDS --env RUN_DISPLAY_URL --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
+docker_run = 'docker/bash.sh --env CI --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
 docker_build = 'docker/build.sh'
 // timeout in minutes
 max_time = 180
@@ -404,13 +404,6 @@ def prepare(node_type) {
     }
   }
 }
-def ci_setup(image) {
-  sh (
-    script: "${docker_run} ${image} ./tests/scripts/task_clear_pytest.sh",
-    label: 'Clean up old workspace',
-  )
-}
-
 def python_unittest(image) {
   sh (
     script: "${docker_run} ${image} ./tests/scripts/task_python_unittest.sh",
@@ -510,52 +503,7 @@ build()
 
 
 
-
-def shard_run_unittest_CPU_1_of_2(node_type) {
-  echo 'Begin running on node_type ' + node_type
-  if (!skip_ci && is_docs_only_build != 1) {
-    node(node_type) {
-      ws("workspace/exec_${env.EXECUTOR_NUMBER}/tvm/ut-python-cpu") {
-        // NOTE: if exception happens, it will be caught outside
-        init_git()
-        docker_init(ci_cpu)
-        timeout(time: max_time, unit: 'MINUTES') {
-          withEnv([
-            'PLATFORM=cpu',
-            'TEST_STEP_NAME=unittest: CPU',
-            'TVM_NUM_SHARDS=2',
-            'TVM_SHARD_INDEX=0',
-            "SKIP_SLOW_TESTS=${skip_slow_tests}"], {
-            sh(
-                  script: "./${jenkins_scripts_root}/s3.py --action download 
--bucket ${s3_bucket} --prefix ${s3_prefix}/cpu",
-                  label: 'Download artifacts from S3',
-                )
-
-              ci_setup(ci_cpu)
-              cpp_unittest(ci_cpu)
-              python_unittest(ci_cpu)
-          })
-        }
-        // only run upload if things are successful
-        try {
-          sh(
-            script: "./${jenkins_scripts_root}/s3.py --action upload --bucket 
${s3_bucket} --prefix ${s3_prefix}/pytest-results/unittest_CPU --items 
build/pytest-results",
-            label: 'Upload JUnits to S3',
-          )
-
-          junit 'build/pytest-results/*.xml'
-        } catch (Exception e) {
-          echo 'Exception during JUnit upload: ' + e.toString()
-        }
-      }
-    }
-    echo 'End running on node_type ' + node_type
-  } else {
-    Utils.markStageSkippedForConditional('unittest: CPU 1 of 2')
-  }
-}
-
-def shard_run_unittest_CPU_2_of_2(node_type) {
+def run_unittest_CPU(node_type) {
   echo 'Begin running on node_type ' + node_type
   if (!skip_ci && is_docs_only_build != 1) {
     node(node_type) {
@@ -567,35 +515,21 @@ def shard_run_unittest_CPU_2_of_2(node_type) {
           withEnv([
             'PLATFORM=cpu',
             'TEST_STEP_NAME=unittest: CPU',
-            'TVM_NUM_SHARDS=2',
-            'TVM_SHARD_INDEX=1',
             "SKIP_SLOW_TESTS=${skip_slow_tests}"], {
             sh(
                   script: "./${jenkins_scripts_root}/s3.py --action download 
--bucket ${s3_bucket} --prefix ${s3_prefix}/cpu",
                   label: 'Download artifacts from S3',
                 )
 
-              ci_setup(ci_cpu)
               cpp_unittest(ci_cpu)
               python_unittest(ci_cpu)
           })
         }
-        // only run upload if things are successful
-        try {
-          sh(
-            script: "./${jenkins_scripts_root}/s3.py --action upload --bucket 
${s3_bucket} --prefix ${s3_prefix}/pytest-results/unittest_CPU --items 
build/pytest-results",
-            label: 'Upload JUnits to S3',
-          )
-
-          junit 'build/pytest-results/*.xml'
-        } catch (Exception e) {
-          echo 'Exception during JUnit upload: ' + e.toString()
-        }
       }
     }
     echo 'End running on node_type ' + node_type
   } else {
-    Utils.markStageSkippedForConditional('unittest: CPU 2 of 2')
+    Utils.markStageSkippedForConditional('unittest: CPU')
   }
 }
 
@@ -606,27 +540,9 @@ def test() {
       SKIP_SLOW_TESTS = "${skip_slow_tests}"
     }
     parallel(
-    'unittest: CPU 1 of 2': {
-      try {
-      shard_run_unittest_CPU_1_of_2('CPU-SMALL-SPOT')
-      } catch (Throwable ex) {
-        echo 'Exception during SPOT run ' + ex.toString()
-        if (is_last_build()) {
-          // retry if at last build
-          // mark the current stage as success
-          // and try again via on demand node
-          echo 'Retry on-demand given it is last build'
-          currentBuild.result = 'SUCCESS'
-          shard_run_unittest_CPU_1_of_2('CPU-SMALL')
-        } else {
-          echo 'Exit since it is not last build'
-          throw ex
-        }
-      }
-    },
-    'unittest: CPU 2 of 2': {
+    'unittest: CPU': {
       try {
-      shard_run_unittest_CPU_2_of_2('CPU-SMALL-SPOT')
+      run_unittest_CPU('CPU-SMALL-SPOT')
       } catch (Throwable ex) {
         echo 'Exception during SPOT run ' + ex.toString()
         if (is_last_build()) {
@@ -635,7 +551,7 @@ def test() {
           // and try again via on demand node
           echo 'Retry on-demand given it is last build'
           currentBuild.result = 'SUCCESS'
-          shard_run_unittest_CPU_2_of_2('CPU-SMALL')
+          run_unittest_CPU('CPU-SMALL')
         } else {
           echo 'Exit since it is not last build'
           throw ex
diff --git a/ci/jenkins/generated/docker_jenkinsfile.groovy 
b/ci/jenkins/generated/docker_jenkinsfile.groovy
index f5409e23aa..8ffe78942a 100644
--- a/ci/jenkins/generated/docker_jenkinsfile.groovy
+++ b/ci/jenkins/generated/docker_jenkinsfile.groovy
@@ -60,7 +60,7 @@
 // 'python3 jenkins/generate.py'
 // Note: This timestamp is here to ensure that updates to the Jenkinsfile are
 // always rebased on main before merging:
-// Generated at 2026-06-23T03:28:14.487314
+// Generated at 2026-07-05T01:05:57.759905
 
 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
 // These are set at runtime from data in ci/jenkins/docker-images.yml, update
@@ -97,7 +97,7 @@ properties([
 upstream_revision = null
 
 // command to start a docker container
-docker_run = 'docker/bash.sh --env CI --env PLATFORM --env TVM_SHARD_INDEX 
--env TVM_NUM_SHARDS --env RUN_DISPLAY_URL --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
+docker_run = 'docker/bash.sh --env CI --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
 docker_build = 'docker/build.sh'
 // timeout in minutes
 max_time = 180
@@ -404,13 +404,6 @@ def prepare(node_type) {
     }
   }
 }
-def ci_setup(image) {
-  sh (
-    script: "${docker_run} ${image} ./tests/scripts/task_clear_pytest.sh",
-    label: 'Clean up old workspace',
-  )
-}
-
 def python_unittest(image) {
   sh (
     script: "${docker_run} ${image} ./tests/scripts/task_python_unittest.sh",
diff --git a/ci/jenkins/generated/gpu_jenkinsfile.groovy 
b/ci/jenkins/generated/gpu_jenkinsfile.groovy
index 28c9a6040e..792b7eadc4 100644
--- a/ci/jenkins/generated/gpu_jenkinsfile.groovy
+++ b/ci/jenkins/generated/gpu_jenkinsfile.groovy
@@ -60,7 +60,7 @@
 // 'python3 jenkins/generate.py'
 // Note: This timestamp is here to ensure that updates to the Jenkinsfile are
 // always rebased on main before merging:
-// Generated at 2026-06-23T03:28:14.533751
+// Generated at 2026-07-05T01:05:57.780838
 
 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
 // These are set at runtime from data in ci/jenkins/docker-images.yml, update
@@ -97,7 +97,7 @@ properties([
 upstream_revision = null
 
 // command to start a docker container
-docker_run = 'docker/bash.sh --env CI --env PLATFORM --env TVM_SHARD_INDEX 
--env TVM_NUM_SHARDS --env RUN_DISPLAY_URL --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
+docker_run = 'docker/bash.sh --env CI --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
 docker_build = 'docker/build.sh'
 // timeout in minutes
 max_time = 180
@@ -404,13 +404,6 @@ def prepare(node_type) {
     }
   }
 }
-def ci_setup(image) {
-  sh (
-    script: "${docker_run} ${image} ./tests/scripts/task_clear_pytest.sh",
-    label: 'Clean up old workspace',
-  )
-}
-
 def python_unittest(image) {
   sh (
     script: "${docker_run} ${image} ./tests/scripts/task_python_unittest.sh",
@@ -515,8 +508,7 @@ def build() {
 build()
 
 
-
-def shard_run_unittest_GPU_1_of_2(node_type) {
+def run_unittest_GPU(node_type) {
   echo 'Begin running on node_type ' + node_type
   if (!skip_ci && is_docs_only_build != 1) {
     node(node_type) {
@@ -528,65 +520,12 @@ def shard_run_unittest_GPU_1_of_2(node_type) {
           withEnv([
             'PLATFORM=gpu',
             'TEST_STEP_NAME=unittest: GPU',
-            'TVM_NUM_SHARDS=2',
-            'TVM_SHARD_INDEX=0',
             "SKIP_SLOW_TESTS=${skip_slow_tests}"], {
             sh(
                   script: "./${jenkins_scripts_root}/s3.py --action download 
--bucket ${s3_bucket} --prefix ${s3_prefix}/gpu",
                   label: 'Download artifacts from S3',
                 )
 
-              ci_setup(ci_gpu)
-              sh (
-                script: "${docker_run} ${ci_gpu} 
./tests/scripts/task_python_unittest_gpuonly.sh",
-                label: 'Run Python GPU unit tests',
-              )
-              sh (
-                script: "${docker_run} ${ci_gpu} 
./tests/scripts/task_python_integration_gpuonly.sh",
-                label: 'Run Python GPU integration tests',
-              )
-          })
-        }
-        // only run upload if things are successful
-        try {
-          sh(
-            script: "./${jenkins_scripts_root}/s3.py --action upload --bucket 
${s3_bucket} --prefix ${s3_prefix}/pytest-results/unittest_GPU --items 
build/pytest-results",
-            label: 'Upload JUnits to S3',
-          )
-
-          junit 'build/pytest-results/*.xml'
-        } catch (Exception e) {
-          echo 'Exception during JUnit upload: ' + e.toString()
-        }
-      }
-    }
-    echo 'End running on node_type ' + node_type
-  } else {
-    Utils.markStageSkippedForConditional('unittest: GPU 1 of 2')
-  }
-}
-
-def shard_run_unittest_GPU_2_of_2(node_type) {
-  echo 'Begin running on node_type ' + node_type
-  if (!skip_ci && is_docs_only_build != 1) {
-    node(node_type) {
-      ws("workspace/exec_${env.EXECUTOR_NUMBER}/tvm/ut-python-gpu") {
-        // NOTE: if exception happens, it will be caught outside
-        init_git()
-        docker_init(ci_gpu)
-        timeout(time: max_time, unit: 'MINUTES') {
-          withEnv([
-            'PLATFORM=gpu',
-            'TEST_STEP_NAME=unittest: GPU',
-            'TVM_NUM_SHARDS=2',
-            'TVM_SHARD_INDEX=1',
-            "SKIP_SLOW_TESTS=${skip_slow_tests}"], {
-            sh(
-                  script: "./${jenkins_scripts_root}/s3.py --action download 
--bucket ${s3_bucket} --prefix ${s3_prefix}/gpu",
-                  label: 'Download artifacts from S3',
-                )
-
-              ci_setup(ci_gpu)
               sh (
                 script: "${docker_run} ${ci_gpu} 
./tests/scripts/task_java_unittest.sh",
                 label: 'Run Java unit tests',
@@ -601,29 +540,17 @@ def shard_run_unittest_GPU_2_of_2(node_type) {
               )
           })
         }
-        // only run upload if things are successful
-        try {
-          sh(
-            script: "./${jenkins_scripts_root}/s3.py --action upload --bucket 
${s3_bucket} --prefix ${s3_prefix}/pytest-results/unittest_GPU --items 
build/pytest-results",
-            label: 'Upload JUnits to S3',
-          )
-
-          junit 'build/pytest-results/*.xml'
-        } catch (Exception e) {
-          echo 'Exception during JUnit upload: ' + e.toString()
-        }
       }
     }
     echo 'End running on node_type ' + node_type
   } else {
-    Utils.markStageSkippedForConditional('unittest: GPU 2 of 2')
+    Utils.markStageSkippedForConditional('unittest: GPU')
   }
 }
 
 
 
-
-def shard_run_docs_GPU_1_of_1(node_type) {
+def run_docs_GPU(node_type) {
   echo 'Begin running on node_type ' + node_type
   if (!skip_ci) {
     node(node_type) {
@@ -635,15 +562,12 @@ def shard_run_docs_GPU_1_of_1(node_type) {
           withEnv([
             'PLATFORM=gpu',
             'TEST_STEP_NAME=docs: GPU',
-            'TVM_NUM_SHARDS=1',
-            'TVM_SHARD_INDEX=0',
             "SKIP_SLOW_TESTS=${skip_slow_tests}"], {
             sh(
                   script: "./${jenkins_scripts_root}/s3.py --action download 
--bucket ${s3_bucket} --prefix ${s3_prefix}/gpu",
                   label: 'Download artifacts from S3',
                 )
 
-              ci_setup(ci_gpu)
               sh (
                 script: "${docker_run} ${ci_gpu} 
./tests/scripts/task_python_docs.sh",
                 label: 'Build docs',
@@ -659,22 +583,11 @@ def shard_run_docs_GPU_1_of_1(node_type) {
               )
           })
         }
-        // only run upload if things are successful
-        try {
-          sh(
-            script: "./${jenkins_scripts_root}/s3.py --action upload --bucket 
${s3_bucket} --prefix ${s3_prefix}/pytest-results/docs_GPU --items 
build/pytest-results",
-            label: 'Upload JUnits to S3',
-          )
-
-          junit 'build/pytest-results/*.xml'
-        } catch (Exception e) {
-          echo 'Exception during JUnit upload: ' + e.toString()
-        }
       }
     }
     echo 'End running on node_type ' + node_type
   } else {
-    Utils.markStageSkippedForConditional('docs: GPU 1 of 1')
+    Utils.markStageSkippedForConditional('docs: GPU')
   }
 }
 
@@ -686,27 +599,9 @@ def test() {
       SKIP_SLOW_TESTS = "${skip_slow_tests}"
     }
     parallel(
-    'unittest: GPU 1 of 2': {
-      try {
-      shard_run_unittest_GPU_1_of_2('GPU-SPOT')
-      } catch (Throwable ex) {
-        echo 'Exception during SPOT run ' + ex.toString()
-        if (is_last_build()) {
-          // retry if at last build
-          // mark the current stage as success
-          // and try again via on demand node
-          echo 'Retry on-demand given it is last build'
-          currentBuild.result = 'SUCCESS'
-          shard_run_unittest_GPU_1_of_2('GPU')
-        } else {
-          echo 'Exit since it is not last build'
-          throw ex
-        }
-      }
-    },
-    'unittest: GPU 2 of 2': {
+    'unittest: GPU': {
       try {
-      shard_run_unittest_GPU_2_of_2('GPU-SPOT')
+      run_unittest_GPU('GPU-SPOT')
       } catch (Throwable ex) {
         echo 'Exception during SPOT run ' + ex.toString()
         if (is_last_build()) {
@@ -715,16 +610,16 @@ def test() {
           // and try again via on demand node
           echo 'Retry on-demand given it is last build'
           currentBuild.result = 'SUCCESS'
-          shard_run_unittest_GPU_2_of_2('GPU')
+          run_unittest_GPU('GPU')
         } else {
           echo 'Exit since it is not last build'
           throw ex
         }
       }
     },
-    'docs: GPU 1 of 1': {
+    'docs: GPU': {
       try {
-      shard_run_docs_GPU_1_of_1('GPU-SPOT')
+      run_docs_GPU('GPU-SPOT')
       } catch (Throwable ex) {
         echo 'Exception during SPOT run ' + ex.toString()
         if (is_last_build()) {
@@ -733,7 +628,7 @@ def test() {
           // and try again via on demand node
           echo 'Retry on-demand given it is last build'
           currentBuild.result = 'SUCCESS'
-          shard_run_docs_GPU_1_of_1('GPU')
+          run_docs_GPU('GPU')
         } else {
           echo 'Exit since it is not last build'
           throw ex
diff --git a/ci/jenkins/generated/wasm_jenkinsfile.groovy 
b/ci/jenkins/generated/wasm_jenkinsfile.groovy
index ab64444e4a..7421fa86ca 100644
--- a/ci/jenkins/generated/wasm_jenkinsfile.groovy
+++ b/ci/jenkins/generated/wasm_jenkinsfile.groovy
@@ -60,7 +60,7 @@
 // 'python3 jenkins/generate.py'
 // Note: This timestamp is here to ensure that updates to the Jenkinsfile are
 // always rebased on main before merging:
-// Generated at 2026-06-23T03:28:14.550555
+// Generated at 2026-07-05T01:05:57.802104
 
 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
 // These are set at runtime from data in ci/jenkins/docker-images.yml, update
@@ -97,7 +97,7 @@ properties([
 upstream_revision = null
 
 // command to start a docker container
-docker_run = 'docker/bash.sh --env CI --env PLATFORM --env TVM_SHARD_INDEX 
--env TVM_NUM_SHARDS --env RUN_DISPLAY_URL --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
+docker_run = 'docker/bash.sh --env CI --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
 docker_build = 'docker/build.sh'
 // timeout in minutes
 max_time = 180
@@ -404,13 +404,6 @@ def prepare(node_type) {
     }
   }
 }
-def ci_setup(image) {
-  sh (
-    script: "${docker_run} ${image} ./tests/scripts/task_clear_pytest.sh",
-    label: 'Clean up old workspace',
-  )
-}
-
 def python_unittest(image) {
   sh (
     script: "${docker_run} ${image} ./tests/scripts/task_python_unittest.sh",
@@ -471,7 +464,6 @@ def run_build(node_type) {
         cmake_build(ci_wasm, 'build')
         make_cpp_tests(ci_wasm, 'build')
         cpp_unittest(ci_wasm)
-        ci_setup(ci_wasm)
         sh (
           script: "${docker_run} ${ci_wasm} ./tests/scripts/task_web_wasm.sh",
           label: 'Run WASM lint and tests',
diff --git a/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2 
b/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2
index d2e479d5e8..62b7c3dfea 100644
--- a/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2
+++ b/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2
@@ -37,16 +37,14 @@
 {% set test_method_names = [] %}
 
 
-{% call(shard_index, num_shards) m.sharded_test_step(
+{% call m.test_step(
   name="unittest: CPU",
   ws="tvm/ut-python-cpu",
   platform="cpu",
-  num_shards=2,
   docker_image="ci_cpu",
   test_method_names=test_method_names,
 ) %}
   {{ m.download_artifacts(tag='cpu') }}
-  ci_setup(ci_cpu)
   cpp_unittest(ci_cpu)
   python_unittest(ci_cpu)
 {% endcall %}
diff --git a/ci/jenkins/templates/gpu_jenkinsfile.groovy.j2 
b/ci/jenkins/templates/gpu_jenkinsfile.groovy.j2
index 7ab5256419..3a13dfe7f3 100644
--- a/ci/jenkins/templates/gpu_jenkinsfile.groovy.j2
+++ b/ci/jenkins/templates/gpu_jenkinsfile.groovy.j2
@@ -38,22 +38,18 @@
 
 {% set test_method_names = [] %}
 
-{% call(shard_index, num_shards) m.sharded_test_step(
+{% call m.test_step(
   name="unittest: GPU",
-  num_shards=2,
   ws="tvm/ut-python-gpu",
   platform="gpu",
   docker_image="ci_gpu",
   test_method_names=test_method_names,
 ) %}
   {{ m.download_artifacts(tag='gpu') }}
-  ci_setup(ci_gpu)
-  {% if shard_index == 2 or num_shards < 2 %}
   sh (
     script: "${docker_run} ${ci_gpu} ./tests/scripts/task_java_unittest.sh",
     label: 'Run Java unit tests',
   )
-  {% endif %}
   sh (
     script: "${docker_run} ${ci_gpu} 
./tests/scripts/task_python_unittest_gpuonly.sh",
     label: 'Run Python GPU unit tests',
@@ -65,9 +61,8 @@
 {% endcall %}
 
 
-{% call(shard_index, num_shards) m.sharded_test_step(
+{% call m.test_step(
   name="docs: GPU",
-  num_shards=1,
   ws="tvm/docs-python-gpu",
   platform="gpu",
   docker_image="ci_gpu",
@@ -75,7 +70,6 @@
   test_method_names=test_method_names,
 ) %}
   {{ m.download_artifacts(tag='gpu') }}
-  ci_setup(ci_gpu)
   sh (
     script: "${docker_run} ${ci_gpu} ./tests/scripts/task_python_docs.sh",
     label: 'Build docs',
diff --git a/ci/jenkins/templates/utils/Build.groovy.j2 
b/ci/jenkins/templates/utils/Build.groovy.j2
index c20a1c5c43..42bd4a991f 100644
--- a/ci/jenkins/templates/utils/Build.groovy.j2
+++ b/ci/jenkins/templates/utils/Build.groovy.j2
@@ -1,10 +1,3 @@
-def ci_setup(image) {
-  sh (
-    script: "${docker_run} ${image} ./tests/scripts/task_clear_pytest.sh",
-    label: 'Clean up old workspace',
-  )
-}
-
 def python_unittest(image) {
   sh (
     script: "${docker_run} ${image} ./tests/scripts/task_python_unittest.sh",
diff --git a/ci/jenkins/templates/utils/base.groovy.j2 
b/ci/jenkins/templates/utils/base.groovy.j2
index 813ceee886..a8fda460b7 100644
--- a/ci/jenkins/templates/utils/base.groovy.j2
+++ b/ci/jenkins/templates/utils/base.groovy.j2
@@ -82,7 +82,7 @@ properties([
 upstream_revision = null
 
 // command to start a docker container
-docker_run = 'docker/bash.sh --env CI --env PLATFORM --env TVM_SHARD_INDEX 
--env TVM_NUM_SHARDS --env RUN_DISPLAY_URL --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
+docker_run = 'docker/bash.sh --env CI --env PLATFORM --env SKIP_SLOW_TESTS 
--env TEST_STEP_NAME'
 docker_build = 'docker/build.sh'
 // timeout in minutes
 max_time = 180
diff --git a/ci/jenkins/templates/utils/macros.j2 
b/ci/jenkins/templates/utils/macros.j2
index b1bd3679ac..959d91725f 100644
--- a/ci/jenkins/templates/utils/macros.j2
+++ b/ci/jenkins/templates/utils/macros.j2
@@ -19,18 +19,8 @@
   "workspace/exec_${env.EXECUTOR_NUMBER}/{{ folder }}"
 {%- endmacro -%}
 
-{% macro junit_to_s3(test_dir_name) %}
-sh(
-            script: "./${jenkins_scripts_root}/s3.py --action upload --bucket 
${s3_bucket} --prefix ${s3_prefix}/pytest-results/{{ test_dir_name }} --items 
build/pytest-results",
-            label: 'Upload JUnits to S3',
-          )
-{% endmacro %}
-
-{% macro sharded_test_step(name, num_shards, ws, docker_image, platform, 
test_method_names, condition="!skip_ci && is_docs_only_build != 1") %}
-
-{% for shard_index in range(1, num_shards + 1) %}
-{% set method_name = "shard_run_" + name.replace(":", "").replace(" ", 
"-").replace("-", "_") + "_" + shard_index|string + "_of_" + num_shards|string 
%}
-{% set test_dir_name = name.replace(":", "").replace(" ", "-").replace("-", 
"_")|string %}
+{% macro test_step(name, ws, docker_image, platform, test_method_names, 
condition="!skip_ci && is_docs_only_build != 1") %}
+{% set method_name = "run_" + name.replace(":", "").replace(" ", 
"-").replace("-", "_") %}
 def {{ method_name }}(node_type) {
   echo 'Begin running on node_type ' + node_type
   if ({{ condition }}) {
@@ -43,29 +33,19 @@ def {{ method_name }}(node_type) {
           withEnv([
             'PLATFORM={{ platform }}',
             'TEST_STEP_NAME={{ name }}',
-            'TVM_NUM_SHARDS={{ num_shards }}',
-            'TVM_SHARD_INDEX={{ shard_index - 1 }}',
             "SKIP_SLOW_TESTS=${skip_slow_tests}"], {
-            {{ caller(shard_index, num_shards) | trim | indent(width=12) }}
+            {{ caller() | trim | indent(width=12) }}
           })
         }
-        // only run upload if things are successful
-        try {
-          {{ junit_to_s3(test_dir_name) }}
-          junit 'build/pytest-results/*.xml'
-        } catch (Exception e) {
-          echo 'Exception during JUnit upload: ' + e.toString()
-        }
       }
     }
     echo 'End running on node_type ' + node_type
   } else {
-    Utils.markStageSkippedForConditional('{{ name }} {{ shard_index }} of {{ 
num_shards }}')
+    Utils.markStageSkippedForConditional('{{ name }}')
   }
 }
-{% set _ = test_method_names.append((name + " " + shard_index|string + " of " 
+ num_shards|string, method_name)) %}
+{% set _ = test_method_names.append((name, method_name)) %}
 
-{% endfor %}
 {% endmacro %}
 
 {% macro invoke_build(name, condition, node, docker_image, ws, platform) %}
diff --git a/ci/jenkins/templates/wasm_jenkinsfile.groovy.j2 
b/ci/jenkins/templates/wasm_jenkinsfile.groovy.j2
index 0d119f043e..8e7d909bd1 100644
--- a/ci/jenkins/templates/wasm_jenkinsfile.groovy.j2
+++ b/ci/jenkins/templates/wasm_jenkinsfile.groovy.j2
@@ -32,7 +32,6 @@
   cmake_build(ci_wasm, 'build')
   make_cpp_tests(ci_wasm, 'build')
   cpp_unittest(ci_wasm)
-  ci_setup(ci_wasm)
   sh (
     script: "${docker_run} ${ci_wasm} ./tests/scripts/task_web_wasm.sh",
     label: 'Run WASM lint and tests',
diff --git a/ci/scripts/github/__init__.py b/ci/scripts/github/__init__.py
index a6226fec29..0e55424eee 100644
--- a/ci/scripts/github/__init__.py
+++ b/ci/scripts/github/__init__.py
@@ -17,4 +17,4 @@
 # under the License.
 """Package to enable testing of GitHub scripts"""
 
-from . import github_skipped_tests_comment, github_pr_comment, 
github_tag_teams, github_docs_comment
+from . import github_docs_comment, github_pr_comment, github_tag_teams
diff --git a/ci/scripts/github/github_pr_comment.py 
b/ci/scripts/github/github_pr_comment.py
index 2d523b21b3..81347659d9 100755
--- a/ci/scripts/github/github_pr_comment.py
+++ b/ci/scripts/github/github_pr_comment.py
@@ -30,7 +30,6 @@ from cmd_utils import init_log
 from git_utils import DRY_RUN, GitHubRepo, git, parse_remote
 from github_commenter import BotCommentBuilder
 from github_docs_comment import get_doc_url
-from github_skipped_tests_comment import get_skipped_tests_comment
 from github_tag_teams import get_tags
 
 PR_QUERY = """
@@ -132,17 +131,14 @@ if __name__ == "__main__":
 
     if args.test_comments is not None:
         test_comments = json.loads(args.test_comments)
-        skipped_tests = test_comments["skipped-tests"]
         ccs = test_comments["ccs"]
         docs_info = test_comments["docs"]
     else:
-        skipped_tests = get_skipped_tests_comment(pr_data, github=github)
         ccs = get_tags(pr_data, github, team_issue=10317)
         docs_info = get_doc_url(pr_data)
 
     items = {
         "ccs": ccs,
-        "skipped-tests": skipped_tests,
         "docs": docs_info,
     }
     commenter.post_items(items=items.items())
diff --git a/ci/scripts/github/github_skipped_tests_comment.py 
b/ci/scripts/github/github_skipped_tests_comment.py
deleted file mode 100755
index 10789f7561..0000000000
--- a/ci/scripts/github/github_skipped_tests_comment.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/env python3
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# ruff: noqa: E501
-import json
-import logging
-import os
-import subprocess
-from pathlib import Path
-from typing import Any
-from xml.etree import ElementTree
-
-
-def run_subprocess(command):
-    logging.info(f"Running command {command}")
-    proc = subprocess.run(command, shell=True, stdout=subprocess.PIPE, 
encoding="utf-8")
-    if proc.returncode != 0:
-        raise RuntimeError(f"Command failed 
{command}:\nstdout:\n{proc.stdout}")
-    return proc
-
-
-def retrieve_test_report(s3_url, target_dir):
-    command = f"aws --region us-west-2 s3 cp {s3_url} {target_dir} --recursive 
--no-sign-request"
-    run_subprocess(command)
-
-
-def get_common_commit_sha():
-    command = "git merge-base origin/main HEAD"
-    proc = run_subprocess(command)
-    return proc.stdout.strip()
-
-
-def get_main_jenkins_build_number(github, common_commit):
-    json = github.get(f"commits/{common_commit}/status")
-    for status in reversed(json["statuses"]):
-        if status["context"] != "tvm-ci/branch":
-            continue
-        state = status["state"]
-        target_url = str(status["target_url"])
-        build_number = (
-            target_url[target_url.find("job/main") : len(target_url)]
-            .strip("job/main/")
-            .strip("/display/redirect")
-        )
-        assert build_number.isdigit()
-        return {"build_number": build_number, "state": state}
-    raise RuntimeError(f"Failed to find main build number for commit 
{common_commit}")
-
-
-def retrieve_test_reports(
-    common_main_build, pr_number, build_number, s3_prefix, pr_test_report_dir, 
main_test_report_dir
-):
-    cur_build_s3_link = 
f"s3://{s3_prefix}/tvm/PR-{pr_number!s}/{build_number!s}/pytest-results"
-    retrieve_test_report(cur_build_s3_link, pr_test_report_dir)
-
-    common_build_s3_link = 
f"s3://{s3_prefix}/tvm/main/{common_main_build}/pytest-results"
-    retrieve_test_report(common_build_s3_link, main_test_report_dir)
-
-
-def get_pr_and_build_numbers(target_url):
-    target_url = target_url[target_url.find("PR-") : len(target_url)]
-    split = target_url.split("/")
-    pr_number = split[0].strip("PR-")
-    build_number = split[1]
-    return {"pr_number": pr_number, "build_number": build_number}
-
-
-def build_test_set(directory):
-    directory = Path(directory)
-    subdir_to_skipped = {}
-    subdirs = [
-        item for item in os.listdir(directory) if 
os.path.isdir(os.path.join(directory, item))
-    ]
-    for subdir in subdirs:
-        subdir_to_skipped[subdir] = set()
-        for root, _, files in os.walk(directory / subdir):
-            for file in files:
-                test_report = ElementTree.parse(Path(root) / file)
-                for testcase in test_report.iter("testcase"):
-                    skipped = testcase.find("skipped")
-                    if skipped is not None:
-                        key = testcase.attrib["classname"] + "#" + 
testcase.attrib["name"]
-                        subdir_to_skipped[subdir].add(key)
-    return subdir_to_skipped
-
-
-def to_node_name(dir_name: str):
-    return dir_name.replace("_", ": ", 1)
-
-
-def build_diff_comment_with_main(
-    common_commit_sha,
-    skipped_list,
-    commit_sha,
-):
-    if len(skipped_list) == 0:
-        return f"No diff in skipped tests with main found in this branch for 
commit {commit_sha}.\n"
-
-    text = (
-        f"The list below shows tests that ran in main {common_commit_sha} but 
were "
-        f"skipped in the CI build of {commit_sha}:\n"
-        f"```\n"
-    )
-    for skip in skipped_list:
-        text += skip + "\n"
-    text += "```\n"
-    return text
-
-
-def build_comment(
-    common_commit_sha,
-    common_main_build,
-    skipped_list,
-    additional_skipped_list,
-    pr_number,
-    build_number,
-    commit_sha,
-    jenkins_prefix,
-):
-    if common_main_build["state"] != "success":
-        return f"Unable to run tests bot because main failed to pass CI at 
{common_commit_sha}."
-
-    text = build_diff_comment_with_main(common_commit_sha, skipped_list, 
commit_sha)
-
-    if len(additional_skipped_list) != 0:
-        text += "\n"
-        text += (
-            "Additional tests that were skipped in the CI build and present in 
the [`required_tests_to_run`]"
-            
"(https://github.com/apache/tvm/blob/main/ci/scripts/github/required_tests_to_run.json)
 file:"
-            "\n```\n"
-        )
-        for skip in additional_skipped_list:
-            text += skip + "\n"
-        text += "```\n"
-
-    text += (
-        f"A detailed report of ran tests is 
[here](https://{jenkins_prefix}/job/tvm/job/PR-{pr_number!s}";
-        f"/{build_number!s}/testReport/)."
-    )
-    return text
-
-
-def find_target_url(pr_head: dict[str, Any]):
-    for status in pr_head["statusCheckRollup"]["contexts"]["nodes"]:
-        if status.get("context", "") == "tvm-ci/pr-head":
-            return status["targetUrl"]
-
-    raise RuntimeError(f"Unable to find tvm-ci/pr-head status in {pr_head}")
-
-
-def get_skipped_tests_comment(
-    pr: dict[str, Any],
-    github,
-    s3_prefix: str = "tvm-jenkins-artifacts-prod",
-    jenkins_prefix: str = "ci.tlcpack.ai",
-    pr_test_report_dir: str = "pr-reports",
-    main_test_report_dir: str = "main-reports",
-    common_commit_sha: str | None = None,
-    common_main_build: dict[str, Any] | None = None,
-    additional_tests_to_check_file: str = "required_tests_to_run.json",
-) -> str:
-    pr_head = pr["commits"]["nodes"][0]["commit"]
-    target_url = find_target_url(pr_head)
-    pr_and_build = get_pr_and_build_numbers(target_url)
-    logging.info(f"Getting comment for {pr_head} with target {target_url}")
-
-    commit_sha = pr_head["oid"]
-
-    is_dry_run = common_commit_sha is not None
-
-    if not is_dry_run:
-        logging.info("Fetching common commit sha and build info")
-        common_commit_sha = get_common_commit_sha()
-        common_main_build = get_main_jenkins_build_number(github, 
common_commit_sha)
-
-        retrieve_test_reports(
-            common_main_build=common_main_build["build_number"],
-            pr_number=pr_and_build["pr_number"],
-            build_number=pr_and_build["build_number"],
-            s3_prefix=s3_prefix,
-            main_test_report_dir=main_test_report_dir,
-            pr_test_report_dir=pr_test_report_dir,
-        )
-    else:
-        logging.info("Dry run, expecting PR and main reports on disk")
-
-    main_tests = build_test_set(main_test_report_dir)
-    build_tests = build_test_set(pr_test_report_dir)
-
-    skipped_list = []
-    for subdir, skipped_set in build_tests.items():
-        skipped_main = main_tests[subdir]
-        if skipped_main is None:
-            logging.warning(f"Could not find directory {subdir} in main.")
-            continue
-
-        diff_set = skipped_set - skipped_main
-        if len(diff_set) != 0:
-            for test in diff_set:
-                skipped_list.append(f"{to_node_name(subdir)} -> {test}")
-
-    # Sort the list to maintain an order in the output. Helps when validating 
the output in tests.
-    skipped_list.sort()
-
-    if len(skipped_list) == 0:
-        logging.info("No skipped tests found.")
-
-    if not is_dry_run:
-        current_file = Path(__file__).resolve()
-        additional_tests_to_check_file = Path(current_file).parent / 
"required_tests_to_run.json"
-
-    logging.info(
-        f"Checking additional tests in file {additional_tests_to_check_file} 
are not skipped."
-    )
-    try:
-        with open(additional_tests_to_check_file) as f:
-            additional_tests_to_check = json.load(f)
-    except OSError:
-        logging.info(
-            f"Failed to read additional tests from file: 
{additional_tests_to_check_file}."
-        )
-        additional_tests_to_check = {}
-
-    # Assert that tests present in "required_tests_to_run.json" are not 
skipped.
-    additional_skipped_tests = []
-    for subdir, test_set in additional_tests_to_check.items():
-        if subdir not in build_tests.keys():
-            logging.warning(f"Could not find directory {subdir} in the build 
test set.")
-            continue
-
-        for test in test_set:
-            if test in build_tests[subdir]:
-                additional_skipped_tests.append(f"{to_node_name(subdir)} -> 
{test}")
-
-    if len(additional_skipped_tests) == 0:
-        logging.info("No skipped tests found in the additional list.")
-
-    body = build_comment(
-        common_commit_sha,
-        common_main_build,
-        skipped_list,
-        additional_skipped_tests,
-        pr_and_build["pr_number"],
-        pr_and_build["build_number"],
-        commit_sha,
-        jenkins_prefix,
-    )
-
-    return body
diff --git a/ci/scripts/jenkins/pytest_ids.py b/ci/scripts/jenkins/pytest_ids.py
deleted file mode 100755
index 548069e855..0000000000
--- a/ci/scripts/jenkins/pytest_ids.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-import argparse
-import io
-from contextlib import redirect_stdout
-
-import pytest
-
-
-class NodeidsCollector:
-    def pytest_collection_modifyitems(self, items):
-        self.nodeids = [item.nodeid for item in items]
-
-
-def main(folder):
-    collector = NodeidsCollector()
-    f = io.StringIO()
-    with redirect_stdout(f):
-        pytest.main(["-qq", "--collect-only", folder], plugins=[collector])
-    for nodeid in collector.nodeids:
-        print(nodeid)
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser(description="List pytest nodeids for a 
folder")
-    parser.add_argument("--folder", required=True, help="test folder to 
inspect")
-    args = parser.parse_args()
-    main(args.folder)
diff --git a/ci/scripts/jenkins/pytest_wrapper.py 
b/ci/scripts/jenkins/pytest_wrapper.py
deleted file mode 100755
index a667810293..0000000000
--- a/ci/scripts/jenkins/pytest_wrapper.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python3
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# ruff: noqa: E501
-import argparse
-import logging
-import os
-import textwrap
-import urllib.parse
-from pathlib import Path
-
-import junitparser
-from cmd_utils import init_log
-
-REPO_ROOT = Path(__file__).resolve().parent.parent.parent.parent
-
-
-def lstrip(s: str, prefix: str) -> str:
-    if s.startswith(prefix):
-        s = s[len(prefix) :]
-    return s
-
-
-def classname_to_file(classname: str) -> str:
-    classname = lstrip(classname, "cython.")
-    classname = lstrip(classname, "ctypes.")
-    return classname.replace(".", "/") + ".py"
-
-
-def failed_test_ids() -> list[str]:
-    FAILURE_TYPES = (junitparser.Failure, junitparser.Error)
-    junit_dir = REPO_ROOT / "build" / "pytest-results"
-    failed_node_ids = []
-    for junit in junit_dir.glob("*.xml"):
-        xml = junitparser.JUnitXml.fromfile(str(junit))
-        for suite in xml:
-            # handle suites
-            for case in suite:
-                if case.result is None:
-                    logging.warn(f"Incorrectly formatted JUnit found, result 
was None on {case}")
-                    continue
-
-                if len(case.result) > 0 and isinstance(case.result[0], 
FAILURE_TYPES):
-                    node_id = classname_to_file(case.classname) + "::" + 
case.name
-                    failed_node_ids.append(node_id)
-
-    return list(set(failed_node_ids))
-
-
-def repro_command(build_type: str, failed_node_ids: list[str]) -> str | None:
-    """
-    Parse available JUnit XML files and output a command that users can run to
-    reproduce CI failures locally
-    """
-    test_args = [f"--tests {node_id}" for node_id in failed_node_ids]
-    test_args_str = " ".join(test_args)
-    return f"python3 tests/scripts/ci.py {build_type} {test_args_str}"
-
-
-def make_issue_url(failed_node_ids: list[str]) -> str:
-    names = [f"`{node_id}`" for node_id in failed_node_ids]
-    run_url = os.getenv("RUN_DISPLAY_URL", "<insert run URL>")
-    test_bullets = [f"  - `{node_id}`" for node_id in failed_node_ids]
-    params = {
-        "labels": "test: flaky",
-        "title": "[Flaky Test] " + ", ".join(names),
-        "body": textwrap.dedent(
-            """
-            These tests were found to be flaky (intermittently failing on 
`main` or failed in a PR with unrelated changes). See [the 
docs](https://github.com/apache/tvm/blob/main/docs/contribute/ci.rst#handling-flaky-failures)
 for details.
-
-            ### Tests(s)\n
-            """
-        )
-        + "\n".join(test_bullets)
-        + f"\n\n### Jenkins Links\n\n  - {run_url}",
-    }
-    return "https://github.com/apache/tvm/issues/new?"; + 
urllib.parse.urlencode(params)
-
-
-def show_failure_help(failed_suites: list[str]) -> None:
-    failed_node_ids = failed_test_ids()
-
-    if len(failed_node_ids) == 0:
-        return
-
-    build_type = os.getenv("PLATFORM")
-
-    if build_type is None:
-        raise RuntimeError("build type was None, cannot show command")
-
-    repro = repro_command(build_type=build_type, 
failed_node_ids=failed_node_ids)
-    if repro is None:
-        print("No test failures detected")
-        return
-
-    print(f"Report flaky test shortcut: {make_issue_url(failed_node_ids)}")
-    print("=============================== PYTEST FAILURES 
================================")
-    print(
-        "These pytest suites failed to execute. The results can be found in 
the "
-        "Jenkins 'Tests' tab or by scrolling up through the raw logs here. "
-        "If there is no test listed below, the failure likely came from a 
segmentation "
-        "fault which you can find in the logs above.\n"
-    )
-    if failed_suites is not None and len(failed_suites) > 0:
-        print("\n".join([f"    - {suite}" for suite in failed_suites]))
-        print("")
-
-    print("You can reproduce these specific failures locally with this 
command:\n")
-    print(textwrap.indent(repro, prefix="    "))
-    print("")
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser(description="Print information about a 
failed pytest run")
-    args, other = parser.parse_known_args()
-    init_log()
-
-    try:
-        show_failure_help(failed_suites=other)
-    except Exception as e:
-        # This script shouldn't ever introduce failures since it's just there 
to
-        # add extra information, so ignore any errors
-        logging.exception(e)
diff --git a/conftest.py b/conftest.py
index dd32937620..dd294ea548 100644
--- a/conftest.py
+++ b/conftest.py
@@ -14,8 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-# ruff: noqa: E501
-import hashlib
 import os
 import sys
 from pathlib import Path
@@ -25,58 +23,6 @@ IS_IN_CI = os.getenv("CI", "") == "true"
 REPO_ROOT = Path(__file__).resolve().parent
 
 
-# These are long running tests (manually curated and extracted from CI logs)
-# that should be allocated to test shards in a round-robin fashion. These are
-# taken from the 20 (arbitrary number) of tests as from
-# https://ci.tlcpack.ai/job/tvm/job/main/2907/testReport
-_slowest_tests = []
-HARDCODED_ALLOCATIONS = {}
-for idx, test in enumerate(_slowest_tests):
-    HARDCODED_ALLOCATIONS[test] = idx
-
-# These rely on running on the same node to pass successfully
-FIXED_ALLOCATION_PREFIXES = {
-    "tests/python/testing/test_tvm_testing_features.py": 0,
-}
-
-
-def find_shard_index(nodeid: str, num_shards: int) -> int:
-    """
-    Return the index of the shard that should run this test
-    """
-    for prefix, target_shard_idx in FIXED_ALLOCATION_PREFIXES.items():
-        if nodeid.startswith(prefix):
-            if target_shard_idx >= num_shards:
-                raise RuntimeError(
-                    f"Cannot collect sharded tests, {nodeid} has hardcoded 
shard index {target_shard_idx} among only {num_shards} shards"
-                )
-            return target_shard_idx
-
-    if nodeid in HARDCODED_ALLOCATIONS:
-        hash = HARDCODED_ALLOCATIONS[nodeid]
-    else:
-        hash = hashlib.md5(nodeid.encode())
-        hash = int(hash.hexdigest(), 16)
-
-    return hash % num_shards
-
-
-def pytest_collection_modifyitems(config, items):
-    if not all(k in os.environ for k in ["CI", "TVM_NUM_SHARDS", 
"TVM_SHARD_INDEX"]):
-        # Only apportion tests if in CI and in a job that is set up for it
-        return
-
-    num_shards = int(os.environ["TVM_NUM_SHARDS"])
-    shard_index = int(os.environ["TVM_SHARD_INDEX"])
-
-    print(f"Marking tests for shard {shard_index} of {num_shards}")
-    items_copy = list(items)
-    for item in items_copy:
-        item_shard_index = find_shard_index(item.nodeid, num_shards=num_shards)
-        if item_shard_index != shard_index:
-            items.remove(item)
-
-
 def pytest_sessionstart():
     if IS_IN_CI:
         hook_script_dir = REPO_ROOT / "tests" / "scripts" / "request_hook"
diff --git a/docker/install/ubuntu_install_python_package.sh 
b/docker/install/ubuntu_install_python_package.sh
index d07f19ed3c..4445dfd83e 100755
--- a/docker/install/ubuntu_install_python_package.sh
+++ b/docker/install/ubuntu_install_python_package.sh
@@ -32,13 +32,11 @@ uv pip install --upgrade \
     Pillow==12.1.1 \
     "psutil~=7.0" \
     "pytest~=8.3" \
-    "pytest-profiling~=1.8" \
     "pytest-xdist~=3.6" \
     pytest-rerunfailures==16.1 \
     "requests~=2.32" \
     "scipy~=1.13" \
     "Jinja2~=3.1" \
-    junitparser==4.0.2 \
     "six~=1.17" \
     "tornado~=6.4" \
     "ml_dtypes~=0.5" \
diff --git a/docs/contribute/pull_request.rst b/docs/contribute/pull_request.rst
index 8ee4f2c65a..c645ce2e4d 100644
--- a/docs/contribute/pull_request.rst
+++ b/docs/contribute/pull_request.rst
@@ -242,7 +242,7 @@ Necessary dependencies:
 
 .. code:: bash
 
-  pip install --user pytest Cython
+  pip install --user pytest pytest-xdist Cython
 
 If you want to run all tests:
 
diff --git a/python/tvm/testing/plugin.py b/python/tvm/testing/plugin.py
index dfb858f1b8..2869664842 100644
--- a/python/tvm/testing/plugin.py
+++ b/python/tvm/testing/plugin.py
@@ -33,7 +33,6 @@ directory as the test scripts.
 """
 
 import _pytest
-import pytest
 
 
 def pytest_collection_modifyitems(config, items):
@@ -44,14 +43,6 @@ def pytest_collection_modifyitems(config, items):
     _sort_tests(items)
 
 
-def pytest_sessionfinish(session, exitstatus):
-    # Don't exit with an error if we select a subset of tests that doesn't
-    # include anything
-    if session.config.option.markexpr != "":
-        if exitstatus == pytest.ExitCode.NO_TESTS_COLLECTED:
-            session.exitstatus = pytest.ExitCode.OK
-
-
 def _count_num_fixture_uses(items):
     # Helper function, counts the number of tests that use each cached
     # fixture.  Should be called from pytest_collection_modifyitems().
diff --git a/tests/python/ci/test_ci.py b/tests/python/ci/test_ci.py
index bfd4b32491..e152d8cb41 100644
--- a/tests/python/ci/test_ci.py
+++ b/tests/python/ci/test_ci.py
@@ -18,8 +18,6 @@
 """Test various CI scripts and GitHub Actions workflows"""
 
 import json
-import logging
-import shutil
 import subprocess
 import sys
 import textwrap
@@ -50,277 +48,6 @@ def parameterize_named(**kwargs):
     )
 
 
-# pylint: disable=line-too-long
-TEST_DATA_SKIPPED_BOT = {
-    "found-diff-no-additional": {
-        "main_xml_file": "unittest/file1.xml",
-        "main_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "pr_xml_file": "unittest/file2.xml",
-        "pr_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                            <skipped message="This test is skipped" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                        <testcase 
classname="ctypes.tests.python.unittest.test_roofline"
-                                  name="test_estimate_peak_bandwidth[cuda]" 
time="4.679">
-                            <skipped message="This is another skippe test" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "additional_tests_to_check": """{
-                    "unittest": ["dummy_class#dummy_test"],
-                    "unittest_GPU": ["another_dummy_class#another_dummy_test"]
-                }
-                """,
-        "target_url": 
"https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/display/redirect";,
-        "s3_prefix": "tvm-jenkins-artifacts-prod",
-        "jenkins_prefix": "ci.tlcpack.ai",
-        "common_main_build": """{"build_number": "4115", "state": 
"success"}""",
-        "commit_sha": "sha1234",
-        "expected_body": "The list below shows tests that ran in main sha1234 
but were skipped in the CI build of sha1234:\n```\nunittest -> 
ctypes.tests.python.unittest.test_auto_scheduler_search_policy#test_sketch_search_policy_cuda_rpc_runner\nunittest
 -> 
ctypes.tests.python.unittest.test_roofline#test_estimate_peak_bandwidth[cuda]\n```\nA
 detailed report of ran tests is 
[here](https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/testReport/).",
-    },
-    "found-diff-skipped-additional": {
-        "main_xml_file": "unittest/file1.xml",
-        "main_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "pr_xml_file": "unittest/file2.xml",
-        "pr_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                            <skipped message="This test is skipped" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                        <testcase 
classname="ctypes.tests.python.unittest.test_roofline"
-                                  name="test_estimate_peak_bandwidth[cuda]" 
time="4.679">
-                            <skipped message="This is another skippe test" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "additional_tests_to_check": """{
-                    "unittest": 
["ctypes.tests.python.unittest.test_auto_scheduler_search_policy#test_sketch_search_policy_cuda_rpc_runner",
 "dummy_class#dummy_test"],
-                    "unittest_GPU": ["another_dummy_class#another_dummy_test"]
-                }
-                """,
-        "target_url": 
"https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/display/redirect";,
-        "s3_prefix": "tvm-jenkins-artifacts-prod",
-        "jenkins_prefix": "ci.tlcpack.ai",
-        "common_main_build": """{"build_number": "4115", "state": 
"success"}""",
-        "commit_sha": "sha1234",
-        "expected_body": "The list below shows tests that ran in main sha1234 
but were skipped in the CI build of sha1234:\n```\nunittest -> 
ctypes.tests.python.unittest.test_auto_scheduler_search_policy#test_sketch_search_policy_cuda_rpc_runner\nunittest
 -> 
ctypes.tests.python.unittest.test_roofline#test_estimate_peak_bandwidth[cuda]\n```\n\nAdditional
 tests that were skipped in the CI build and present in the 
[`required_tests_to_run`](https://github.com/apache/tvm/blob/main/ci/scripts/ 
[...]
-    },
-    "no-diff": {
-        "main_xml_file": "unittest/file1.xml",
-        "main_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                            <skipped message="This test is skipped" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "pr_xml_file": "unittest/file2.xml",
-        "pr_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                            <skipped message="This test is skipped" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "additional_tests_to_check": """{
-                }
-                """,
-        "target_url": 
"https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/display/redirect";,
-        "s3_prefix": "tvm-jenkins-artifacts-prod",
-        "jenkins_prefix": "ci.tlcpack.ai",
-        "common_main_build": """{"build_number": "4115", "state": 
"success"}""",
-        "commit_sha": "sha1234",
-        "expected_body": "No diff in skipped tests with main found in this 
branch for commit sha1234.\nA detailed report of ran tests is 
[here](https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/testReport/).",
-    },
-    "no-diff-skipped-additional": {
-        "main_xml_file": "unittest/file1.xml",
-        "main_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                            <skipped message="This test is skipped" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "pr_xml_file": "unittest/file2.xml",
-        "pr_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                <testsuites>
-                    <testsuite errors="0" failures="0" hostname="13e7c5f749d8" 
name="python-unittest-gpu-0-shard-1-ctypes" skipped="102"
-                               tests="165" time="79.312" 
timestamp="2022-08-10T22:39:36.673781">
-                        <testcase 
classname="ctypes.tests.python.unittest.test_auto_scheduler_search_policy"
-                                  
name="test_sketch_search_policy_cuda_rpc_runner" time="9.679">
-                            <skipped message="This test is skipped" 
type="pytest.skip">
-                                Skipped
-                            </skipped>
-                        </testcase>
-                    </testsuite>
-                </testsuites>
-                """,
-        "additional_tests_to_check": """{
-                    "unittest": ["dummy_class#dummy_test", 
"ctypes.tests.python.unittest.test_auto_scheduler_search_policy#test_sketch_search_policy_cuda_rpc_runner"],
-                    "unittest_GPU": ["another_dummy_class#another_dummy_test"]
-                }
-                """,
-        "target_url": 
"https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/display/redirect";,
-        "s3_prefix": "tvm-jenkins-artifacts-prod",
-        "jenkins_prefix": "ci.tlcpack.ai",
-        "common_main_build": """{"build_number": "4115", "state": 
"success"}""",
-        "commit_sha": "sha1234",
-        "expected_body": "No diff in skipped tests with main found in this 
branch for commit sha1234.\n\nAdditional tests that were skipped in the CI 
build and present in the 
[`required_tests_to_run`](https://github.com/apache/tvm/blob/main/ci/scripts/github/required_tests_to_run.json)
 file:\n```\nunittest -> 
ctypes.tests.python.unittest.test_auto_scheduler_search_policy#test_sketch_search_policy_cuda_rpc_runner\n```\nA
 detailed report of ran tests is [here](https://ci.tlcpack.ai/job/tvm [...]
-    },
-    "unable-to-run": {
-        "main_xml_file": "unittest/file1.xml",
-        "main_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                    <testsuites>
-                    </testsuites>
-                    """,
-        "pr_xml_file": "unittest/file2.xml",
-        "pr_xml_content": """<?xml version="1.0" encoding="utf-8"?>
-                    <testsuites>
-                    </testsuites>
-                    """,
-        "additional_tests_to_check": """{
-                    "unittest": 
["ctypes.tests.python.unittest.test_auto_scheduler_search_policy#test_sketch_search_policy_cuda_rpc_runner",
 "dummy_class#dummy_test"],
-                    "unittest_GPU": ["another_dummy_class#another_dummy_test"]
-                }
-                """,
-        "target_url": 
"https://ci.tlcpack.ai/job/tvm/job/PR-11594/3/display/redirect";,
-        "s3_prefix": "tvm-jenkins-artifacts-prod",
-        "jenkins_prefix": "ci.tlcpack.ai",
-        "common_main_build": """{"build_number": "4115", "state": "failed"}""",
-        "commit_sha": "sha1234",
-        "expected_body": "Unable to run tests bot because main failed to pass 
CI at sha1234.",
-    },
-}
-# pylint: enable=line-too-long
-
-
[email protected]_if_wheel_test
-@parameterize_named(**TEST_DATA_SKIPPED_BOT)
-# pylint: enable=line-too-long
-def test_skipped_tests_comment(
-    caplog,
-    tmpdir_factory,
-    main_xml_file,
-    main_xml_content,
-    pr_xml_file,
-    pr_xml_content,
-    additional_tests_to_check,
-    target_url,
-    s3_prefix,
-    jenkins_prefix,
-    common_main_build,
-    commit_sha,
-    expected_body,
-):
-    """
-    Test that a comment with a link to the docs is successfully left on PRs
-    """
-
-    def write_xml_file(root_dir, xml_file, xml_content):
-        shutil.rmtree(root_dir, ignore_errors=True)
-        file = root_dir / xml_file
-        file.parent.mkdir(parents=True)
-        with open(file, "w") as f:
-            f.write(textwrap.dedent(xml_content))
-
-    git = TempGit(tmpdir_factory.mktemp("tmp_git_dir"))
-    pr_test_report_dir = Path(git.cwd) / "pr-reports"
-    write_xml_file(pr_test_report_dir, pr_xml_file, pr_xml_content)
-    main_test_report_dir = Path(git.cwd) / "main-reports"
-    write_xml_file(main_test_report_dir, main_xml_file, main_xml_content)
-    with open(Path(git.cwd) / "required_tests_to_run.json", "w") as f:
-        f.write(additional_tests_to_check)
-
-    pr_data = {
-        "commits": {
-            "nodes": [
-                {
-                    "commit": {
-                        "oid": commit_sha,
-                        "statusCheckRollup": {
-                            "contexts": {
-                                "nodes": [
-                                    {
-                                        "context": "tvm-ci/pr-head",
-                                        "targetUrl": target_url,
-                                    }
-                                ]
-                            }
-                        },
-                    }
-                }
-            ]
-        }
-    }
-    with caplog.at_level(logging.INFO):
-        comment = 
scripts.github.github_skipped_tests_comment.get_skipped_tests_comment(
-            pr=pr_data,
-            github=None,
-            s3_prefix=s3_prefix,
-            jenkins_prefix=jenkins_prefix,
-            common_commit_sha=commit_sha,
-            pr_test_report_dir=pr_test_report_dir,
-            main_test_report_dir=main_test_report_dir,
-            common_main_build=json.loads(common_main_build),
-            additional_tests_to_check_file=Path(git.cwd) / 
"required_tests_to_run.json",
-        )
-    assert_in(expected_body, comment)
-    assert_in(f"with target {target_url}", caplog.text)
-
-
 @tvm.testing.skip_if_wheel_test
 @parameterize_named(
     doc_link=dict(
@@ -548,8 +275,7 @@ def test_update_branch(tmpdir_factory, statuses, 
expected_rc, expected_output):
         Thanks for contributing to TVM! Please refer to the contributing 
guidelines https://tvm.apache.org/docs/contribute/ for useful information and 
tips. Please request code reviews from 
[Reviewers](https://github.com/apache/incubator-tvm/blob/master/CONTRIBUTORS.md#reviewers)
 by @-ing them in a comment.
 
         <!--bot-comment-ccs-start-->
-         * the 
cc<!--bot-comment-ccs-end--><!--bot-comment-skipped-tests-start-->
-         * the skipped 
tests<!--bot-comment-skipped-tests-end--><!--bot-comment-docs-start-->
+         * the cc<!--bot-comment-ccs-end--><!--bot-comment-docs-start-->
          * the docs<!--bot-comment-docs-end-->
         """
         ).strip(),
@@ -584,8 +310,7 @@ def test_update_branch(tmpdir_factory, statuses, 
expected_rc, expected_output):
         <!--bot-comment-ccs-start-->
          * the 
cc<!--bot-comment-ccs-end--><!--bot-comment-something-tests-start-->
          * something 
else<!--bot-comment-something-tests-end--><!--bot-comment-docs-start-->
-         * the 
docs<!--bot-comment-docs-end--><!--bot-comment-skipped-tests-start-->
-         * the skipped tests<!--bot-comment-skipped-tests-end-->
+         * the docs<!--bot-comment-docs-end-->
         """
         ).strip(),
     ),
@@ -638,7 +363,6 @@ def test_pr_comment(tmpdir_factory, pr_author, comments, 
expected):
     comments = {
         "ccs": "the cc",
         "docs": "the docs",
-        "skipped-tests": "the skipped tests",
     }
     proc = run_script(
         [
diff --git a/tests/python/s_tir/meta_schedule/test_meta_schedule_cost_model.py 
b/tests/python/s_tir/meta_schedule/test_meta_schedule_cost_model.py
index 1e209cacbc..97c9469ccf 100644
--- a/tests/python/s_tir/meta_schedule/test_meta_schedule_cost_model.py
+++ b/tests/python/s_tir/meta_schedule/test_meta_schedule_cost_model.py
@@ -149,7 +149,7 @@ def _dummy_result(num_samples: int = 4, max_run_sec: int = 
10):
 @requires_xgboost
 def test_meta_schedule_xgb_model():
     extractor = RandomFeatureExtractor()
-    model = XGBModel(extractor=extractor, num_warmup_samples=2)
+    model = XGBModel(extractor=extractor, num_warmup_samples=2, 
num_tuning_cores=1)
     update_sample_count = 10
     predict_sample_count = 100
     model.update(
@@ -162,9 +162,10 @@ def test_meta_schedule_xgb_model():
 
 @requires_xgboost
 def test_meta_schedule_xgb_model_no_feature():
-    model = XGBModel(num_warmup_samples=0)
+    model = XGBModel(num_warmup_samples=0, num_tuning_cores=1)
     tune_ctx = TuneContext(
         FullModule,
+        num_threads=1,
         target={"kind": "llvm", "num-cores": 16},
         space_generator="post-order-apply",
         search_strategy="evolutionary",
@@ -177,7 +178,7 @@ def test_meta_schedule_xgb_model_no_feature():
 @requires_xgboost
 def test_meta_schedule_xgb_model_reload():
     extractor = RandomFeatureExtractor()
-    model = XGBModel(extractor=extractor, num_warmup_samples=10)
+    model = XGBModel(extractor=extractor, num_warmup_samples=10, 
num_tuning_cores=1)
     update_sample_count = 20
     predict_sample_count = 30
     model.update(
@@ -221,7 +222,7 @@ def test_meta_schedule_xgb_model_reload():
 @requires_xgboost
 def test_meta_schedule_xgb_model_reupdate():
     extractor = RandomFeatureExtractor()
-    model = XGBModel(extractor=extractor, num_warmup_samples=2)
+    model = XGBModel(extractor=extractor, num_warmup_samples=2, 
num_tuning_cores=1)
     update_sample_count = 60
     predict_sample_count = 100
     model.update(
@@ -252,7 +253,7 @@ def test_meta_schedule_xgb_model_callback_as_function():
     # pylint: enable=import-outside-toplevel
 
     extractor = RandomFeatureExtractor()
-    model = XGBModel(extractor=extractor, num_warmup_samples=10)
+    model = XGBModel(extractor=extractor, num_warmup_samples=10, 
num_tuning_cores=1)
     update_sample_count = 20
     predict_sample_count = 30
 
diff --git 
a/tests/python/s_tir/meta_schedule/test_meta_schedule_search_strategy.py 
b/tests/python/s_tir/meta_schedule/test_meta_schedule_search_strategy.py
index 002741c6bf..6451a94ec9 100644
--- a/tests/python/s_tir/meta_schedule/test_meta_schedule_search_strategy.py
+++ b/tests/python/s_tir/meta_schedule/test_meta_schedule_search_strategy.py
@@ -103,6 +103,7 @@ def test_meta_schedule_replay_func(
 
     context = ms.TuneContext(
         mod=Matmul,
+        num_threads=1,
         space_generator=ms.space_generator.ScheduleFn(sch_fn=_schedule_matmul, 
postprocs=[]),
         search_strategy=TestClass(),
     )
diff --git 
a/tests/python/s_tir/meta_schedule/test_meta_schedule_task_scheduler.py 
b/tests/python/s_tir/meta_schedule/test_meta_schedule_task_scheduler.py
index 61f5583c2a..6dc351761a 100644
--- a/tests/python/s_tir/meta_schedule/test_meta_schedule_task_scheduler.py
+++ b/tests/python/s_tir/meta_schedule/test_meta_schedule_task_scheduler.py
@@ -157,6 +157,7 @@ def test_meta_schedule_task_scheduler_single():
         [
             ms.TuneContext(
                 MatmulModule,
+                num_threads=1,
                 target=tvm.target.Target("llvm"),
                 space_generator=_schedule_matmul,
                 search_strategy=ms.search_strategy.ReplayTrace(),
@@ -183,6 +184,7 @@ def test_meta_schedule_task_scheduler_multiple():
     tasks = [
         ms.TuneContext(
             MatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -191,6 +193,7 @@ def test_meta_schedule_task_scheduler_multiple():
         ),
         ms.TuneContext(
             MatmulReluModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -199,6 +202,7 @@ def test_meta_schedule_task_scheduler_multiple():
         ),
         ms.TuneContext(
             BatchMatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_batch_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -255,6 +259,7 @@ def 
test_meta_schedule_task_scheduler_override_next_task_id_only():  # pylint: d
     tasks = [
         ms.TuneContext(
             MatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -263,6 +268,7 @@ def 
test_meta_schedule_task_scheduler_override_next_task_id_only():  # pylint: d
         ),
         ms.TuneContext(
             MatmulReluModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -271,6 +277,7 @@ def 
test_meta_schedule_task_scheduler_override_next_task_id_only():  # pylint: d
         ),
         ms.TuneContext(
             BatchMatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_batch_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -310,6 +317,7 @@ def 
test_meta_schedule_task_scheduler_multiple_gradient_based():
     tasks = [
         ms.TuneContext(
             MatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -318,6 +326,7 @@ def 
test_meta_schedule_task_scheduler_multiple_gradient_based():
         ),
         ms.TuneContext(
             MatmulReluModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -326,6 +335,7 @@ def 
test_meta_schedule_task_scheduler_multiple_gradient_based():
         ),
         ms.TuneContext(
             BatchMatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_batch_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
@@ -394,6 +404,7 @@ def 
test_meta_schedule_task_scheduler_gradient_based_with_null_search_strategy()
     tasks = [
         ms.TuneContext(
             MatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=NullSearchStrategy(rounds_with_empty_candidates=5),
@@ -402,6 +413,7 @@ def 
test_meta_schedule_task_scheduler_gradient_based_with_null_search_strategy()
         ),
         ms.TuneContext(
             BatchMatmulModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_batch_matmul,
             search_strategy=NullSearchStrategy(rounds_with_empty_candidates=0),
@@ -410,6 +422,7 @@ def 
test_meta_schedule_task_scheduler_gradient_based_with_null_search_strategy()
         ),
         ms.TuneContext(
             MatmulReluModule,
+            num_threads=1,
             target=tvm.target.Target("llvm"),
             space_generator=_schedule_matmul,
             search_strategy=ms.search_strategy.ReplayTrace(),
diff --git a/tests/python/testing/test_tvm_testing_features.py 
b/tests/python/testing/test_tvm_testing_features.py
index 549aedda6a..2f4c798947 100644
--- a/tests/python/testing/test_tvm_testing_features.py
+++ b/tests/python/testing/test_tvm_testing_features.py
@@ -14,10 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-# ruff: noqa: F401, RUF012
+# ruff: noqa: RUF012
 
 import os
-import sys
 
 import pytest
 
diff --git a/tests/scripts/setup-pytest-env.sh 
b/tests/scripts/setup-pytest-env.sh
deleted file mode 100755
index 171ddbc2d0..0000000000
--- a/tests/scripts/setup-pytest-env.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# NOTE: allow unbound variable here
-set +u
-
-if [[ ! -z $CI_PYTEST_ADD_OPTIONS ]]; then
-    export PYTEST_ADDOPTS="-s -vv $CI_PYTEST_ADD_OPTIONS $PYTEST_ADDOPTS"
-else
-    export PYTEST_ADDOPTS="-s -vv $PYTEST_ADDOPTS"
-fi
-set -ux
-
-export TVM_PATH=`pwd`
-export PYTHONPATH="${TVM_PATH}/python"
-
-export TVM_PYTEST_RESULT_DIR="${TVM_PATH}/build/pytest-results"
-mkdir -p "${TVM_PYTEST_RESULT_DIR}"
-pytest_errors=()
-
-# This ensures that all pytest invocations that are run through run_pytest will
-# complete and errors will be reported once Bash is done executing all scripts.
-function cleanup() {
-    set +x
-    if [ "${#pytest_errors[@]}" -gt 0 ]; then
-        echo "These pytest invocations failed, the results can be found in the 
Jenkins 'Tests' tab or by scrolling up through the raw logs here."
-        python3 ci/scripts/jenkins/pytest_wrapper.py "${pytest_errors[@]}"
-        exit 1
-    fi
-    set -x
-}
-trap cleanup 0
-
-function run_pytest() {
-    ffi_type="cython"
-    set -e
-    local test_suite_name="$1"
-    shift
-    extra_args=( "$@" )
-    if [ -z "${ffi_type}" -o -z "${test_suite_name}" ]; then
-        echo "error: run_pytest called incorrectly: run_pytest 
${test_suite_name}" "${extra_args[@]}"
-        echo "usage: run_pytest <TEST_SUITE_NAME> [pytest args...]"
-        exit 2
-    fi
-
-    # Allow unbound variable here.
-    set +u
-    if [[ -z "${TVM_SHARD_INDEX}" ]]; then
-      current_shard="no-shard"
-    else
-      current_shard="shard-${TVM_SHARD_INDEX}"
-    fi
-    set -u
-
-    has_reruns=$(python3 -m pytest --help 2>&1 | grep 'reruns=' || true)
-    if [ -n "$has_reruns" ]; then
-        if [[ ! "${extra_args[*]}" == *"--reruns"* ]]; then
-          extra_args+=('--reruns=3')
-        fi
-    fi
-
-    suite_name="${test_suite_name}-${current_shard}-${ffi_type}"
-
-    DEFAULT_PARALLELISM=1
-
-    if [[ ! "${extra_args[*]}" == *" -n"* ]] && [[ ! "${extra_args[*]}" == *" 
-dist"* ]]; then
-        extra_args+=("-n=$DEFAULT_PARALLELISM")
-    fi
-
-    exit_code=0
-    set +e
-    python3 -m pytest \
-           -o "junit_suite_name=${suite_name}" \
-           "--junit-xml=${TVM_PYTEST_RESULT_DIR}/${suite_name}.xml" \
-           "--junit-prefix=${ffi_type}" \
-           "${extra_args[@]}" || exit_code=$?
-    # Pytest will return error code -5 if no test is collected.
-    if [ "$exit_code" -ne "0" ] && [ "$exit_code" -ne "5" ]; then
-        pytest_errors+=("${suite_name}: $@")
-    fi
-    # To avoid overwriting.
-    set -e
-}
diff --git a/tests/scripts/task_clear_pytest.sh 
b/tests/scripts/task_clear_pytest.sh
deleted file mode 100755
index 0a24f62531..0000000000
--- a/tests/scripts/task_clear_pytest.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euxo pipefail
-
-# Ensure no stale pytest-results remain from a previous test run.
-pushd build
-rm -rf pytest-results
-popd
diff --git a/tests/scripts/task_python_docs.sh 
b/tests/scripts/task_python_docs.sh
index 7c3122cd92..11b2501b7b 100755
--- a/tests/scripts/task_python_docs.sh
+++ b/tests/scripts/task_python_docs.sh
@@ -18,7 +18,7 @@
 
 set -euxo pipefail
 
-source tests/scripts/setup-pytest-env.sh
+export PYTHONPATH="$(pwd)/python"
 
 # to avoid CI CPU thread throttling.
 export TVM_BIND_THREADS=0
diff --git a/tests/scripts/task_python_integration.sh 
b/tests/scripts/task_python_integration.sh
index dcd7b8ff47..c7cf1f4329 100755
--- a/tests/scripts/task_python_integration.sh
+++ b/tests/scripts/task_python_integration.sh
@@ -18,7 +18,7 @@
 
 set -euxo pipefail
 
-source tests/scripts/setup-pytest-env.sh
+export PYTHONPATH="$(pwd)/python"
 export LD_LIBRARY_PATH="build:${LD_LIBRARY_PATH:-}"
 
 # to avoid CI CPU thread throttling.
diff --git a/tests/scripts/task_python_nightly.sh 
b/tests/scripts/task_python_nightly.sh
deleted file mode 100755
index b480563a8c..0000000000
--- a/tests/scripts/task_python_nightly.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euxo pipefail
-
-source tests/scripts/setup-pytest-env.sh
-
-# setup tvm-ffi into python folder
-uv pip install -v --target=python ./3rdparty/tvm-ffi/
-
-# cleanup pycache
-find . -type f -path "*.pyc" | xargs rm -f
-
-run_pytest python-topi-nightly tests/python/topi/nightly
-
-# Tensorflow device verification and network tests on nightly
-export CI_ENV_NIGHTLY
-python3 tests/python/relax/test_frontend_tflite.py
diff --git a/tests/scripts/task_python_unittest.sh 
b/tests/scripts/task_python_unittest.sh
index 7e09926cc0..c05f8503d3 100755
--- a/tests/scripts/task_python_unittest.sh
+++ b/tests/scripts/task_python_unittest.sh
@@ -18,7 +18,8 @@
 
 set -euxo pipefail
 
-source tests/scripts/setup-pytest-env.sh
+export PYTHONPATH="$(pwd)/python"
+export PYTEST_ADDOPTS="-s -vv ${CI_PYTEST_ADD_OPTIONS:-} ${PYTEST_ADDOPTS:-}"
 
 # cleanup pycache
 find . -type f -path "*.pyc" | xargs rm -f
@@ -26,23 +27,20 @@ find . -type f -path "*.pyc" | xargs rm -f
 # setup tvm-ffi into python folder
 uv pip install -v --target=python ./3rdparty/tvm-ffi/
 
-# NOTE: also set by task_python_unittest_gpuonly.sh.
-if [ -z "${TVM_UNITTEST_TESTSUITE_NAME:-}" ]; then
-    TVM_UNITTEST_TESTSUITE_NAME=python-unittest
+# First run the minimal platform test.  A GPU-only run can select no tests 
here.
+if [ ! -d tests/python/all-platform-minimal-test ]; then
+    echo "Missing pytest target: tests/python/all-platform-minimal-test" >&2
+    exit 1
 fi
+python3 -m pytest -n auto tests/python/all-platform-minimal-test || [ "$?" -eq 
5 ]
 
-# First run minimal test on both ctypes and cython.
-run_pytest ${TVM_UNITTEST_TESTSUITE_NAME}-platform-minimal-test 
tests/python/all-platform-minimal-test
-
-# Then run all unittests on both ctypes and cython.
+# Then run all unit tests.
 TEST_FILES=(
-  "ffi"
   "arith"
   "ci"
   "codegen"
   "driver"
   "ir"
-  "meta_schedule"
   "runtime"
   "target"
   "te"
@@ -51,6 +49,7 @@ TEST_FILES=(
   "s_tir/schedule"
   "s_tir/dlight"
   "s_tir/analysis"
+  "s_tir/meta_schedule"
   "s_tir/transform"
   "tirx-analysis"
   "tirx-base"
@@ -62,7 +61,13 @@ TEST_FILES=(
 
 PYTEST_TARGETS=()
 for TEST_FILE in "${TEST_FILES[@]}"; do
-    PYTEST_TARGETS+=("tests/python/${TEST_FILE}")
+    TEST_PATH="tests/python/${TEST_FILE}"
+    if [ ! -d "${TEST_PATH}" ]; then
+        echo "Missing pytest target: ${TEST_PATH}" >&2
+        exit 1
+    fi
+    PYTEST_TARGETS+=("${TEST_PATH}")
 done
 
-run_pytest "${TVM_UNITTEST_TESTSUITE_NAME}" "${PYTEST_TARGETS[@]}"
+# Do not mask pytest's exit 5: an unexpectedly empty broad suite must fail CI.
+python3 -m pytest -n auto --dist=loadgroup "${PYTEST_TARGETS[@]}"
diff --git a/tests/scripts/task_python_unittest_gpuonly.sh 
b/tests/scripts/task_python_unittest_gpuonly.sh
index be3ea07947..8194b23ac4 100755
--- a/tests/scripts/task_python_unittest_gpuonly.sh
+++ b/tests/scripts/task_python_unittest_gpuonly.sh
@@ -24,15 +24,18 @@ export PYTEST_ADDOPTS="-m gpu ${PYTEST_ADDOPTS:-}"
 # Test most of the enabled runtimes here.
 # TODO: disabled opencl tests due to segmentation fault.
 export TVM_TEST_TARGETS='cuda;metal;rocm;nvptx'
-export TVM_UNITTEST_TESTSUITE_NAME=python-unittest-gpu
 
 ./tests/scripts/task_python_unittest.sh
 
 # Kept separate to avoid increasing time needed to run CI, testing
 # only minimal functionality of Vulkan runtime.
 export TVM_TEST_TARGETS='{"kind":"vulkan","from_device":0}'
-export TVM_UNITTEST_TESTSUITE_NAME=python-codegen-vulkan
 
-source tests/scripts/setup-pytest-env.sh
+export PYTHONPATH="$(pwd)/python"
+export PYTEST_ADDOPTS="-s -vv ${CI_PYTEST_ADD_OPTIONS:-} ${PYTEST_ADDOPTS:-}"
 
-run_pytest ${TVM_UNITTEST_TESTSUITE_NAME}-1 
tests/python/codegen/test_target_codegen_vulkan.py
+if [ ! -f tests/python/codegen/test_target_codegen_vulkan.py ]; then
+    echo "Missing pytest target: 
tests/python/codegen/test_target_codegen_vulkan.py" >&2
+    exit 1
+fi
+python3 -m pytest -n auto tests/python/codegen/test_target_codegen_vulkan.py

Reply via email to