From f9ad429c00d09ec7c15b54afa981611318bdea93 Mon Sep 17 00:00:00 2001 From: Seltyk Date: Mon, 7 Aug 2023 16:17:09 -0400 Subject: [PATCH 1/3] Add endpoint to get repo by ID Also wrote API documentation for it using an example 3scale repo in my testing Signed-off-by: Seltyk --- augur/api/routes/util.py | 62 +++++++++++++--- docs/source/rest-api/spec.yml | 129 ++++++++++++++++++++++------------ 2 files changed, 137 insertions(+), 54 deletions(-) diff --git a/augur/api/routes/util.py b/augur/api/routes/util.py index cd6a8ad3bc..8a32618554 100644 --- a/augur/api/routes/util.py +++ b/augur/api/routes/util.py @@ -1,10 +1,11 @@ #SPDX-License-Identifier: MIT +from augur.api.routes import AUGUR_API_VERSION +from ..server import app, engine import base64 import sqlalchemy as s import pandas as pd import json from flask import Response -import logging from augur.application.db.session import DatabaseSession from augur.application.logs import AugurLogger @@ -12,10 +13,6 @@ logger = AugurLogger("augur").get_logger() -from augur.api.routes import AUGUR_API_VERSION -from ..server import app, engine - - @app.route('/{}/repo-groups'.format(AUGUR_API_VERSION)) def get_all_repo_groups(): #TODO: make this name automatic - wrapper? repoGroupsSQL = s.sql.text(""" @@ -52,9 +49,9 @@ def get_all_repos(): (select * from api_get_all_repos_issues) b on repo.repo_id = b.repo_id - left outer join - (select * from api_get_all_repo_prs) c - on repo.repo_id=c.repo_id + left outer join + (select * from api_get_all_repo_prs) c + on repo.repo_id=c.repo_id JOIN repo_groups ON repo_groups.repo_group_id = repo.repo_group_id order by repo_name """) @@ -91,9 +88,9 @@ def get_repos_in_repo_group(repo_group_id): (select * from api_get_all_repos_issues) b on repo.repo_id = b.repo_id - left outer join - (select * from api_get_all_repo_prs) c - on repo.repo_id=c.repo_id + left outer join + (select * from api_get_all_repo_prs) c + on repo.repo_id=c.repo_id JOIN repo_groups ON repo_groups.repo_group_id = repo.repo_group_id WHERE repo_groups.repo_group_id = :repo_group_id @@ -106,6 +103,49 @@ def get_repos_in_repo_group(repo_group_id): status=200, mimetype="application/json") +@app.route('/{}/repos/'.format(AUGUR_API_VERSION)) +def get_repo_by_id(repo_id: int) -> Response: + repo_by_id_SQL = s.sql.text(""" + SELECT + repo.repo_id, + repo.repo_name, + repo.description, + repo.repo_git AS url, + a.commits_all_time, + b.issues_all_time, + c.pull_requests_all_time, + rg_name, + repo.repo_group_id + FROM + repo + LEFT OUTER JOIN + (SELECT * FROM api_get_all_repos_commits) a + ON repo.repo_id = a.repo_id + LEFT OUTER JOIN + (SELECT * FROM api_get_all_repos_issues) b + ON repo.repo_id = b.repo_id + LEFT OUTER JOIN + (SELECT * FROM api_get_all_repo_prs) c + ON repo.repo_id = c.repo_id + JOIN repo_groups ON repo_groups.repo_group_id = repo.repo_group_id + WHERE + repo.repo_id = :id + """) + + results = pd.read_sql(repo_by_id_SQL, engine, params={"id": repo_id}) + results["url"] = results["url"].apply(lambda datum: datum.split("//")[1]) # cut "https://" off the URL + results["base64_url"] = [base64.b64encode(results.at[i, "url"].encode()) for i in results.index] + data = results.to_json(orient="records", date_format="iso", date_unit="ms") + + if not data or data == "[]": + return Response(response='{"status": "Repository ' + str(repo_id) + ' does not exist"}', + status=400, + mimetype="application/json") + + return Response(response=data[1:-1], # cut off brackets at each end, turns list of length 1 into single value + status=200, + mimetype="application/json") + @app.route('/{}/owner//repo/'.format(AUGUR_API_VERSION)) def get_repo_by_git_name(owner, repo): diff --git a/docs/source/rest-api/spec.yml b/docs/source/rest-api/spec.yml index ae583dbbbb..50643d9164 100644 --- a/docs/source/rest-api/spec.yml +++ b/docs/source/rest-api/spec.yml @@ -96,6 +96,49 @@ paths: type: array tags: - utility + /repos/:id: + get: + description: Get a downloaded repo by its ID in Augur. + operationId: Get Repo By ID + responses: + '200': + description: OK + scema: + items: + properties: + base64_url: + description: 'Base64 encode of the full URL. Example Z2l0aHViLmNvbS8zc2NhbGUvM3NjYWxlLW9wZXJhdG9yLW1ldGFkYXRh' + type: string + description: + description: 'Repository description. Example: null' + type: string + commits_all_time: + description: 'How many commits have been made to this respository. Example: 24' + type: integer + issues_all_time: + description: 'How many issues have been raised on this respository. Example: 1' + type: integer + pull_requests_all_time: + description: 'How many pull requests have been made to this reqpository. Example: 7' + type: integer + repo_id: + description: 'Repository ID, should match provided URL parameter. Example: 25551' + type: integer + repo_name: + description: 'Name of the provided rpository. Example: 3scale-operator-metadata' + type: string + rg_name: + description: 'Name of the repository group containing this repo. Example: 3scale' + type: string + repo_group_id: + description: 'ID of the repository group containing this repo. Example: 25431' + type: integer + url: + description: 'URL of this repository, sans leading protocol. Example: github.com/3scale/3scale-operator-metadata' + type: string + type: object + tags: + - utility /owner/:owner/repo/:repo: get: description: Get the repo_group_id and repo_id of a particular repo. @@ -284,12 +327,12 @@ paths: tags: - utility #risk endpoints - /metadata/repo_info: - get: - description: 'Returns the metadata about all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the default branch name, repository license file, forks, stars, watchers, and committers. Also includes metadata about current repository issue and pull request status and counts.' + /metadata/repo_info: + get: + description: 'Returns the metadata about all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the default branch name, repository license file, forks, stars, watchers, and committers. Also includes metadata about current repository issue and pull request status and counts.' externalDocs: description: CHAOSS Metric Definition - url: https://github.com/chaoss/wg-risk/blob/main/focus-areas/business-risk.md + url: https://github.com/chaoss/wg-risk/blob/main/focus-areas/business-risk.md operationId: Activity Metadata (Repo) responses: '200': @@ -315,45 +358,45 @@ paths: fork_count: description: 'Example: 554' type: integer - watchers_count: + watchers_count: description: 'Example: 424' type: integer - stars_count: + stars_count: description: 'Example: 443' type: integer - commits_count: + commits_count: description: '4434' - type: integer - committers_count: + type: integer + committers_count: description: 'Example: 42' type: integer - open_issues: + open_issues: description: 'Example: 7' - type: integer - issues_count: + type: integer + issues_count: description: 'Example: 23332' type: integer - issues_closed: + issues_closed: description: 'Example: 23322' type: integer - pull_request_count: + pull_request_count: description: 'Example: 19445' type: integer - pull_requests_open: + pull_requests_open: description: 'Example: 10' type: integer - pull_requests_closed: + pull_requests_closed: description: 'Example: 19435' type: integer - pull_requests_merged: + pull_requests_merged: description: 'Example: 17473' type: integer type: array tags: - risk - /metadata/contributions_count: - get: - description: 'Returns a list of repositories contributed to by all the contributors in an Augur Instance: INCLUDING all repositories on a platform, *not* merely those repositories in the Augur Instance. Numerical totals represent total CONTRIBUTIONS.' + /metadata/contributions_count: + get: + description: 'Returns a list of repositories contributed to by all the contributors in an Augur Instance: INCLUDING all repositories on a platform, *not* merely those repositories in the Augur Instance. Numerical totals represent total CONTRIBUTIONS.' externalDocs: description: CHAOSS Metric Definition url: https://github.com/chaoss/wg-risk/blob/main/focus-areas/business-risk.md @@ -373,9 +416,9 @@ paths: type: array tags: - risk - /metadata/contributors_count: - get: - description: 'Returns a list of repositories contributed to by all the contributors in an Augur Instance: INCLUDING all repositories on a platform, *not* merely those repositories in the Augur Instance. Numerical totals represent total CONTRIBUTORS.' + /metadata/contributors_count: + get: + description: 'Returns a list of repositories contributed to by all the contributors in an Augur Instance: INCLUDING all repositories on a platform, *not* merely those repositories in the Augur Instance. Numerical totals represent total CONTRIBUTORS.' externalDocs: description: CHAOSS Metric Definition url: https://github.com/chaoss/wg-risk/blob/main/focus-areas/business-risk.md @@ -5144,9 +5187,9 @@ paths: type: object tags: - visualizations - /complexity/project_lines: - get: - description: 'Returns project line data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average number of lines in the project repository.' + /complexity/project_lines: + get: + description: 'Returns project line data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average number of lines in the project repository.' operationId: Total Lines (repo) responses: '200': @@ -5172,9 +5215,9 @@ paths: type: array tags: - complexity - /complexity/project_file_complexity: - get: - description: 'Returns project file complexity data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average file complexity of the project repository.' + /complexity/project_file_complexity: + get: + description: 'Returns project file complexity data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average file complexity of the project repository.' operationId: File Complexity (repo) responses: '200': @@ -5200,9 +5243,9 @@ paths: type: array tags: - complexity - /complexity/project_blank_lines: - get: - description: 'Returns project blank line data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average number of blank lines in the project repository.' + /complexity/project_blank_lines: + get: + description: 'Returns project blank line data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average number of blank lines in the project repository.' operationId: Total Blank Lines (repo) responses: '200': @@ -5228,9 +5271,9 @@ paths: type: array tags: - complexity - /complexity/project_comment_lines: - get: - description: 'Returns project comment line data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average number of comment lines in the project repository.' + /complexity/project_comment_lines: + get: + description: 'Returns project comment line data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total and average number of comment lines in the project repository.' operationId: Total Comment Lines (repo) responses: '200': @@ -5256,9 +5299,9 @@ paths: type: array tags: - complexity - /complexity/project_files: - get: - description: 'Returns project file data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total number of files in the project repository.' + /complexity/project_files: + get: + description: 'Returns project file data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the total number of files in the project repository.' operationId: Total Files (repo) responses: '200': @@ -5281,9 +5324,9 @@ paths: type: array tags: - complexity - /complexity/project_languages: - get: - description: 'Returns project language data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the lines and files of a language in a repository.' + /complexity/project_languages: + get: + description: 'Returns project language data for all repositories in an Augur instance, using information from a git platform (GitHub, GitLab, etc.). Each record includes the lines and files of a language in a repository.' operationId: Project Languages (repo) responses: '200': @@ -5317,7 +5360,7 @@ paths: description: 'The number of messages exchanged for a repository group over a specified period.' externalDocs: description: CHAOSS Metric Definition - url: + url: operationId: Repository Messages (Repo Group) parameters: - description: Repository Group ID @@ -5633,4 +5676,4 @@ paths: type: string enum: ["Missing argument"] tags: - - DEI Badging \ No newline at end of file + - DEI Badging From a83fee5c2a5d71922277478763b8f1451501eb32 Mon Sep 17 00:00:00 2001 From: Seltyk Date: Tue, 8 Aug 2023 09:25:58 -0400 Subject: [PATCH 2/3] It would maybe help if I spelled "schema" right Signed-off-by: Seltyk --- docs/source/rest-api/spec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/rest-api/spec.yml b/docs/source/rest-api/spec.yml index 50643d9164..c7ed3601a7 100644 --- a/docs/source/rest-api/spec.yml +++ b/docs/source/rest-api/spec.yml @@ -103,7 +103,7 @@ paths: responses: '200': description: OK - scema: + schema: items: properties: base64_url: From 577c4f8994c350de7f6070fb9f9ecbb127fce242 Mon Sep 17 00:00:00 2001 From: Seltyk Date: Tue, 8 Aug 2023 09:59:26 -0400 Subject: [PATCH 3/3] Pretend the schema is an array for rendering I'm honestly not sure why "object" doesn't work out, so for the first time in my life, I had to write docs for the docs in the docs! Signed-off-by: Seltyk --- docs/source/rest-api/spec.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/rest-api/spec.yml b/docs/source/rest-api/spec.yml index c7ed3601a7..15423e9a64 100644 --- a/docs/source/rest-api/spec.yml +++ b/docs/source/rest-api/spec.yml @@ -98,7 +98,7 @@ paths: - utility /repos/:id: get: - description: Get a downloaded repo by its ID in Augur. + description: Get a downloaded repo by its ID in Augur. The schema block below says it is an array, but it is not. operationId: Get Repo By ID responses: '200': @@ -136,7 +136,7 @@ paths: url: description: 'URL of this repository, sans leading protocol. Example: github.com/3scale/3scale-operator-metadata' type: string - type: object + type: array tags: - utility /owner/:owner/repo/:repo: