This plugin listens for *.git.receive messages on the bus sent by fedora_messaging_git_hook and sends mails to scm-commit-list. Fixes: #183 Signed-off-by: Nils Philippsen <nils@redhat.com>
214 lines
7.1 KiB
Python
214 lines
7.1 KiB
Python
from contextlib import nullcontext
|
||
import datetime as dt
|
||
import random
|
||
from typing import ContextManager, Optional
|
||
from unittest import mock
|
||
|
||
from fedora_messaging.message import Message
|
||
from fedora_messaging_git_hook_messages import CommitV1
|
||
import pytest
|
||
|
||
from toddlers.exceptions import ConfigError
|
||
from toddlers.plugins import distgit_commit_processor
|
||
|
||
|
||
class TestDistGitCommitProcessor:
|
||
"""Test the DistGitCommitProcessor toddler plugin."""
|
||
|
||
toddler_cls = distgit_commit_processor.DistGitCommitProcessor
|
||
|
||
@pytest.mark.parametrize(
|
||
"topic, valid",
|
||
(
|
||
pytest.param("org.fedoraproject.prod.git.receive", True, id="prod-valid"),
|
||
pytest.param("org.fedoraproject.stg.git.receive", True, id="stg-valid"),
|
||
pytest.param(
|
||
"org.fedoraproject.prod.pagure.git.receive",
|
||
False,
|
||
id="pagure-prod-invalid",
|
||
),
|
||
pytest.param(
|
||
"org.fedoraproject.stg.pagure.git.receive",
|
||
False,
|
||
id="pagure-stg-invalid",
|
||
),
|
||
pytest.param(
|
||
"pagure.io.prod.pagure.git.receive", False, id="pagure-io-invalid"
|
||
),
|
||
),
|
||
)
|
||
def test_accepts_topic(
|
||
self,
|
||
topic: str,
|
||
valid: bool,
|
||
toddler: distgit_commit_processor.DistGitCommitProcessor,
|
||
) -> None:
|
||
assert toddler.accepts_topic(topic) is valid
|
||
|
||
@pytest.mark.parametrize(
|
||
"namespace, repo, path, result",
|
||
(
|
||
("rpms", "kernel", "/some/root/rpms/kernel.git/", False),
|
||
("rpms", "kernel", "/some/root/rpms/kernel/", False),
|
||
("frobozzniks", "blomp", "/some/root/rpms/kernel.git/", False),
|
||
("rpms", "kernel", "/some/root/fork/foo/rpms/kernel.git/", True),
|
||
("rpms", "kernel", "/some/root/fork/foo/rpms/kernel", True),
|
||
(None, "project", "/some/root/project.git/", False),
|
||
),
|
||
)
|
||
def test_ignore_commit(
|
||
self,
|
||
namespace: Optional[str],
|
||
repo: str,
|
||
path: str,
|
||
result: bool,
|
||
toddler: distgit_commit_processor.DistGitCommitProcessor,
|
||
caplog: pytest.LogCaptureFixture,
|
||
):
|
||
if namespace:
|
||
repo_with_ns = namespace + "/" + repo
|
||
else:
|
||
repo_with_ns = repo
|
||
|
||
commit = {
|
||
"namespace": namespace,
|
||
"repo": repo,
|
||
"path": path,
|
||
}
|
||
body = {"id": "BOO", "agent": "m0rk", "commit": commit}
|
||
|
||
message = CommitV1(body=body)
|
||
|
||
assert toddler.ignore_commit(message) is result
|
||
|
||
if repo_with_ns in path:
|
||
assert f"Message {message.id} mismatch" not in caplog.text
|
||
else:
|
||
assert f"Message {message.id} mismatch" in caplog.text
|
||
|
||
@pytest.mark.parametrize(
|
||
"testcase",
|
||
(
|
||
"success",
|
||
"success-loglevel-info",
|
||
"success-default-subject",
|
||
"success-default-content",
|
||
"failure-wrong-msg-type",
|
||
"failure-wrong-msg-type-loglevel-info",
|
||
"failure-fork-commit",
|
||
"failure-config-error",
|
||
),
|
||
)
|
||
def test_process(
|
||
self,
|
||
testcase: str,
|
||
toddler: distgit_commit_processor.DistGitCommitProcessor,
|
||
caplog: pytest.LogCaptureFixture,
|
||
) -> None:
|
||
success = "success" in testcase
|
||
wrong_msg_type = "wrong-msg-type" in testcase
|
||
fork_commit = "fork-commit" in testcase
|
||
config_error = "config-error" in testcase
|
||
loglevel_info = "loglevel-info" in testcase
|
||
default_subject = "default-subject" in testcase
|
||
default_content = "default-content" in testcase
|
||
|
||
# Appease mypy
|
||
exception_ctx: ContextManager
|
||
|
||
now = dt.datetime.now(tz=dt.timezone.utc).isoformat()
|
||
|
||
commit = {
|
||
"namespace": "rpms",
|
||
"repo": "kernel",
|
||
"path": "/some/root/rpms/kernel.git/",
|
||
"branch": "rawhide",
|
||
"rev": "deadbeef",
|
||
"name": "Mork",
|
||
"email": "mork@ork.org",
|
||
"date": now,
|
||
"summary": "Did the thing",
|
||
"message": "Did the thing\n\nAmazing.",
|
||
"patch": "No, I won’t fake a diff here.",
|
||
}
|
||
body = {"agent": "m0rk", "commit": commit}
|
||
|
||
if fork_commit:
|
||
commit["path"] = "/some/root/fork/foo/rpms/kernel.git/"
|
||
|
||
msg = CommitV1(body=body)
|
||
if wrong_msg_type:
|
||
msg = Message(body=body)
|
||
|
||
# Config items which must be set
|
||
config = {
|
||
"mail_server": "bastion.fedoraproject.org",
|
||
"mail_from": "notifications@fedoraproject.org",
|
||
"mail_to": "scm-commits@lists.fedoraproject.org",
|
||
}
|
||
if config_error:
|
||
# Nuke a random configuration item
|
||
del config[list(config)[random.randint(0, len(config) - 1)]]
|
||
exception_ctx = pytest.raises(ConfigError)
|
||
else:
|
||
exception_ctx = nullcontext()
|
||
|
||
if not default_subject:
|
||
config["mail_subject_tmpl"] = "SUBJECT-IS-SET: {message.summary}"
|
||
|
||
if not default_content:
|
||
config["mail_content_tmpl"] = "CONTENT-IS-SET\n{message}"
|
||
|
||
with caplog.at_level(
|
||
"INFO" if loglevel_info else "DEBUG"
|
||
), exception_ctx, mock.patch.object(
|
||
distgit_commit_processor, "send_email"
|
||
) as send_email:
|
||
toddler.process(config, msg)
|
||
|
||
if not loglevel_info:
|
||
assert "Processing message:" in caplog.text
|
||
|
||
if success:
|
||
send_email.assert_called_with(
|
||
to_addresses=[config["mail_to"]],
|
||
from_address=config["mail_from"],
|
||
subject=mock.ANY,
|
||
content=mock.ANY,
|
||
mail_server=config["mail_server"],
|
||
)
|
||
|
||
subject = send_email.call_args.kwargs["subject"]
|
||
assert (
|
||
f"{body['agent']} pushed to {commit['namespace']}/{commit['repo']}"
|
||
in subject
|
||
)
|
||
assert f"({commit['branch']})" in subject
|
||
assert f"\"{commit['summary']}\"" in subject
|
||
if default_subject:
|
||
assert "SUBJECT-IS-SET" not in subject
|
||
else:
|
||
assert "SUBJECT-IS-SET" in subject
|
||
|
||
content = send_email.call_args.kwargs["content"]
|
||
assert f"From {commit['rev']}" in content
|
||
assert f"From: {commit['name']} <{commit['email']}>" in content
|
||
assert f"Date: {now}" in content
|
||
assert f"Subject: {commit['summary']}" in content
|
||
assert commit["message"] in content
|
||
if default_content:
|
||
assert "CONTENT-IS-SET" not in content
|
||
else:
|
||
assert "CONTENT-IS-SET" in content
|
||
else:
|
||
send_email.assert_not_called()
|
||
|
||
if wrong_msg_type and not loglevel_info:
|
||
assert "Skipping message" in caplog.text
|
||
else:
|
||
assert "Skipping message" not in caplog.text
|
||
|
||
if fork_commit:
|
||
assert "Ignoring message" in caplog.text
|
||
else:
|
||
assert "Ignoring message" not in caplog.text
|