From 465cdab9958f23864c8a6953df4130df57175004 Mon Sep 17 00:00:00 2001 From: Corentin Forler Date: Thu, 19 Sep 2024 09:49:43 +0200 Subject: [PATCH 1/2] feat(app_source): Handle GitLab app sources --- .../press/doctype/app_source/app_source.json | 13 ++++ press/press/doctype/app_source/app_source.py | 59 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/press/press/doctype/app_source/app_source.json b/press/press/doctype/app_source/app_source.json index d20e97801b..f73c11bcc7 100644 --- a/press/press/doctype/app_source/app_source.json +++ b/press/press/doctype/app_source/app_source.json @@ -21,6 +21,8 @@ "column_break_11", "github_installation_id", "uninstalled", + "gitlab_project_id", + "gitlab_access_token", "section_break_12", "versions", "github_section", @@ -77,6 +79,17 @@ "fieldtype": "Data", "label": "GitHub Installation ID" }, + { + "fieldname": "gitlab_project_id", + "fieldtype": "Data", + "label": "GitLab Project ID" + }, + { + "depends_on": "eval:doc.gitlab_project_id", + "fieldname": "gitlab_access_token", + "fieldtype": "Password", + "label": "GitLab Access Token" + }, { "fieldname": "data_3", "fieldtype": "Column Break" diff --git a/press/press/doctype/app_source/app_source.py b/press/press/doctype/app_source/app_source.py index 8f09741791..59a8da6fda 100644 --- a/press/press/doctype/app_source/app_source.py +++ b/press/press/doctype/app_source/app_source.py @@ -33,6 +33,8 @@ class AppSource(Document): enabled: DF.Check frappe: DF.Check github_installation_id: DF.Data | None + gitlab_access_token: DF.Password | None + gitlab_project_id: DF.Data | None last_github_poll_failed: DF.Check last_github_response: DF.Code | None last_synced: DF.Datetime | None @@ -99,12 +101,64 @@ def before_save(self): _, self.repository_owner, self.repository = self.repository_url.rsplit("/", 2) # self.create_release() + def create_gitlab_release(self, force=False): + from urllib.parse import urlparse + + repo_url = urlparse(self.repository_url) + api_path = ( + f"/api/v4/projects/{self.gitlab_project_id}/repository/branches/{self.branch}" + ) + url = f"{repo_url.scheme}://{repo_url.netloc}{api_path}" + + headers = {} + + gitlab_token = "" + if self.get("gitlab_access_token"): + gitlab_token = gitlab_token or self.get_password("gitlab_access_token") + + if gitlab_token: + headers["Authorization"] = f"Bearer {gitlab_token}" + + res = requests.get(url, headers=headers).json() + + frappe.db.set_value( + "App Source", + self.name, + { + "last_github_response": "GitLab", + "last_github_poll_failed": False, + "last_synced": frappe.utils.now(), + }, + ) + commit_hash = res["commit"]["id"] + commit_message = res["commit"]["message"] + commit_author = res["commit"]["author_name"] + if not frappe.db.exists( + "App Release", {"app": self.app, "source": self.name, "hash": commit_hash} + ): + frappe.get_doc( + { + "doctype": "App Release", + "app": self.app, + "source": self.name, + "hash": commit_hash, + "team": self.team, + "message": commit_message, + "author": commit_author, + "deployable": False, + } + ).insert(set_name=f"{self.name}-{commit_hash}") + @frappe.whitelist() def create_release( self, force: bool = False, commit_hash: str | None = None, ): + if self.gitlab_project_id: + self.create_gitlab_release(force) + return + if self.last_github_poll_failed and not force: return @@ -234,6 +288,11 @@ def get_access_token(self) -> Optional[str]: return frappe.get_value("Press Settings", None, "github_access_token") def get_repo_url(self) -> str: + if self.get("gitlab_access_token"): + return self.repository_url.replace( + "https://", f"https://oauth2:{self.get_password('gitlab_access_token')}@" + ) + if not self.github_installation_id: return self.repository_url From 09cff2ee2c37f4951186efd795b935deb09ec8dc Mon Sep 17 00:00:00 2001 From: Corentin Forler Date: Thu, 19 Sep 2024 09:50:02 +0200 Subject: [PATCH 2/2] refactor: Keep _get_repo_url DRY --- press/press/doctype/app_release/app_release.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/press/press/doctype/app_release/app_release.py b/press/press/doctype/app_release/app_release.py index 13d5f8993e..da86b63ce8 100644 --- a/press/press/doctype/app_release/app_release.py +++ b/press/press/doctype/app_release/app_release.py @@ -11,7 +11,6 @@ import frappe from frappe.model.document import Document -from press.api.github import get_access_token from press.press.doctype.app_source.app_source import AppSource from press.utils import log_error @@ -222,15 +221,7 @@ def _clone_repo(self): self.output += self.run(f"git reset --hard {self.hash}") def _get_repo_url(self, source: "AppSource") -> str: - if not source.github_installation_id: - return source.repository_url - - token = get_access_token(source.github_installation_id) - if token is None: - # Do not edit without updating deploy_notifications.py - raise Exception("App installation token could not be fetched", self.app) - - return f"https://x-access-token:{token}@github.com/{source.repository_owner}/{source.repository}" + return source.get_repo_url() def on_trash(self): if self.clone_directory and os.path.exists(self.clone_directory):