diff --git a/scripts/pyproject.toml b/scripts/pyproject.toml index 8c68f7a8df..35dfb511ae 100644 --- a/scripts/pyproject.toml +++ b/scripts/pyproject.toml @@ -26,5 +26,11 @@ select = [ "RUF", ] +ignore = [ + # only relevant if you run a script with `python -0`, + # which seems unlikely for any of the scripts in this directory + "B011" +] + [tool.ruff.lint.isort] required-imports = ["from __future__ import annotations"] diff --git a/scripts/update_schemastore.py b/scripts/update_schemastore.py index 967ca7b75b..39b1d1997c 100644 --- a/scripts/update_schemastore.py +++ b/scripts/update_schemastore.py @@ -7,13 +7,13 @@ to schemastore in the CLI. from __future__ import annotations +import enum import json from pathlib import Path from subprocess import check_call, check_output from tempfile import TemporaryDirectory +from typing import NamedTuple, assert_never -schemastore_fork = "git@github.com:astral-sh/schemastore.git" -schemastore_upstream = "git@github.com:SchemaStore/schemastore.git" ruff_repo = "https://github.com/astral-sh/ruff" root = Path( check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip(), @@ -21,35 +21,64 @@ root = Path( ruff_json = Path("schemas/json/ruff.json") -def update_schemastore(schemastore: Path) -> None: - if not schemastore.is_dir(): - check_call(["git", "clone", schemastore_fork, schemastore]) +class SchemastoreRepos(NamedTuple): + fork: str + upstream: str + + +class GitProtocol(enum.Enum): + SSH = "ssh" + HTTPS = "https" + + def schemastore_repos(self) -> SchemastoreRepos: + match self: + case GitProtocol.SSH: + return SchemastoreRepos( + fork="git@github.com:astral-sh/schemastore.git", + upstream="git@github.com:SchemaStore/schemastore.git", + ) + case GitProtocol.HTTPS: + return SchemastoreRepos( + fork="https://github.com/astral-sh/schemastore.git", + upstream="https://github.com/SchemaStore/schemastore.git", + ) + case _: + assert_never(self) + + +def update_schemastore( + schemastore_path: Path, schemastore_repos: SchemastoreRepos +) -> None: + if not schemastore_path.is_dir(): + check_call( + ["git", "clone", schemastore_repos.fork, schemastore_path, "--depth=1"] + ) check_call( [ "git", "remote", "add", "upstream", - schemastore_upstream, + schemastore_repos.upstream, ], - cwd=schemastore, + cwd=schemastore_path, ) # Create a new branch tagged with the current ruff commit up to date with the latest # upstream schemastore - check_call(["git", "fetch", "upstream"], cwd=schemastore) + check_call(["git", "fetch", "upstream"], cwd=schemastore_path) current_sha = check_output(["git", "rev-parse", "HEAD"], text=True).strip() branch = f"update-ruff-{current_sha}" check_call( ["git", "switch", "-c", branch], - cwd=schemastore, + cwd=schemastore_path, ) check_call( ["git", "reset", "--hard", "upstream/master"], - cwd=schemastore, + cwd=schemastore_path, ) # Run npm install - src = schemastore.joinpath("src") + src = schemastore_path.joinpath("src") check_call(["npm", "install"], cwd=src) # Update the schema and format appropriately @@ -71,7 +100,7 @@ def update_schemastore(schemastore: Path) -> None: # Check if the schema has changed # https://stackoverflow.com/a/9393642/3549270 - if check_output(["git", "status", "-s"], cwd=schemastore).strip(): + if check_output(["git", "status", "-s"], cwd=schemastore_path).strip(): # Schema has changed, commit and push commit_url = f"{ruff_repo}/commit/{current_sha}" commit_body = ( @@ -88,24 +117,43 @@ def update_schemastore(schemastore: Path) -> None: "-m", commit_body, ], - cwd=schemastore, + cwd=schemastore_path, ) # This should show the link to create a PR check_call( ["git", "push", "--set-upstream", "origin", branch], - cwd=schemastore, + cwd=schemastore_path, ) else: print("No changes") +def determine_git_protocol(argv: list[str] | None = None) -> GitProtocol: + import argparse + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--proto", + required=True, + choices=[proto.value for proto in GitProtocol], + help="Protocol to use for cloning git repos", + ) + args = parser.parse_args(argv) + return GitProtocol(args.proto) + + def main() -> None: + schemastore_repos = determine_git_protocol().schemastore_repos() schemastore_existing = root.joinpath("schemastore") if schemastore_existing.is_dir(): - update_schemastore(schemastore_existing) + update_schemastore(schemastore_existing, schemastore_repos) else: with TemporaryDirectory() as temp_dir: - update_schemastore(Path(temp_dir).joinpath("schemastore")) + update_schemastore( + Path(temp_dir).joinpath("schemastore"), schemastore_repos + ) if __name__ == "__main__":