|
18 | 18 |
|
19 | 19 | from __future__ import annotations |
20 | 20 |
|
| 21 | +from pathlib import Path |
21 | 22 | from unittest.mock import patch |
22 | 23 |
|
23 | 24 | import pytest |
|
29 | 30 | check_funding_file, |
30 | 31 | check_immutable_releases, |
31 | 32 | check_inline_pins_match_upstream, |
| 33 | + check_install_guide_downloads, |
32 | 34 | check_package_name_vs_repo, |
33 | 35 | check_pat_stale_statuses_permission, |
34 | 36 | check_pr_templates, |
|
46 | 48 | ) |
47 | 49 | from repomatic.matrix_axes import UNSTABLE_PYTHON_VERSIONS |
48 | 50 | from repomatic.pypi import TrustedPublisher |
| 51 | +from repomatic.registry import INSTALL_GUIDE_PATH |
49 | 52 | from tests.conftest import metadata_from_pyproject, pat_results |
50 | 53 |
|
51 | 54 |
|
@@ -658,6 +661,102 @@ def test_stale_drafts_none(): |
658 | 661 | assert "No stale" in result.message |
659 | 662 |
|
660 | 663 |
|
| 664 | +# --- Install guide download URL check unit tests --- |
| 665 | + |
| 666 | + |
| 667 | +def _write_install_guide(root: Path, body: str) -> None: |
| 668 | + """Materialize an install guide under *root*, directories included.""" |
| 669 | + guide = root / INSTALL_GUIDE_PATH |
| 670 | + guide.parent.mkdir(parents=True, exist_ok=True) |
| 671 | + guide.write_text(body, encoding="UTF-8") |
| 672 | + |
| 673 | + |
| 674 | +GUIDE_WITH_DOWNLOADS = ( |
| 675 | + "[Download `papaya-1.2.3-linux-x64.bin`]" |
| 676 | + "(https://github.com/owner/repo/releases/download/v1.2.3/" |
| 677 | + "papaya-1.2.3-linux-x64.bin)\n" |
| 678 | + "[Download `papaya-1.2.3-macos-arm64.bin`]" |
| 679 | + "(https://github.com/owner/repo/releases/download/v1.2.3/" |
| 680 | + "papaya-1.2.3-macos-arm64.bin)\n" |
| 681 | +) |
| 682 | + |
| 683 | + |
| 684 | +def test_install_guide_downloads_all_present(tmp_path, monkeypatch): |
| 685 | + """Pass when every referenced file is attached to its release.""" |
| 686 | + monkeypatch.chdir(tmp_path) |
| 687 | + _write_install_guide(tmp_path, GUIDE_WITH_DOWNLOADS) |
| 688 | + with patch("repomatic.lint_repo.gh_api_json") as mock_gh: |
| 689 | + mock_gh.return_value = { |
| 690 | + "assets": [ |
| 691 | + {"name": "papaya-1.2.3-linux-x64.bin"}, |
| 692 | + {"name": "papaya-1.2.3-macos-arm64.bin"}, |
| 693 | + ] |
| 694 | + } |
| 695 | + result = check_install_guide_downloads("owner/repo") |
| 696 | + assert result.passed is True |
| 697 | + |
| 698 | + |
| 699 | +def test_install_guide_downloads_missing_asset(tmp_path, monkeypatch): |
| 700 | + """Warn naming each referenced file the release does not carry.""" |
| 701 | + monkeypatch.chdir(tmp_path) |
| 702 | + _write_install_guide(tmp_path, GUIDE_WITH_DOWNLOADS) |
| 703 | + with patch("repomatic.lint_repo.gh_api_json") as mock_gh: |
| 704 | + mock_gh.return_value = {"assets": [{"name": "papaya-1.2.3-linux-x64.bin"}]} |
| 705 | + result = check_install_guide_downloads("owner/repo") |
| 706 | + assert result.passed is False |
| 707 | + assert "v1.2.3/papaya-1.2.3-macos-arm64.bin" in result.message |
| 708 | + # The healthy link is not reported as a problem. |
| 709 | + assert "v1.2.3/papaya-1.2.3-linux-x64.bin" not in result.message |
| 710 | + |
| 711 | + |
| 712 | +def test_install_guide_downloads_release_without_assets(tmp_path, monkeypatch): |
| 713 | + """A release carrying no assets at all reports every referenced file. |
| 714 | +
|
| 715 | + This is the `7.7.0` shape: the release published, so the API answers, but |
| 716 | + the binary upload never ran. |
| 717 | + """ |
| 718 | + monkeypatch.chdir(tmp_path) |
| 719 | + _write_install_guide(tmp_path, GUIDE_WITH_DOWNLOADS) |
| 720 | + with patch("repomatic.lint_repo.gh_api_json") as mock_gh: |
| 721 | + mock_gh.return_value = {"assets": []} |
| 722 | + result = check_install_guide_downloads("owner/repo") |
| 723 | + assert result.passed is False |
| 724 | + assert "2 missing release file(s)" in result.message |
| 725 | + |
| 726 | + |
| 727 | +@pytest.mark.parametrize( |
| 728 | + ("body", "needle"), |
| 729 | + ( |
| 730 | + pytest.param(None, "no install guide", id="no-guide"), |
| 731 | + pytest.param( |
| 732 | + "Install it with `uv tool install papaya`.", "no release", id="no-urls" |
| 733 | + ), |
| 734 | + ), |
| 735 | +) |
| 736 | +def test_install_guide_downloads_skipped(tmp_path, monkeypatch, body, needle): |
| 737 | + """Skip when there is no guide, or no download URL to verify.""" |
| 738 | + monkeypatch.chdir(tmp_path) |
| 739 | + if body is not None: |
| 740 | + _write_install_guide(tmp_path, body) |
| 741 | + result = check_install_guide_downloads("owner/repo") |
| 742 | + assert result.passed is None |
| 743 | + assert needle in result.message |
| 744 | + |
| 745 | + |
| 746 | +def test_install_guide_downloads_unreadable_release(tmp_path, monkeypatch): |
| 747 | + """Skip rather than warn when the release cannot be read. |
| 748 | +
|
| 749 | + A transient API failure must not be reported as a broken install guide. |
| 750 | + """ |
| 751 | + monkeypatch.chdir(tmp_path) |
| 752 | + _write_install_guide(tmp_path, GUIDE_WITH_DOWNLOADS) |
| 753 | + with patch("repomatic.lint_repo.gh_api_json") as mock_gh: |
| 754 | + mock_gh.return_value = None |
| 755 | + result = check_install_guide_downloads("owner/repo") |
| 756 | + assert result.passed is None |
| 757 | + assert "skipped" in result.message |
| 758 | + |
| 759 | + |
661 | 760 | def test_stale_drafts_unreadable_payload(): |
662 | 761 | """Skip gracefully when the release list cannot be read.""" |
663 | 762 | with patch("repomatic.lint_repo.gh_api_json") as mock_gh: |
|
0 commit comments