From c668e58408c35c5bbe762b804993f2107f2325e6 Mon Sep 17 00:00:00 2001 From: herr kaste Date: Tue, 3 Feb 2026 13:41:04 +0100 Subject: [PATCH] Grab all versions of the running year --- scripts/crawl.py | 38 ++++----- tests/crawl/test_basic.py | 162 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 19 deletions(-) diff --git a/scripts/crawl.py b/scripts/crawl.py index 38c835715..719035c2c 100644 --- a/scripts/crawl.py +++ b/scripts/crawl.py @@ -495,12 +495,13 @@ async def resolve_tags( tag_prefix = "" if tag_definition is True else tag_definition resolved_releases: list[Release] = [] + now = datetime.now(timezone.utc) + cutoff = now - timedelta(weeks=53) - # preleases are rare, but if used there can be many pre-releases - # before a valid final release. We only need the first (newest) - # one, and `prerelease_pushed` is used to track that. - prerelease_pushed = False - prerelease_version = None + # We take all releases from the current (rolling) year, but if there + # aren't any, things get trickier; and we get at most one leading + # prerelease before exactly one final version. + prerelease_found: str | None = None found_final = False async for tag in info["tags"]: if ( @@ -512,30 +513,29 @@ async def resolve_tags( )) and (version := parse_version(version_string)) ): - if version.is_prerelease and not prerelease_pushed: - r_ = deepcopy(definition) - r_.pop("tags") - r_ |= pick(("url", "date"), tag) - r_ |= {"version": version_string} - resolved_releases.append(r_) # type: ignore[arg-type] - prerelease_pushed = True - prerelease_version = version_string - continue + tag_date = datetime.strptime(tag["date"], UTC_FORMAT).replace(tzinfo=timezone.utc) + if tag_date < cutoff and found_final: + break - elif version.is_final: + if tag_date >= cutoff or ( + version.is_final or + (version.is_prerelease and not prerelease_found) + ): r_ = deepcopy(definition) r_.pop("tags") r_ |= pick(("url", "date"), tag) r_ |= {"version": version_string} resolved_releases.append(r_) # type: ignore[arg-type] - found_final = True - break + if version.is_final: + found_final = True + elif version.is_prerelease: + prerelease_found = version_string if found_final: return resolved_releases, None - if prerelease_pushed: - version_note = f" {prerelease_version}" if prerelease_version else "" + if prerelease_found: + version_note = f" {prerelease_found}" if prerelease_found else "" the = "the" if version_note else "a" base_url = definition.get("base") err(f"No final tag found for {base_url}. Using {the} pre-release{version_note}.") diff --git a/tests/crawl/test_basic.py b/tests/crawl/test_basic.py index 48b165e16..d1d3ff84c 100644 --- a/tests/crawl/test_basic.py +++ b/tests/crawl/test_basic.py @@ -824,6 +824,168 @@ async def test_tag_true_includes_prerelease_and_final(set_now, set_github_info): assert versions == {"1.0.1", "1.0.1-beta.1"} +@pytest.mark.asyncio +async def test_tag_true_filters_to_running_year(set_now, set_github_info): + registry = { + "repositories": [ + "https://raw.githubusercontent.com/wbond/package_control_channel/refs/heads/master/repository.json" + ], + "packages": [ + { + "name": "TagRunningYear", + "details": "https://github.com/example/tag-running-year", + "releases": [ + { + "sublime_text": "*", + "tags": True + } + ], + "source": "https://raw.githubusercontent.com/wbond/package_control_channel/refs/heads/master/repository.json", + "schema_version": "3.0.0" + } + ] + } + + workspace = {"packages": {}} + + github_info = { + "metadata": { + "id": "R_tagrunningyear", + "name": "TagRunningYear", + "description": "Fixture package with running year tags", + "homepage": "https://github.com/example/tag-running-year", + "author": "example", + "readme": "https://raw.githubusercontent.com/example/tag-running-year/main/README.md", + "default_branch": "main", + "stars": 0, + "created_at": "2024-01-01T00:00:00Z" + }, + "tags": [ + { + "name": "v1.2.0", + "sha": "new123", + "date": "2026-06-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-running-year/zip/v1.2.0" + }, + { + "name": "v1.2.1-beta.1", + "sha": "beta123", + "date": "2026-04-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-running-year/zip/v1.2.1-beta.1" + }, + { + "name": "v1.1.0", + "sha": "mid123", + "date": "2025-08-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-running-year/zip/v1.1.0" + }, + { + "name": "v1.0.0", + "sha": "old123", + "date": "2025-05-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-running-year/zip/v1.0.0" + } + ], + "branches": [] + } + + set_now("2026-07-01T00:00:00Z") + set_github_info(github_info) + + await main_(registry, workspace, None, 100) + + package = workspace["packages"].get("TagRunningYear") + assert package is not None + releases = package.get("releases", []) + assert len(releases) == 3 + versions = {release["version"] for release in releases} + assert versions == {"1.2.0", "1.2.1-beta.1", "1.1.0"} + + +@pytest.mark.asyncio +async def test_tag_true_returns_latest_when_running_year_empty( + set_now, set_github_info, capsys +): + registry = { + "repositories": [ + "https://raw.githubusercontent.com/wbond/package_control_channel/refs/heads/master/repository.json" + ], + "packages": [ + { + "name": "TagLatestRelease", + "details": "https://github.com/example/tag-latest-release", + "releases": [ + { + "sublime_text": "*", + "tags": True + } + ], + "source": "https://raw.githubusercontent.com/wbond/package_control_channel/refs/heads/master/repository.json", + "schema_version": "3.0.0" + } + ] + } + + workspace = {"packages": {}} + + github_info = { + "metadata": { + "id": "R_taglatestrelease", + "name": "TagLatestRelease", + "description": "Fixture package with old tags", + "homepage": "https://github.com/example/tag-latest-release", + "author": "example", + "readme": "https://raw.githubusercontent.com/example/tag-latest-release/main/README.md", + "default_branch": "main", + "stars": 0, + "created_at": "2024-01-01T00:00:00Z" + }, + "tags": [ + { + "name": "v2.1.0-beta.1", + "sha": "beta123", + "date": "2024-02-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-latest-release/zip/v2.1.0-beta.1" + }, + { + "name": "v2.0.0", + "sha": "new123", + "date": "2024-01-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-latest-release/zip/v2.0.0" + }, + { + "name": "v1.5.0", + "sha": "old123", + "date": "2023-06-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-latest-release/zip/v1.5.0" + } + ], + "branches": [ + { + "name": "main", + "version": "2024.01.01.00.00.00", + "sha": "main123", + "date": "2024-01-01T00:00:00Z", + "url": "https://codeload.github.com/example/tag-latest-release/zip/main" + } + ] + } + + set_now("2026-07-01T00:00:00Z") + set_github_info(github_info) + + await main_(registry, workspace, None, 100) + err = capsys.readouterr().err + assert "Falling back to tip of" not in err + + package = workspace["packages"].get("TagLatestRelease") + assert package is not None + releases = package.get("releases", []) + assert len(releases) == 2 + versions = {release["version"] for release in releases} + assert versions == {"2.1.0-beta.1", "2.0.0"} + + @pytest.mark.asyncio async def test_tag_prefixes_do_not_apply_when_tags_true(set_now, set_github_info): registry = {