diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b44ede..c1918fa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,7 +4,7 @@ on: - cron: "0 */4 * * *" workflow_dispatch: repository_dispatch: - types: [ pypi_release ] + types: [pypi_release] jobs: build: @@ -14,24 +14,23 @@ jobs: - if: ${{ startsWith(github.event_name, 'repository_dispatch') }} run: sleep 30 - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: - python-version: "3.x" + python-version: "3.11" + cache: pip + cache-dependency-path: requirements-dev.txt - - run: pip install pre-commit-mirror-maker + - run: pip install -r requirements-dev.txt - name: set git config run: | git config user.name 'Github Actions' git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' - - run: pre-commit-mirror --language python --package-name ruff --entry 'ruff check --force-exclude' --id ruff --types-or python --types-or pyi --require-serial --description "Run 'ruff' for extremely fast Python linting" . + - run: python mirror.py - - run: git push origin HEAD:refs/heads/main --tags - - - name: "Update version in README.md" - run: python update_version.py - - - run: git push origin HEAD:refs/heads/main + - run: | + git push origin HEAD:refs/heads/main + git push origin HEAD:refs/heads/main --tags diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 3dce9c5..2c1ddf8 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -3,17 +3,18 @@ description: "Run 'ruff' for extremely fast Python linting" entry: ruff check --force-exclude language: python - "types_or": [python, pyi] + types_or: [python, pyi] args: [] require_serial: true additional_dependencies: [] minimum_pre_commit_version: "2.9.2" + - id: ruff-format name: ruff-format description: "Run 'ruff format' for extremely fast Python formatting" entry: ruff format --force-exclude language: python - "types_or": [python, pyi] + types_or: [python, pyi] args: [] require_serial: true additional_dependencies: [] diff --git a/.version b/.version deleted file mode 100644 index fa175fd..0000000 --- a/.version +++ /dev/null @@ -1 +0,0 @@ -0.0.291 diff --git a/mirror.py b/mirror.py new file mode 100644 index 0000000..48ae1c0 --- /dev/null +++ b/mirror.py @@ -0,0 +1,75 @@ +import re +import subprocess +import typing +from pathlib import Path + +import tomllib +import urllib3 +from packaging.requirements import Requirement +from packaging.version import Version + + +def main(): + with open(Path(__file__).parent / "pyproject.toml", "rb") as f: + pyproject = tomllib.load(f) + + all_versions = get_all_versions() + current_version = get_current_version(pyproject=pyproject) + target_versions = [v for v in all_versions if v > current_version] + + for version in target_versions: + paths = process_version(version) + if subprocess.check_output(["git", "status", "-s"]).strip(): + subprocess.run(["git", "add", *paths]) + subprocess.run(["git", "commit", "-m", f"Mirror: {version}"]) + subprocess.run(["git", "tag", f"v{version}"]) + else: + print(f"No change v{version}") + + +def get_all_versions() -> typing.List[Version]: + response = urllib3.request("GET", "https://pypi.org/pypi/ruff/json") + if response.status != 200: + raise RuntimeError("Failed to fetch versions from pypi") + + versions = [Version(release) for release in response.json()["releases"]] + return sorted(versions) + + +def get_current_version(pyproject: dict) -> Version: + requirements = [Requirement(d) for d in pyproject["project"]["dependencies"]] + requirement = next((r for r in requirements if r.name == "ruff"), None) + assert requirement is not None, "pyproject.toml does not have ruff requirement" + + specifiers = list(requirement.specifier) + assert ( + len(specifiers) == 1 and specifiers[0].operator == "==" + ), f"ruff's specifier should be exact matching, but `{requirement}`" + + return Version(specifiers[0].version) + + +def process_version(version: Version) -> typing.Sequence[str]: + def replace_pyproject_toml(content: str) -> str: + return re.sub(r'"ruff==.*"', f'"ruff=={version}"', content) + + def replace_readme_md(content: str) -> str: + content = re.sub(r"rev: v\d+\.\d+\.\d+", f"rev: v{version}", content) + return re.sub(r"/ruff/\d+\.\d+\.\d+\.svg", f"/ruff/{version}.svg", content) + + paths = { + "pyproject.toml": replace_pyproject_toml, + "README.md": replace_readme_md, + } + + for path, replacer in paths.items(): + with open(path) as f: + content = replacer(f.read()) + with open(path, mode="w") as f: + f.write(content) + + return tuple(paths.keys()) + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9499a00 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "ruff-pre-commit" +version = "0.0.0" +dependencies = [ + "ruff==0.0.291", +] + +[project.optional-dependencies] +dev = [ + "packaging~=23.1", + "pip-tools>=7.3.0,<8.0.0", + "urllib3>=2.0.5,<3.0.0", +] diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..ec9cbe4 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,49 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --extra=dev --generate-hashes --output-file=./requirements-dev.txt --unsafe-package=ruff ./pyproject.toml +# +build==1.0.3 \ + --hash=sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b \ + --hash=sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f + # via pip-tools +click==8.1.7 \ + --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ + --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de + # via pip-tools +packaging==23.1 \ + --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ + --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f + # via + # build + # ruff-pre-commit (./pyproject.toml) +pip==23.2.1 \ + --hash=sha256:7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be \ + --hash=sha256:fb0bd5435b3200c602b5bf61d2d43c2f13c02e29c1707567ae7fbc514eb9faf2 + # via pip-tools +pip-tools==7.3.0 \ + --hash=sha256:8717693288720a8c6ebd07149c93ab0be1fced0b5191df9e9decd3263e20d85e \ + --hash=sha256:8e9c99127fe024c025b46a0b2d15c7bd47f18f33226cf7330d35493663fc1d1d + # via ruff-pre-commit (./pyproject.toml) +pyproject-hooks==1.0.0 \ + --hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \ + --hash=sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5 + # via build +setuptools==68.2.2 \ + --hash=sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87 \ + --hash=sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a + # via pip-tools +urllib3==2.0.5 \ + --hash=sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594 \ + --hash=sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e + # via ruff-pre-commit (./pyproject.toml) +wheel==0.41.2 \ + --hash=sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985 \ + --hash=sha256:75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8 + # via pip-tools + +# WARNING: The following packages were not pinned, but pip requires them to be +# pinned when the requirements file includes hashes and the requirement is not +# satisfied by a package already installed. Consider using the --allow-unsafe flag. +# ruff diff --git a/setup.py b/setup.py deleted file mode 100644 index 0ff87ce..0000000 --- a/setup.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import annotations - -from setuptools import setup - - -setup( - name='pre_commit_placeholder_package', - version='0.0.0', - install_requires=['ruff==0.0.291'], -) diff --git a/update_version.py b/update_version.py deleted file mode 100644 index b98868f..0000000 --- a/update_version.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Updates the version in the readme and git commit.""" - -import re -from pathlib import Path -from subprocess import check_call, check_output - - -def main(): - readme_md = Path("README.md") - readme = readme_md.read_text() - rev = Path(".version").read_text().strip() - readme = re.sub(r"rev: v\d+\.\d+\.\d+", f"rev: v{rev}", readme) - readme = re.sub(r"/ruff/\d+\.\d+\.\d+\.svg", f"/ruff/{rev}.svg", readme) - readme_md.write_text(readme) - - # Only commit on change. - # https://stackoverflow.com/a/9393642/3549270 - if check_output(["git", "status", "-s"]).strip(): - check_call(["git", "add", readme_md]) - check_call(["git", "commit", "-m", f"Bump README.md version to {rev}"]) - else: - print("No change") - - -if __name__ == "__main__": - main()