diff --git a/src/clusterfuzz/_internal/cron/oss_fuzz_build_status.py b/src/clusterfuzz/_internal/cron/oss_fuzz_build_status.py index 887a950b48..38147fdb44 100644 --- a/src/clusterfuzz/_internal/cron/oss_fuzz_build_status.py +++ b/src/clusterfuzz/_internal/cron/oss_fuzz_build_status.py @@ -22,6 +22,7 @@ from clusterfuzz._internal.base import utils from clusterfuzz._internal.datastore import data_types +from clusterfuzz._internal.issue_management import issue_tracker_policy from clusterfuzz._internal.issue_management import issue_tracker_utils from clusterfuzz._internal.metrics import logs @@ -135,7 +136,7 @@ def get_build_time(build): stripped_timestamp.group(0), TIMESTAMP_FORMAT) -def file_bug(issue_tracker, project_name, build_id, ccs, build_type): +def file_bug(issue_tracker, policy, project_name, build_id, ccs, build_type): """File a new bug for a build failure.""" logs.info('Filing bug for new build failure (project=%s, build_type=%s, ' 'build_id=%s).' % (project_name, build_type, build_id)) @@ -144,8 +145,7 @@ def file_bug(issue_tracker, project_name, build_id, ccs, build_type): issue.title = '{project_name}: {build_type} build failure'.format( project_name=project_name, build_type=build_type.capitalize()) issue.body = _get_issue_body(project_name, build_id, build_type) - issue.status = 'New' - issue.labels.add('Proj-' + project_name) + issue.status = policy.status('new') for cc in ccs: issue.ccs.add(cc) @@ -154,13 +154,13 @@ def file_bug(issue_tracker, project_name, build_id, ccs, build_type): return str(issue.id) -def close_bug(issue_tracker, issue_id, project_name): +def close_bug(issue_tracker, policy, issue_id, project_name): """Close a build failure bug.""" logs.info('Closing build failure bug (project=%s, issue_id=%s).' % (project_name, issue_id)) issue = issue_tracker.get_original_issue(issue_id) - issue.status = 'Fixed' + issue.status = policy.status('verified') issue.save( new_comment='The latest build has succeeded, closing this issue.', notify=True) @@ -184,6 +184,8 @@ def _close_fixed_builds(projects, build_type): if not issue_tracker: raise OssFuzzBuildStatusError('Failed to get issue tracker.') + policy = issue_tracker_policy.get('oss-fuzz') + for project in projects: project_name = project['name'] builds = project['history'] @@ -205,7 +207,7 @@ def _close_fixed_builds(projects, build_type): continue if build_failure.issue_id is not None: - close_bug(issue_tracker, build_failure.issue_id, project_name) + close_bug(issue_tracker, policy, build_failure.issue_id, project_name) close_build_failure(build_failure) @@ -216,6 +218,8 @@ def _process_failures(projects, build_type): if not issue_tracker: raise OssFuzzBuildStatusError('Failed to get issue tracker.') + policy = issue_tracker_policy.get('oss-fuzz') + for project in projects: project_name = project['name'] builds = project['history'] @@ -255,7 +259,7 @@ def _process_failures(projects, build_type): 'Project %s is disabled, skipping bug filing.' % project_name) continue - build_failure.issue_id = file_bug(issue_tracker, project_name, + build_failure.issue_id = file_bug(issue_tracker, policy, project_name, build['build_id'], oss_fuzz_project.ccs, build_type) elif (build_failure.consecutive_failures - diff --git a/src/clusterfuzz/_internal/tests/appengine/handlers/cron/oss_fuzz_build_status_test.py b/src/clusterfuzz/_internal/tests/appengine/handlers/cron/oss_fuzz_build_status_test.py index 30faf9cb31..b13bacf884 100644 --- a/src/clusterfuzz/_internal/tests/appengine/handlers/cron/oss_fuzz_build_status_test.py +++ b/src/clusterfuzz/_internal/tests/appengine/handlers/cron/oss_fuzz_build_status_test.py @@ -20,11 +20,66 @@ from clusterfuzz._internal.cron import oss_fuzz_build_status from clusterfuzz._internal.datastore import data_types +from clusterfuzz._internal.issue_management import issue_tracker_policy from clusterfuzz._internal.issue_management import monorail from clusterfuzz._internal.issue_management.monorail.issue import Issue from clusterfuzz._internal.tests.test_libs import helpers as test_helpers from clusterfuzz._internal.tests.test_libs import test_utils +OSS_FUZZ_POLICY = issue_tracker_policy.IssueTrackerPolicy({ + 'status': { + 'assigned': 'Assigned', + 'duplicate': 'Duplicate', + 'verified': 'Verified', + 'new': 'New', + 'wontfix': 'WontFix', + 'fixed': 'Fixed' + }, + 'all': { + 'status': 'new', + 'labels': ['ClusterFuzz', 'Stability-%SANITIZER%'], + 'issue_body_footer': + 'When you fix this bug, please\n' + ' * mention the fix revision(s).\n' + ' * state whether the bug was a short-lived regression or an old ' + 'bug in any stable releases.\n' + ' * add any other useful information.\n' + 'This information can help downstream consumers.\n\n' + 'If you need to contact the OSS-Fuzz team with a question, ' + 'concern, or any other feedback, please file an issue at ' + 'https://github.com/google/oss-fuzz/issues.' + }, + 'non_security': { + 'labels': ['Type-Bug'] + }, + 'labels': { + 'ignore': 'ClusterFuzz-Ignore', + 'verified': 'ClusterFuzz-Verified', + 'security_severity': 'Security_Severity-%SEVERITY%', + 'needs_feedback': 'Needs-Feedback', + 'invalid_fuzzer': 'ClusterFuzz-Invalid-Fuzzer', + 'reported': 'Reported-%YYYY-MM-DD%', + 'wrong': 'ClusterFuzz-Wrong', + 'fuzz_blocker': 'Fuzz-Blocker', + 'reproducible': 'Reproducible', + 'auto_cc_from_owners': 'ClusterFuzz-Auto-CC', + 'os': 'OS-%PLATFORM%', + 'unreproducible': 'Unreproducible', + 'restrict_view': 'Restrict-View-Commit' + }, + 'security': { + 'labels': ['Type-Bug-Security'] + }, + 'deadline_policy_message': + 'This bug is subject to a 90 day disclosure deadline. If 90 days ' + 'elapse\n' + 'without an upstream patch, then the bug report will automatically\n' + 'become visible to the public.', + 'existing': { + 'labels': ['Stability-%SANITIZER%'] + } +}) + class MockResponse: """Mock url request's response.""" @@ -67,6 +122,8 @@ def setUp(self): test_helpers.patch(self, [ 'clusterfuzz._internal.base.utils.utcnow', 'handlers.base_handler.Handler.is_cron', + ('policy_get', + 'clusterfuzz._internal.issue_management.issue_tracker_policy.get'), 'clusterfuzz._internal.issue_management.issue_tracker_utils.get_issue_tracker', 'clusterfuzz._internal.metrics.logs.error', 'requests.get', @@ -77,6 +134,7 @@ def setUp(self): self.itm = IssueTrackerManager('oss-fuzz') self.mock.get_issue_tracker.return_value = monorail.IssueTracker(self.itm) + self.mock.policy_get.return_value = OSS_FUZZ_POLICY self.maxDiff = None @@ -386,8 +444,6 @@ def _mock_requests_get(url, timeout=None): '**This bug will be automatically closed within a ' 'day once it is fixed.**', issue.body) - self.assertTrue(issue.has_label('Proj-proj2')) - issue = self.itm.issues[2] self.assertCountEqual(['b@user.com'], issue.cc) self.assertEqual('New', issue.status) @@ -407,8 +463,6 @@ def _mock_requests_get(url, timeout=None): '**This bug will be automatically closed within a ' 'day once it is fixed.**', issue.body) - self.assertTrue(issue.has_label('Proj-proj6')) - def test_recovered_build_failure(self): """Test fixed build failures.""" # Use the same status for all build types. @@ -436,7 +490,6 @@ def test_recovered_build_failure(self): issue = Issue() issue.open = True issue.add_label('Type-Build-Failure') - issue.add_label('Proj-proj2') issue.summary = 'Build failure in proj2' issue.body = 'Build failure' @@ -446,7 +499,7 @@ def test_recovered_build_failure(self): self.assertEqual(0, data_types.OssFuzzBuildFailure.query().count()) issue = self.itm.issues[1] - self.assertEqual('Fixed', issue.status) + self.assertEqual('Verified', issue.status) self.assertEqual('The latest build has succeeded, closing this issue.', issue.comment)