Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions repomatic/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2373,9 +2373,7 @@ def setup_guide(
# provenance confirms the entry is wired. None (no published release yet,
# or pre-OIDC release) keeps the step open. When the project does not
# publish to PyPI (no package_name), the gate is a no-op.
pypi_publisher_gate = (
bool(pypi_publisher_ok) if md.package_name else True
)
pypi_publisher_gate = bool(pypi_publisher_ok) if md.package_name else True
needs_issue = not (
token_ok
and dependabot_ok
Expand Down
4 changes: 1 addition & 3 deletions repomatic/init_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@
from importlib.abc import Traversable


RUNTIME_FRAGMENTS: tuple[str, ...] = (
"release-publish-pypi-job.yaml",
)
RUNTIME_FRAGMENTS: tuple[str, ...] = ("release-publish-pypi-job.yaml",)
"""Bundled YAML fragments loaded by `repomatic` at runtime.

These files live in `repomatic/data/` so they ship in the wheel and are
Expand Down
12 changes: 3 additions & 9 deletions repomatic/lint_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,9 +657,7 @@ def check_pypi_trusted_publisher(
:return: Tuple of ``(passed_or_None, message)``.
"""
if not package_name:
return None, (
"PyPI Trusted Publisher check: skipped (no package name)."
)
return None, ("PyPI Trusted Publisher check: skipped (no package name).")

latest = get_latest_release_file(package_name)
if latest is None:
Expand Down Expand Up @@ -694,12 +692,8 @@ def check_pypi_trusted_publisher(
f" via {publisher.workflow}."
)

observed = ", ".join(
f"{p.repository}:{p.workflow}" for p in publishers
)
settings_url = PYPI_TRUSTED_PUBLISHER_SETTINGS_URL.format(
package=package_name
)
observed = ", ".join(f"{p.repository}:{p.workflow}" for p in publishers)
settings_url = PYPI_TRUSTED_PUBLISHER_SETTINGS_URL.format(package=package_name)
msg = (
f"PyPI Trusted Publisher mismatch for '{package_name}' {version}."
f" Expected {repo} via {PYPI_TRUSTED_PUBLISHER_WORKFLOW},"
Expand Down
13 changes: 8 additions & 5 deletions repomatic/pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ def get_latest_release_file(package: str) -> tuple[str, str] | None:
return version, filename


def get_trusted_publishers(package: str, version: str, filename: str) -> (
list[TrustedPublisher] | None
):
def get_trusted_publishers(
package: str, version: str, filename: str
) -> list[TrustedPublisher] | None:
"""Fetch PEP 740 provenance for a file and extract publisher entries.

Calls :data:`PYPI_PROVENANCE_URL` and parses the ``attestation_bundles``
Expand Down Expand Up @@ -282,8 +282,11 @@ def get_trusted_publishers(package: str, version: str, filename: str) -> (
kind = publisher.get("kind")
repository = publisher.get("repository")
workflow = publisher.get("workflow")
if not (isinstance(kind, str) and isinstance(repository, str)
and isinstance(workflow, str)):
if not (
isinstance(kind, str)
and isinstance(repository, str)
and isinstance(workflow, str)
):
continue
environment = publisher.get("environment")
if environment is not None and not isinstance(environment, str):
Expand Down
4 changes: 1 addition & 3 deletions tests/test_lint_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,9 +727,7 @@ def test_pypi_trusted_publisher_workflow_mismatch():
assert passed is False
assert "mismatch" in msg
assert "publish.yaml" in msg
assert (
"https://pypi.org/manage/project/cherries/settings/publishing/" in msg
)
assert "https://pypi.org/manage/project/cherries/settings/publishing/" in msg


def test_pypi_trusted_publisher_repository_mismatch():
Expand Down
9 changes: 6 additions & 3 deletions tests/test_pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,12 @@ def test_get_trusted_publishers_empty_bundles():
"repomatic.pypi.urlopen",
return_value=_FakeResponse(body),
):
assert get_trusted_publishers(
"cherries", "1.2.3", "cherries-1.2.3-py3-none-any.whl"
) == []
assert (
get_trusted_publishers(
"cherries", "1.2.3", "cherries-1.2.3-py3-none-any.whl"
)
== []
)


def test_get_trusted_publishers_network_failure():
Expand Down
18 changes: 5 additions & 13 deletions tests/test_workflow_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

from repomatic.config import Config, WorkflowConfig
from repomatic.github.actions import AnnotationLevel
from repomatic.init_project import get_data_content
from repomatic.github.workflow_sync import (
LintResult,
PathsSpec,
Expand All @@ -48,6 +47,7 @@
identify_canonical_workflow,
run_workflow_lint,
)
from repomatic.init_project import get_data_content
from repomatic.pyproject import derive_source_paths, resolve_source_paths
from repomatic.registry import (
ALL_WORKFLOW_FILES,
Expand Down Expand Up @@ -275,9 +275,7 @@ def test_release_thin_caller_emits_publish_pypi_job() -> None:
assert "needs: release" in content
assert "needs.release.outputs.release_commits_matrix" in content
assert "id-token: write" in content
assert (
f"{DEFAULT_REPO}/.github/actions/publish-pypi@v9.9.9" in content
)
assert f"{DEFAULT_REPO}/.github/actions/publish-pypi@v9.9.9" in content
assert (
"artifact-name: ${{ github.event.repository.name }}-${{ matrix.short_sha }}"
in content
Expand All @@ -287,12 +285,8 @@ def test_release_thin_caller_emits_publish_pypi_job() -> None:
def test_release_thin_caller_publish_pypi_uses_sha_pin() -> None:
"""Verify SHA-pinned commit form propagates to the publish-pypi action ref."""
sha = "1234567890abcdef1234567890abcdef12345678"
content = generate_thin_caller(
"release.yaml", version="v9.9.9", commit_sha=sha
)
assert (
f"{DEFAULT_REPO}/.github/actions/publish-pypi@{sha} # v9.9.9" in content
)
content = generate_thin_caller("release.yaml", version="v9.9.9", commit_sha=sha)
assert f"{DEFAULT_REPO}/.github/actions/publish-pypi@{sha} # v9.9.9" in content


def test_non_release_thin_caller_omits_publish_pypi_job() -> None:
Expand Down Expand Up @@ -334,9 +328,7 @@ def test_release_thin_caller_loads_fragment_from_data() -> None:
assert job["permissions"]["id-token"] == "write"
# The fragment ships with the upstream's own working ref so it parses as
# a real, copy-pasteable workflow snippet.
assert (
f"{DEFAULT_REPO}/.github/actions/publish-pypi@main" in fragment
)
assert f"{DEFAULT_REPO}/.github/actions/publish-pypi@main" in fragment


def test_renovate_passes_secrets_explicitly() -> None:
Expand Down
Loading