def test_get_copr_build(clean_before_and_after, a_copr_build_for_pr): assert a_copr_build_for_pr.id b = CoprBuildModel.get_by_build_id(a_copr_build_for_pr.build_id, TARGET) assert b.id == a_copr_build_for_pr.id # let's make sure passing int works as well b = CoprBuildModel.get_by_build_id(int(a_copr_build_for_pr.build_id), TARGET) assert b.id == a_copr_build_for_pr.id b2 = CoprBuildModel.get_by_id(b.id) assert b2.id == a_copr_build_for_pr.id
def test_get_by_build_id(clean_before_and_after, multiple_copr_builds): # these are not iterable and thus should be accessible directly build_a = CoprBuildModel.get_by_build_id(str(123456), "fedora-42-x86_64") assert build_a.project_name == "SomeUser-hello-world-9" assert build_a.target == "fedora-42-x86_64" build_b = CoprBuildModel.get_by_build_id(str(123456), "fedora-43-x86_64") assert build_b.project_name == "SomeUser-hello-world-9" assert build_b.target == "fedora-43-x86_64" build_c = CoprBuildModel.get_by_build_id(str(987654), "fedora-43-x86_64") assert build_c.project_name == "SomeUser-random-text-7"
def test_get_by_build_id(clean_before_and_after, multiple_copr_builds): # these are not iterable and thus should be accessible directly build_a = CoprBuildModel.get_by_build_id(SampleValues.build_id, SampleValues.target) assert build_a.project_name == "the-project-name" assert build_a.target == "fedora-42-x86_64" build_b = CoprBuildModel.get_by_build_id(SampleValues.build_id, SampleValues.different_target) assert build_b.project_name == "the-project-name" assert build_b.target == "fedora-43-x86_64" build_c = CoprBuildModel.get_by_build_id(SampleValues.different_build_id, SampleValues.target) assert build_c.project_name == "different-project-name"
def _payload_install_test(self, build_id: int, chroot: str) -> dict: """ If the project doesn't use fmf, but still wants to run tests in TF. TF provides 'installation test', we request it in ['test']['fmf']['url']. We don't specify 'artifacts' as in _payload(), but 'variables'. """ copr_build = CoprBuildModel.get_by_build_id(build_id) compose, arch = self.get_compose_arch(chroot) return { "api_key": self.service_config.testing_farm_secret, "test": { "fmf": { "url": TESTING_FARM_INSTALLABILITY_TEST_URL, }, }, "environments": [ { "arch": arch, "os": {"compose": compose}, "variables": { "REPOSITORY": f"{copr_build.owner}/{copr_build.project_name}", }, } ], "notification": { "webhook": { "url": f"{self.api_url}/testing-farm/results", "token": self.service_config.testing_farm_secret, }, }, }
def test_copr_build_set_status(clean_before_and_after, a_copr_build_for_pr): assert a_copr_build_for_pr.status == "pending" a_copr_build_for_pr.set_status("awesome") assert a_copr_build_for_pr.status == "awesome" b = CoprBuildModel.get_by_build_id(a_copr_build_for_pr.build_id, SampleValues.target) assert b.status == "awesome"
def from_build_id( cls, topic: str, build_id: int, chroot: str, status: int, owner: str, project_name: str, pkg: str, ) -> Optional["CoprBuildEvent"]: """ Return cls instance or None if build_id not in CoprBuildDB""" build = CoprBuildModel.get_by_build_id(str(build_id), chroot) if not build: logger.warning(f"Build id: {build_id} not in CoprBuildDB") return None return cls( topic, build_id, build, chroot, status, owner, project_name, pkg, )
def run(self): if self.event.chroot == "srpm-builds": # we don't want to set the check status for this msg = "SRPM build in copr has started" logger.debug(msg) return HandlerResults(success=True, details={"msg": msg}) # TODO: drop the code below once we move to PG completely; the build is present in event # pg build = CoprBuildModel.get_by_build_id(str(self.event.build_id), self.event.chroot) if not build: msg = f"Copr build {self.event.build_id} not in CoprBuildDB" logger.warning(msg) return HandlerResults(success=False, details={"msg": msg}) url = get_log_url(build.id) build.set_status("pending") copr_build_logs = get_copr_build_logs_url(self.event) build.set_build_logs_url(copr_build_logs) self.build_job_helper.report_status_to_all_for_chroot( description="RPM build has started...", state=CommitStatus.pending, url=url, chroot=self.event.chroot, ) msg = f"Build on {self.event.chroot} in copr has started..." return HandlerResults(success=True, details={"msg": msg})
def get(self): """ List all Copr builds. """ # Return relevant info thats concise # Usecases like the packit-dashboard copr-builds table result = [] first, last = indices() for build in CoprBuildModel.get_merged_chroots(first, last): build_info = CoprBuildModel.get_by_build_id(build.build_id, None) project_info = build_info.get_project() build_dict = { "project": build_info.project_name, "build_id": build.build_id, "status_per_chroot": {}, "build_submitted_time": optional_time(build_info.build_submitted_time), "web_url": build_info.web_url, "ref": build_info.commit_sha, "pr_id": build_info.get_pr_id(), "branch_name": build_info.get_branch_name(), "repo_namespace": project_info.namespace, "repo_name": project_info.repo_name, } for count, chroot in enumerate(build.target): # [0] because sqlalchemy returns a single element sub-list build_dict["status_per_chroot"][chroot[0]] = build.status[count][0] result.append(build_dict) resp = response_maker(result, status=HTTPStatus.PARTIAL_CONTENT,) resp.headers["Content-Range"] = f"copr-builds {first + 1}-{last}/*" return resp
def from_build_id( cls, topic: str, build_id: int, chroot: str, status: int, owner: str, project_name: str, pkg: str, timestamp, ) -> Optional["AbstractCoprBuildEvent"]: """Return cls instance or None if build_id not in CoprBuildDB""" build: Optional[Union[SRPMBuildModel, CoprBuildModel]] if chroot == COPR_SRPM_CHROOT: build = SRPMBuildModel.get_by_copr_build_id(str(build_id)) else: build = CoprBuildModel.get_by_build_id(str(build_id), chroot) if not build: logger.warning( f"Build id {build_id} not in " f"{'SRPMBuildDB' if chroot == COPR_SRPM_CHROOT else 'CoprBuildDB'}." ) return None return cls(topic, build_id, build, chroot, status, owner, project_name, pkg, timestamp)
def test_copr_build_set_build_logs_url(clean_before_and_after, a_copr_build_for_pr): url = "https://copr.fp.o/logs/12456/build.log" a_copr_build_for_pr.set_build_logs_url(url) assert a_copr_build_for_pr.build_logs_url == url b = CoprBuildModel.get_by_build_id(a_copr_build_for_pr.build_id, SampleValues.target) assert b.build_logs_url == url
def build(self): if not self._build: build_id = str(self.copr_event.build_id) if self.copr_event.chroot == COPR_SRPM_CHROOT: self._build = SRPMBuildModel.get_by_copr_build_id(build_id) else: self._build = CoprBuildModel.get_by_build_id( build_id, self.copr_event.chroot) return self._build
def test_get_copr_build(clean_before_and_after, a_copr_build_for_pr): assert a_copr_build_for_pr.id # pass in a build_id and a target b = CoprBuildModel.get_by_build_id(a_copr_build_for_pr.build_id, SampleValues.target) assert b.id == a_copr_build_for_pr.id # let's make sure passing int works as well b2 = CoprBuildModel.get_by_build_id(int(a_copr_build_for_pr.build_id), SampleValues.target) assert b2.id == a_copr_build_for_pr.id # pass in a build_id and without a target b3 = CoprBuildModel.get_by_build_id(a_copr_build_for_pr.build_id, None) assert b3.commit_sha == a_copr_build_for_pr.commit_sha b4 = CoprBuildModel.get_by_id(b.id) assert b4.id == a_copr_build_for_pr.id
def test_copr_build_info_view(client, clean_before_and_after, multiple_copr_builds): build = CoprBuildModel.get_by_build_id(123456, SampleValues.chroots[0]) build.set_build_logs_url( "https://copr.somewhere/results/owner/package/target/build.logs") response = client.get(url_for("builds.copr_build_info", id_=str(build.id))) response = response.data.decode() assert "Builds for the-namespace/the-repo-name: PR #342" in response assert build.status in response assert build.target in response assert str(build.srpm_build_id) in response assert build.build_logs_url in response assert f"Status: {build.status}" in response assert "For more info see" in response assert "just now" in response
def test_copr_build_info_view(client, clean_before_and_after, multiple_copr_builds): flexmock(models).should_receive("optional_time").and_return( "2020-05-19 16:17:14 UTC") build = CoprBuildModel.get_by_build_id(123456, SampleValues.chroots[0]) build.set_build_logs_url( "https://copr.somewhere/results/owner/package/target/build.logs") response = client.get(url_for("builds.copr_build_info", id_=str(build.id))) response = response.data.decode() assert "Builds for the-namespace/the-repo-name: PR #342" in response assert "2020-05-19 16:17:14 UTC" in response assert build.status in response assert build.target in response assert str(build.srpm_build_id) in response assert build.build_logs_url in response
def test_copr_build_logs_view(client, clean_before_and_after, multiple_copr_builds): flexmock(models).should_receive("optional_time").and_return( "19/05/2020 16:17:14") build = CoprBuildModel.get_by_build_id(123456, SampleValues.chroots[0]) response = client.get( url_for("builds.get_copr_build_logs_by_id", id_=str(build.id))) assert response.data.decode() == ( "<html><head><title>COPR build the-namespace/the-repo-name: " "PR #342</title></head><body>COPR build ID: 123456<br>" "Submitted: 19/05/2020 16:17:14<br>" "State: pending<br><br>" "Build web interface URL: " '<a href="https://copr.something.somewhere/123456">' "https://copr.something.somewhere/123456</a>" "<br>SRPM creation logs:<br><br><pre>" "some\nboring\nlogs</pre><br></body></html>")
def run(self): build_job_helper = CoprBuildJobHelper( config=self.config, package_config=self.event.package_config, project=self.event.project, event=self.event, ) if self.event.chroot == "srpm-builds": # we don't want to set the check status for this msg = "SRPM build in copr has started." logger.debug(msg) return HandlerResults(success=True, details={"msg": msg}) # TODO: drop the code below once we move to PG completely; the build is present in event # pg build = CoprBuildModel.get_by_build_id( str(self.event.build_id), self.event.chroot ) if not build: msg = f"Copr build {self.event.build_id} not in CoprBuildDB." logger.warning(msg) return HandlerResults(success=False, details={"msg": msg}) start_time = ( datetime.utcfromtimestamp(self.event.timestamp) if self.event.timestamp else None ) build.set_start_time(start_time) url = get_copr_build_log_url_from_flask(build.id) build.set_status("pending") copr_build_logs = get_copr_build_logs_url(self.event) build.set_build_logs_url(copr_build_logs) build_job_helper.report_status_to_all_for_chroot( description="RPM build is in progress...", state=CommitStatus.pending, url=url, chroot=self.event.chroot, ) msg = f"Build on {self.event.chroot} in copr has started..." return HandlerResults(success=True, details={"msg": msg})
def build(self): if not self._build: self._build = CoprBuildModel.get_by_build_id( str(self.copr_event.build_id), self.copr_event.chroot) return self._build
def run(self): build_job_helper = CoprBuildJobHelper( config=self.config, package_config=self.event.package_config, project=self.event.project, event=self.event, ) if self.event.chroot == "srpm-builds": # we don't want to set check for this msg = "SRPM build in copr has finished." logger.debug(msg) return HandlerResults(success=True, details={"msg": msg}) build = CoprBuildModel.get_by_build_id( str(self.event.build_id), self.event.chroot ) if not build: # TODO: how could this happen? msg = f"Copr build {self.event.build_id} not in CoprBuildDB." logger.warning(msg) return HandlerResults(success=False, details={"msg": msg}) if build.status in [ PG_COPR_BUILD_STATUS_FAILURE, PG_COPR_BUILD_STATUS_SUCCESS, ]: msg = ( f"Copr build {self.event.build_id} is already" f" processed (status={build.status})." ) logger.info(msg) return HandlerResults(success=True, details={"msg": msg}) end_time = ( datetime.utcfromtimestamp(self.event.timestamp) if self.event.timestamp else None ) build.set_end_time(end_time) url = get_copr_build_log_url_from_flask(build.id) # https://pagure.io/copr/copr/blob/master/f/common/copr_common/enums.py#_42 if self.event.status != COPR_API_SUCC_STATE: failed_msg = "RPMs failed to be built." build_job_helper.report_status_to_all_for_chroot( state=CommitStatus.failure, description=failed_msg, url=url, chroot=self.event.chroot, ) build.set_status(PG_COPR_BUILD_STATUS_FAILURE) return HandlerResults(success=False, details={"msg": failed_msg}) if ( build_job_helper.job_build and build_job_helper.job_build.trigger == JobConfigTriggerType.pull_request and self.event.pr_id and isinstance(self.event.project, GithubProject) and not self.was_last_packit_comment_with_congratulation() and self.event.package_config.notifications.pull_request.successful_build ): msg = ( f"Congratulations! One of the builds has completed. :champagne:\n\n" "You can install the built RPMs by following these steps:\n\n" "* `sudo yum install -y dnf-plugins-core` on RHEL 8\n" "* `sudo dnf install -y dnf-plugins-core` on Fedora\n" f"* `dnf copr enable {self.event.owner}/{self.event.project_name}`\n" "* And now you can install the packages.\n" "\nPlease note that the RPMs should be used only in a testing environment." ) self.event.project.pr_comment(pr_id=self.event.pr_id, body=msg) build_job_helper.report_status_to_build_for_chroot( state=CommitStatus.success, description="RPMs were built successfully.", url=url, chroot=self.event.chroot, ) build_job_helper.report_status_to_test_for_chroot( state=CommitStatus.pending, description="RPMs were built successfully.", url=url, chroot=self.event.chroot, ) build.set_status(PG_COPR_BUILD_STATUS_SUCCESS) if ( build_job_helper.job_tests and self.event.chroot in build_job_helper.tests_targets ): testing_farm_handler = GithubTestingFarmHandler( config=self.config, job_config=build_job_helper.job_tests, event=self.event, chroot=self.event.chroot, ) testing_farm_handler.run() else: logger.debug("Testing farm not in the job config.") return HandlerResults(success=True, details={})