Title: [295540] trunk
Revision
295540
Author
jbed...@apple.com
Date
2022-06-14 15:14:47 -0700 (Tue, 14 Jun 2022)

Log Message

[git-webkit] Automatically grant team access to private forks
https://bugs.webkit.org/show_bug.cgi?id=240819
<rdar://93780380>

Reviewed by Stephanie Lewis.

* Tools/Scripts/libraries/webkitbugspy/webkitbugspy/github.py:
(Tracker): Share ACCEPT_HEADER string.
(Tracker.credentials.validater): Ditto.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py:
(Setup.github): Allow provided team access to forked repository.
(Setup.git): Pass team for repo access from webkitscmpy.access config value.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py:
(GitHub): Share ACCEPT_HEADER string.
(GitHub.PRGenerator.create): Ditto.
(GitHub.PRGenerator.update): Ditto.
(GitHub.request): Ditto.
* metadata/git_config_extension: Define group to have access to apple/WebKit forks.

Canonical link: https://commits.webkit.org/251545@main

Modified Paths

Diff

Modified: trunk/Tools/Scripts/libraries/webkitbugspy/webkitbugspy/github.py (295539 => 295540)


--- trunk/Tools/Scripts/libraries/webkitbugspy/webkitbugspy/github.py	2022-06-14 21:59:59 UTC (rev 295539)
+++ trunk/Tools/Scripts/libraries/webkitbugspy/webkitbugspy/github.py	2022-06-14 22:14:47 UTC (rev 295540)
@@ -48,6 +48,7 @@
     REFRESH_TOKEN_PROMPT = "Is your API token out of date? Run 'git-webkit setup' to refresh credentials\n"
     DEFAULT_COMPONENT_COLOR = 'FFFFFF'
     DEFAULT_VERSION_COLOR = 'EEEEEE'
+    ACCEPT_HEADER = 'application/vnd.github.v3+json'
 
 
     class Encoder(GenericTracker.Encoder):
@@ -105,7 +106,7 @@
                 return False
             response = self.session.get(
                 '{}/user'.format(self.api_url),
-                headers=dict(Accept='application/vnd.github.v3+json'),
+                headers=dict(Accept=self.ACCEPT_HEADER),
                 auth=HTTPBasicAuth(username, access_token),
             )
             expiration = response.headers.get('github-authentication-token-expiration', None)
@@ -144,7 +145,7 @@
 
     def request(self, path=None, params=None, method='GET', headers=None, authenticated=None, paginate=True, json=None, error_message=None):
         headers = {key: value for key, value in headers.items()} if headers else dict()
-        headers['Accept'] = headers.get('Accept', 'application/vnd.github.v3+json')
+        headers['Accept'] = headers.get('Accept', self.ACCEPT_HEADER)
 
         username, access_token = self.credentials(required=bool(authenticated))
         auth = HTTPBasicAuth(username, access_token) if username and access_token else None
@@ -196,7 +197,7 @@
         url = ''.format(api_url=self.api_url, username=username)
         response = self.session.get(
             url, auth=HTTPBasicAuth(*self.credentials(required=True)),
-            headers=dict(Accept='application/vnd.github.v3+json'),
+            headers=dict(Accept=self.ACCEPT_HEADER),
         )
         if response.status_code // 100 != 2:
             sys.stderr.write("Request to '{}' returned status code '{}'\n".format(url, response.status_code))

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py (295539 => 295540)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py	2022-06-14 21:59:59 UTC (rev 295539)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py	2022-06-14 22:14:47 UTC (rev 295540)
@@ -37,7 +37,7 @@
     help = 'Configure local settings for the current repository'
 
     @classmethod
-    def github(cls, args, repository, additional_setup=None, remote=None, **kwargs):
+    def github(cls, args, repository, additional_setup=None, remote=None, team=None, **kwargs):
         log.info('Saving GitHub credentials in system credential store...')
         username, access_token = repository.credentials(required=True, validate=True, save_in_keyring=True)
         log.info('GitHub credentials saved via Keyring!')
@@ -47,16 +47,54 @@
         if additional_setup:
             result += additional_setup(args, repository)
 
+        team_id = None
+        auth = HTTPBasicAuth(username, access_token)
+        if team:
+            response = requests.get('{}/orgs/{}'.format(
+                repository.api_url,
+                team,
+            ), auth=auth, headers=dict(Accept=repository.ACCEPT_HEADER))
+            if response.status_code == 200:
+                team_id = response.json().get('id', None)
+            else:
+                sys.stderr.write('You are not a member of {}\n'.format(team))
+                sys.stderr.write('Created "{}" fork will not be accessible to other contributors\n'.format(remote))
+
         forked_name = '{}{}'.format(repository.name, '-{}'.format(remote) if remote else '')
         log.info('Verifying user owned fork...')
-        auth = HTTPBasicAuth(username, access_token)
         response = requests.get('{}/repos/{}/{}'.format(
             repository.api_url,
             username,
             forked_name,
-        ), auth=auth, headers=dict(Accept='application/vnd.github.v3+json'))
+        ), auth=auth, headers=dict(Accept=repository.ACCEPT_HEADER))
 
         if response.status_code == 200:
+            has_team = False
+            if team_id:
+                log.info("Checking if '{}' has access to '{}/{}'...".format(team, username, forked_name))
+                teams = requests.get('{}/repos/{}/{}/teams'.format(
+                    repository.api_url,
+                    username,
+                    forked_name,
+                ), auth=auth, headers=dict(Accept=repository.ACCEPT_HEADER))
+                if teams.status_code == 200 and any([team_id == node.get('id') for node in teams.json()]):
+                    log.info("'{}' has access to '{}/{}'!".format(team, username, forked_name))
+                    has_team = True
+
+            if not has_team and team:
+                log.info("Granting '{}' access to '{}/{}'...".format(team, username, forked_name))
+                granting = requests.put('{}/orgs/{}/repos/{}/{}'.format(
+                    repository.api_url,
+                    team,
+                    username,
+                    forked_name,
+                ), json=dict(permission='push'), auth=auth, headers=dict(Accept=repository.ACCEPT_HEADER))
+                if granting.status_code // 100 != 2:
+                    sys.stderr.write("Failed to grant '{}' access to '{}/{}'\n".format(team, username, forked_name))
+                    sys.stderr.write("Other contributors do not have access to '{}/{}'\n".format(username, forked_name))
+                else:
+                    log.info("Granted '{}' access to '{}/{}'!".format(team, username, forked_name))
+
             parent_name = response.json().get('parent', {}).get('full_name', None)
             if parent_name == '{}/{}'.format(repository.owner, repository.name):
                 log.info("User already owns a fork of '{}'!".format(parent_name))
@@ -69,16 +107,19 @@
             log.info("Continuing without forking '{}'".format(forked_name))
             return 1
 
+        data = ""
+            owner=username,
+            description="{}'s fork of {}{}".format(username, repository.name, ' ({})'.format(remote) if remote else ''),
+            private=True,
+        )
+        if team_id:
+            data[team_id] = team_id
         response = requests.post('{}/repos/{}/{}/forks'.format(
             repository.api_url,
             repository.owner,
             repository.name,
-        ), json=dict(
-            owner=username,
-            description="{}'s fork of {}{}".format(username, repository.name, ' ({})'.format(remote) if remote else ''),
-            private=True,
-        ), auth=auth, headers=dict(Accept='application/vnd.github.v3+json'))
-        if response.status_code not in (200, 202):
+        ), json=data, auth=auth, headers=dict(Accept=repository.ACCEPT_HEADER))
+        if response.status_code // 100 != 2:
             sys.stderr.write("Failed to create a fork of '{}' belonging to '{}'\n".format(forked_name, username))
             sys.stderr.write("URL: {}\nServer replied with status code {}:\n{}\n".format(response.url, response.status_code, response.text))
             return 1
@@ -89,10 +130,8 @@
                 repository.api_url,
                 username,
                 set_name,
-            ), json=dict(
-                name=forked_name
-            ), auth=auth, headers=dict(Accept='application/vnd.github.v3+json'))
-            if response.status_code not in (200, 202):
+            ), json=dict(name=forked_name), auth=auth, headers=dict(Accept=repository.ACCEPT_HEADER))
+            if response.status_code // 100 != 2:
                 sys.stderr.write("Fork created with name '{}' belonging to '{}'\n Failed to change name to {}\n".format(set_name, username, forked_name))
                 sys.stderr.write("URL: {}\nServer replied with status code {}:\n{}\n".format(response.url, response.status_code, response.text))
                 return 1
@@ -99,7 +138,7 @@
 
         response = None
         attempts = 0
-        while response and response.status_code != 200:
+        while response and response.status_code // 100 != 2:
             if attempts > 3:
                 sys.stderr.write("Waiting on '{}' belonging to '{}' took to long\n".format(forked_name, username))
                 sys.stderr.write("Wait until '{}/{}/{}' is accessible and then re-run setup\n".format(
@@ -436,7 +475,7 @@
                     available_remotes.append(name)
                 if not isinstance(nw_rmt, remote.GitHub):
                     continue
-                if cls.github(args, nw_rmt, remote=name):
+                if cls.github(args, nw_rmt, remote=name, team=repository.config().get('webkitscmpy.access.{}'.format(name), None)):
                     result += 1
                     continue
                 log.info("Adding forked {remote} remote as '{username}-{remote}' and '{remote}-fork'...".format(
@@ -462,7 +501,7 @@
         if not forking or forking == 'No':
             return result
 
-        if cls.github(args, rmt, **kwargs):
+        if cls.github(args, rmt, team=repository.config().get('webkitscmpy.access.origin', None), **kwargs):
             return result + 1
 
         log.info("Adding forked remote as '{}' and 'fork'...".format(username))

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py (295539 => 295540)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py	2022-06-14 21:59:59 UTC (rev 295539)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py	2022-06-14 22:14:47 UTC (rev 295540)
@@ -40,6 +40,7 @@
 class GitHub(Scm):
     URL_RE = re.compile(r'\Ahttps?://github.(?P<domain>\S+)/(?P<owner>\S+)/(?P<repository>\S+)\Z')
     EMAIL_RE = re.compile(r'(?P<email>[^@]+@[^@]+)(@.*)?')
+    ACCEPT_HEADER = Tracker.ACCEPT_HEADER
 
     class PRGenerator(Scm.PRGenerator):
         SUPPORTS_DRAFTS = True
@@ -113,7 +114,7 @@
             )
             response = self.repository.session.post(
                 url, auth=HTTPBasicAuth(*self.repository.credentials(required=True)),
-                headers=dict(Accept='application/vnd.github.v3+json'),
+                headers=dict(Accept=self.repository.ACCEPT_HEADER),
                 json=dict(
                     title=title,
                     body=PullRequest.create_body(body, commits),
@@ -167,7 +168,7 @@
             )
             response = self.repository.session.post(
                 url, auth=HTTPBasicAuth(*self.repository.credentials(required=True)),
-                headers=dict(Accept='application/vnd.github.v3+json'),
+                headers=dict(Accept=self.repository.ACCEPT_HEADER),
                 json=updates,
             )
             if response.status_code == 422:
@@ -317,7 +318,7 @@
 
     def request(self, path=None, params=None, headers=None, authenticated=None, paginate=True):
         headers = {key: value for key, value in headers.items()} if headers else dict()
-        headers['Accept'] = headers.get('Accept', 'application/vnd.github.v3+json')
+        headers['Accept'] = headers.get('Accept', self.ACCEPT_HEADER)
 
         username, access_token = self.credentials(required=bool(authenticated))
         auth = HTTPBasicAuth(username, access_token) if username and access_token else None

Modified: trunk/metadata/git_config_extension (295539 => 295540)


--- trunk/metadata/git_config_extension	2022-06-14 21:59:59 UTC (rev 295539)
+++ trunk/metadata/git_config_extension	2022-06-14 22:14:47 UTC (rev 295540)
@@ -8,5 +8,7 @@
 [webkitscmpy "remotes"]
         origin = g...@github.com:WebKit/WebKit.git
         apple = g...@github.com:apple/WebKit.git
+[webkitscmpy "access"]
+        apple = apple/teams/WebKit
 [webkitscmpy "pre-pr"]
         style-checker = python3 Tools/Scripts/check-webkit-style
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to