def test_koji_build_failed_srpm(github_pr_event): trigger = flexmock(job_config_trigger_type=JobConfigTriggerType.release, id=123) flexmock(AddPullRequestDbTrigger).should_receive("db_trigger").and_return(trigger) helper = build_helper( event=github_pr_event, metadata=JobMetadataConfig(targets=["bright-future"]), db_trigger=trigger, ) srpm_build_url = get_srpm_log_url_from_flask(2) flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.pending, description="Building SRPM ...", check_name="packit-stg/production-build-bright-future", url="", ).and_return() flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.failure, description="SRPM build failed, check the logs for details.", check_name="packit-stg/production-build-bright-future", url=srpm_build_url, ).and_return() flexmock(GitProject).should_receive("set_commit_status").and_return().never() flexmock(PackitAPI).should_receive("create_srpm").and_raise(Exception, "some error") flexmock(SRPMBuildModel).should_receive("create").and_return( SRPMBuildModel(id=2, success=False) ) flexmock(KojiBuildModel).should_receive("get_or_create").never() flexmock(sentry_integration).should_receive("send_to_sentry").and_return().once() result = helper.run_koji_build() assert not result["success"] assert "SRPM build failed" in result["details"]["msg"]
def test_koji_build_target_not_supported(github_pr_event): flexmock(AddPullRequestDbTrigger).should_receive("db_trigger").and_return( flexmock(job_config_trigger_type=JobConfigTriggerType.release)) helper = build_helper( event=github_pr_event, metadata=JobMetadataConfig(targets=["nonexisting-target"]), ) flexmock(koji_build).should_receive("get_all_koji_targets").and_return( ["dark-past", "bright-future"]).once() flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.pending, description="Building SRPM ...", check_name="packit-stg/production-build-nonexisting-target", url="", ).and_return() flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.error, description="Target not supported: nonexisting-target", check_name="packit-stg/production-build-nonexisting-target", url=get_srpm_log_url_from_flask(1), ).and_return() flexmock(GitProject).should_receive( "set_commit_status").and_return().never() flexmock(SRPMBuildModel).should_receive("create").and_return( SRPMBuildModel(id=1, success=True)) flexmock(KojiBuildModel).should_receive("get_or_create").and_return( KojiBuildModel(id=1)) flexmock(PackitAPI).should_receive("create_srpm").and_return("my.srpm") response = helper.run_koji_build() assert not response["success"] assert ("Target not supported: nonexisting-target" == response["details"] ["errors"]["nonexisting-target"])
def test_koji_build_failed_kerberos(github_pr_event): trigger = flexmock( job_config_trigger_type=JobConfigTriggerType.pull_request, id=123 ) flexmock(AddPullRequestDbTrigger).should_receive("db_trigger").and_return(trigger) helper = build_helper( event=github_pr_event, metadata=JobMetadataConfig(targets=["bright-future"], scratch=True), db_trigger=trigger, ) flexmock(koji_build).should_receive("get_all_koji_targets").and_return( ["dark-past", "bright-future"] ).never() flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.pending, description="Building SRPM ...", check_name="packit-stg/production-build-bright-future", url="", ).and_return() flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.error, description="Kerberos authentication error: the bad authentication error", check_name="packit-stg/production-build-bright-future", url=get_srpm_log_url_from_flask(1), ).and_return() flexmock(GitProject).should_receive("get_pr").and_return( flexmock(source_project=flexmock()) ) flexmock(GitProject).should_receive("set_commit_status").and_return().never() flexmock(SRPMBuildModel).should_receive("create").and_return( SRPMBuildModel(id=1, success=True) ) flexmock(KojiBuildModel).should_receive("get_or_create").and_return( KojiBuildModel(id=1) ) flexmock(PackitAPI).should_receive("create_srpm").and_return("my.srpm") flexmock(PackitAPI).should_receive("init_kerberos_ticket").and_raise( PackitCommandFailedError, "Command failed", stdout_output="", stderr_output="the bad authentication error", ) response = helper.run_koji_build() assert not response["success"] assert ( "Kerberos authentication error: the bad authentication error" == response["details"]["msg"] )
def test_get_srpm_logs(client): srpm_build = SRPMBuildModel() srpm_build.id = 2 srpm_build.logs = "asd\nqwe" flexmock(SRPMBuildModel).should_receive("get_by_id").and_return(srpm_build) url = "/srpm-build/2/logs" logs_url = get_srpm_log_url_from_flask(2) assert logs_url.endswith(url) resp = client.get(url).data.decode() assert srpm_build.logs in resp assert f"build {srpm_build.id}" in resp
def test_koji_build_failed(github_pr_event): trigger = flexmock( job_config_trigger_type=JobConfigTriggerType.pull_request, id=123 ) flexmock(AddPullRequestDbTrigger).should_receive("db_trigger").and_return(trigger) helper = build_helper( event=github_pr_event, metadata=JobMetadataConfig(targets=["bright-future"], scratch=True), db_trigger=trigger, ) flexmock(koji_build).should_receive("get_all_koji_targets").and_return( ["dark-past", "bright-future"] ).once() flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.pending, description="Building SRPM ...", check_name="packit-stg/production-build-bright-future", url="", ).and_return() srpm_build_url = get_srpm_log_url_from_flask(2) flexmock(StatusReporter).should_receive("set_status").with_args( state=CommitStatus.error, description="Submit of the build failed: some error", check_name="packit-stg/production-build-bright-future", url=srpm_build_url, ).and_return() flexmock(GitProject).should_receive("get_pr").and_return( flexmock(source_project=flexmock()) ) flexmock(GitProject).should_receive("set_commit_status").and_return().never() flexmock(SRPMBuildModel).should_receive("create").and_return( SRPMBuildModel(id=2, success=True) ) flexmock(KojiBuildModel).should_receive("get_or_create").and_return( KojiBuildModel(id=1) ) flexmock(PackitAPI).should_receive("create_srpm").and_return("my.srpm") # koji build flexmock(sentry_integration).should_receive("send_to_sentry").and_return().once() flexmock(Upstream).should_receive("koji_build").and_raise(Exception, "some error") result = helper.run_koji_build() assert not result["success"] assert result["details"]["errors"] assert result["details"]["errors"]["bright-future"] == "some error"
def test_get_srpm_logs(client): srpm_build = SRPMBuildModel() srpm_build.id = 2 srpm_build.logs = "asd\nqwe" flexmock(SRPMBuildModel).should_receive("get_by_id").and_return(srpm_build) url = f"/srpm-build/2/logs" logs_url = get_srpm_log_url_from_flask(2) assert logs_url.endswith(url) resp = client.get(url) expected = ("<html><head>" "<title>SRPM Build id=2</title></head><body>" "SRPM creation logs:<br><br>" "<pre>asd\nqwe</pre>" "<br></body></html>") assert resp.data == expected.encode()
def run_koji_build(self) -> TaskResults: if not self.is_scratch: msg = "Non-scratch builds not possible from upstream." self.report_status_to_all( description=msg, state=CommitStatus.error, url=KOJI_PRODUCTION_BUILDS_ISSUE, ) return TaskResults(success=True, details={"msg": msg}) self.report_status_to_all( description="Building SRPM ...", state=CommitStatus.pending ) self.create_srpm_if_needed() if not self.srpm_model.success: msg = "SRPM build failed, check the logs for details." self.report_status_to_all( state=CommitStatus.failure, description=msg, url=get_srpm_log_url_from_flask(self.srpm_model.id), ) return TaskResults(success=False, details={"msg": msg}) try: # We need to do it manually # because we don't use PackitAPI.build, but PackitAPI.up.koji_build self.api.init_kerberos_ticket() except PackitCommandFailedError as ex: msg = f"Kerberos authentication error: {ex.stderr_output}" logger.error(msg) self.report_status_to_all( state=CommitStatus.error, description=msg, url=get_srpm_log_url_from_flask(self.srpm_model.id), ) return TaskResults(success=False, details={"msg": msg}) errors: Dict[str, str] = {} for target in self.build_targets: if target not in self.supported_koji_targets: msg = f"Target not supported: {target}" self.report_status_to_all_for_chroot( state=CommitStatus.error, description=msg, url=get_srpm_log_url_from_flask(self.srpm_model.id), chroot=target, ) errors[target] = msg continue try: build_id, web_url = self.run_build(target=target) except Exception as ex: sentry_integration.send_to_sentry(ex) # TODO: Where can we show more info about failure? # TODO: Retry self.report_status_to_all_for_chroot( state=CommitStatus.error, description=f"Submit of the build failed: {ex}", url=get_srpm_log_url_from_flask(self.srpm_model.id), chroot=target, ) errors[target] = str(ex) continue koji_build = KojiBuildModel.get_or_create( build_id=str(build_id), commit_sha=self.metadata.commit_sha, web_url=web_url, target=target, status="pending", srpm_build=self.srpm_model, trigger_model=self.db_trigger, ) url = get_koji_build_info_url_from_flask(id_=koji_build.id) self.report_status_to_all_for_chroot( state=CommitStatus.pending, description="Building RPM ...", url=url, chroot=target, ) if errors: return TaskResults( success=False, details={ "msg": "Koji build submit was not successful for all chroots.", "errors": errors, }, ) # TODO: release the hounds! """ celery_app.send_task( "task.babysit_koji_build", args=(build_metadata.build_id,), countdown=120, # do the first check in 120s ) """ return TaskResults(success=True, details={})
def run_copr_build(self) -> HandlerResults: if not (self.job_build or self.job_tests): msg = "No copr_build or tests job defined." # we can't report it to end-user at this stage return HandlerResults(success=False, details={"msg": msg}) self.report_status_to_all( description="Building SRPM ...", state=CommitStatus.pending, # pagure requires "valid url" url="", ) self.create_srpm_if_needed() if not self.srpm_model.success: msg = "SRPM build failed, check the logs for details." self.report_status_to_all( state=CommitStatus.failure, description=msg, url=get_srpm_log_url_from_flask(self.srpm_model.id), ) return HandlerResults(success=False, details={"msg": msg}) try: build_id, web_url = self.run_build() except Exception as ex: sentry_integration.send_to_sentry(ex) # TODO: Where can we show more info about failure? # TODO: Retry self.report_status_to_all( state=CommitStatus.error, description=f"Submit of the build failed: {ex}", ) return HandlerResults(success=False, details={"error": str(ex)}) for chroot in self.build_targets: copr_build = CoprBuildModel.get_or_create( build_id=str(build_id), commit_sha=self.event.commit_sha, project_name=self.job_project, owner=self.job_owner, web_url=web_url, target=chroot, status="pending", srpm_build=self.srpm_model, trigger_model=self.event.db_trigger, ) url = get_copr_build_log_url_from_flask(id_=copr_build.id) self.report_status_to_all_for_chroot( state=CommitStatus.pending, description="Starting RPM build...", url=url, chroot=chroot, ) # release the hounds! celery_app.send_task( "task.babysit_copr_build", args=(build_id,), countdown=120, # do the first check in 120s ) return HandlerResults(success=True, details={})
def run_copr_build(self) -> TaskResults: if not (self.job_build or self.job_tests): msg = "No copr_build or tests job defined." # we can't report it to end-user at this stage return TaskResults(success=False, details={"msg": msg}) self.report_status_to_all( description="Building SRPM ...", state=CommitStatus.pending, # pagure requires "valid url" url="", ) self.create_srpm_if_needed() if not self.srpm_model.success: msg = "SRPM build failed, check the logs for details." self.report_status_to_all( state=CommitStatus.failure, description=msg, url=get_srpm_log_url_from_flask(self.srpm_model.id), ) return TaskResults(success=False, details={"msg": msg}) try: build_id, web_url = self.run_build() Pushgateway().push_copr_build_created() except Exception as ex: sentry_integration.send_to_sentry(ex) # TODO: Where can we show more info about failure? # TODO: Retry self.report_status_to_all( state=CommitStatus.error, description=f"Submit of the build failed: {ex}", ) return TaskResults( success=False, details={"msg": "Submit of the Copr build failed.", "error": str(ex)}, ) unprocessed_chroots = [] for chroot in self.build_targets: if chroot not in self.available_chroots: self.report_status_to_all_for_chroot( state=CommitStatus.error, description=f"Not supported target: {chroot}", url=get_srpm_log_url_from_flask(self.srpm_model.id), chroot=chroot, ) unprocessed_chroots.append(chroot) continue copr_build = CoprBuildModel.get_or_create( build_id=str(build_id), commit_sha=self.metadata.commit_sha, project_name=self.job_project, owner=self.job_owner, web_url=web_url, target=chroot, status="pending", srpm_build=self.srpm_model, trigger_model=self.db_trigger, ) url = get_copr_build_info_url_from_flask(id_=copr_build.id) self.report_status_to_all_for_chroot( state=CommitStatus.pending, description="Starting RPM build...", url=url, chroot=chroot, ) if unprocessed_chroots: unprocessed = "\n".join(sorted(unprocessed_chroots)) available = "\n".join(sorted(self.available_chroots)) self.project.pr_comment( pr_id=self.metadata.pr_id, body="There are build targets that are not supported by COPR.\n" "<details>\n<summary>Unprocessed build targets</summary>\n\n" f"```\n{unprocessed}\n```\n</details>\n" "<details>\n<summary>Available build targets</summary>\n\n" f"```\n{available}\n```\n</details>", ) # release the hounds! celery_app.send_task( "task.babysit_copr_build", args=(build_id,), countdown=120, # do the first check in 120s ) return TaskResults(success=True, details={})