class_docstr: State transition logic
class_docstr_tok: ["State","transition","logic"]
code: def _trigger_bisect(self) -> None:
      if self._bisect_rate_limit_exceeded():
          logger.info(
              f"Skip bisect {self.test.get_name()} due to rate limit"
          )
          return
      build = self.ray_buildkite.builds().create_build(
          BUILDKITE_ORGANIZATION,
          BUILDKITE_BISECT_PIPELINE,
          "HEAD",
          "master",
          message=f"[ray-test-bot] {self.test.get_name()} failing",
          env={
              "UPDATE_TEST_STATE_MACHINE": "1",
          },
      )
      failing_commit = self.test_results[0].commit
      passing_commits = [
          r.commit for r in self.test_results if r.is_passing()
      ]
      if not passing_commits:
          logger.info(
              f"Skip bisect {self.test.get_name()} due to no passing commit"
          )
          return
      passing_commit = passing_commits[0]
      self.ray_buildkite.jobs().unblock_job(
          BUILDKITE_ORGANIZATION,
          BUILDKITE_BISECT_PIPELINE,
          build["number"],
          build["jobs"][0]["id"],  # first job is the blocked job
          fields={
              "test-name": self.test.get_name(),
              "passing-commit": passing_commit,
              "failing-commit": failing_commit,
              "concurrency": "3",
              "run-per-commit": "1",
          },
      )
      self.test[Test.KEY_BISECT_BUILD_NUMBER] = build["number"]
  
file_path: ray/release/ray_release/test_automation/release_state_machine.py
imports: from datetime import datetime, timedelta
  from ray_release.test_automation.state_machine import TestStateMachine, DEFAULT_ISSUE_OWNER
  from ray_release.test import Test, TestState
  from ray_release.logger import logger
label_desc: Use image node_id 10 for calling the ReleaseTestStateMachine obj's underlying member method code with example usage: obj._trigger_bisect() without return types