diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55fe5f1441cb3..077fbb7ce68a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,12 +36,15 @@ concurrency: jobs: MacOS: - if: ${{ github.repository == 'apache/tvm' }} - runs-on: macOS-latest + if: ${{ github.repository == 'driazati/tvm' }} + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: submodules: 'recursive' + - name: fail + run: | + exit 1 - name: Set up environment uses: ./.github/actions/setup - name: Conda Build diff --git a/.github/workflows/tvmbot.yml b/.github/workflows/tvmbot.yml index 792977f92ee5d..06e4f3b80142c 100644 --- a/.github/workflows/tvmbot.yml +++ b/.github/workflows/tvmbot.yml @@ -1,7 +1,6 @@ name: tvm-bot on: - status: pull_request_review: types: - submitted @@ -21,13 +20,14 @@ jobs: issues: write pull-requests: write statuses: write - if: ${{ github.event.issue.pull_request && github.repository == 'apache/tvm' }} + if: ${{ github.event.issue.pull_request && github.repository == 'driazati/tvm' }} runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Run tvm-bot env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_API_TOKEN: ${{ secrets.GH_API_TOKEN }} TVM_BOT_JENKINS_TOKEN: ${{ secrets.TVM_BOT_JENKINS_TOKEN }} PR_NUMBER: ${{ github.event.issue.number }} ISSUE_COMMENT: ${{ toJson(github.event.comment) }} diff --git a/tests/scripts/git_utils.py b/tests/scripts/git_utils.py index f0d300e2f0b87..2ab68dde03559 100644 --- a/tests/scripts/git_utils.py +++ b/tests/scripts/git_utils.py @@ -89,9 +89,9 @@ def _request(self, full_url: str, body: Dict[str, Any], method: str) -> Dict[str with request.urlopen(req, data) as response: content = response.read() except error.HTTPError as e: - logging.info(f"Error response: {e.read().decode()}") - e.seek(0) - raise e + msg = str(e) + error_data = e.read.decode() + raise RuntimeError(f"Error response: {msg}\n{error_data}") logging.info(f"Got response from {full_url}: {content}") try: diff --git a/tests/scripts/github_tvmbot.py b/tests/scripts/github_tvmbot.py index e83318e18e513..2bdad00b27340 100755 --- a/tests/scripts/github_tvmbot.py +++ b/tests/scripts/github_tvmbot.py @@ -37,6 +37,7 @@ EXPECTED_JOBS = ["tvm-ci/pr-head"] TVM_BOT_JENKINS_TOKEN = os.environ["TVM_BOT_JENKINS_TOKEN"] +GH_API_TOKEN = os.environ["GH_API_TOKEN"] JENKINS_URL = "https://ci.tlcpack.ai/" THANKS_MESSAGE = r"(\s*)Thanks for contributing to TVM! Please refer to guideline https://tvm.apache.org/docs/contribute/ for useful information and tips. After the pull request is submitted, please request code reviews from \[Reviewers\]\(https://github.com/apache/incubator-tvm/blob/master/CONTRIBUTORS.md#reviewers\) by them in the pull request thread.(\s*)" @@ -106,6 +107,7 @@ def to_json_str(obj: Any) -> str: nodes { ... on CheckRun { name + databaseId checkSuite { workflowRun { workflow { @@ -503,6 +505,28 @@ def rerun_jenkins_ci(self) -> None: else: post(url, auth=("tvm-bot", TVM_BOT_JENKINS_TOKEN)) + def rerun_github_actions(self) -> None: + job_ids = [] + for item in self.head_commit()["statusCheckRollup"]["contexts"]["nodes"]: + if "checkSuite" in item: + job_ids.append(item["databaseId"]) + + logging.info(f"Rerunning GitHub Actions jobs with IDs: {job_ids}") + actions_github = GitHubRepo( + user=self.github.user, repo=self.github.repo, token=GH_API_TOKEN + ) + for job_id in job_ids: + try: + actions_github.post(f"actions/jobs/{job_id}/rerun", data={}) + except RuntimeError as e: + # Ignore errors about jobs that are part of the same workflow to avoid + # having to figure out which jobs are in which workflows ahead of time + if "The workflow run containing this job is already running" in str(e): + pass + else: + raise e + + def comment_failure(self, msg: str, exception: Exception): if not self.dry_run: exception_msg = traceback.format_exc() @@ -514,6 +538,40 @@ def comment_failure(self, msg: str, exception: Exception): return exception +def check_author(pr, triggering_comment, args): + comment_author = triggering_comment["user"]["login"] + if pr.author() == comment_author: + logging.info("Comment user is PR author, continuing") + return True + return False + + +def check_collaborator(pr, triggering_comment, args): + logging.info("Checking collaborators") + # Get the list of collaborators for the repo filtered by the comment + # author + if args.testing_collaborators_json: + collaborators = json.loads(args.testing_collaborators_json) + else: + collaborators = pr.search_collaborator(triggering_comment["user"]["login"]) + logging.info(f"Found collaborators: {collaborators}") + + return len(collaborators) > 0 + + +def check_anyone(pr, triggering_comment, args): + return True + + +AUTH_CHECKS = { + "anyone": check_anyone, + "collaborators": check_collaborator, + "author": check_author, +} +# Stash the keys so they're accessible from the values +AUTH_CHECKS = {k: (k, v) for k, v in AUTH_CHECKS.items()} + + class Merge: triggers = [ "merge", @@ -521,6 +579,8 @@ class Merge: "merge this pr", ] + auth = [AUTH_CHECKS["collaborators"], AUTH_CHECKS["author"]] + @staticmethod def run(pr: PR): info = None @@ -548,9 +608,15 @@ class Rerun: "run ci", ] + auth = [AUTH_CHECKS["anyone"]] + @staticmethod def run(pr: PR): - pr.rerun_jenkins_ci() + try: + # pr.rerun_jenkins_ci() + pr.rerun_github_actions() + except Exception as e: + pr.comment_failure("Failed to re-run CI", e) if __name__ == "__main__": @@ -618,24 +684,11 @@ def run(pr: PR): # Acknowledge the comment with a react pr.plus_one(comment) - # Check the comment author - comment_author = comment["user"]["login"] - if pr.author() == comment_author: - logging.info("Comment user is PR author, continuing") - else: - logging.info("Comment is not from PR author, checking collaborators") - # Get the list of collaborators for the repo filtered by the comment - # author - if args.testing_collaborators_json: - collaborators = json.loads(args.testing_collaborators_json) - else: - collaborators = pr.search_collaborator(comment_author) - logging.info(f"Found collaborators: {collaborators}") - - if len(collaborators) > 0: - logging.info("Comment is from collaborator") + for name, check in command_to_run.auth: + if check(pr, comment, args): + logging.info(f"Passed auth check '{name}', continuing") else: - logging.info("Comment is not from from PR author or collaborator, quitting") + logging.info(f"Failed auth check '{name}', quitting") exit(0) state = pr.state()