chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
# 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
|
||||
"""
|
||||
Test the @tvm-bot merge code
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import tvm
|
||||
|
||||
from .test_utils import GITHUB_SCRIPT_ROOT, TempGit, run_script
|
||||
|
||||
SUCCESS_EXPECTED_OUTPUT = """
|
||||
Dry run, would have merged with url=pulls/10786/merge and data={
|
||||
"commit_title": "[Hexagon] 2-d allocation cleanup (#10786)",
|
||||
"commit_message": "- Added device validity check in allocation. HexagonDeviceAPI should only be called for CPU/Hexagon types.\\n\\n- Check for \\"global.vtcm\\" scope instead of \\"vtcm\\". The ccope of N-d allocations produced by `LowerVtcmAlloc` should be `\\"global.vtcm\\"`. The previous check allowed unsupported scope such as `\\"local.vtcm\\"`.\\n\\n- Remove `vtcmallocs` entry after calling free.\\n\\nPreviously, the vtcm allocation map kept dangling pointers to `HexagonBuffer` objects after they had been freed.\\n\\n- Rename N-d alloc and free packed functions. Since most of the similar device functions use snake case, renaming `*.AllocND` to `*.alloc_nd` and `*.FreeND` to `*.free_nd`.\\n\\n\\ncc someone\\n\\n\\nCo-authored-by: Adam Straw <astraw@octoml.ai>",
|
||||
"sha": "6f04bcf57d07f915a98fd91178f04d9e92a09fcd",
|
||||
"merge_method": "squash"
|
||||
}
|
||||
""".strip()
|
||||
|
||||
|
||||
class _TvmBotTest:
|
||||
NUMBER = 10786
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]):
|
||||
"""
|
||||
Used to pre-process PR data before running the test. Override as
|
||||
necessary to edit data for specific test cases.
|
||||
"""
|
||||
return data
|
||||
|
||||
@tvm.testing.skip_if_wheel_test
|
||||
def test(self, tmpdir_factory):
|
||||
"""
|
||||
Run the tvm-bot script using the data from preprocess_data
|
||||
"""
|
||||
mergebot_script = GITHUB_SCRIPT_ROOT / "github_tvmbot.py"
|
||||
test_json_dir = Path(__file__).resolve().parent / "sample_prs"
|
||||
with open(test_json_dir / f"pr{self.NUMBER}.json") as f:
|
||||
test_data = json.load(f)
|
||||
|
||||
# Update testing data with replacements / additions
|
||||
test_data = self.preprocess_data(test_data)
|
||||
|
||||
git = TempGit(tmpdir_factory.mktemp("tmp_git_dir"))
|
||||
|
||||
comment = {
|
||||
"body": self.COMMENT,
|
||||
"id": 123,
|
||||
"user": {
|
||||
"login": self.USER,
|
||||
},
|
||||
}
|
||||
allowed_users = [{"login": "abc"}, {"login": "other-abc"}]
|
||||
|
||||
proc = run_script(
|
||||
[
|
||||
mergebot_script,
|
||||
"--pr",
|
||||
self.NUMBER,
|
||||
"--dry-run",
|
||||
"--run-url",
|
||||
"https://example.com",
|
||||
"--testing-pr-json",
|
||||
json.dumps(test_data),
|
||||
"--testing-collaborators-json",
|
||||
json.dumps(allowed_users),
|
||||
"--testing-mentionable-users-json",
|
||||
json.dumps(allowed_users),
|
||||
"--trigger-comment-json",
|
||||
json.dumps(comment),
|
||||
],
|
||||
env={
|
||||
"TVM_BOT_JENKINS_TOKEN": "123",
|
||||
"GH_ACTIONS_TOKEN": "123",
|
||||
},
|
||||
cwd=git.cwd,
|
||||
)
|
||||
|
||||
if self.EXPECTED not in proc.stderr:
|
||||
raise RuntimeError(f"{proc.stderr}\ndid not contain\n{self.EXPECTED}")
|
||||
|
||||
|
||||
class TestNoRequest(_TvmBotTest):
|
||||
"""
|
||||
A PR for which the mergebot runs but no merge is requested
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot do something else"
|
||||
USER = "abc"
|
||||
EXPECTED = "Command 'do something else' did not match anything"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]):
|
||||
data["reviews"]["nodes"][0]["body"] = "nothing"
|
||||
return data
|
||||
|
||||
|
||||
class TestSuccessfulMerge(_TvmBotTest):
|
||||
"""
|
||||
Everything is fine so this PR will merge
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = SUCCESS_EXPECTED_OUTPUT
|
||||
|
||||
|
||||
class TestBadCI(_TvmBotTest):
|
||||
"""
|
||||
A PR which failed CI and cannot merge
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Cannot merge, these CI jobs are not successful on"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]):
|
||||
# Mark the Jenkins build as failed
|
||||
contexts = data["commits"]["nodes"][0]["commit"]["statusCheckRollup"]["contexts"]["nodes"]
|
||||
for context in contexts:
|
||||
if "context" in context and context["context"] == "tvm-ci/pr-head":
|
||||
context["state"] = "FAILED"
|
||||
return data
|
||||
|
||||
|
||||
class TestOldReview(_TvmBotTest):
|
||||
"""
|
||||
A PR with passing CI and approving reviews on an old commit so it cannot merge
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Cannot merge, did not find any approving reviews"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
data["reviews"]["nodes"][0]["commit"]["oid"] = "abc12345"
|
||||
return data
|
||||
|
||||
|
||||
class TestMissingJob(_TvmBotTest):
|
||||
"""
|
||||
PR missing an expected CI job and cannot merge
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Cannot merge, missing expected jobs"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
contexts = data["commits"]["nodes"][0]["commit"]["statusCheckRollup"]["contexts"]["nodes"]
|
||||
for context in contexts:
|
||||
if "context" in context and context["context"] == "tvm-ci/pr-head":
|
||||
context["context"] = "something"
|
||||
return data
|
||||
|
||||
|
||||
class TestInvalidAuthor(_TvmBotTest):
|
||||
"""
|
||||
Merge requester is not a committer and cannot merge
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "not-abc"
|
||||
EXPECTED = "Failed auth check 'collaborators', quitting"
|
||||
|
||||
|
||||
class TestUnauthorizedComment(_TvmBotTest):
|
||||
"""
|
||||
Check that a merge comment not from a CONTRIBUTOR is rejected
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "not-abc2"
|
||||
EXPECTED = "Failed auth check 'collaborators'"
|
||||
|
||||
|
||||
class TestNoReview(_TvmBotTest):
|
||||
"""
|
||||
Check that a merge request without any reviews is rejected
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Cannot merge, did not find any approving reviews from users with write access"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
data["reviews"]["nodes"] = []
|
||||
return data
|
||||
|
||||
|
||||
class TestChangesRequested(_TvmBotTest):
|
||||
"""
|
||||
Check that a merge request with a 'Changes Requested' review is rejected
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Cannot merge, found [this review]"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
data["reviews"]["nodes"][0]["state"] = "CHANGES_REQUESTED"
|
||||
data["reviews"]["nodes"][0]["url"] = "http://example.com"
|
||||
return data
|
||||
|
||||
|
||||
class TestCoAuthors(_TvmBotTest):
|
||||
"""
|
||||
Check that a merge request with co-authors generates the correct commit message
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Co-authored-by: Some One <someone@email.com>"
|
||||
|
||||
def preprocess_data(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
data["authorCommits"]["nodes"][0]["commit"]["authors"]["nodes"].append(
|
||||
{"name": "Some One", "email": "someone@email.com"}
|
||||
)
|
||||
return data
|
||||
|
||||
|
||||
class TestRerunCI(_TvmBotTest):
|
||||
"""
|
||||
Start a new CI job
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot rerun"
|
||||
USER = "abc"
|
||||
EXPECTED = "Rerunning ci with"
|
||||
|
||||
|
||||
class TestRerunPermissions(_TvmBotTest):
|
||||
"""
|
||||
Start a new CI job as an unauthorized user
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot rerun"
|
||||
USER = "someone"
|
||||
EXPECTED = "Failed auth check 'mentionable_users', quitting"
|
||||
|
||||
|
||||
class TestRerunNonAuthor(_TvmBotTest):
|
||||
"""
|
||||
Start a new CI job as a mentionable user
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot rerun"
|
||||
USER = "other-abc"
|
||||
EXPECTED = "Passed auth check 'mentionable_users', continuing"
|
||||
|
||||
|
||||
class TestIgnoreJobs(_TvmBotTest):
|
||||
"""
|
||||
Ignore GitHub Actions jobs that don't start with CI /
|
||||
"""
|
||||
|
||||
COMMENT = "@tvm-bot merge"
|
||||
USER = "abc"
|
||||
EXPECTED = "Dry run, would have merged"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
tvm.testing.main()
|
||||
Reference in New Issue
Block a user