1010
1111from workflow .integrations .base import BaseIntegration
1212
13- FORGEJO_API_URL = ""
13+ FORGEJO_API_PATH = "/api/v1 "
1414
1515
1616class ForgejoIntegration (BaseIntegration ):
@@ -19,40 +19,46 @@ class ForgejoIntegration(BaseIntegration):
1919 from DejaCode requests.
2020 """
2121
22- api_url = FORGEJO_API_URL
22+ open_status = "open"
23+ closed_status = "closed"
2324
2425 def get_headers (self ):
25- forgejo_token = self .dataspace .get_configuration (field_name = "forgejo_token" )
26+ forgejo_token = self .dataspace .get_configuration ("forgejo_token" )
2627 if not forgejo_token :
2728 raise ValueError ("The forgejo_token is not set on the Dataspace." )
2829 return {"Authorization" : f"token { forgejo_token } " }
2930
3031 def sync (self , request ):
3132 """Sync the given request with Forgejo by creating or updating an issue."""
3233 try :
33- repo_id = self .extract_forgejo_repo_path (request .request_template .issue_tracker_id )
34+ base_url , repo_path = self .extract_forgejo_info (
35+ request .request_template .issue_tracker_id
36+ )
3437 except ValueError as error :
35- raise ValueError (f"Invalid Forgejo repository URL: { error } " )
38+ raise ValueError (f"Invalid Forgejo tracker URL: { error } " )
39+
40+ self .api_url = base_url .rstrip ("/" ) + FORGEJO_API_PATH
3641
3742 external_issue = request .external_issue
3843 if external_issue :
3944 self .update_issue (
40- repo_id = repo_id ,
45+ repo_id = repo_path ,
4146 issue_id = external_issue .issue_id ,
4247 title = self .make_issue_title (request ),
4348 body = self .make_issue_body (request ),
44- state = "closed" if request .is_closed else "open" ,
49+ state = self . closed_status if request .is_closed else self . open_status ,
4550 )
4651 else :
4752 issue = self .create_issue (
48- repo_id = repo_id ,
53+ repo_id = repo_path ,
4954 title = self .make_issue_title (request ),
5055 body = self .make_issue_body (request ),
5156 )
5257 request .link_external_issue (
5358 platform = "forgejo" ,
54- repo = repo_id ,
59+ repo = repo_path ,
5560 issue_id = issue ["number" ],
61+ base_url = base_url ,
5662 )
5763
5864 def create_issue (self , repo_id , title , body = "" ):
@@ -78,22 +84,28 @@ def update_issue(self, repo_id, issue_id, title=None, body=None, state=None):
7884
7985 return self .patch (url , json = data )
8086
81- def post_comment (self , repo_id , issue_id , comment_body ):
87+ def post_comment (self , repo_id , issue_id , comment_body , base_url = None ):
8288 """Post a comment on an existing Forgejo issue."""
83- url = f"{ self .api_url } /repos/{ repo_id } /issues/{ issue_id } /comments"
84- data = {"body" : comment_body }
85-
86- return self .post (url , json = data )
89+ url = f"{ base_url } /{ FORGEJO_API_PATH } /repos/{ repo_id } /issues/{ issue_id } /comments"
90+ return self .post (url , json = {"body" : comment_body })
8791
8892 @staticmethod
89- def extract_forgejo_repo_path (url ):
90- """Extract 'owner/repo-name' from a Forgejo URL."""
93+ def extract_forgejo_info (url ):
94+ """
95+ Extract the Forgejo base domain and repo path (org/repo) from a repo URL.
96+
97+ Example:
98+ - https://forgejo.example.org/org/repo → ("https://forgejo.example.org", "org/repo")
99+
100+ """
91101 parsed = urlparse (url )
92102 if not parsed .netloc :
93- raise ValueError ("URL must include a hostname ." )
103+ raise ValueError ("Missing hostname in Forgejo URL ." )
94104
95- path_parts = [part for part in parsed .path .split ("/" ) if part ]
105+ base_url = f"{ parsed .scheme } ://{ parsed .netloc } "
106+ path_parts = [p for p in parsed .path .split ("/" ) if p ]
96107 if len (path_parts ) < 2 :
97108 raise ValueError ("Incomplete Forgejo repository path." )
98109
99- return f"{ path_parts [0 ]} /{ path_parts [1 ]} "
110+ repo_path = f"{ path_parts [0 ]} /{ path_parts [1 ]} "
111+ return base_url , repo_path
0 commit comments