Skip to content

Commit c272969

Browse files
committed
Bug 1529990 - Fix Mobile bustage
1 parent dc088ba commit c272969

File tree

9 files changed

+595
-154
lines changed

9 files changed

+595
-154
lines changed

scriptworker/constants.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,10 @@
313313
}),
314314
'mobile': frozendict({
315315
'project:mobile:android-components:releng:beetmover:bucket:maven-production': 'android-components-repo',
316+
'project:mobile:android-components:releng:beetmover:bucket:maven-snapshot-production': 'android-components-repo',
317+
318+
'project:mobile:fenix:releng:googleplay:product:fenix': 'fenix-repo',
319+
'project:mobile:fenix:releng:signing:cert:release-signing': 'fenix-repo',
316320

317321
'project:mobile:focus:googleplay:product:focus': 'focus-repo',
318322
'project:mobile:focus:releng:signing:cert:release-signing': 'focus-repo',
@@ -409,6 +413,9 @@
409413
),
410414
}),
411415
'mobile': frozendict({
416+
'fenix-repo': (
417+
'/mozilla-mobile/fenix',
418+
),
412419
'focus-repo': (
413420
'/mozilla-mobile/focus-android',
414421
),

scriptworker/cot/verify.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -121,19 +121,18 @@ def dependent_task_ids(self):
121121
"""
122122
return [x.task_id for x in self.links]
123123

124-
def is_try_or_pull_request(self):
124+
async def is_try_or_pull_request(self):
125125
"""Determine if any task in the chain is a try task.
126126
127127
Returns:
128128
bool: True if a task is a try task.
129129
130130
"""
131-
result = is_try_or_pull_request(self.context, self.task)
132-
for link in self.links:
133-
if link.is_try_or_pull_request:
134-
result = True
135-
break
136-
return result
131+
tasks = [asyncio.ensure_future(link.is_try_or_pull_request()) for link in self.links]
132+
tasks.insert(0, asyncio.ensure_future(is_try_or_pull_request(self.context, self.task)))
133+
134+
conditions = await raise_future_exceptions(tasks)
135+
return any(conditions)
137136

138137
def get_link(self, task_id):
139138
"""Get a ``LinkOfTrust`` by task id.
@@ -243,10 +242,9 @@ def task(self, task):
243242
self.parent_task_id = get_parent_task_id(self.task)
244243
self.worker_impl = guess_worker_impl(self)
245244

246-
@property
247-
def is_try_or_pull_request(self):
245+
async def is_try_or_pull_request(self):
248246
"""bool: the task is either a try or a pull request one."""
249-
return is_try_or_pull_request(self.context, self.task)
247+
return await is_try_or_pull_request(self.context, self.task)
250248

251249
@property
252250
def cot(self):
@@ -2072,7 +2070,7 @@ async def trace_back_to_tree(chain):
20722070
obj.name, obj.task_id
20732071
))
20742072
# Disallow restricted privs on is_try_or_pull_request. This may be a redundant check.
2075-
if restricted_privs and chain.is_try_or_pull_request():
2073+
if restricted_privs and await chain.is_try_or_pull_request():
20762074
errors.append(
20772075
"{} {} has restricted privilege scope, and is_try_or_pull_request()!".format(
20782076
chain.name, chain.task_id

scriptworker/github.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
"""GitHub helper functions."""
22

3+
import re
4+
35
from github3 import GitHub
46

7+
from scriptworker.exceptions import ConfigError
8+
from scriptworker.utils import (
9+
get_single_item_from_sequence,
10+
get_parts_of_url_path,
11+
retry_request,
12+
)
13+
14+
_GIT_FULL_HASH_PATTERN = re.compile(r'^[0-9a-f]{40}$')
15+
516

617
class GitHubRepository():
718
"""Wrapper around GitHub API. Used to access public data."""
@@ -65,3 +76,152 @@ def get_release(self, tag_name):
6576
6677
"""
6778
return self._github_repository.release_from_tag(tag_name).as_dict()
79+
80+
def get_tag_hash(self, tag_name):
81+
"""Fetch the commit hash that was tagged with ``tag_name``.
82+
83+
Args:
84+
tag_name (str): the name of the tag
85+
86+
Returns:
87+
str: the commit hash linked by the tag
88+
89+
"""
90+
tag_object = get_single_item_from_sequence(
91+
sequence=self._github_repository.tags(),
92+
condition=lambda tag: tag.name == tag_name,
93+
no_item_error_message='No tag "{}" exist'.format(tag_name),
94+
too_many_item_error_message='Too many tags "{}" found'.format(tag_name),
95+
)
96+
97+
return tag_object.commit.sha
98+
99+
async def has_commit_landed_on_repository(self, context, revision):
100+
"""Tell if a commit was landed on the repository or if it just comes from a pull request.
101+
102+
Args:
103+
context (scriptworker.context.Context): the scriptworker context.
104+
revision (str): the commit hash or the tag name.
105+
106+
Returns:
107+
bool: True if the commit is present in one of the branches of the main repository
108+
109+
"""
110+
# Revision may be a tag name. `branch_commits` doesn't work on tags
111+
if not _is_git_full_hash(revision):
112+
revision = self.get_tag_hash(tag_name=revision)
113+
114+
repo = self._github_repository.html_url
115+
116+
url = '/'.join([repo.rstrip('/'), 'branch_commits', revision])
117+
html_data = await retry_request(context, url)
118+
html_text = html_data.strip()
119+
# https://github.com/{repo_owner}/{repo_name}/branch_commits/{revision} just returns some \n
120+
# when the commit hasn't landed on the origin repo. Otherwise, some HTML data is returned - it
121+
# represents the branches on which the given revision is present.
122+
return html_text != ''
123+
124+
125+
def is_github_url(url):
126+
"""Tell if a given URL matches a Github one.
127+
128+
Args:
129+
url (str): The URL to test. It can be None.
130+
131+
Returns:
132+
bool: False if the URL is not a string or if it doesn't match a Github URL
133+
134+
"""
135+
if isinstance(url, str):
136+
return url.startswith('https://github.com/')
137+
else:
138+
return False
139+
140+
141+
def extract_github_repo_owner_and_name(url):
142+
"""Given an URL, return the repo name and who owns it.
143+
144+
Args:
145+
url (str): The URL to the GitHub repository
146+
147+
Raises:
148+
ValueError: on url that aren't from github
149+
150+
Returns:
151+
str, str: the owner of the repository, the repository name
152+
153+
"""
154+
_check_github_url_is_supported(url)
155+
156+
parts = get_parts_of_url_path(url)
157+
repo_owner = parts[0]
158+
repo_name = parts[1]
159+
160+
return repo_owner, _strip_trailing_dot_git(repo_name)
161+
162+
163+
def extract_github_repo_and_revision_from_source_url(url):
164+
"""Given an URL, return the repo name and who owns it.
165+
166+
Args:
167+
url (str): The URL to the GitHub repository
168+
169+
Raises:
170+
ValueError: on url that aren't from github or when the revision cannot be extracted
171+
172+
Returns:
173+
str, str: the owner of the repository, the repository name
174+
175+
"""
176+
_check_github_url_is_supported(url)
177+
178+
parts = get_parts_of_url_path(url)
179+
repo_name = parts[1]
180+
try:
181+
revision = parts[3]
182+
except IndexError:
183+
raise ValueError('Revision cannot be extracted from url: {}'.format(url))
184+
185+
end_index = url.index(repo_name) + len(repo_name)
186+
repo_url = url[:end_index]
187+
188+
return _strip_trailing_dot_git(repo_url), revision
189+
190+
191+
def _strip_trailing_dot_git(url):
192+
if url.endswith('.git'):
193+
url = url[:-len('.git')]
194+
return url
195+
196+
197+
def is_github_repo_owner_the_official_one(context, repo_owner):
198+
"""Given a repo_owner, check if it matches the one configured to be the official one.
199+
200+
Args:
201+
context (scriptworker.context.Context): the scriptworker context.
202+
repo_owner (str): the repo_owner to verify
203+
204+
Raises:
205+
scriptworker.exceptions.ConfigError: when no official owner was defined
206+
207+
Returns:
208+
bool: True when ``repo_owner`` matches the one configured to be the official one
209+
210+
"""
211+
official_repo_owner = context.config['official_github_repos_owner']
212+
if not official_repo_owner:
213+
raise ConfigError(
214+
'This worker does not have a defined owner for official GitHub repositories. '
215+
'Given "official_github_repos_owner": {}'.format(official_repo_owner)
216+
)
217+
218+
return official_repo_owner == repo_owner
219+
220+
221+
def _is_git_full_hash(revision):
222+
return _GIT_FULL_HASH_PATTERN.match(revision) is not None
223+
224+
225+
def _check_github_url_is_supported(url):
226+
if not is_github_url(url):
227+
raise ValueError('"{}" is not a supported GitHub URL!'.format(url))

0 commit comments

Comments
 (0)