Skip to content

Commit 20c06a3

Browse files
committed
fix paths 2 and tests
1 parent cef3ab6 commit 20c06a3

10 files changed

Lines changed: 337 additions & 71 deletions

File tree

osa_tool/operations/docs/community_docs_generation/community.py

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
from osa_tool.core.git.metadata import RepositoryMetadata
77
from osa_tool.operations.docs.readme_generation.readme_utils import (
88
find_in_repo_tree,
9+
resolve_repo_host_and_root_url,
910
save_sections,
1011
to_repo_relative_link,
1112
)
1213
from osa_tool.tools.repository_analysis.sourcerank import SourceRank
1314
from osa_tool.utils.logger import logger
14-
from osa_tool.utils.utils import osa_project_root, parse_folder_name
15+
from osa_tool.utils.utils import osa_project_root, resolve_repo_path
1516

1617

1718
class CommunityTemplateBuilder:
@@ -25,21 +26,26 @@ def __init__(self, config_manager: ConfigManager, metadata: RepositoryMetadata):
2526
self.sourcerank = SourceRank(self.config_manager)
2627
self.metadata = metadata
2728
self.template_path = os.path.join(osa_project_root(), "docs", "templates", "community.toml")
28-
self.url_path = f"https://{self.config_manager.get_git_settings().host_domain}/{self.config_manager.get_git_settings().full_name}/"
29+
git = self.config_manager.get_git_settings()
30+
self.host, self.url_path = resolve_repo_host_and_root_url(
31+
repo_url=self.repo_url,
32+
clone_url_http=self.metadata.clone_url_http,
33+
host=git.host,
34+
host_domain=git.host_domain,
35+
full_name=git.full_name,
36+
)
2937
self._template = self.load_template()
3038

31-
self.repo_root = os.path.join(os.getcwd(), parse_folder_name(self.repo_url))
32-
self.repo_path = os.path.join(
33-
self.repo_root, "." + self.config_manager.get_git_settings().host
34-
)
39+
self.repo_root = str(resolve_repo_path(self.repo_url))
40+
self.repo_path = self.repo_root if "sourcecraft" in self.host else os.path.join(self.repo_root, f".{self.host}")
3541
self.code_of_conduct_to_save = os.path.join(self.repo_path, "CODE_OF_CONDUCT.md")
3642
self.security_to_save = os.path.join(self.repo_path, "SECURITY.md")
3743
self._setup_paths_depends_on_platform()
3844

3945
def _setup_paths_depends_on_platform(self) -> None:
4046
"""Configures file save paths depending on the platform."""
4147

42-
if "gitlab" in self.config_manager.get_git_settings().host:
48+
if "gitlab" in self.host:
4349
self.issue_templates_path = os.path.join(self.repo_path, "issue_templates")
4450
self.merge_request_templates_path = os.path.join(self.repo_path, "merge_request_templates")
4551
os.makedirs(self.issue_templates_path, exist_ok=True)
@@ -52,26 +58,22 @@ def _setup_paths_depends_on_platform(self) -> None:
5258
self.vulnerability_disclosure_to_save = os.path.join(
5359
self.issue_templates_path, "Vulnerability_Disclosure.md"
5460
)
55-
elif "github" in self.config_manager.get_git_settings().host:
61+
elif "github" in self.host:
5662
self.issue_templates_path = os.path.join(self.repo_path, "ISSUE_TEMPLATE")
5763
os.makedirs(self.issue_templates_path, exist_ok=True)
5864
self.pr_to_save = os.path.join(self.repo_path, "PULL_REQUEST_TEMPLATE.md")
5965
self.docs_issue_to_save = os.path.join(self.issue_templates_path, "DOCUMENTATION_ISSUE.md")
6066
self.feature_issue_to_save = os.path.join(self.issue_templates_path, "FEATURE_ISSUE.md")
6167
self.bug_issue_to_save = os.path.join(self.issue_templates_path, "BUG_ISSUE.md")
62-
elif "sourcecraft" in self.config_manager.get_git_settings().host:
63-
self.code_of_conduct_to_save = os.path.join(self.repo_root, "CODE_OF_CONDUCT.md")
64-
self.security_to_save = os.path.join(self.repo_root, "SECURITY.md")
65-
self.pr_to_save = os.path.join(self.repo_root, "PULL_REQUEST_TEMPLATE.md")
66-
self.docs_issue_to_save = os.path.join(self.repo_root, "DOCUMENTATION_ISSUE.md")
67-
self.feature_issue_to_save = os.path.join(self.repo_root, "FEATURE_ISSUE.md")
68-
self.bug_issue_to_save = os.path.join(self.repo_root, "BUG_ISSUE.md")
68+
elif "sourcecraft" in self.host:
69+
self.pr_to_save = os.path.join(self.repo_path, "PULL_REQUEST_TEMPLATE.md")
70+
self.docs_issue_to_save = os.path.join(self.repo_path, "DOCUMENTATION_ISSUE.md")
71+
self.feature_issue_to_save = os.path.join(self.repo_path, "FEATURE_ISSUE.md")
72+
self.bug_issue_to_save = os.path.join(self.repo_path, "BUG_ISSUE.md")
6973

7074
def _local_repo_link(self, pattern: str, *, from_path: str) -> str:
7175
rel_path = find_in_repo_tree(self.sourcerank.tree, pattern)
7276
from_dir = os.path.relpath(os.path.dirname(from_path), self.repo_root).replace("\\", "/")
73-
if from_dir == ".":
74-
from_dir = ""
7577
return to_repo_relative_link(rel_path, from_dir=from_dir)
7678

7779
def load_template(self) -> dict:
@@ -81,6 +83,12 @@ def load_template(self) -> dict:
8183
with open(self.template_path, "rb") as file:
8284
return tomli.load(file)
8385

86+
def _build_security_repo_reference(self) -> str:
87+
"""Return a web repository reference or an editable local placeholder."""
88+
if self.url_path != ".":
89+
return self.url_path.rstrip("/")
90+
return f"...{resolve_repo_path(self.repo_url).name}"
91+
8492
def build_code_of_conduct(self) -> bool:
8593
"""
8694
Generates and saves the CODE_OF_CONDUCT.md file.
@@ -99,13 +107,12 @@ def build_code_of_conduct(self) -> bool:
99107
def build_pull_request(self) -> bool:
100108
"""Generates and saves the PULL_REQUEST_TEMPLATE.md file."""
101109
try:
110+
contributing_url = ""
102111
if self.sourcerank.contributing_presence():
103112
pattern = r"\b\w*contribut\w*\.(md|rst|txt)$"
104113
contributing_url = self._local_repo_link(pattern, from_path=self.pr_to_save)
105-
else:
106-
contributing_url = "Provide the link"
107114

108-
content = self._template["pull_request"].format(contributing_url=contributing_url)
115+
content = self._template["pull_request"].format(contributing_url=contributing_url or "Provide the link")
109116
save_sections(content, self.pr_to_save)
110117
logger.info(f"PULL_REQUEST_TEMPLATE.md successfully generated in folder {os.path.dirname(self.pr_to_save)}")
111118
except Exception as e:
@@ -195,9 +202,7 @@ def build_security(self) -> bool:
195202
Has the task been completed successfully
196203
"""
197204
try:
198-
content = self._template[f"security_{self.config_manager.get_git_settings().host}"].format(
199-
repo_url=self.repo_url
200-
)
205+
content = self._template[f"security_{self.host}"].format(repo_url=self._build_security_repo_reference())
201206
save_sections(content, self.security_to_save)
202207
logger.info(f"SECURITY.md successfully generated in folder {self.repo_path}")
203208
except Exception as e:

osa_tool/operations/docs/community_docs_generation/contributing.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
from osa_tool.operations.docs.readme_generation.readme_utils import (
88
find_in_repo_tree,
99
remove_extra_blank_lines,
10+
resolve_repo_host_and_root_url,
1011
save_sections,
1112
to_repo_relative_link,
1213
)
1314
from osa_tool.tools.repository_analysis.sourcerank import SourceRank
1415
from osa_tool.utils.logger import logger
15-
from osa_tool.utils.utils import osa_project_root, parse_folder_name
16+
from osa_tool.utils.utils import osa_project_root, resolve_repo_path
1617

1718

1819
class ContributingBuilder:
@@ -26,26 +27,26 @@ def __init__(self, config_manager: ConfigManager, metadata: RepositoryMetadata):
2627
self.repo_url = self.config_manager.get_git_settings().repository
2728
self.metadata = metadata
2829
self.template_path = os.path.join(osa_project_root(), "docs", "templates", "contributing.toml")
29-
self.url_path = f"https://{self.config_manager.get_git_settings().host_domain}/{self.config_manager.get_git_settings().full_name}/"
30-
self.issues_url = self.url_path + (
31-
"tasktracker" if "gitverse" in self.config_manager.get_git_settings().host else "issues"
30+
git = self.config_manager.get_git_settings()
31+
self.host, self.url_path = resolve_repo_host_and_root_url(
32+
repo_url=self.repo_url,
33+
clone_url_http=self.metadata.clone_url_http,
34+
host=git.host,
35+
host_domain=git.host_domain,
36+
full_name=git.full_name,
37+
)
38+
self.issues_url = self.metadata.issues_url or (
39+
f"{self.url_path}{'tasktracker' if 'gitverse' in self.host else 'issues'}" if self.url_path != "." else "."
3240
)
3341
self._template = self.load_template()
3442

35-
self.repo_root = os.path.join(os.getcwd(), parse_folder_name(self.repo_url))
36-
self.repo_path = os.path.join(
37-
self.repo_root, "." + self.config_manager.get_git_settings().host
38-
)
43+
self.repo_root = str(resolve_repo_path(self.repo_url))
44+
self.repo_path = self.repo_root if "sourcecraft" in self.host else os.path.join(self.repo_root, f".{self.host}")
3945
self.file_to_save = os.path.join(self.repo_path, "CONTRIBUTING.md")
4046

41-
if "sourcecraft" in self.config_manager.get_git_settings().host:
42-
self.file_to_save = os.path.join(self.repo_root, "CONTRIBUTING.md")
43-
4447
def _local_repo_link(self, pattern: str, *, prefer_directory: bool = False) -> str:
4548
rel_path = find_in_repo_tree(self.sourcerank.tree, pattern, prefer_directory=prefer_directory)
4649
from_dir = os.path.relpath(os.path.dirname(self.file_to_save), self.repo_root).replace("\\", "/")
47-
if from_dir == ".":
48-
from_dir = ""
4950
return to_repo_relative_link(rel_path, from_dir=from_dir)
5051

5152
def load_template(self) -> dict:
@@ -67,7 +68,7 @@ def introduction(self) -> str:
6768
def guide(self) -> str:
6869
"""Generates the guide section with basic project contribution instructions."""
6970
return self._template["guide"].format(
70-
url=self.url_path,
71+
url=self.url_path if self.url_path != "." else "./",
7172
project_name=self.metadata.name,
7273
clone_url=self.metadata.clone_url_http or self.url_path,
7374
)

osa_tool/operations/docs/community_docs_generation/docs_run.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ def generate_documentation(config_manager: ConfigManager, metadata: RepositoryMe
2525
events: list[OperationEvent] = []
2626
generated_files: list[str] = []
2727
contributing = ContributingBuilder(config_manager, metadata)
28-
community = CommunityTemplateBuilder(config_manager, metadata)
29-
platform_host = getattr(community, "host", None) or config_manager.get_git_settings().host
3028

3129
try:
3230
contributing.build()
@@ -36,6 +34,9 @@ def generate_documentation(config_manager: ConfigManager, metadata: RepositoryMe
3634
logger.error("Failed to generate CONTRIBUTING: %s", repr(e), exc_info=True)
3735
events.append(OperationEvent(kind=EventKind.FAILED, target="CONTRIBUTING", data={"error": repr(e)}))
3836

37+
community = CommunityTemplateBuilder(config_manager, metadata)
38+
platform_host = community.host
39+
3940
try:
4041
community.build_code_of_conduct()
4142
events.append(OperationEvent(kind=EventKind.GENERATED, target="CODE_OF_CONDUCT"))

osa_tool/operations/docs/readme_generation/pipeline/nodes/deterministic_builder.py

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44
from datetime import datetime
5+
from pathlib import Path
56
from typing import Any
67

78
import requests
@@ -16,12 +17,13 @@
1617
from osa_tool.operations.docs.readme_generation.readme_utils import (
1718
build_system_message,
1819
find_in_repo_tree,
20+
resolve_repo_host_and_root_url,
1921
to_readme_relative_link,
2022
)
2123
from osa_tool.tools.repository_analysis.sourcerank import SourceRank
2224
from osa_tool.utils.logger import logger
2325
from osa_tool.utils.prompts_builder import PromptBuilder
24-
from osa_tool.utils.utils import extract_readme_content, osa_project_root, parse_folder_name
26+
from osa_tool.utils.utils import extract_readme_content, osa_project_root, resolve_repo_path
2527

2628

2729
def _load_template() -> dict[str, Any]:
@@ -48,12 +50,39 @@ def __init__(self, context: ReadmeContext) -> None:
4850
self._tpl = _load_template()
4951

5052
git = self._cm.get_git_settings()
51-
self._url_path = f"https://{git.host_domain}/{git.full_name}/"
53+
self._host, self._repo_root_url = resolve_repo_host_and_root_url(
54+
repo_url=git.repository,
55+
clone_url_http=self._meta.clone_url_http,
56+
host=git.host,
57+
host_domain=git.host_domain,
58+
full_name=git.full_name,
59+
)
60+
self._is_local_repo = Path(git.repository).expanduser().is_dir()
5261

5362
def _local_repo_link(self, pattern: str, *, prefer_directory: bool = False) -> str:
5463
rel_path = find_in_repo_tree(self._sr.tree, pattern, prefer_directory=prefer_directory)
5564
return to_readme_relative_link(rel_path)
5665

66+
def _issues_link(self) -> str:
67+
if self._meta.issues_url:
68+
return self._meta.issues_url.split("{", 1)[0]
69+
if self._repo_root_url != ".":
70+
suffix = "tasktracker" if self._host == "gitverse" else "issues"
71+
return f"{self._repo_root_url}{suffix}"
72+
pattern = r"\bBUG_ISSUE\.(md|rst|txt)$"
73+
return self._local_repo_link(pattern)
74+
75+
def _contributing_link(self) -> str:
76+
pattern = r"\b\w*contribut\w*\.(md|rst|txt)$"
77+
return self._local_repo_link(pattern)
78+
79+
def _citation_repository_reference(self) -> str:
80+
if self._meta.clone_url_http:
81+
return self._meta.clone_url_http.removesuffix(".git")
82+
if self._repo_root_url != ".":
83+
return self._repo_root_url.rstrip("/")
84+
return "REPOSITORY_URL"
85+
5786
def header(self) -> str:
5887
logger.info("[DeterministicBuilder] Building section: header")
5988
content = HeaderBuilder(self._cm, self._meta).build_header()
@@ -94,23 +123,23 @@ def documentation(self) -> str:
94123

95124
def contributing(self) -> str:
96125
logger.info("[DeterministicBuilder] Building section: contributing")
97-
discussions_url = self._url_path + "discussions"
98-
discussions_enabled = _check_url(discussions_url)
126+
discussions_url = f"{self._repo_root_url}discussions" if self._repo_root_url != "." else "."
127+
discussions_enabled = discussions_url != "." and _check_url(discussions_url)
99128
discussions = (
100129
self._tpl["discussion_section"].format(discussions_url=discussions_url) if discussions_enabled else ""
101130
)
102131

103-
issues_url = self._url_path + "issues"
104-
issues = self._tpl["issues_section"].format(issues_url=issues_url)
132+
issues_url = self._issues_link()
133+
issues = self._tpl["issues_section"].format(issues_url=issues_url) if issues_url else ""
105134

106-
contributing_text = ""
107-
has_contributing = self._sr.contributing_presence()
108-
if has_contributing:
109-
pattern = r"\b\w*contribut\w*\.(md|rst|txt)$"
110-
contributing_url = self._local_repo_link(pattern)
111-
contributing_text = self._tpl["contributing_section"].format(
135+
contributing_url = self._contributing_link() if self._sr.contributing_presence() else ""
136+
contributing_text = (
137+
self._tpl["contributing_section"].format(
112138
contributing_url=contributing_url, name=self._cm.get_git_settings().name
113139
)
140+
if contributing_url
141+
else ""
142+
)
114143

115144
content = self._tpl["contributing"].format(
116145
dicsussion_section=discussions,
@@ -120,7 +149,7 @@ def contributing(self) -> str:
120149
logger.info(
121150
"[DeterministicBuilder] Section 'contributing' built (discussions=%s, contributing_file=%s)",
122151
discussions_enabled,
123-
has_contributing,
152+
bool(contributing_url),
124153
)
125154
return content
126155

@@ -169,20 +198,30 @@ def citation(self) -> str:
169198

170199
git = self._cm.get_git_settings()
171200
year = self._meta.created_at.split("-")[0] if self._meta.created_at else str(datetime.now().year)
201+
repository_reference = self._citation_repository_reference()
202+
if self._is_local_repo and not self._meta.clone_url_http:
203+
content = self._tpl["citation"] + self._tpl["citation_v3"].format(
204+
owner=self._meta.owner or "",
205+
year=year,
206+
repo_name=git.name,
207+
repository_hint=repository_reference,
208+
)
209+
logger.info("[DeterministicBuilder] Section 'citation' built from local fallback template")
210+
return content
172211
content = self._tpl["citation"] + self._tpl["citation_v2"].format(
173212
owner=self._meta.owner or "",
174213
year=year,
175214
repo_name=git.name,
176-
publisher=git.host_domain,
177-
repository_url=git.repository,
215+
publisher=git.host_domain or "Repository host",
216+
repository_url=repository_reference,
178217
)
179218
logger.info("[DeterministicBuilder] Section 'citation' built from fallback template")
180219
return content
181220

182221
def _extract_citation_from_readme(self) -> str:
183222
"""Ask the shared model_handler to find citations in the existing README."""
184223
logger.info("[DeterministicBuilder] Checking existing README for citation block")
185-
repo_path = os.path.join(os.getcwd(), parse_folder_name(self._cm.get_git_settings().repository))
224+
repo_path = str(resolve_repo_path(self._cm.get_git_settings().repository))
186225
readme_content = extract_readme_content(repo_path)
187226

188227
logger.info("[DeterministicBuilder] Detecting citations in README via LLM...")

0 commit comments

Comments
 (0)