diff --git a/packit_service/utils.py b/packit_service/utils.py index 70a2e6f6d..6df032ac0 100644 --- a/packit_service/utils.py +++ b/packit_service/utils.py @@ -334,12 +334,28 @@ def get_comment_parser_fedora_ci( ) test_parser = subparsers.add_parser("test", help="Run tests in Testing Farm") test_parser.add_argument( - "target", + "test_identifier", nargs="?", choices=["installability", "rpmlint", "rpminspect", "custom"], help="Specific type of tests to run", ) - subparsers.add_parser("scratch-build", help="Build package in Koji") + + test_parser.add_argument( + "--target", + dest="check_target", + nargs="?", + choices=["eln", "rawhide"], + help="Target for which to trigger tests", + ) + + scratch_build_parser = subparsers.add_parser("scratch-build", help="Build package in Koji") + scratch_build_parser.add_argument( + "--target", + dest="check_target", + nargs="?", + choices=["eln", "rawhide"], + help="Target for which to trigger a scratch build in Koji", + ) return parser diff --git a/packit_service/worker/handlers/abstract.py b/packit_service/worker/handlers/abstract.py index cc7728c70..9aa2988a5 100644 --- a/packit_service/worker/handlers/abstract.py +++ b/packit_service/worker/handlers/abstract.py @@ -70,6 +70,37 @@ class RateLimitRequeueException(Exception): MAP_COMMENT_TO_HANDLER_FEDORA_CI: dict[str, set[type["FedoraCIJobHandler"]]] = defaultdict(set) MAP_CHECK_PREFIX_TO_HANDLER: dict[str, set[type["JobHandler"]]] = defaultdict(set) +MAP_TARGET_TO_HANDLER: dict[type["FedoraCIJobHandler"], str] = defaultdict(str) + + +def corresponds_to_check_target(check_target: str): + """ + [class decorator] + Specify which target the handler corresponds to. + + Normally, when retriggering jobs on ELN rawhide PRs with no + existing eln branch, jobs would be run for both the rawhide + and eln targets. When the check target is specified like this, + + /packit-ci test installability rawhide + + then only the handler corresponding to the specified target + (rawhide in this example) will be run, resulting in jobs being run + only for the desired target. + + Example: + ``` + @corresponds_to_check_target(check_target="rawhide") + class DownstreamKojiScratchBuildHandler( + ``` + """ + + def _add_to_mapping(kls: type["FedoraCIJobHandler"]): + MAP_TARGET_TO_HANDLER[kls] = check_target + return kls + + return _add_to_mapping + def configured_as(job_type: JobType): """ diff --git a/packit_service/worker/handlers/distgit.py b/packit_service/worker/handlers/distgit.py index 18ece4e14..b12f7f983 100644 --- a/packit_service/worker/handlers/distgit.py +++ b/packit_service/worker/handlers/distgit.py @@ -95,6 +95,7 @@ RetriableJobHandler, TaskName, configured_as, + corresponds_to_check_target, reacts_to, reacts_to_as_fedora_ci, run_for_check_rerun, @@ -776,6 +777,7 @@ def _run(self) -> TaskResults: @run_for_comment_as_fedora_ci(command="scratch-build") +@corresponds_to_check_target(check_target="rawhide") @reacts_to_as_fedora_ci(event=pagure.pr.Action) @reacts_to_as_fedora_ci(event=pagure.pr.Comment) class DownstreamKojiScratchBuildHandler( @@ -1010,6 +1012,7 @@ def run_koji_build( @run_for_comment_as_fedora_ci(command="scratch-build") +@corresponds_to_check_target(check_target="eln") @reacts_to_as_fedora_ci(event=pagure.pr.Action) @reacts_to_as_fedora_ci(event=pagure.pr.Comment) class DownstreamKojiELNScratchBuildHandler(DownstreamKojiScratchBuildHandler): diff --git a/packit_service/worker/handlers/testing_farm.py b/packit_service/worker/handlers/testing_farm.py index 987bdf06e..0572b5d5f 100644 --- a/packit_service/worker/handlers/testing_farm.py +++ b/packit_service/worker/handlers/testing_farm.py @@ -66,6 +66,7 @@ RetriableJobHandler, TaskName, configured_as, + corresponds_to_check_target, reacts_to, reacts_to_as_fedora_ci, run_for_check_rerun, @@ -358,6 +359,7 @@ def _run(self) -> TaskResults: @run_for_comment_as_fedora_ci(command="test") +@corresponds_to_check_target(check_target="rawhide") @reacts_to_as_fedora_ci(event=koji.result.Task) @reacts_to_as_fedora_ci(event=pagure.pr.Comment) class DownstreamTestingFarmHandler( @@ -518,6 +520,7 @@ def _run(self) -> TaskResults: @run_for_comment_as_fedora_ci(command="test") +@corresponds_to_check_target(check_target="eln") @reacts_to_as_fedora_ci(event=pagure.pr.Comment) class DownstreamTestingFarmELNHandler(DownstreamTestingFarmHandler): """ diff --git a/packit_service/worker/jobs.py b/packit_service/worker/jobs.py index 8e31e25fb..d881af0f9 100644 --- a/packit_service/worker/jobs.py +++ b/packit_service/worker/jobs.py @@ -66,6 +66,7 @@ MAP_COMMENT_TO_HANDLER_FEDORA_CI, MAP_JOB_TYPE_TO_HANDLER, MAP_REQUIRED_JOB_TYPE_TO_HANDLER, + MAP_TARGET_TO_HANDLER, SUPPORTED_EVENTS_FOR_HANDLER, SUPPORTED_EVENTS_FOR_HANDLER_FEDORA_CI, FedoraCIJobHandler, @@ -112,6 +113,7 @@ class ParsedComment: command: Optional[str] = None package: Optional[str] = None + check_target: Optional[str] = None def parse_comment( @@ -143,7 +145,8 @@ def parse_comment( try: args = parser.parse_args(commands) - return ParsedComment(command=args.command, package=args.package) + check_target = getattr(args, "check_target", None) + return ParsedComment(command=args.command, package=args.package, check_target=check_target) except SystemExit: # tests expect invalid syntax comments be ignored logger.debug( @@ -176,12 +179,16 @@ def get_handlers_for_command( def get_handlers_for_command_fedora_ci( command: str, + check_target: Optional[str], ) -> set[type[FedoraCIJobHandler]]: """ - Get handlers for the given command. + Get handlers for the given command. If check_target is specified + (for example: eln), then only handlers relevant to this target + will be returned. Args: command: command to get handler to + check_target: target for which to run jobs Returns: Set of handlers for Fecora CI that are triggered by command. @@ -192,6 +199,12 @@ def get_handlers_for_command_fedora_ci( handlers = MAP_COMMENT_TO_HANDLER_FEDORA_CI[command] if not handlers: logger.debug(f"Command {command} not supported by packit.") + + if check_target: + handlers = { + handler for handler in handlers if MAP_TARGET_TO_HANDLER[handler] == check_target + } + return handlers @@ -550,7 +563,11 @@ def _post_fedora_ci_transition_comment(self) -> None: # Don't fail the job if we can't post the comment logger.warning(f"Failed to post CI transition comment: {ex}") - def report_task_accepted_for_fedora_ci(self, handler_kls: type[FedoraCIJobHandler]): + def report_task_accepted_for_fedora_ci( + self, + handler_kls: type[FedoraCIJobHandler], + user_specified_target_branch: Optional[str] = None, + ): """ For CI-related dist-git PR comment events report the initial status "Task was accepted" to inform user we are working on the request. @@ -570,10 +587,12 @@ def report_task_accepted_for_fedora_ci(self, handler_kls: type[FedoraCIJobHandle if (target_branch := self.event.pull_request_object.target_branch) == "main": target_branch = "rawhide" + # target_branch determines the check's title such as: + # "Packit - installability - rawhide [beaf90b]" helper = FedoraCIHelper( project=self.event.project, metadata=metadata, - target_branch=target_branch, + target_branch=user_specified_target_branch or target_branch, ) first_status_reported = False @@ -681,9 +700,10 @@ def process_fedora_ci_jobs(self) -> list[TaskResults]: A list of task results for each task created. """ handlers_triggered_by_job = None + check_target = None + # [XXX] if there are ever monorepos in Fedora CI… # monorepo_package = None - if isinstance(self.event, abstract.comment.CommentEvent): arguments = parse_comment( self.event.comment, @@ -693,7 +713,8 @@ def process_fedora_ci_jobs(self) -> list[TaskResults]: # [XXX] if there are ever monorepos in Fedora CI… # monorepo_package = arguments.package command = arguments.command - handlers_triggered_by_job = get_handlers_for_command_fedora_ci(command) + check_target = getattr(arguments, "check_target", None) + handlers_triggered_by_job = get_handlers_for_command_fedora_ci(command, check_target) matching_handlers = { handler @@ -724,7 +745,7 @@ def process_fedora_ci_jobs(self) -> list[TaskResults]: # if monorepo_package and handler_kls.job_config.package == monorepo_package: # continue - self.report_task_accepted_for_fedora_ci(handler_kls) + self.report_task_accepted_for_fedora_ci(handler_kls, check_target) celery_signature = celery.signature( handler_kls.task_name.value, diff --git a/tests/integration/test_pr_comment.py b/tests/integration/test_pr_comment.py index 23d29399a..ee6ced1a4 100644 --- a/tests/integration/test_pr_comment.py +++ b/tests/integration/test_pr_comment.py @@ -103,7 +103,9 @@ from packit_service.worker.result import TaskResults from packit_service.worker.tasks import ( run_downstream_koji_build, + run_downstream_koji_eln_scratch_build_handler, run_downstream_koji_scratch_build_handler, + run_downstream_testing_farm_eln_handler, run_downstream_testing_farm_handler, run_help_pr_handler, run_koji_build_handler, @@ -3630,3 +3632,398 @@ def test_downstream_testing_farm_retrigger_specific_plan_via_dist_git_pr_comment [(uid, check_name)], comment, ) + + +@pytest.mark.parametrize( + "comment, target_branch, checks, test_runs, check_target", + [ + pytest.param( + "/packit-ci test installability --target rawhide", + "rawhide", + { + ( + "Packit-stg - installability - rawhide [beaf90b]", + "be4571bd828a699b35ed3102fc7e88f5", + ) + }, + 1, + "rawhide", + id="installability - rawhide branch, rawhide target", + ), + pytest.param( + "/packit-ci test rpminspect --target eln", + "rawhide", + {("Packit-stg - rpminspect - eln [beaf90b]", "bb18abcfd81c6e8f66320513e432b4cd")}, + 1, + "eln", + id="rpminspect - rawhide branch, eln target", + ), + pytest.param( + "/packit-ci test --target eln", + "rawhide", + { + ("Packit-stg - installability - eln [beaf90b]", "ca546b82b2aeb2fcef8bf12746f0bd06"), + ("Packit-stg - rpminspect - eln [beaf90b]", "bb18abcfd81c6e8f66320513e432b4cd"), + ("Packit-stg - rpmlint - eln [beaf90b]", "de24b7b63bf38420bdfea804d3bf56d7"), + }, + 3, + "eln", + id="rpminspect - rawhide branch, eln target", + ), + ], +) +def test_downstream_testing_farm_retrigger_rawhide_pr_eln_package_fedora_ci( + pagure_pr_comment_added, + comment, + target_branch, + checks, + test_runs, + check_target, +): + pagure_pr_comment_added["pullrequest"]["comments"][0]["comment"] = comment + pagure_pr_comment_added["pullrequest"]["branch"] = target_branch + + pr_object = flexmock(target_branch=target_branch, head_commit="abcdef") + + for check_name, uid in checks: + pr_object.should_receive("set_flag").with_args( + username=check_name, + comment="The task was accepted.", + url=str, + status=CommitStatus, + uid=uid, + ) + + dg_project = ( + flexmock( + PagureProject( + namespace="rpms", repo="python-teamcity-messages", service=flexmock(read_only=False) + ), + default_branch="main", + ) + .should_receive("is_private") + .and_return(False) + .mock() + .should_receive("get_pr") + .and_return(pr_object) + .mock() + .should_receive("get_files") + .and_return([]) + .mock() + .should_receive("get_file_content") + .and_raise(FileNotFoundError) + .mock() + .should_receive("get_web_url") + .and_return("URL") + .mock() + .should_receive("get_git_urls") + .and_return( + {"git": "https://src.fedoraproject.org/rpms/python-teamcity-messages.git"}, + ) + .mock() + ) + service_config = ( + flexmock( + enabled_projects_for_fedora_ci="https://src.fedoraproject.org/rpms/python-teamcity-messages", + fedora_ci_run_by_default=False, + disabled_projects_for_fedora_ci=set(), + command_handler_work_dir=SANDCASTLE_WORK_DIR, + repository_cache="/tmp/repository-cache", + add_repositories_to_repository_cache=False, + deployment=Deployment.stg, + comment_command_prefix="/packit", + package_config_path_override=None, + testing_farm_api_url="https://api.dev.testing-farm.io/api", + testing_farm_secret="secret", + ) + .should_receive("get_project") + .and_return(dg_project) + .mock() + ) + flexmock(ServiceConfig).should_receive("get_service_config").and_return(service_config) + flexmock(PackitAPIWithDownstreamMixin).should_receive("is_packager").and_return( + True, + ) + db_project_object = flexmock( + id=9, + job_config_trigger_type=JobConfigTriggerType.pull_request, + project_event_model_type=ProjectEventModelType.pull_request, + project=flexmock(project_url="https://src.fedoraproject.org/rpms/python-teamcity-messages"), + ) + db_project_event = ( + flexmock().should_receive("get_project_event_object").and_return(db_project_object).mock() + ) + flexmock(ProjectEventModel).should_receive("get_or_create").with_args( + type=ProjectEventModelType.pull_request, + event_id=9, + commit_sha="abcd", + ).and_return(flexmock()) + flexmock(PullRequestModel).should_receive("get_or_create").with_args( + pr_id=36, + namespace="rpms", + repo_name="python-teamcity-messages", + project_url="https://src.fedoraproject.org/rpms/python-teamcity-messages", + ).and_return(db_project_object) + flexmock(ProjectEventModel).should_receive("get_or_create").and_return( + db_project_event, + ) + + run = flexmock(test_run_group=None) + koji_build = flexmock( + id=123, + target="eln" if check_target == "eln" else "main", + status="success", + group_of_targets=flexmock(runs=[run]), + ) + + test_run = flexmock( + id=1, + status=TestingFarmResult.new, + koji_builds=[koji_build], + target=check_target, + ) + flexmock(PipelineModel).should_receive("create").and_return(run) + flexmock(TFTTestRunTargetModel).should_receive("create").and_return(test_run) + flexmock(TFTTestRunGroupModel).should_receive("create").with_args( + run, ranch="public" + ).and_return( + flexmock(grouped_targets=[test_run]), + ) + + flexmock(KojiBuildTargetModel).should_receive( + "get_last_successful_scratch_by_commit_target" + ).with_args("abcdef", check_target).and_return(koji_build) + + flexmock(DownstreamTestingFarmJobHelper).should_receive("run_testing_farm").times( + test_runs + ).and_return( + TaskResults(success=True, details={}), + ) + + flexmock(utils).should_receive("get_eln_packages").and_return(["python-teamcity-messages"]) + + flexmock(Signature).should_receive("apply_async").once() + flexmock(Pushgateway).should_receive("push").times(2).and_return() + + flexmock(commands).should_receive("run_command").with_args( + [ + "git", + "ls-remote", + "https://src.fedoraproject.org/rpms/python-teamcity-messages.git", + "eln", + ], + output=True, + ).and_return(flexmock(stdout="")) + + processing_results = SteveJobs().process_message(pagure_pr_comment_added) + event_dict, _, job_config, package_config = get_parameters_from_results( + processing_results, + ) + assert json.dumps(event_dict) + + if check_target == "rawhide": + results = run_downstream_testing_farm_handler( + event=event_dict, + package_config=package_config, + job_config=job_config, + ) + + elif check_target == "eln": + results = run_downstream_testing_farm_eln_handler( + event=event_dict, + package_config=package_config, + job_config=job_config, + ) + + assert first_dict_value(results["job"])["success"] + + +@pytest.mark.parametrize( + "comment, target_branch, uid, check_name, check_target", + [ + pytest.param( + "/packit-ci scratch-build --target rawhide", + "rawhide", + "7f6d17aef35c10b4429b018288140d2e", + "Packit-stg - scratch build - rawhide [beaf90b]", + "rawhide", + id="rawhide branch, rawhide target", + ), + pytest.param( + "/packit-ci scratch-build --target eln", + "rawhide", + "558fbdb3248ec9d5dc762d3002368f60", + "Packit-stg - scratch build - eln [beaf90b]", + "eln", + id="rawhide branch, eln target", + ), + ], +) +def test_downstream_build_retrigger_rawhide_pr_eln_package_fedora_ci( + pagure_pr_comment_added, + comment, + target_branch, + uid, + check_name, + check_target, +): + pagure_pr_comment_added["pullrequest"]["comments"][0]["comment"] = comment + pagure_pr_comment_added["pullrequest"]["branch"] = target_branch + + pr_object = ( + flexmock(target_branch=target_branch) + .should_receive("set_flag") + .with_args(username=check_name, comment=str, url=str, status=CommitStatus, uid=uid) + .mock() + ) + + dg_project = ( + flexmock( + PagureProject( + namespace="rpms", repo="python-teamcity-messages", service=flexmock(read_only=False) + ), + default_branch="main", + ) + .should_receive("is_private") + .and_return(False) + .mock() + .should_receive("get_pr") + .and_return(pr_object) + .mock() + .should_receive("get_files") + .and_return([]) + .mock() + .should_receive("get_file_content") + .and_raise(FileNotFoundError) + .mock() + .should_receive("get_web_url") + .and_return("URL") + .mock() + .should_receive("get_git_urls") + .and_return( + {"git": "https://src.fedoraproject.org/rpms/python-teamcity-messages.git"}, + ) + .mock() + ) + service_config = ( + flexmock( + enabled_projects_for_fedora_ci="https://src.fedoraproject.org/rpms/python-teamcity-messages", + fedora_ci_run_by_default=False, + disabled_projects_for_fedora_ci=set(), + command_handler_work_dir=SANDCASTLE_WORK_DIR, + repository_cache="/tmp/repository-cache", + add_repositories_to_repository_cache=False, + deployment=Deployment.stg, + comment_command_prefix="/packit", + package_config_path_override=None, + testing_farm_api_url="https://api.dev.testing-farm.io/api", + testing_farm_secret="secret", + ) + .should_receive("get_project") + .and_return(dg_project) + .mock() + ) + + flexmock(ServiceConfig).should_receive("get_service_config").and_return(service_config) + flexmock(PackitAPIWithDownstreamMixin).should_receive("is_packager").and_return( + True, + ) + + db_project_object = flexmock( + id=9, + job_config_trigger_type=JobConfigTriggerType.pull_request, + project_event_model_type=ProjectEventModelType.pull_request, + project=flexmock(project_url="https://src.fedoraproject.org/rpms/python-teamcity-messages"), + ) + db_project_event = ( + flexmock().should_receive("get_project_event_object").and_return(db_project_object).mock() + ) + flexmock(ProjectEventModel).should_receive("get_or_create").with_args( + type=ProjectEventModelType.pull_request, + event_id=9, + commit_sha="abcd", + ).and_return(flexmock()) + flexmock(PullRequestModel).should_receive("get_or_create").with_args( + pr_id=36, + namespace="rpms", + repo_name="python-teamcity-messages", + project_url="https://src.fedoraproject.org/rpms/python-teamcity-messages", + ).and_return(db_project_object) + flexmock(ProjectEventModel).should_receive("get_or_create").and_return( + db_project_event, + ) + flexmock(PipelineModel).should_receive("create") + + flexmock(utils).should_receive("get_eln_packages").and_return(["python-teamcity-messages"]) + flexmock(commands).should_receive("run_command").with_args( + [ + "git", + "ls-remote", + "https://src.fedoraproject.org/rpms/python-teamcity-messages.git", + "eln", + ], + output=True, + ).and_return(flexmock(stdout="")) + + koji_build = flexmock( + id=123, + target="main", + status="queued", + set_status=lambda x: None, + set_task_id=lambda x: None, + set_web_url=lambda x: None, + set_build_logs_urls=lambda x: None, + set_data=lambda x: None, + set_build_submission_stdout=lambda x: None, + ) + + flexmock(KojiBuildTargetModel).should_receive("create").and_return(koji_build) + flexmock(KojiBuildGroupModel).should_receive("create").and_return( + flexmock(grouped_targets=[koji_build]), + ) + + flexmock(LocalProjectBuilder, _refresh_the_state=lambda *args: None) + flexmock(Signature).should_receive("apply_async").once() + flexmock(Pushgateway).should_receive("push").times(2).and_return() + flexmock(commands).should_receive("run_command_remote").with_args( + cmd=[ + "koji", + "build", + "--scratch", + "--nowait", + check_target, + "git+https://src.fedoraproject.org/rpms/python-teamcity-messages.git#beaf90bcecc51968a46663f8d6f092bfdc92e682", + ], + cwd=Path, + output=True, + print_live=True, + ).and_return(flexmock(stdout="some output")) + + flexmock(PackitAPI).should_receive("init_kerberos_ticket").and_return() + + flexmock(distgit).should_receive("get_koji_task_id_and_url_from_stdout").and_return( + (123, "koji-web-url") + ).once() + + processing_results = SteveJobs().process_message(pagure_pr_comment_added) + event_dict, _, job_config, package_config = get_parameters_from_results( + processing_results[:1], + ) + assert json.dumps(event_dict) + if check_target == "rawhide": + results = run_downstream_koji_scratch_build_handler( + package_config=package_config, + event=event_dict, + job_config=job_config, + ) + + assert first_dict_value(results["job"])["success"] + + elif check_target == "eln": + results = run_downstream_koji_eln_scratch_build_handler( + package_config=package_config, + event=event_dict, + job_config=job_config, + ) + + assert first_dict_value(results["job"])["success"] diff --git a/tests/unit/test_comment_parsers.py b/tests/unit/test_comment_parsers.py index 9f10bbaa1..243d1256a 100644 --- a/tests/unit/test_comment_parsers.py +++ b/tests/unit/test_comment_parsers.py @@ -246,7 +246,7 @@ def test_test_installability_comment_fedora_ci(comment_parser_fedora_ci): args = comment_parser_fedora_ci.parse_args(commands) assert args.command == "test" - assert args.target == "installability" + assert args.test_identifier == "installability" def test_test_rpmlint_comment_fedora_ci(comment_parser_fedora_ci): @@ -255,7 +255,7 @@ def test_test_rpmlint_comment_fedora_ci(comment_parser_fedora_ci): args = comment_parser_fedora_ci.parse_args(commands) assert args.command == "test" - assert args.target == "rpmlint" + assert args.test_identifier == "rpmlint" def test_test_rpminspect_comment_fedora_ci(comment_parser_fedora_ci): @@ -264,7 +264,7 @@ def test_test_rpminspect_comment_fedora_ci(comment_parser_fedora_ci): args = comment_parser_fedora_ci.parse_args(commands) assert args.command == "test" - assert args.target == "rpminspect" + assert args.test_identifier == "rpminspect" def test_test_custom_comment_fedora_ci(comment_parser_fedora_ci): @@ -273,7 +273,7 @@ def test_test_custom_comment_fedora_ci(comment_parser_fedora_ci): args = comment_parser_fedora_ci.parse_args(commands) assert args.command == "test" - assert args.target == "custom" + assert args.test_identifier == "custom" def test_test_unsupported_comment_fedora_ci(comment_parser_fedora_ci): @@ -282,3 +282,31 @@ def test_test_unsupported_comment_fedora_ci(comment_parser_fedora_ci): with pytest.raises(SystemExit): comment_parser_fedora_ci.parse_args(commands) + + +def test_scratch_build_rawhide_branch_comment_fedora_ci(comment_parser_fedora_ci): + comment = "/packit-ci scratch-build --target rawhide" + commands = get_packit_commands_from_comment(comment, packit_comment_command_prefix_fedora_ci) + + args = comment_parser_fedora_ci.parse_args(commands) + assert args.command == "scratch-build" + assert args.check_target == "rawhide" + + +def test_test_rmpinspect_eln_branch_comment_fedora_ci(comment_parser_fedora_ci): + comment = "/packit-ci test rpminspect --target eln" + commands = get_packit_commands_from_comment(comment, packit_comment_command_prefix_fedora_ci) + + args = comment_parser_fedora_ci.parse_args(commands) + assert args.command == "test" + assert args.test_identifier == "rpminspect" + assert args.check_target == "eln" + + +def test_test_eln_branch_comment_fedora_ci(comment_parser_fedora_ci): + comment = "/packit-ci test --target eln" + commands = get_packit_commands_from_comment(comment, packit_comment_command_prefix_fedora_ci) + + args = comment_parser_fedora_ci.parse_args(commands) + assert args.command == "test" + assert args.check_target == "eln"