diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index d47ddb7..77785c8 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -336,14 +336,14 @@ jobs: - name: Publish to TestPyPI if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_target == 'testpypi' }} - uses: pypa/gh-action-pypi-publish@v1.14.2 # v1.14.2 image tag is required by this composite action + uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 with: packages-dir: dist repository-url: https://test.pypi.org/legacy/ - name: Publish to PyPI if: ${{ (github.event_name == 'push' && github.ref_type == 'tag') || (github.event_name == 'workflow_dispatch' && inputs.publish_target == 'pypi') }} - uses: pypa/gh-action-pypi-publish@v1.14.2 # v1.14.2 image tag is required by this composite action + uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 with: packages-dir: dist diff --git a/tests/test_package_workflow.py b/tests/test_package_workflow.py index 38dd089..959c048 100644 --- a/tests/test_package_workflow.py +++ b/tests/test_package_workflow.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re from pathlib import Path import yaml @@ -24,11 +25,24 @@ def test_package_workflow_can_recover_an_immutable_tag_from_default_branch() -> assert '--source-commit "$SOURCE_COMMIT"' in workflow -def test_package_workflow_uses_a_published_pypi_publisher_image_tag() -> None: +def test_package_workflow_uses_the_pinned_pypi_publisher_release() -> None: workflow = (Path(__file__).resolve().parents[1] / ".github/workflows/package.yml").read_text(encoding="utf-8") - assert workflow.count("uses: pypa/gh-action-pypi-publish@v1.14.2") == 2 - assert "pypa/gh-action-pypi-publish@a892a5a61159132606e93a2fa6f4358831b04d26" not in workflow + assert workflow.count("uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086") == 2 + + +def test_all_workflows_pin_every_third_party_action_to_a_full_sha() -> None: + workflow_dir = Path(__file__).resolve().parents[1] / ".github/workflows" + workflows = sorted(workflow_dir.glob("*.yml")) + assert workflows + + unpinned: list[tuple[str, str]] = [] + for workflow_path in workflows: + workflow = workflow_path.read_text(encoding="utf-8") + refs = re.findall(r"^\s*-?\s*uses:\s+[^@\s]+@([^\s#]+)", workflow, flags=re.MULTILINE) + unpinned.extend((workflow_path.name, ref) for ref in refs if not re.fullmatch(r"[0-9a-f]{40}", ref)) + + assert unpinned == [] def test_package_workflow_does_not_replace_published_release_assets() -> None: