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:
Michal Konečný 2022-03-14 17:13:03 +01:00
parent e94e1e7162
commit 0ec16b0195
2 changed files with 91 additions and 125 deletions

View file

@ -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 # This is the same format as used by the distgit_bugzilla_sync cron/app
email_overrides_file = "/path/to/email_overrides.toml" 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] [consumer_config.default.pdc_config]
# Configuration to talk to PDC, as understood by pdc-client. # Configuration to talk to PDC, as understood by pdc-client.
server = "https://pdc.fedoraproject.org/rest_api/v1/" server = "https://pdc.fedoraproject.org/rest_api/v1/"

View file

@ -6,14 +6,16 @@ https://pagure.io/releng/fedora-scm-requests/issues.
Authors: Michal Konecny <mkonecny@redhat.com> Authors: Michal Konecny <mkonecny@redhat.com>
""" """
import fnmatch
import logging import logging
import re import re
from tempfile import TemporaryDirectory
import arrow import arrow
from pagure_messages.issue_schema import IssueNewV1 from pagure_messages.issue_schema import IssueNewV1
from toddlers.base import ToddlerBase 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 from toddlers.exceptions import ValidationError
# Regex for branch name validation # Regex for branch name validation
@ -67,6 +69,9 @@ class SCMRequestProcessor(ToddlerBase):
# Pagure object connected to dist-git # Pagure object connected to dist-git
dist_git = None dist_git = None
# Path to temporary dir
temp_dir = None
def accepts_topic(self, topic: str) -> bool: def accepts_topic(self, topic: str) -> bool:
"""Returns a boolean whether this toddler is interested in messages """Returns a boolean whether this toddler is interested in messages
from this specific topic. from this specific topic.
@ -113,6 +118,7 @@ class SCMRequestProcessor(ToddlerBase):
self.monitoring_choices = config.get("monitoring_choices") self.monitoring_choices = config.get("monitoring_choices")
self.pagure_namespace_to_component = config.get("pagure_namespace_to_component") self.pagure_namespace_to_component = config.get("pagure_namespace_to_component")
self.pagure_namespace_to_product = config.get("pagure_namespace_to_product") self.pagure_namespace_to_product = config.get("pagure_namespace_to_product")
self.temp_dir = config.get("temp_dir")
_log.info("Setting up PDC client") _log.info("Setting up PDC client")
pdc.set_pdc(config) pdc.set_pdc(config)
@ -518,18 +524,19 @@ class SCMRequestProcessor(ToddlerBase):
) )
return return
if create_git_branch:
assert_git_repo_initialized_remotely(namespace, repo)
branch_name = issue_body_json['branch'].strip() branch_name = issue_body_json['branch'].strip()
if is_epel(branch_name) and not valid_epel_package(repo, branch_name): if re.match(EPEL_REGEX, branch_name) and not self.valid_epel_package(repo, branch_name):
if not force: self.pagure_io.close_issue(
prompt_to_close_bad_ticket(issue_json, INVALID_EPEL_ERROR) issue["id"],
namespace=PROJECT_NAMESPACE,
message=INVALID_EPEL_ERROR,
reason="Invalid"
)
return return
# Pagure uses plural names for namespaces, but PDC does not use the # Pagure uses plural names for namespaces, but PDC does not use the
# plural version for branch types # plural version for branch types
branch_type = pdc.component_type_to_singular(namespace) branch_type = namespace.strip().rstrip('s')
click.echo('- Checking if {0} already exists in PDC.'.format(branch_name)) _log.info('- Checking if {0} already exists in PDC.'.format(branch_name))
pdc_branch = pdc.get_branch(repo, branch_name, branch_type) pdc_branch = pdc.get_branch(repo, branch_name, branch_type)
if pdc_branch: if pdc_branch:
ticket_text = \ ticket_text = \
@ -540,21 +547,22 @@ class SCMRequestProcessor(ToddlerBase):
"``git checkout -b <branch_name> && git push -u origin <branch_name>``.\n" \ "``git checkout -b <branch_name> && git push -u origin <branch_name>``.\n" \
"``<branch_name>`` is the name of the branch you requested. \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." "You only need to do this once and you can then use fedpkg as you normally do."
prompt_to_close_bad_ticket( self.pagure_io.close_issue(
issue_json, ticket_text) issue["id"],
namespace=PROJECT_NAMESPACE,
message=ticket_text,
reason="Invalid"
)
return return
issue_id = issue_json['id'] issue_id = issue['id']
issue_title = issue_json['title'].strip() issue_title = issue['title'].strip()
issue_owner = issue_json['user']['name'] issue_owner = issue['user']['name']
issue_ui_url = pagure.get_pagure_issue_url(issue_id) issue_ui_url = issue["full_url"]
# Check if the branch requestor is one of the maintainers or part of the groups # 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)) _log.info('- 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 # Get the list of maintainers of the package
maintainers = set(contributors['users']['admin']) | \ maintainers = set(contributors['users']['admin']) | \
set(contributors['users']['commit']) | \ set(contributors['users']['commit']) | \
@ -571,48 +579,25 @@ class SCMRequestProcessor(ToddlerBase):
group_member = False group_member = False
for access_group in access_groups: for access_group in access_groups:
# Check if the requestor is part of any of the FAS groups who can maintain the package # 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): if fedora_account.user_member_of(fedora_account.get_user_by_username(issue_owner), access_group):
group_member = True group_member = True
break break
if issue_owner not in maintainers and not group_member: if issue_owner not in maintainers and not group_member:
prompt_to_close_bad_ticket( self.pagure_io.close_issue(
issue_json, '{0} is not a maintainer of the {1} package'.format(issue_owner, repo) issue["id"],
namespace=PROJECT_NAMESPACE,
message='{0} is not a maintainer of the {1} package'.format(issue_owner, repo),
reason="Invalid"
) )
return return
if auto_approve and \ _log.info("Ticket passed all validations. Creating repository.")
not ticket_requires_approval('new_branch', issue_body_json): # Create the PDC entry
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( dist_git_url = '{0}/{1}/{2}'.format(
pagure_url.rstrip('/'), namespace, repo) self.dist_git._pagure_url.rstrip('/'), namespace, repo)
# If the global component already exists, this will not try to create # If the global component already exists, this will not try to create
# it # it
pdc.new_global_component(repo, dist_git_url) 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) pdc.new_branch(repo, branch_name, branch_type)
for sla, eol in issue_body_json['sls'].items(): for sla, eol in issue_body_json['sls'].items():
@ -620,7 +605,11 @@ class SCMRequestProcessor(ToddlerBase):
sla, eol, repo, branch_name, branch_type) sla, eol, repo, branch_name, branch_type)
if create_git_branch: if create_git_branch:
new_git_branch(namespace, repo, branch_name) 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 ' new_branch_comment = ('The branch was created in PDC and git. It '
'may take up to 10 minutes before you have ' 'may take up to 10 minutes before you have '
'write access on the branch.') 'write access on the branch.')
@ -629,17 +618,12 @@ class SCMRequestProcessor(ToddlerBase):
'The branch in PDC was created. Pagure is still processing ' 'The branch in PDC was created. Pagure is still processing '
'the request, but in about 10 minutes, you may create the ' 'the request, but in about 10 minutes, you may create the '
'branch in Pagure using git.') 'branch in Pagure using git.')
comment_and_close_ticket(issue_id, bug_id, new_branch_comment, self.pagure_io.close_issue(
prompt_for_comment=False) issue["id"],
elif action == 'deny': namespace=PROJECT_NAMESPACE,
comment_body = click.prompt( message=new_branch_comment,
'Please enter a comment explaining the denial') reason="Processed"
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
return
def validate_review_bug(self, bug_id: str, pkg: str, branch: str, def validate_review_bug(self, bug_id: str, pkg: str, branch: str,
require_auth: bool = False, check_fas: bool = False, require_auth: bool = False, check_fas: bool = False,
@ -923,25 +907,3 @@ class SCMRequestProcessor(ToddlerBase):
'git branch can\'t be created.') 'git branch can\'t be created.')
pagure.new_branch( pagure.new_branch(
namespace, repo, branch, from_commit=git_obj.first_commit(namespace, repo)) 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))