From 6dffcfd53038053f56e81da06bb8941ea04435fd Mon Sep 17 00:00:00 2001 From: Abigail Fox Date: Thu, 21 Jul 2022 15:48:50 -0700 Subject: [PATCH] Automatically route PRs to specific remotes https://bugs.webkit.org/show_bug.cgi?id=242129 rdar://96161931 Reviewed by Jonathan Bedard. * Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py * Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py: (PullRequest.create_pull_request): Canonical link: https://commits.webkit.org/252715@main --- .../webkitscmpy/program/pull_request.py | 30 +++++++-- .../webkitscmpy/test/pull_request_unittest.py | 64 ++++++++++++++++++- 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py b/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py index 198c0d979c4b1..c9bbc048e2d7b 100644 --- a/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py +++ b/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py @@ -345,8 +345,31 @@ def create_pull_request(cls, repository, args, branch_point, callback=None, unbl if did_remove: pr_issue.set_labels(labels) + commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=repository.branch))) + + issue = None + for line in commits[0].message.split() if commits[0] and commits[0].message else []: + issue = Tracker.from_string(line) + if issue: + break + if isinstance(remote_repo, remote.GitHub): + if issue and issue.redacted and args.remote is None: + print("Your issue is redacted, diverting to a secure, non-origin remote you have access to.") + original_remote = source_remote + if len(repository.source_remotes()) < 2: + print("Error. You do not have access to a secure, non-origin remote") + if args.defaults or Terminal.choose( + "Would you like to proceed anyways? \n", + default='No', + ) == 'No': + sys.stderr.write("Failed to create pull request due to non-suitable remote\n") + return 1 + else: + source_remote = repository.source_remotes()[1] + print("Making PR against '{}' instead of '{}'".format(source_remote, original_remote)) target = 'fork' if source_remote == repository.default_remote else '{}-fork'.format(source_remote) + if not repository.config().get('remote.{}.url'.format(target)): sys.stderr.write("'{}' is not a remote in this repository. Have you run `{} setup` yet?\n".format( source_remote, os.path.basename(sys.argv[0]), @@ -390,13 +413,6 @@ def create_pull_request(cls, repository, args, branch_point, callback=None, unbl sys.stderr.write("'{}' does not support draft pull requests, aborting\n".format(remote_repo.url)) return 1 - commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=repository.branch))) - - issue = None - for line in commits[0].message.split() if commits[0] and commits[0].message else []: - issue = Tracker.from_string(line) - if issue: - break if existing_pr: log.info("Updating pull-request for '{}'...".format(repository.branch)) diff --git a/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py b/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py index 7181e89131ec4..034db3d044ad6 100644 --- a/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py +++ b/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py @@ -686,6 +686,64 @@ def test_github_branch_bugzilla(self): ], ) + def test_github_branch_bugzilla_redacted_to_origin(self): + with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub(projects=bmocks.PROJECTS) as remote, bmocks.Bugzilla( + self.BUGZILLA.split('://')[-1], + projects=bmocks.PROJECTS, issues=bmocks.ISSUES, + environment=Environment( + BUGS_EXAMPLE_COM_USERNAME='tcontributor@example.com', + BUGS_EXAMPLE_COM_PASSWORD='password', + )), patch( + 'webkitbugspy.Tracker._trackers', [bugzilla.Tracker(self.BUGZILLA, redact={'.*': True})], + ), mocks.local.Git( + self.path, remote='https://{}'.format(remote.remote), + remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])), + ) as repo, mocks.local.Svn(), MockTerminal.input('y'): + + repo.staged['added.txt'] = 'added' + self.assertEqual(0, program.main( + args=('pull-request', '-i', 'https://bugs.example.com/show_bug.cgi?id=1', '-v', '--no-history', '--remote', 'origin'), + path=self.path, + )) + + self.assertEqual( + Tracker.instance().issue(1).comments[-1].content, + 'Pull request: https://github.example.com/WebKit/WebKit/pull/1', + ) + gh_issue = github.Tracker('https://github.example.com/WebKit/WebKit').issue(1) + self.assertEqual(gh_issue.project, 'WebKit') + self.assertEqual(gh_issue.component, 'Text') + self.assertEqual(gh_issue.version, 'Other') + + self.assertEqual( + captured.stdout.getvalue(), + "Created the local development branch 'eng/1'\n" + "Created 'PR 1 | Example issue 1'!\n" + "Posted pull request link to https://bugs.example.com/show_bug.cgi?id=1\n" + "https://github.example.com/WebKit/WebKit/pull/1\n", + ) + self.assertEqual(captured.stderr.getvalue(), '') + log = captured.root.log.getvalue().splitlines() + self.assertEqual( + [line for line in log if 'Mock process' not in line], [ + "Creating the local development branch 'eng/1'...", + 'Creating commit...', + "Rebasing 'eng/1' on 'main'...", + "Rebased 'eng/1' on 'main!'", + 'Running pre-PR checks...', + 'No pre-PR checks to run', + 'Checking if PR already exists...', + 'PR not found.', + "Pushing 'eng/1' to 'fork'...", + "Syncing 'main' to remote 'fork'", + "Creating pull-request for 'eng/1'...", + 'Checking issue assignee...', + 'Checking for pull request link in associated issue...', + 'Syncing PR labels with issue component...', + 'Synced PR labels with issue component!', + ], + ) + def test_github_branch_bugzilla_redacted(self): with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub(projects=bmocks.PROJECTS) as remote, bmocks.Bugzilla( self.BUGZILLA.split('://')[-1], @@ -698,7 +756,7 @@ def test_github_branch_bugzilla_redacted(self): ), mocks.local.Git( self.path, remote='https://{}'.format(remote.remote), remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])), - ) as repo, mocks.local.Svn(): + ) as repo, mocks.local.Svn(), MockTerminal.input('y'): repo.staged['added.txt'] = 'added' self.assertEqual(0, program.main( @@ -718,6 +776,10 @@ def test_github_branch_bugzilla_redacted(self): self.assertEqual( captured.stdout.getvalue(), "Created the local development branch 'eng/1'\n" + "Your issue is redacted, diverting to a secure, non-origin remote you have access to.\n" + "Error. You do not have access to a secure, non-origin remote\n" + "Would you like to proceed anyways? \n" + " (Yes/[No]): \n" "Created 'PR 1 | Example issue 1'!\n" "Posted pull request link to https://bugs.example.com/show_bug.cgi?id=1\n" "https://github.example.com/WebKit/WebKit/pull/1\n",