diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ee54c63..32cdaf0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,33 +30,5 @@ jobs: git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - run: python mirror.py - - - name: check for unpushed commits - id: check_unpushed - run: | - UNPUSHED_COMMITS=$(git log origin/main..HEAD) - if [ -z "$UNPUSHED_COMMITS" ]; then - echo "No unpushed commits found." - echo "changes_exist=false" >> $GITHUB_ENV - else - echo "Unpushed commits found." - echo "changes_exist=true" >> $GITHUB_ENV - fi - - - name: push changes if they exist - if: env.changes_exist == 'true' - run: | - git push origin HEAD:refs/heads/main - git push origin HEAD:refs/heads/main --tags - - - name: create release on new tag if new changes exist - if: env.changes_exist == 'true' - run: | - TAG_NAME=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo $TAG_NAME - gh release create "$TAG_NAME" \ - --title "$TAG_NAME" \ - --notes "See: https://github.com/astral-sh/uv/releases/tag/$TAG_NAME" \ - --latest env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/mirror.py b/mirror.py index 317dd63..382467a 100644 --- a/mirror.py +++ b/mirror.py @@ -13,27 +13,84 @@ def main(): with open(Path(__file__).parent / "pyproject.toml", "rb") as f: pyproject = tomllib.load(f) - all_versions = get_all_versions() + all_releases = get_all_releases() current_version = get_current_version(pyproject=pyproject) - target_versions = [v for v in all_versions if v > current_version] + all_non_yanked_versions = sorted([ + release_version + for release_version, release in all_releases.items() + if not any([asset["yanked"] for asset in release]) + ]) + + target_versions = [v for v in all_non_yanked_versions if v > current_version] + + if not target_versions and not any([ + asset["yanked"] for asset in all_releases[current_version] + ]): + last_valid_version = all_non_yanked_versions[-1] + paths = process_version(last_valid_version) + if subprocess.check_output(["git", "status", "-s"]).strip(): + push_changed_version(paths, f"Mirror: yanked {current_version}") + + # Make `last_valid_version` the top tag and release + subprocess.run( + [ + "gh", + "release", + "delete", + f"{last_valid_version}", + "--cleanup-tag", + "--yes", + ], + check=True, + ) + create_tagged_release(last_valid_version) + return for version in target_versions: paths = process_version(version) if subprocess.check_output(["git", "status", "-s"]).strip(): - subprocess.run(["git", "add", *paths], check=True) - subprocess.run(["git", "commit", "-m", f"Mirror: {version}"], check=True) - subprocess.run(["git", "tag", f"{version}"], check=True) + push_changed_version(paths, f"Mirror: {version}") + create_tagged_release(version) else: print(f"No change {version}") -def get_all_versions() -> list[Version]: +def push_changed_version(paths: typing.Sequence[str], commit_message: str) -> None: + subprocess.run(["git", "add", *paths], check=True) + subprocess.run(["git", "commit", "-m", commit_message], check=True) + subprocess.run(["git", "push", "origin", "HEAD:refs/heads/main"], check=True) + + +def create_tagged_release(version: Version) -> None: + subprocess.run(["git", "tag", f"{version}"], check=True) + subprocess.run( + ["git", "push", "origin", "HEAD:refs/heads/main", "--tags"], check=False + ) + subprocess.run( + [ + "gh", + "release", + "create", + f"{version}", + "--title", + f"{version}", + "--notes", + f"See: https://github.com/astral-sh/uv/releases/tag/{version}", + "--latest", + ], + check=False, + ) + + +def get_all_releases() -> dict[Version, list[dict[str, typing.Any]]]: response = urllib3.request("GET", "https://pypi.org/pypi/uv/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) + return { + Version(release_version): release + for release_version, release in response.json()["releases"].items() + } def get_current_version(pyproject: dict) -> Version: