From ed94220f2feb660d63b56cb32cdd0bdf7844bcca Mon Sep 17 00:00:00 2001 From: dariyaanis Date: Thu, 24 Sep 2026 16:53:41 +0300 Subject: [PATCH] ci: generate changelog on release --- .github/scripts/generate_changelog.py | 72 +++++++++++++++++++++++++++ .github/workflows/publish.yml | 25 ++++++++++ CHANGELOG.md | 24 +++++++++ 3 files changed, 121 insertions(+) create mode 100644 .github/scripts/generate_changelog.py create mode 100644 CHANGELOG.md diff --git a/.github/scripts/generate_changelog.py b/.github/scripts/generate_changelog.py new file mode 100644 index 0000000..6ba3bb6 --- /dev/null +++ b/.github/scripts/generate_changelog.py @@ -0,0 +1,72 @@ +"""Generate a Keep a Changelog section from Conventional Commit subjects.""" + +import argparse +import datetime as dt +import re +import subprocess +from pathlib import Path + +GROUPS = { + "feat": "Added", + "fix": "Fixed", + "perf": "Changed", + "refactor": "Changed", + "docs": "Documentation", + "build": "Maintenance", + "ci": "Maintenance", + "chore": "Maintenance", + "test": "Maintenance", +} + + +def git(*args: str) -> str: + return subprocess.check_output(["git", *args], text=True, encoding="utf-8").strip() + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--tag", required=True) + parser.add_argument("--repository", required=True) + args = parser.parse_args() + tags = git("tag", "--sort=-version:refname").splitlines() + previous = next((tag for tag in tags if tag != args.tag), None) + revision = f"{previous}..{args.tag}" if previous else args.tag + subjects = git("log", revision, "--format=%s").splitlines() + grouped: dict[str, list[str]] = {} + for subject in subjects: + match = re.match(r"([a-z]+)(?:\([^)]*\))?(!)?:\s*(.+)", subject) + if not match: + continue + kind, breaking, text = match.groups() + heading = "Breaking changes" if breaking else GROUPS.get(kind) + if heading: + grouped.setdefault(heading, []).append(text) + version = args.tag.removeprefix("v") + date = dt.date.today().isoformat() + order = ["Breaking changes", "Added", "Fixed", "Changed", "Documentation", "Maintenance"] + body = [f"## [{version}] - {date}", ""] + for heading in order: + if heading in grouped: + body.extend([f"### {heading}", "", *[f"- {item}" for item in grouped[heading]], ""]) + compare = ( + f"https://github.com/{args.repository}/compare/{previous}...{args.tag}" + if previous + else f"https://github.com/{args.repository}/releases/tag/{args.tag}" + ) + body.append(f"[Full diff]({compare})") + section = "\n".join(body).rstrip() + "\n" + changelog = Path("CHANGELOG.md") + existing = ( + changelog.read_text(encoding="utf-8") + if changelog.exists() + else "# Changelog\n\nAll notable changes are documented here.\n" + ) + if f"## [{version}]" not in existing: + marker = "All notable changes are documented here.\n" + existing = existing.replace(marker, marker + "\n" + section + "\n", 1) + changelog.write_text(existing, encoding="utf-8") + Path("release-notes.md").write_text(section, encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 368b88e..7aba79d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -86,3 +86,28 @@ jobs: files: dist/* # Requires Discussions enabled in the repo with this category present. discussion_category_name: Announcements + + changelog: + needs: publish + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + - name: Generate changelog + run: python .github/scripts/generate_changelog.py --tag "$GITHUB_REF_NAME" --repository "$GITHUB_REPOSITORY" + - name: Commit changelog + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add CHANGELOG.md + git diff --cached --quiet || git commit -m "docs: update changelog for $GITHUB_REF_NAME" + git push origin main + - name: Use changelog as release notes + run: gh release edit "$GITHUB_REF_NAME" --notes-file release-notes.md + env: + GH_TOKEN: ${{ github.token }} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5ca3d59 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +All notable changes are documented here. + +New sections are generated from Conventional Commits when a version tag is published. + +## [1.0.2] - 2026-09-18 + +### Fixed + +- Removed the unsupported Yandex image puzzle mode. +- Kept reCAPTCHA v3 support proxyless-only. + +## [1.0.1] - 2026-09-17 + +### Fixed + +- Aligned the polling interval with API recommendations. + +## [1.0.0] - 2026-09-17 + +### Added + +- Published the initial Python SDK release.