Migrate create_new_branch to toddler in scm_request_processor
The method is migrated from fedscm_admin to scm_request_processor. Now we need to continue with writing test for scm_request_processor.
This commit is contained in:
parent
e94e1e7162
commit
0ec16b0195
2 changed files with 91 additions and 125 deletions
|
@ -101,6 +101,10 @@ dist_git_token = "private random string to change"
|
|||
# This is the same format as used by the distgit_bugzilla_sync cron/app
|
||||
email_overrides_file = "/path/to/email_overrides.toml"
|
||||
|
||||
# Path to temporary directory
|
||||
# Will be used for creating temporary files and directories
|
||||
temp_dir = "path/to/temporary/folder"
|
||||
|
||||
[consumer_config.default.pdc_config]
|
||||
# Configuration to talk to PDC, as understood by pdc-client.
|
||||
server = "https://pdc.fedoraproject.org/rest_api/v1/"
|
||||
|
|
|
@ -6,14 +6,16 @@ https://pagure.io/releng/fedora-scm-requests/issues.
|
|||
Authors: Michal Konecny <mkonecny@redhat.com>
|
||||
|
||||
"""
|
||||
import fnmatch
|
||||
import logging
|
||||
import re
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import arrow
|
||||
from pagure_messages.issue_schema import IssueNewV1
|
||||
|
||||
from toddlers.base import ToddlerBase
|
||||
from toddlers.utils import bugzilla_system, fedora_account, pagure, pdc
|
||||
from toddlers.utils import bugzilla_system, fedora_account, pagure, pdc, git
|
||||
from toddlers.exceptions import ValidationError
|
||||
|
||||
# Regex for branch name validation
|
||||
|
@ -67,6 +69,9 @@ class SCMRequestProcessor(ToddlerBase):
|
|||
# Pagure object connected to dist-git
|
||||
dist_git = None
|
||||
|
||||
# Path to temporary dir
|
||||
temp_dir = None
|
||||
|
||||
def accepts_topic(self, topic: str) -> bool:
|
||||
"""Returns a boolean whether this toddler is interested in messages
|
||||
from this specific topic.
|
||||
|
@ -113,6 +118,7 @@ class SCMRequestProcessor(ToddlerBase):
|
|||
self.monitoring_choices = config.get("monitoring_choices")
|
||||
self.pagure_namespace_to_component = config.get("pagure_namespace_to_component")
|
||||
self.pagure_namespace_to_product = config.get("pagure_namespace_to_product")
|
||||
self.temp_dir = config.get("temp_dir")
|
||||
|
||||
_log.info("Setting up PDC client")
|
||||
pdc.set_pdc(config)
|
||||
|
@ -518,18 +524,19 @@ class SCMRequestProcessor(ToddlerBase):
|
|||
)
|
||||
return
|
||||
|
||||
if create_git_branch:
|
||||
assert_git_repo_initialized_remotely(namespace, repo)
|
||||
|
||||
branch_name = issue_body_json['branch'].strip()
|
||||
if is_epel(branch_name) and not valid_epel_package(repo, branch_name):
|
||||
if not force:
|
||||
prompt_to_close_bad_ticket(issue_json, INVALID_EPEL_ERROR)
|
||||
return
|
||||
if re.match(EPEL_REGEX, branch_name) and not self.valid_epel_package(repo, branch_name):
|
||||
self.pagure_io.close_issue(
|
||||
issue["id"],
|
||||
namespace=PROJECT_NAMESPACE,
|
||||
message=INVALID_EPEL_ERROR,
|
||||
reason="Invalid"
|
||||
)
|
||||
return
|
||||
# Pagure uses plural names for namespaces, but PDC does not use the
|
||||
# plural version for branch types
|
||||
branch_type = pdc.component_type_to_singular(namespace)
|
||||
click.echo('- Checking if {0} already exists in PDC.'.format(branch_name))
|
||||
branch_type = namespace.strip().rstrip('s')
|
||||
_log.info('- Checking if {0} already exists in PDC.'.format(branch_name))
|
||||
pdc_branch = pdc.get_branch(repo, branch_name, branch_type)
|
||||
if pdc_branch:
|
||||
ticket_text = \
|
||||
|
@ -540,107 +547,84 @@ class SCMRequestProcessor(ToddlerBase):
|
|||
"``git checkout -b <branch_name> && git push -u origin <branch_name>``.\n" \
|
||||
"``<branch_name>`` is the name of the branch you requested. \n" \
|
||||
"You only need to do this once and you can then use fedpkg as you normally do."
|
||||
prompt_to_close_bad_ticket(
|
||||
issue_json, ticket_text)
|
||||
self.pagure_io.close_issue(
|
||||
issue["id"],
|
||||
namespace=PROJECT_NAMESPACE,
|
||||
message=ticket_text,
|
||||
reason="Invalid"
|
||||
)
|
||||
return
|
||||
|
||||
issue_id = issue_json['id']
|
||||
issue_title = issue_json['title'].strip()
|
||||
issue_owner = issue_json['user']['name']
|
||||
issue_ui_url = pagure.get_pagure_issue_url(issue_id)
|
||||
issue_id = issue['id']
|
||||
issue_title = issue['title'].strip()
|
||||
issue_owner = issue['user']['name']
|
||||
issue_ui_url = issue["full_url"]
|
||||
|
||||
# Check if the branch requestor is one of the maintainers or part of the groups
|
||||
click.echo('- Checking if {0} is one of the maintainers of the package'.format(issue_owner))
|
||||
if force:
|
||||
msg = ' WARNING: Checking of maintainers is skipped'
|
||||
click.secho(msg, fg='yellow')
|
||||
else:
|
||||
# Get the list of maintainers of the package
|
||||
maintainers = set(contributors['users']['admin']) | \
|
||||
set(contributors['users']['commit']) | \
|
||||
set(u['user']
|
||||
for u in contributors['users']['collaborators']
|
||||
if fnmatch.fnmatch(branch_name, u['branches']))
|
||||
_log.info('- Checking if {0} is one of the maintainers of the package'.format(issue_owner))
|
||||
|
||||
# Get the list of FAS groups who can maintain the package
|
||||
access_groups = set(contributors['groups']['admin']) | \
|
||||
set(contributors['groups']['commit']) | \
|
||||
set(g['user']
|
||||
for g in contributors['groups']['collaborators']
|
||||
if fnmatch.fnmatch(branch_name, g['branches']))
|
||||
group_member = False
|
||||
for access_group in access_groups:
|
||||
# Check if the requestor is part of any of the FAS groups who can maintain the package
|
||||
if FAS_CLIENT.user_member_of(FAS_CLIENT.get_fas_user(issue_owner), access_group):
|
||||
group_member = True
|
||||
break
|
||||
if issue_owner not in maintainers and not group_member:
|
||||
prompt_to_close_bad_ticket(
|
||||
issue_json, '{0} is not a maintainer of the {1} package'.format(issue_owner, repo)
|
||||
)
|
||||
return
|
||||
# Get the list of maintainers of the package
|
||||
maintainers = set(contributors['users']['admin']) | \
|
||||
set(contributors['users']['commit']) | \
|
||||
set(u['user']
|
||||
for u in contributors['users']['collaborators']
|
||||
if fnmatch.fnmatch(branch_name, u['branches']))
|
||||
|
||||
if auto_approve and \
|
||||
not ticket_requires_approval('new_branch', issue_body_json):
|
||||
click.echo('- Auto-approving the new branch request for "{0}" on '
|
||||
'{1}/{2}'.format(branch_name, namespace, repo))
|
||||
action = 'approve'
|
||||
else:
|
||||
click.echo('\nTicket #{0}'.format(issue_id))
|
||||
click.echo(' Ticket Title: {0}'.format(issue_title))
|
||||
click.echo(' Ticket Opened By: {0}'.format(issue_owner))
|
||||
click.echo(' Ticket URL: {0}'.format(issue_ui_url))
|
||||
click.echo(' Action: New Branch')
|
||||
click.echo(' Namespace: {0}'.format(namespace))
|
||||
click.echo(' Name: {0}'.format(repo))
|
||||
click.echo(' Branch: {0}'.format(branch_name))
|
||||
click.echo(' SLs: {0}'.format(', '.join(sla_list)))
|
||||
click.echo(' Git Branch: {0}'.format(bool_to_word(
|
||||
create_git_branch)))
|
||||
|
||||
if not auto_approve:
|
||||
action = prompt_for_ticket_action()
|
||||
else:
|
||||
action = 'approve'
|
||||
|
||||
if action == 'approve':
|
||||
pagure_url = get_config_item(CONFIG, 'pagure_dist_git_url')
|
||||
dist_git_url = '{0}/{1}/{2}'.format(
|
||||
pagure_url.rstrip('/'), namespace, repo)
|
||||
# If the global component already exists, this will not try to create
|
||||
# it
|
||||
pdc.new_global_component(repo, dist_git_url)
|
||||
# Pagure uses plural names for namespaces, but PDC does not use the
|
||||
# plural version for branch types
|
||||
branch_type = pdc.component_type_to_singular(namespace)
|
||||
|
||||
pdc.new_branch(repo, branch_name, branch_type)
|
||||
for sla, eol in issue_body_json['sls'].items():
|
||||
pdc.new_sla_to_branch(
|
||||
sla, eol, repo, branch_name, branch_type)
|
||||
|
||||
if create_git_branch:
|
||||
new_git_branch(namespace, repo, branch_name)
|
||||
new_branch_comment = ('The branch was created in PDC and git. It '
|
||||
'may take up to 10 minutes before you have '
|
||||
'write access on the branch.')
|
||||
else:
|
||||
new_branch_comment = (
|
||||
'The branch in PDC was created. Pagure is still processing '
|
||||
'the request, but in about 10 minutes, you may create the '
|
||||
'branch in Pagure using git.')
|
||||
comment_and_close_ticket(issue_id, bug_id, new_branch_comment,
|
||||
prompt_for_comment=False)
|
||||
elif action == 'deny':
|
||||
comment_body = click.prompt(
|
||||
'Please enter a comment explaining the denial')
|
||||
pagure.close_issue(issue_id, comment_body, 'Denied')
|
||||
if bug_id:
|
||||
BUGZILLA_CLIENT.comment(bug_id, comment_body)
|
||||
else:
|
||||
# This means the admin is skipping this ticket for now
|
||||
# Get the list of FAS groups who can maintain the package
|
||||
access_groups = set(contributors['groups']['admin']) | \
|
||||
set(contributors['groups']['commit']) | \
|
||||
set(g['user']
|
||||
for g in contributors['groups']['collaborators']
|
||||
if fnmatch.fnmatch(branch_name, g['branches']))
|
||||
group_member = False
|
||||
for access_group in access_groups:
|
||||
# Check if the requestor is part of any of the FAS groups who can maintain the package
|
||||
if fedora_account.user_member_of(fedora_account.get_user_by_username(issue_owner), access_group):
|
||||
group_member = True
|
||||
break
|
||||
if issue_owner not in maintainers and not group_member:
|
||||
self.pagure_io.close_issue(
|
||||
issue["id"],
|
||||
namespace=PROJECT_NAMESPACE,
|
||||
message='{0} is not a maintainer of the {1} package'.format(issue_owner, repo),
|
||||
reason="Invalid"
|
||||
)
|
||||
return
|
||||
|
||||
_log.info("Ticket passed all validations. Creating repository.")
|
||||
# Create the PDC entry
|
||||
dist_git_url = '{0}/{1}/{2}'.format(
|
||||
self.dist_git._pagure_url.rstrip('/'), namespace, repo)
|
||||
# If the global component already exists, this will not try to create
|
||||
# it
|
||||
pdc.new_global_component(repo, dist_git_url)
|
||||
|
||||
pdc.new_branch(repo, branch_name, branch_type)
|
||||
for sla, eol in issue_body_json['sls'].items():
|
||||
pdc.new_sla_to_branch(
|
||||
sla, eol, repo, branch_name, branch_type)
|
||||
|
||||
if create_git_branch:
|
||||
with TemporaryDirectory(dir=self.temp_dir) as tmp_dir:
|
||||
repo = git.clone_repo(dist_git_url, tmp_dir)
|
||||
default_branch = self.dist_git.get_default_branch(namespace, repo)
|
||||
commit = repo.first_commit(default_branch)
|
||||
self.dist_git.new_branch(namespace, repo, branch_name, from_commit=commit)
|
||||
new_branch_comment = ('The branch was created in PDC and git. It '
|
||||
'may take up to 10 minutes before you have '
|
||||
'write access on the branch.')
|
||||
else:
|
||||
new_branch_comment = (
|
||||
'The branch in PDC was created. Pagure is still processing '
|
||||
'the request, but in about 10 minutes, you may create the '
|
||||
'branch in Pagure using git.')
|
||||
self.pagure_io.close_issue(
|
||||
issue["id"],
|
||||
namespace=PROJECT_NAMESPACE,
|
||||
message=new_branch_comment,
|
||||
reason="Processed"
|
||||
)
|
||||
|
||||
def validate_review_bug(self, bug_id: str, pkg: str, branch: str,
|
||||
require_auth: bool = False, check_fas: bool = False,
|
||||
namespace: str = 'rpms', pagure_user: Optional[str] = None
|
||||
|
@ -923,25 +907,3 @@ class SCMRequestProcessor(ToddlerBase):
|
|||
'git branch can\'t be created.')
|
||||
pagure.new_branch(
|
||||
namespace, repo, branch, from_commit=git_obj.first_commit(namespace, repo))
|
||||
|
||||
|
||||
def ticket_requires_approval(issue_type, issue):
|
||||
"""
|
||||
Determines if the issue requires approval from an administrator.
|
||||
:param issue_type: a string determining the issue type
|
||||
:param issue: a dictionary of the issue
|
||||
:return: a boolean
|
||||
"""
|
||||
# Only some new_branch requests can be auto-approved
|
||||
if issue_type != 'new_branch':
|
||||
return True
|
||||
|
||||
namespace = issue['namespace'].strip()
|
||||
# Only some RPM requests can be auto-approved for now
|
||||
if namespace != 'rpms':
|
||||
return True
|
||||
|
||||
branch_name = issue['branch'].strip()
|
||||
standard_branch = is_valid_standard_branch(branch_name)
|
||||
return not (standard_branch and not re.match(r'^(el|epel)[0-9]+$',
|
||||
branch_name))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue