mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-03 17:39:42 +02:00
feat: Add sync README dependencies workflow and script
Introduce an automated workflow to keep the README's Python Dependencies section in sync with requirements.txt. Adds .github/workflows/sync-readme-dependencies.yml which runs scripts/sync_readme_dependencies.py on changes to requirements.txt (or manually), then opens a PR via peter-evans/create-pull-request. Adds the sync_readme_dependencies.py script that parses requirements.txt and replaces a managed block in README.md delimited by <!-- python-dependencies:start --> / <!-- python-dependencies:end -->. Also updates README.md to include those markers and correct dependency names/formatting. Additionally, change create-release.yml to use RELEASE_TOKEN (secrets.RELEASE_TOKEN) for release uploads instead of the repository GITHUB_TOKEN.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
|
||||
ROOT_DIR = Path(__file__).resolve().parent.parent
|
||||
README_PATH = ROOT_DIR / "README.md"
|
||||
REQUIREMENTS_PATH = ROOT_DIR / "requirements.txt"
|
||||
|
||||
START_MARKER = "<!-- python-dependencies:start -->"
|
||||
END_MARKER = "<!-- python-dependencies:end -->"
|
||||
REQUIREMENT_PATTERN = re.compile(
|
||||
r"^(?P<name>[A-Za-z0-9_.\-\[\]]+)\s*(?P<specifier>(==|~=|>=|<=|!=|>|<).+)?$"
|
||||
)
|
||||
|
||||
|
||||
def iter_requirements(requirements_text: str) -> list[str]:
|
||||
formatted_lines: list[str] = []
|
||||
|
||||
for raw_line in requirements_text.splitlines():
|
||||
line = raw_line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
|
||||
match = REQUIREMENT_PATTERN.match(line)
|
||||
if not match:
|
||||
formatted_lines.append(f" {line}")
|
||||
continue
|
||||
|
||||
name = match.group("name")
|
||||
specifier = (match.group("specifier") or "").strip()
|
||||
|
||||
if specifier.startswith("=="):
|
||||
formatted_lines.append(f" {name} ({specifier[2:]})")
|
||||
elif specifier:
|
||||
formatted_lines.append(f" {name} {specifier}")
|
||||
else:
|
||||
formatted_lines.append(f" {name}")
|
||||
|
||||
return formatted_lines
|
||||
|
||||
|
||||
def render_dependency_block(requirements_text: str) -> str:
|
||||
dependency_lines = iter_requirements(requirements_text)
|
||||
return "\n".join(
|
||||
[
|
||||
START_MARKER,
|
||||
" ```text",
|
||||
*dependency_lines,
|
||||
" ```",
|
||||
END_MARKER,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def replace_managed_block(readme_text: str, rendered_block: str) -> str:
|
||||
start_index = readme_text.find(START_MARKER)
|
||||
end_index = readme_text.find(END_MARKER)
|
||||
|
||||
if start_index == -1 or end_index == -1 or end_index < start_index:
|
||||
raise RuntimeError("README dependency markers are missing or invalid.")
|
||||
|
||||
end_index += len(END_MARKER)
|
||||
return readme_text[:start_index] + rendered_block + readme_text[end_index:]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
requirements_text = REQUIREMENTS_PATH.read_text(encoding="utf-8")
|
||||
readme_text = README_PATH.read_text(encoding="utf-8")
|
||||
rendered_block = render_dependency_block(requirements_text)
|
||||
updated_readme = replace_managed_block(readme_text, rendered_block)
|
||||
|
||||
if updated_readme != readme_text:
|
||||
README_PATH.write_text(updated_readme, encoding="utf-8")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user