diff --git a/.bin/bump.py b/.bin/bump.py new file mode 100755 index 0000000..df02034 --- /dev/null +++ b/.bin/bump.py @@ -0,0 +1,154 @@ +#!/usr/bin/env -S uv run --quiet +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "bumpver", +# "typer", +# ] +# /// +from __future__ import annotations + +import re +import subprocess +import sys +from enum import Enum +from pathlib import Path +from typing import Annotated +from typing import Any + +import typer +from typer import Option + + +class CommandRunner: + def run_command(self, command: str) -> tuple[bool, str]: + print(f"about to run command: {command}") + try: + output = subprocess.check_output( + command, shell=True, text=True, stderr=subprocess.STDOUT + ).strip() + return True, output + except subprocess.CalledProcessError as e: + return False, e.output + + def _build_command_args(self, **params: Any) -> str: + args = [] + for key, value in params.items(): + key = key.replace("_", "-") + if isinstance(value, bool) and value: + args.append(f"--{key}") + elif value is not None: + args.extend([f"--{key}", str(value)]) + return " ".join(args) + + def run(self, cmd: str, name: str, *args: str, **params: Any) -> str: + command_parts = [cmd, name] + command_parts.extend(args) + if params: + command_parts.append(self._build_command_args(**params)) + success, output = self.run_command(" ".join(command_parts)) + if not success: + print(f"{cmd} failed: {output}", file=sys.stderr) + raise typer.Exit(1) + return output + + +_runner = CommandRunner() + + +def bumpver(name: str, *args: str, **params: Any) -> str: + return _runner.run("bumpver", name, *args, **params) + + +def git(name: str, *args: str, **params: Any) -> str: + return _runner.run("git", name, *args, **params) + + +def gh(name: str, *args: str, **params: Any) -> str: + return _runner.run("gh", name, *args, **params) + + +def update_CHANGELOG(new_version: str) -> None: + repo_url = git("remote", "get-url", "origin").strip().replace(".git", "") + changelog = Path("CHANGELOG.md") + + content = changelog.read_text() + + content = re.sub( + r"## \[Unreleased\]", + f"## [{new_version}]", + content, + count=1, + ) + content = re.sub( + rf"## \[{new_version}\]", + f"## [Unreleased]\n\n## [{new_version}]", + content, + count=1, + ) + content += f"[{new_version}]: {repo_url}/releases/tag/v{new_version}\n" + content = re.sub( + r"\[unreleased\]: .*\n", + f"[unreleased]: {repo_url}/compare/v{new_version}...HEAD\n", + content, + count=1, + ) + + changelog.write_text(content) + + git("add", ".") + git("commit", "-m", f"'update CHANGELOG for version {new_version}'") + + +class Version(str, Enum): + MAJOR = "major" + MINOR = "minor" + PATCH = "patch" + + +class Tag(str, Enum): + DEV = "dev" + ALPHA = "alpha" + BETA = "beta" + RC = "rc" + FINAL = "final" + + +def main( + version: Annotated[ + Version, Option("--version", "-v", help="The tag to add to the new version") + ], + tag: Annotated[Tag, Option("--tag", "-t", help="The tag to add to the new version")] + | None = None, +): + latest_tag = git("tag", "--sort=-creatordate", "|", "head -n 1") + changes = git( + "log", f"{latest_tag}..HEAD", "--pretty=format:'- `%h`: %s'", "--reverse" + ) + new_version = re.search( + r"New Version: (.+)", bumpver("update", dry=True, tag=tag, **{version: True}) + ) + if new_version is None: + new_version = typer.prompt( + "Failed to get the new version from `bumpver`. Please enter it manually" + ) + else: + new_version = new_version.group(1) + release_branch = f"release-v{new_version}" + git("checkout", "-b", release_branch) + bumpver("update", tag=tag, **{version: True}) + title = git("log", "-1", "--pretty=%s") + update_CHANGELOG(new_version) + git("push", "--set-upstream", "'origin'", f"'{release_branch}'") + gh( + "pr", + "create", + "--base 'main'", + f"--head '{release_branch}'", + f"--title '{title}'", + f"--body '{changes}'", + ) + + +if __name__ == "__main__": + typer.run(main) diff --git a/.just/project.just b/.just/project.just new file mode 100644 index 0000000..862a35d --- /dev/null +++ b/.just/project.just @@ -0,0 +1,15 @@ +set unstable := true + +justfile := justfile_directory() + "/.just/project.just" + +[private] +default: + @just --list --justfile {{ justfile }} + +[private] +fmt: + @just --fmt --justfile {{ justfile }} + +[no-cd] +@bump *ARGS: + {{ justfile_directory() }}/.bin/bump.py {{ ARGS }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b0c0b8..85d867a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/ ## [Unreleased] +## [0.3.0] + ### Added - Added `SyncGitHubAPI`, a synchronous implementation of `gidgethub.abc.GitHubAPI` for Django applications running under WSGI. Maintains the familiar gidgethub interface without requiring async/await. @@ -58,7 +60,8 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/ - Josh Thomas (maintainer) -[unreleased]: https://github.com/joshuadavidthomas/django-github-app/compare/v0.2.1...HEAD +[unreleased]: https://github.com/joshuadavidthomas/django-github-app/compare/v0.3.0...HEAD [0.1.0]: https://github.com/joshuadavidthomas/django-github-app/releases/tag/v0.1.0 [0.2.0]: https://github.com/joshuadavidthomas/django-github-app/releases/tag/v0.2.0 [0.2.1]: https://github.com/joshuadavidthomas/django-github-app/releases/tag/v0.2.1 +[0.3.0]: https://github.com/joshuadavidthomas/django-github-app/releases/tag/v0.3.0 diff --git a/Justfile b/Justfile index e243bfa..1d75c33 100644 --- a/Justfile +++ b/Justfile @@ -2,6 +2,7 @@ set dotenv-load := true set unstable := true mod docs ".just/documentation.just" +mod project ".just/project.just" [private] default: diff --git a/pyproject.toml b/pyproject.toml index 4f36e97..bb8c61f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,7 @@ Source = "https://github.com/joshuadavidthomas/django-github-app" [tool.bumpver] commit = true commit_message = ":bookmark: bump version {old_version} -> {new_version}" -current_version = "0.2.1" +current_version = "0.3.0" push = false # set to false for CI tag = false version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" diff --git a/src/django_github_app/__init__.py b/src/django_github_app/__init__.py index e9bea68..4ab2cda 100644 --- a/src/django_github_app/__init__.py +++ b/src/django_github_app/__init__.py @@ -1,3 +1,3 @@ from __future__ import annotations -__version__ = "0.2.1" +__version__ = "0.3.0" diff --git a/tests/test_version.py b/tests/test_version.py index e1f5341..e0318b9 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -4,4 +4,4 @@ def test_version(): - assert __version__ == "0.2.1" + assert __version__ == "0.3.0"