diff --git a/packit_service/models.py b/packit_service/models.py index 3f49eddbf..d0d2e6c7b 100644 --- a/packit_service/models.py +++ b/packit_service/models.py @@ -532,12 +532,14 @@ def get_by_forge( @classmethod def get_by_forge_namespace( - cls, forge: str, namespace: str + cls, first: int, last: int, forge: str, namespace: str ) -> Iterable["GitProjectModel"]: """Return projects of given forge and namespace""" with sa_session_transaction() as session: - return session.query(GitProjectModel).filter_by( - instance_url=forge, namespace=namespace + return ( + session.query(GitProjectModel) + .filter_by(instance_url=forge, namespace=namespace) + .slice(first, last) ) @classmethod @@ -571,7 +573,7 @@ def get_project_prs( @classmethod def get_project_issues( - cls, forge: str, namespace: str, repo_name: str + cls, first: int, last: int, forge: str, namespace: str, repo_name: str ) -> Iterable["IssueModel"]: with sa_session_transaction() as session: return ( @@ -582,11 +584,12 @@ def get_project_issues( GitProjectModel.namespace == namespace, GitProjectModel.repo_name == repo_name, ) + .slice(first, last) ) @classmethod def get_project_branches( - cls, forge: str, namespace: str, repo_name: str + cls, first: int, last: int, forge: str, namespace: str, repo_name: str ) -> Iterable["GitBranchModel"]: with sa_session_transaction() as session: return ( @@ -597,11 +600,12 @@ def get_project_branches( GitProjectModel.namespace == namespace, GitProjectModel.repo_name == repo_name, ) + .slice(first, last) ) @classmethod def get_project_releases( - cls, forge: str, namespace: str, repo_name: str + cls, first: int, last: int, forge: str, namespace: str, repo_name: str ) -> Iterable["ProjectReleaseModel"]: with sa_session_transaction() as session: return ( @@ -612,6 +616,7 @@ def get_project_releases( GitProjectModel.namespace == namespace, GitProjectModel.repo_name == repo_name, ) + .slice(first, last) ) # ACTIVE PROJECTS diff --git a/packit_service/service/api/projects.py b/packit_service/service/api/projects.py index 33fbb8afd..fc87ee9dc 100644 --- a/packit_service/service/api/projects.py +++ b/packit_service/service/api/projects.py @@ -111,11 +111,16 @@ def get(self, forge): @ns.param("forge", "Git Forge") @ns.param("namespace", "Namespace") class ProjectsNamespace(Resource): + @ns.expect(pagination_arguments) @ns.response(HTTPStatus.OK.value, "Projects details follow") def get(self, forge, namespace): """List of projects of given forge and namespace""" result = [] - for project in GitProjectModel.get_by_forge_namespace(forge, namespace): + first, last = indices() + + for project in GitProjectModel.get_by_forge_namespace( + first, last, forge, namespace + ): project_info = { "namespace": project.namespace, "repo_name": project.repo_name, @@ -126,7 +131,13 @@ def get(self, forge, namespace): "issues_handled": len(project.issues), } result.append(project_info) - return response_maker(result) + + resp = response_maker( + result, + status=HTTPStatus.PARTIAL_CONTENT if result else HTTPStatus.OK, + ) + resp.headers["Content-Range"] = f"git-projects {first + 1}-{last}/*" + return resp @ns.route("////prs") @@ -207,41 +218,60 @@ def get(self, forge, namespace, repo_name): @ns.param("namespace", "Namespace") @ns.param("repo_name", "Repo Name") class ProjectIssues(Resource): + @ns.expect(pagination_arguments) @ns.response( HTTPStatus.OK.value, "OK, project issues handled by Packit Service follow" ) def get(self, forge, namespace, repo_name): """Project issues""" - return response_maker( - [ - issue.issue_id - for issue in GitProjectModel.get_project_issues( - forge, namespace, repo_name - ) - ] + first, last = indices() + + issues = [ + issue.issue_id + for issue in GitProjectModel.get_project_issues( + first, last, forge, namespace, repo_name + ) + ] + + resp = response_maker( + issues, + status=HTTPStatus.PARTIAL_CONTENT if issues else HTTPStatus.OK, ) + resp.headers["Content-Range"] = f"git-project-issues {first + 1}-{last}/*" + return resp + @ns.route("////releases") @ns.param("forge", "Git Forge") @ns.param("namespace", "Namespace") @ns.param("repo_name", "Repo Name") class ProjectReleases(Resource): + @ns.expect(pagination_arguments) @ns.response( HTTPStatus.OK.value, "OK, project releases handled by Packit Service follow" ) def get(self, forge, namespace, repo_name): """Project releases""" result = [] + first, last = indices() + for release in GitProjectModel.get_project_releases( - forge, namespace, repo_name + first, last, forge, namespace, repo_name ): release_info = { "tag_name": release.tag_name, "commit_hash": release.commit_hash, } result.append(release_info) - return response_maker(result) + + resp = response_maker( + result, + status=HTTPStatus.PARTIAL_CONTENT if result else HTTPStatus.OK, + ) + + resp.headers["Content-Range"] = f"git-project-releases {first + 1}-{last}/*" + return resp @ns.route("////branches") @@ -249,13 +279,18 @@ def get(self, forge, namespace, repo_name): @ns.param("namespace", "Namespace") @ns.param("repo_name", "Repo Name") class ProjectBranches(Resource): + @ns.expect(pagination_arguments) @ns.response( HTTPStatus.OK.value, "OK, project branches handled by Packit Service follow" ) def get(self, forge, namespace, repo_name): """Project branches""" result = [] - for branch in GitProjectModel.get_project_branches(forge, namespace, repo_name): + first, last = indices() + + for branch in GitProjectModel.get_project_branches( + first, last, forge, namespace, repo_name + ): branch_info = { "branch": branch.name, "builds": [], @@ -300,4 +335,10 @@ def get(self, forge, namespace, repo_name): branch_info["tests"].append(test_info) result.append(branch_info) - return response_maker(result) + resp = response_maker( + result, + status=HTTPStatus.PARTIAL_CONTENT if result else HTTPStatus.OK, + ) + + resp.headers["Content-Range"] = f"git-project-branches {first + 1}-{last}/*" + return resp diff --git a/tests_openshift/database/test_models.py b/tests_openshift/database/test_models.py index cc9379074..3231ec30d 100644 --- a/tests_openshift/database/test_models.py +++ b/tests_openshift/database/test_models.py @@ -684,7 +684,7 @@ def test_get_by_forge(clean_before_and_after, multiple_forge_projects): def test_get_by_forge_namespace(clean_before_and_after, multiple_copr_builds): projects = list( - GitProjectModel.get_by_forge_namespace("github.com", "the-namespace") + GitProjectModel.get_by_forge_namespace(0, 10, "github.com", "the-namespace") ) assert projects[0].namespace == "the-namespace" assert projects[0].repo_name == "the-repo-name" @@ -716,7 +716,7 @@ def test_get_project_prs(clean_before_and_after, a_copr_build_for_pr): def test_get_project_branch(clean_before_and_after, a_copr_build_for_branch_push): branches_list = list( GitProjectModel.get_project_branches( - "github.com", "the-namespace", "the-repo-name" + 0, 10, "github.com", "the-namespace", "the-repo-name" ) ) assert len(branches_list) == 1 @@ -726,7 +726,7 @@ def test_get_project_branch(clean_before_and_after, a_copr_build_for_branch_push def test_get_project_issues(clean_before_and_after, an_issue_model): issues_list = list( GitProjectModel.get_project_issues( - "github.com", "the-namespace", "the-repo-name" + 0, 10, "github.com", "the-namespace", "the-repo-name" ) ) assert len(issues_list) == 1 @@ -736,7 +736,7 @@ def test_get_project_issues(clean_before_and_after, an_issue_model): def test_get_project_releases(clean_before_and_after, release_model): releases = list( GitProjectModel.get_project_releases( - "github.com", "the-namespace", "the-repo-name" + 0, 10, "github.com", "the-namespace", "the-repo-name" ) ) assert releases[0].tag_name == "v1.0.2"