Skip to content

Commit

Permalink
Bug 1529990 - Fix Mobile bustage
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanLorenzo committed Mar 5, 2019
1 parent dc088ba commit 949025b
Show file tree
Hide file tree
Showing 9 changed files with 595 additions and 154 deletions.
7 changes: 7 additions & 0 deletions scriptworker/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@
}),
'mobile': frozendict({
'project:mobile:android-components:releng:beetmover:bucket:maven-production': 'android-components-repo',
'project:mobile:android-components:releng:beetmover:bucket:maven-snapshot-production': 'android-components-repo',

'project:mobile:fenix:releng:googleplay:product:fenix': 'fenix-repo',
'project:mobile:fenix:releng:signing:cert:release-signing': 'fenix-repo',

'project:mobile:focus:googleplay:product:focus': 'focus-repo',
'project:mobile:focus:releng:signing:cert:release-signing': 'focus-repo',
Expand Down Expand Up @@ -409,6 +413,9 @@
),
}),
'mobile': frozendict({
'fenix-repo': (
'/mozilla-mobile/fenix',
),
'focus-repo': (
'/mozilla-mobile/focus-android',
),
Expand Down
20 changes: 9 additions & 11 deletions scriptworker/cot/verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,18 @@ def dependent_task_ids(self):
"""
return [x.task_id for x in self.links]

def is_try_or_pull_request(self):
async def is_try_or_pull_request(self):
"""Determine if any task in the chain is a try task.
Returns:
bool: True if a task is a try task.
"""
result = is_try_or_pull_request(self.context, self.task)
for link in self.links:
if link.is_try_or_pull_request:
result = True
break
return result
tasks = [asyncio.ensure_future(link.is_try_or_pull_request()) for link in self.links]
tasks.insert(0, asyncio.ensure_future(is_try_or_pull_request(self.context, self.task)))

conditions = await raise_future_exceptions(tasks)
return any(conditions)

def get_link(self, task_id):
"""Get a ``LinkOfTrust`` by task id.
Expand Down Expand Up @@ -243,10 +242,9 @@ def task(self, task):
self.parent_task_id = get_parent_task_id(self.task)
self.worker_impl = guess_worker_impl(self)

@property
def is_try_or_pull_request(self):
async def is_try_or_pull_request(self):
"""bool: the task is either a try or a pull request one."""
return is_try_or_pull_request(self.context, self.task)
return await is_try_or_pull_request(self.context, self.task)

@property
def cot(self):
Expand Down Expand Up @@ -2072,7 +2070,7 @@ async def trace_back_to_tree(chain):
obj.name, obj.task_id
))
# Disallow restricted privs on is_try_or_pull_request. This may be a redundant check.
if restricted_privs and chain.is_try_or_pull_request():
if restricted_privs and await chain.is_try_or_pull_request():
errors.append(
"{} {} has restricted privilege scope, and is_try_or_pull_request()!".format(
chain.name, chain.task_id
Expand Down
160 changes: 160 additions & 0 deletions scriptworker/github.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
"""GitHub helper functions."""

import re

from github3 import GitHub

from scriptworker.exceptions import ConfigError
from scriptworker.utils import (
get_single_item_from_sequence,
get_parts_of_url_path,
retry_request,
)

_GIT_FULL_HASH_PATTERN = re.compile(r'^[0-9a-f]{40}$')


class GitHubRepository():
"""Wrapper around GitHub API. Used to access public data."""
Expand Down Expand Up @@ -65,3 +76,152 @@ def get_release(self, tag_name):
"""
return self._github_repository.release_from_tag(tag_name).as_dict()

def get_tag_hash(self, tag_name):
"""Fetch the commit hash that was tagged with ``tag_name``.
Args:
tag_name (str): the name of the tag
Returns:
str: the commit hash linked by the tag
"""
tag_object = get_single_item_from_sequence(
sequence=self._github_repository.tags(),
condition=lambda tag: tag.name == tag_name,
no_item_error_message='No tag "{}" exist'.format(tag_name),
too_many_item_error_message='Too many tags "{}" found'.format(tag_name),
)

return tag_object.commit.sha

async def has_commit_landed_on_repository(self, context, revision):
"""Tell if a commit was landed on the repository or if it just comes from a pull request.
Args:
context (scriptworker.context.Context): the scriptworker context.
revision (str): the commit hash or the tag name.
Returns:
bool: True if the commit is present in one of the branches of the main repository
"""
# Revision may be a tag name. `branch_commits` doesn't work on tags
if not _is_git_full_hash(revision):
revision = self.get_tag_hash(tag_name=revision)

repo = self._github_repository.html_url

url = '/'.join([repo.rstrip('/'), 'branch_commits', revision])
html_data = await retry_request(context, url)
html_text = html_data.strip()
# https://github.com/{repo_owner}/{repo_name}/branch_commits/{revision} just returns some \n
# when the commit hasn't landed on the origin repo. Otherwise, some HTML data is returned - it
# represents the branches on which the given revision is present.
return html_text != ''


def is_github_url(url):
"""Tell if a given URL matches a Github one.
Args:
url (str): The URL to test. It can be None.
Returns:
bool: False if the URL is not a string or if it doesn't match a Github URL
"""
if isinstance(url, str):
return url.startswith('https://github.com/')
else:
return False


def extract_github_repo_owner_and_name(url):
"""Given an URL, return the repo name and who owns it.
Args:
url (str): The URL to the GitHub repository
Raises:
ValueError: on url that aren't from github
Returns:
str, str: the owner of the repository, the repository name
"""
_check_github_url_is_supported(url)

parts = get_parts_of_url_path(url)
repo_owner = parts[0]
repo_name = parts[1]

return repo_owner, _strip_trailing_dot_git(repo_name)


def extract_github_repo_and_revision_from_source_url(url):
"""Given an URL, return the repo name and who owns it.
Args:
url (str): The URL to the GitHub repository
Raises:
ValueError: on url that aren't from github or when the revision cannot be extracted
Returns:
str, str: the owner of the repository, the repository name
"""
_check_github_url_is_supported(url)

parts = get_parts_of_url_path(url)
repo_name = parts[1]
try:
revision = parts[3]
except IndexError:
raise ValueError('Revision cannot be extracted from url: {}'.format(url))

end_index = url.index(repo_name) + len(repo_name)
repo_url = url[:end_index]

return _strip_trailing_dot_git(repo_url), revision


def _strip_trailing_dot_git(url):
if url.endswith('.git'):
url = url[:-len('.git')]
return url


def is_github_repo_owner_the_official_one(context, repo_owner):
"""Given a repo_owner, check if it matches the one configured to be the official one.
Args:
context (scriptworker.context.Context): the scriptworker context.
repo_owner (str): the repo_owner to verify
Raises:
scriptworker.exceptions.ConfigError: when no official owner was defined
Returns:
bool: True when ``repo_owner`` matches the one configured to be the official one
"""
official_repo_owner = context.config['official_github_repos_owner']
if not official_repo_owner:
raise ConfigError(
'This worker does not have a defined owner for official GitHub repositories. '
'Given "official_github_repos_owner": {}'.format(official_repo_owner)
)

return official_repo_owner == repo_owner


def _is_git_full_hash(revision):
return _GIT_FULL_HASH_PATTERN.match(revision) is not None


def _check_github_url_is_supported(url):
if not is_github_url(url):
raise ValueError('"{}" is not a supported GitHub URL!'.format(url))
Loading

0 comments on commit 949025b

Please sign in to comment.