Skip to content

Commit

Permalink
Detect nightly triggers without an open PR better
Browse files Browse the repository at this point in the history
For direct triggered tests using `./tests-trigger` issues where being
created for failing tests. Before 14b13cb an status event
would trigger tests-scan and look up the pull request for the given sha,
given the introduction of the `elif sha` condition it would now omit the
`--pull-number` creating an issue when the test failed.

As we only want this functionality for the nightly scenario triggered on
main, introduce a check if an open pull request exists.
  • Loading branch information
jelly authored and martinpitt committed Sep 1, 2023
1 parent a4fda94 commit 09c8fe4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
6 changes: 6 additions & 0 deletions task/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,12 @@ def issues(self, labels=["bot"], state="open", since=None):
result = result + issues
return result

def has_open_prs(self, sha):
pulls = self.get(f"commits/{sha}/pulls")
if pulls:
return any((pull['state'] == 'open' for pull in pulls))
return True

def getHead(self, pr):
pull = self.get("pulls/{0}".format(pr))
if pull:
Expand Down
54 changes: 52 additions & 2 deletions task/test-tests-scan
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ GITHUB_DATA = {
"statuses": [],
"sha": "abcdef",
},
"/users/user/repos": [{"full_name": "project/repo"}]
"/users/user/repos": [{"full_name": "project/repo"}],
}


Expand All @@ -70,8 +70,12 @@ class Handler(MockHandler):
self.replyJson([])
elif self.path.startswith('/repos/project/repo/pulls'):
self.replyJson([self.server.data['/repos/project/repo/pulls/1']])
elif self.path == "/repos/cockpit-project/cockpit/commits/abcdef/pulls":
self.replyJson([{"state": "closed"}])
elif self.path == "/repos/cockpit-project/cockpit/commits/abcdef2/pulls":
self.replyJson([{"state": "open"}])
elif self.path.endswith("/issues"):
issues = self.server.data['issues']
issues = self.server.data.get('issues', [])
self.replyJson(issues)
else:
self.send_error(404, 'Mock Not Found: ' + self.path)
Expand Down Expand Up @@ -241,6 +245,52 @@ class TestTestsScan(unittest.TestCase):
self.assertEqual(issues[0]['labels'], ["nightly"])
self.assertIsNone(stderr)

def disabled_test_tests_invoke_no_issue(self):
repo = "cockpit-project/cockpit"
revision = "abcdef1"
args = ["--revision", revision, "--repo", repo]
script = os.path.join(BOTS_DIR, "tests-invoke")
with tempfile.TemporaryDirectory() as tempdir:
testdir = f"{tempdir}/.cockpit-ci"
os.makedirs(testdir)
with open(f"{testdir}/run", "w") as fp:
fp.write("#!/bin/bash\nexit 1")
os.system(f"chmod +x {testdir}/run")
proc = subprocess.Popen([script, *args], stdout=subprocess.PIPE, universal_newlines=True,
env={"GITHUB_API": f"http://{ADDRESS[0]}:{ADDRESS[1]}",
"TEST_INVOKE_SLEEP": "1"},
cwd=tempdir)
output, stderr = proc.communicate()
api = github.GitHub(f"http://{ADDRESS[0]}:{ADDRESS[1]}/")
issues = api.get("issues")
self.assertEqual(output, "")
self.assertEqual(proc.returncode, 1)
self.assertEqual(len(issues), 0)
self.assertIsNone(stderr)

def disabled_test_tests_invoke_open_pr(self):
repo = "cockpit-project/cockpit"
revision = "abcdef2"
args = ["--revision", revision, "--repo", repo]
script = os.path.join(BOTS_DIR, "tests-invoke")
with tempfile.TemporaryDirectory() as tempdir:
testdir = f"{tempdir}/.cockpit-ci"
os.makedirs(testdir)
with open(f"{testdir}/run", "w") as fp:
fp.write("#!/bin/bash\nexit 1")
os.system(f"chmod +x {testdir}/run")
proc = subprocess.Popen([script, *args], stdout=subprocess.PIPE, universal_newlines=True,
env={"GITHUB_API": f"http://{ADDRESS[0]}:{ADDRESS[1]}",
"TEST_INVOKE_SLEEP": "1"},
cwd=tempdir)
output, stderr = proc.communicate()
api = github.GitHub(f"http://{ADDRESS[0]}:{ADDRESS[1]}/")
issues = api.get("issues")
self.assertEqual(output, "")
self.assertEqual(proc.returncode, 1)
self.assertEqual(len(issues), 0)
self.assertIsNone(stderr)


if __name__ == '__main__':
unittest.main()
4 changes: 2 additions & 2 deletions tests-invoke
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def main():

# keep track of the most recent pull.updated_at attribute
last_updated_at = "0"
api = github.GitHub(repo=opts.repo)

def detect_collisions(opts):
nonlocal last_updated_at
Expand Down Expand Up @@ -93,8 +94,7 @@ def main():
time.sleep(int(os.getenv("TEST_INVOKE_SLEEP", "60")))
return_code = p.returncode
sys.stderr.write("Test run finished, return code: {0}\n".format(return_code))
if not opts.pull_number and return_code != 0:
api = github.GitHub(repo=opts.repo)
if not api.has_open_prs(opts.revision) and return_code != 0:
data = {
"title": "Nightly tests did not succeed",
"body": f"Tests failed on {opts.revision}",
Expand Down
3 changes: 2 additions & 1 deletion tests-scan
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ def cockpit_tasks(api, update, contexts, repo, pull_data, pull_number, sha, amqp
else:
logging.error("Can't find pull request %s", pull_number)
return 1
elif sha:
elif sha and not api.has_open_prs(sha):
logging.info("Processing revision %s without pull request", sha)
pulls.append({
"title": f"{sha}",
"number": 0,
Expand Down

0 comments on commit 09c8fe4

Please sign in to comment.