Skip to content

Commit

Permalink
Add MergeRequestLabelGitlabEvent & MergeRequestLabelHandler
Browse files Browse the repository at this point in the history
MergeRequestLabelHandler was renamed from PagurePullRequestLabelHandler
and reacts to MergeRequestLabelGitlabEvent (inherits from MergeRequestGitlabEvent
which now has also source_repo_branch & target_repo_branch attributes).

Creating a Bugzilla bug is now restricted also to set of allowed namespaces and branches.

The now unused code for handling labels on Pagure has been removed.
  • Loading branch information
jpopelka committed May 7, 2021
1 parent 33d76e6 commit d1613ea
Show file tree
Hide file tree
Showing 13 changed files with 406 additions and 221 deletions.
18 changes: 13 additions & 5 deletions packit_service/config.py
Expand Up @@ -68,8 +68,6 @@ def __eq__(self, other: object) -> bool:


class ServiceConfig(Config):
service_config = None

def __init__(
self,
deployment: Deployment = Deployment.stg,
Expand All @@ -81,7 +79,9 @@ def __init__(
fas_password: Optional[str] = "",
bugzilla_url: str = "",
bugzilla_api_key: str = "",
pr_accepted_labels: List[str] = None,
bugz_labels: List[str] = None,
bugz_namespaces: List[str] = None,
bugz_branches: List[str] = None,
gitlab_webhook_tokens: List[str] = None,
enabled_private_namespaces: Union[Set[str], List[str]] = None,
gitlab_token_secret: str = "",
Expand All @@ -108,8 +108,14 @@ def __init__(

self.bugzilla_url = bugzilla_url
self.bugzilla_api_key = bugzilla_api_key
# Labels/Tags to mark a PR as accepted - handler will create a bug & attach patch from PR
self.pr_accepted_labels: Set[str] = set(pr_accepted_labels or ["accepted"])
# Labels/Tags to mark a MR as accepted - handler will create a bug & attach patch from PR
self.bugz_labels: Set[str] = set(bugz_labels or ["accepted"])
# Create bugs only for MRs against these namespaces
self.bugz_namespaces: Set[str] = set(
bugz_namespaces or ["redhat/centos-stream/src"]
)
# Create bugs only for MRs against one of these branches (regex set)
self.bugz_branches: Set[str] = set(bugz_branches or [r"^c8s"])

# List of github users who are allowed to trigger p-s on any repository
self.admins: Set[str] = set(admins or [])
Expand Down Expand Up @@ -139,6 +145,8 @@ def __init__(
self.koji_logs_url = koji_logs_url
self.koji_web_url = koji_web_url

service_config = None

def __repr__(self):
def hide(token: str) -> str:
return f"{token[:1]}***{token[-1:]}" if token else ""
Expand Down
4 changes: 3 additions & 1 deletion packit_service/schema.py
Expand Up @@ -52,7 +52,9 @@ class ServiceConfigSchema(UserConfigSchema):
validate_webhooks = fields.Bool(default=False)
bugzilla_url = fields.String(default="")
bugzilla_api_key = fields.String(default="")
pr_accepted_labels = fields.List(fields.String())
bugz_labels = fields.List(fields.String())
bugz_namespaces = fields.List(fields.String())
bugz_branches = fields.List(fields.String())
admins = fields.List(fields.String())
server_name = fields.String()
gitlab_webhook_tokens = fields.List(fields.String())
Expand Down
74 changes: 32 additions & 42 deletions packit_service/service/events.py
Expand Up @@ -13,6 +13,7 @@
from ogr.abstract import GitProject
from ogr.services.pagure import PagureProject
from packit.config import PackageConfig, get_package_config_from_repo

from packit_service.config import PackageConfigGetter, ServiceConfig
from packit_service.constants import KojiBuildState
from packit_service.models import (
Expand Down Expand Up @@ -504,10 +505,12 @@ def __init__(
username: str,
object_id: int,
object_iid: int,
source_repo_name: str,
source_repo_namespace: str,
source_repo_name: str,
source_repo_branch: str,
target_repo_namespace: str,
target_repo_name: str,
target_repo_branch: str,
project_url: str,
commit_sha: str,
):
Expand All @@ -519,10 +522,12 @@ def __init__(
self.user_login = username
self.object_id = object_id
self.identifier = str(object_iid)
self.source_repo_name = source_repo_name
self.source_repo_namespace = source_repo_namespace
self.source_repo_name = source_repo_name
self.source_repo_branch = source_repo_branch
self.target_repo_namespace = target_repo_namespace
self.target_repo_name = target_repo_name
self.target_repo_branch = target_repo_branch
self.project_url = project_url
self.commit_sha = commit_sha

Expand All @@ -539,6 +544,31 @@ def get_base_project(self) -> GitProject:
return fork


class MergeRequestLabelGitlabEvent(MergeRequestGitlabEvent):
def __init__(
self,
mr_event: MergeRequestGitlabEvent,
labels_added: List[str],
labels_removed: List[str],
):
super().__init__(
action=mr_event.action,
username=mr_event.user_login,
object_id=mr_event.object_id,
object_iid=int(mr_event.identifier),
source_repo_namespace=mr_event.source_repo_namespace,
source_repo_name=mr_event.source_repo_name,
source_repo_branch=mr_event.source_repo_branch,
target_repo_namespace=mr_event.target_repo_namespace,
target_repo_name=mr_event.target_repo_name,
target_repo_branch=mr_event.target_repo_branch,
project_url=mr_event.project_url,
commit_sha=mr_event.commit_sha,
)
self.labels_added = labels_added
self.labels_removed = labels_removed


class PullRequestGithubEvent(AddPullRequestDbTrigger, AbstractGithubEvent):
def __init__(
self,
Expand Down Expand Up @@ -1322,43 +1352,3 @@ def get_base_project(self) -> GitProject:
)
logger.debug(f"Base project: {fork} owned by {self.base_repo_owner}")
return fork


class PullRequestLabelPagureEvent(AddPullRequestDbTrigger, AbstractPagureEvent):
def __init__(
self,
action: PullRequestLabelAction,
pr_id: int,
base_repo_namespace: str,
base_repo_name: str,
base_repo_owner: str,
base_ref: Optional[str],
commit_sha: str,
project_url: str,
labels: List[str],
):
super().__init__(project_url=project_url, pr_id=pr_id)
self.action = action
self.base_repo_namespace = base_repo_namespace
self.base_repo_name = base_repo_name
self.base_repo_owner = base_repo_owner
self.base_ref = base_ref
self.identifier = str(pr_id)
self.git_ref = None # pr_id will be used for checkout
self.commit_sha = commit_sha
self.labels = labels

def get_dict(self, default_dict: Optional[Dict] = None) -> dict:
result = super().get_dict()
result["action"] = result["action"].value
return result

def get_base_project(self) -> GitProject:
fork = self.project.service.get_project(
namespace=self.base_repo_namespace,
repo=self.base_repo_name,
username=self.base_repo_owner,
is_fork=True,
)
logger.debug(f"Base project: {fork} owned by {self.base_repo_owner}")
return fork
2 changes: 2 additions & 0 deletions packit_service/worker/handlers/__init__.py
Expand Up @@ -25,6 +25,7 @@
)
from packit_service.worker.handlers.forges_handlers import (
GithubAppInstallationHandler,
MergeRequestLabelHandler,
)
from packit_service.worker.handlers.koji_handlers import (
KojiBuildHandler,
Expand All @@ -43,6 +44,7 @@
CoprBuildEndHandler.__name__,
CoprBuildStartHandler.__name__,
GithubAppInstallationHandler.__name__,
MergeRequestLabelHandler.__name__,
ProposeDownstreamHandler.__name__,
DistGitCommitHandler.__name__,
TestingFarmHandler.__name__,
Expand Down
2 changes: 1 addition & 1 deletion packit_service/worker/handlers/abstract.py
Expand Up @@ -178,7 +178,7 @@ class TaskName(str, enum.Enum):
propose_downstream = "task.run_propose_downstream_handler"
koji_build = "task.run_koji_build_handler"
distgit_commit = "task.run_distgit_commit_handler"
pagure_pr_label = "task.run_pagure_pr_label_handler"
mr_label = "task.run_mr_label_handler"
koji_build_report = "task.run_koji_build_report_handler"


Expand Down
87 changes: 58 additions & 29 deletions packit_service/worker/handlers/forges_handlers.py
Expand Up @@ -6,7 +6,8 @@
TODO: The build and test handlers are independent and should be moved away.
"""
import logging
from typing import Optional
import re
from typing import Optional, Set

from ogr.abstract import CommitStatus, PullRequest
from packit.config import (
Expand All @@ -20,8 +21,7 @@
)
from packit_service.service.events import (
InstallationEvent,
PullRequestLabelPagureEvent,
PullRequestLabelAction,
MergeRequestLabelGitlabEvent,
)
from packit_service.worker.allowlist import Allowlist
from packit_service.worker.handlers.abstract import (
Expand Down Expand Up @@ -97,9 +97,9 @@ def run(self) -> TaskResults:
return TaskResults(success=True, details={"msg": msg})


@reacts_to(event=PullRequestLabelPagureEvent)
class PagurePullRequestLabelHandler(JobHandler):
task_name = TaskName.pagure_pr_label
@reacts_to(MergeRequestLabelGitlabEvent)
class MergeRequestLabelHandler(JobHandler):
task_name = TaskName.mr_label

def __init__(
self, package_config: PackageConfig, job_config: JobConfig, event: dict
Expand All @@ -109,11 +109,16 @@ def __init__(
job_config=job_config,
event=event,
)
self.labels = set(event.get("labels"))
self.action = PullRequestLabelAction(event.get("action"))
self.base_repo_owner = event.get("base_repo_owner")
self.base_repo_name = event.get("base_repo_name")
self.base_repo_namespace = event.get("base_repo_namespace")
self.labels_added: Set[str] = set(
event["labels_added"] if "labels_added" in event else []
)
self.labels_re: Set[str] = set(
event["labels_removed"] if "labels_removed" in event else []
)

self.target_repo_name = event.get("target_repo_name")
self.target_repo_namespace = event.get("target_repo_namespace")
self.target_repo_branch = event.get("target_repo_branch")

self.pr: PullRequest = self.project.get_pr(self.data.pr_id)
# lazy properties
Expand All @@ -126,8 +131,8 @@ def bz_model(self) -> Optional[BugzillaModel]:
if self._bz_model is None:
self._bz_model = BugzillaModel.get_by_pr(
pr_id=self.data.pr_id,
namespace=self.base_repo_namespace,
repo_name=self.base_repo_name,
namespace=self.target_repo_namespace,
repo_name=self.target_repo_name,
project_url=self.data.project_url,
)
return self._bz_model
Expand All @@ -151,17 +156,27 @@ def status_reporter(self) -> StatusReporter:

def _create_bug(self):
"""Fill a Bugzilla bug and store in db."""
description = f"""This bug has been opened as a response to a Merge Request (MR)
{self.pr.url}
in the source-git repository being approved ("accepted" label added).
For more info
https://wiki.centos.org/Contribute/CentOSStream
https://docs.centos.org/en-US/stream-contrib
How to get a patch from the MR:
curl {self.pr.url}.patch"""
bug_id, bug_url = self.bugzilla.create_bug(
product="Red Hat Enterprise Linux 8",
version="CentOS Stream",
component=self.base_repo_name,
component=self.target_repo_name,
summary=self.pr.title,
description=f"Based on approved CentOS Stream pull-request: {self.pr.url}",
description=description,
)
self._bz_model = BugzillaModel.get_or_create(
pr_id=self.data.pr_id,
namespace=self.base_repo_namespace,
repo_name=self.base_repo_name,
namespace=self.target_repo_namespace,
repo_name=self.target_repo_name,
project_url=self.data.project_url,
bug_id=bug_id,
bug_url=bug_url,
Expand All @@ -171,7 +186,7 @@ def _attach_patch(self):
"""Attach a patch from the pull request to the bug."""
if not (self.bz_model and self.bz_model.bug_id):
raise RuntimeError(
"PagurePullRequestLabelHandler._attach_patch(): bug_id not set"
"MergeRequestLabelHandler._attach_patch(): bug_id not set"
)

self.bugzilla.add_patch(
Expand All @@ -186,7 +201,7 @@ def _set_status(self):
"""
if not (self.bz_model and self.bz_model.bug_id and self.bz_model.bug_url):
raise RuntimeError(
"PagurePullRequestLabelHandler._set_status(): bug_id or bug_url not set"
"MergeRequestLabelHandler._set_status(): bug_id or bug_url not set"
)

self.status_reporter.set_status(
Expand All @@ -198,17 +213,31 @@ def _set_status(self):

def run(self) -> TaskResults:
logger.debug(
f"Handling labels/tags {self.labels} {self.action.value} to Pagure PR "
f"{self.base_repo_owner}/{self.base_repo_namespace}/"
f"{self.base_repo_name}/{self.data.identifier}"
f"Handling labels {self.labels_added} added to MR "
f"{self.target_repo_namespace}/{self.target_repo_name}/{self.data.identifier} "
f"branch {self.target_repo_branch}"
)
if self.labels.intersection(self.service_config.pr_accepted_labels):
if not self.bz_model:
self._create_bug()
self._attach_patch()
self._set_status()
else:
if not self.labels_added.intersection(self.service_config.bugz_labels):
logger.debug(f"We accept only {self.service_config.bugz_labels} labels")
return TaskResults(success=True)
if not any(
re.match(n, self.target_repo_namespace)
for n in self.service_config.bugz_namespaces
):
logger.debug(
f"We accept only {self.service_config.pr_accepted_labels} labels/tags"
f"We accept only {self.service_config.bugz_namespaces} namespaces"
)
return TaskResults(success=True)
if not any(
re.match(b, self.target_repo_branch)
for b in self.service_config.bugz_branches
):
logger.debug(f"We accept only {self.service_config.bugz_branches} branches")
return TaskResults(success=True)

if not self.bz_model:
self._create_bug()
# We used to attach patch from CentOS Pagure, but don't do it on Gitlab
# self._attach_patch()
self._set_status()
return TaskResults(success=True)

0 comments on commit d1613ea

Please sign in to comment.