diff --git a/tests/plugins/test_scm_request_processor.py b/tests/plugins/test_scm_request_processor.py index bc1e79f..8fe7e13 100644 --- a/tests/plugins/test_scm_request_processor.py +++ b/tests/plugins/test_scm_request_processor.py @@ -2519,3 +2519,49 @@ class TestValidEpelPackage: ) assert result is True + + +class TestMain: + """ + Test class for `toddlers.plugins.scm_request_processor.main` function. + """ + + def test_main_no_args(self, capsys): + """Assert that help is printed if no arg is provided.""" + with pytest.raises(SystemExit): + scm_request_processor.main([]) + + out, err = capsys.readouterr() + assert out == "" + # Expecting something along these lines, but don't make the test too tight: + # + # usage: pytest [-h] [--dry-run] [-q | --debug] conf [username] + # pytest: error: the following arguments are required: conf + assert err.startswith("usage:") + assert "error: the following arguments are required:" in err + + @patch("toml.load") + @patch("toddlers.plugins.scm_request_processor.SCMRequestProcessor.process") + @patch("toddlers.plugins.scm_request_processor.pagure") + def test_main(self, mock_pagure, mock_process, mock_toml): + """Assert that main is initializing config and message correctly.""" + # Preparation + mock_toml.return_value = {} + mock_pagure_io = Mock() + mock_issue = {"id": 100} + mock_pagure_io.get_issue.return_value = mock_issue + + mock_pagure.set_pagure.return_value = mock_pagure_io + + # Function to test + scm_request_processor.main(["--config", "test.cfg", "100"]) + + # Assertions + mock_toml.assert_called_with("test.cfg") + mock_pagure.set_pagure.assert_called_with({}) + mock_pagure_io.get_issue.assert_called_with( + 100, scm_request_processor.PROJECT_NAMESPACE + ) + message = IssueNewV1() + message.body["issue"] = mock_issue + mock_process.assert_called_with(config={}, message=message) diff --git a/toddlers/plugins/scm_request_processor.py b/toddlers/plugins/scm_request_processor.py index 6cf2aaa..8a177b3 100644 --- a/toddlers/plugins/scm_request_processor.py +++ b/toddlers/plugins/scm_request_processor.py @@ -6,15 +6,19 @@ https://pagure.io/releng/fedora-scm-requests/issues. Authors: Michal Konecny """ +import argparse import fnmatch import json import logging import re +import sys from tempfile import TemporaryDirectory from typing import Optional import arrow +from fedora_messaging.api import Message from pagure_messages.issue_schema import IssueNewV1 +import toml from toddlers.base import ToddlerBase from toddlers.exceptions import ValidationError @@ -91,13 +95,15 @@ class SCMRequestProcessor(ToddlerBase): return True if topic.endswith("pagure.issue.edit"): return True + if topic.endswith("pagure.issue.comment.added"): + return True return False def process( self, config: dict, - message: IssueNewV1, + message: Message, ) -> None: """Process a given message. @@ -931,3 +937,88 @@ class SCMRequestProcessor(ToddlerBase): if pkg_arches == set(["noarch"]) or not (all_arches - pkg_arches): return False return True + + +def _get_arguments(args): + """Load and parse the CLI arguments. + + :arg args: Script arguments + + :returns: Parsed arguments + """ + parser = argparse.ArgumentParser( + description="Processor for SCM requests, handling tickets from '{}'".format( + PROJECT_NAMESPACE + ) + ) + + parser.add_argument("ticket", type=int, help="Number of ticket to process") + + parser.add_argument( + "--config", + help="Configuration file", + ) + + parser.add_argument( + "--debug", + action="store_const", + dest="log_level", + const=logging.DEBUG, + default=logging.INFO, + help="Enable debugging output", + ) + + return parser.parse_args(args) + + +def _setup_logging(log_level: int) -> None: + """Setup the logging level. + + :arg log_level: Log level to set + """ + handlers = [] + + _log.setLevel(log_level) + # We want all messages logged at level INFO or lower to be printed to stdout + info_handler = logging.StreamHandler(stream=sys.stdout) + handlers.append(info_handler) + + if log_level == logging.INFO: + # In normal operation, don't decorate messages + for handler in handlers: + handler.setFormatter(logging.Formatter("%(message)s")) + + logging.basicConfig(level=log_level, handlers=handlers) + + +def main(args): + """Main function.""" + args = _get_arguments(args) + _setup_logging(log_level=args.log_level) + + config = toml.load(args.config) + parsed_config = config.get("consumer_config", {}).get("default", {}) + parsed_config.update( + config.get("consumer_config", {}).get("scm_request_processor", {}) + ) + + ticket = args.ticket + + pagure_io = pagure.set_pagure(parsed_config) + issue = pagure_io.get_issue(ticket, PROJECT_NAMESPACE) + + # Convert issue to message + message = IssueNewV1() + message.body["issue"] = issue + + SCMRequestProcessor().process( + config=parsed_config, + message=message, + ) + + +if __name__ == "__main__": # pragma: no cover + try: + main(sys.argv[1:]) + except KeyboardInterrupt: + pass