From fd3a0390df7ed22b008bd051b9fcec51cf1cb314 Mon Sep 17 00:00:00 2001 From: Vxrtrauter <101264710+Vxrtrauter@users.noreply.github.com> Date: Thu, 9 Apr 2026 00:13:14 +0200 Subject: [PATCH] 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 / . 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. --- .github/workflows/create-release.yml | 2 +- .../workflows/sync-readme-dependencies.yml | 38 +++++++++ README.md | 8 +- scripts/sync_readme_dependencies.py | 79 +++++++++++++++++++ 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/sync-readme-dependencies.yml create mode 100644 scripts/sync_readme_dependencies.py diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 7cddcd5..f1d6e83 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -248,4 +248,4 @@ jobs: release/SoftwareManager-stable-${{ needs.build.outputs.short_sha }}-macos release/SHA256SUMS.txt env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/sync-readme-dependencies.yml b/.github/workflows/sync-readme-dependencies.yml new file mode 100644 index 0000000..5141452 --- /dev/null +++ b/.github/workflows/sync-readme-dependencies.yml @@ -0,0 +1,38 @@ +name: Sync README Dependencies + +on: + push: + branches: + - main + paths: + - requirements.txt + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + + - name: Update README dependencies + run: python scripts/sync_readme_dependencies.py + + - name: Create pull request + uses: peter-evans/create-pull-request@v7 + with: + commit-message: "Sync README dependencies" + branch: auto/sync-readme-dependencies + title: "Sync README dependencies" + body: "Automated update of the Python Dependencies section in README.md to match `requirements.txt`." + labels: documentation \ No newline at end of file diff --git a/README.md b/README.md index 3884415..da00f99 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,11 @@ SoftwareManager is a Python-based GUI tool that simplifies searching and downloa ## Python Dependencies (also included in requirements.txt) - ```bash + + ```text requests (2.32.2) - PySide6 (6.10.1) - beautifulsoup (44.13.5) + PySide6-Essentials (6.10.1) + beautifulsoup4 (4.13.5) darkdetect (0.7.1) pyinstaller (6.15.0) PyQtDarkTheme-fork (2.3.4) @@ -47,6 +48,7 @@ SoftwareManager is a Python-based GUI tool that simplifies searching and downloa libtorrent (2.0.11) libtorrent-windows-dll (0.0.3) ``` + ## Activity diff --git a/scripts/sync_readme_dependencies.py b/scripts/sync_readme_dependencies.py new file mode 100644 index 0000000..5820139 --- /dev/null +++ b/scripts/sync_readme_dependencies.py @@ -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 = "" +END_MARKER = "" +REQUIREMENT_PATTERN = re.compile( + r"^(?P[A-Za-z0-9_.\-\[\]]+)\s*(?P(==|~=|>=|<=|!=|>|<).+)?$" +) + + +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() \ No newline at end of file