forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pythongh-91172: Create a workflow for verifying bundled pip and setup…
…tools (pythonGH-31885) Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> (cherry picked from commit d36954b) Co-authored-by: Illia Volochii <illia.volochii@gmail.com>
- Loading branch information
1 parent
798ace5
commit 1f17ed2
Showing
3 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Verify bundled pip and setuptools | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
paths: | ||
- 'Lib/ensurepip/_bundled/**' | ||
- '.github/workflows/verify-ensurepip-wheels.yml' | ||
- 'Tools/scripts/verify_ensurepip_wheels.py' | ||
pull_request: | ||
paths: | ||
- 'Lib/ensurepip/_bundled/**' | ||
- '.github/workflows/verify-ensurepip-wheels.yml' | ||
- 'Tools/scripts/verify_ensurepip_wheels.py' | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
verify: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3' | ||
- name: Compare checksums of bundled pip and setuptools to ones published on PyPI | ||
run: ./Tools/scripts/verify_ensurepip_wheels.py |
2 changes: 2 additions & 0 deletions
2
Misc/NEWS.d/next/Tests/2022-03-14-23-28-17.bpo-47016.K-t2QX.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Create a GitHub Actions workflow for verifying bundled pip and setuptools. | ||
Patch by Illia Volochii and Adam Turner. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#! /usr/bin/env python3 | ||
|
||
""" | ||
Compare checksums for wheels in :mod:`ensurepip` against the Cheeseshop. | ||
When GitHub Actions executes the script, output is formatted accordingly. | ||
https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message | ||
""" | ||
|
||
import hashlib | ||
import json | ||
import os | ||
import re | ||
from pathlib import Path | ||
from urllib.request import urlopen | ||
|
||
PACKAGE_NAMES = ("pip", "setuptools") | ||
ENSURE_PIP_ROOT = Path(__file__).parent.parent.parent / "Lib/ensurepip" | ||
WHEEL_DIR = ENSURE_PIP_ROOT / "_bundled" | ||
ENSURE_PIP_INIT_PY_TEXT = (ENSURE_PIP_ROOT / "__init__.py").read_text(encoding="utf-8") | ||
GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true" | ||
|
||
|
||
def print_notice(file_path: str, message: str) -> None: | ||
if GITHUB_ACTIONS: | ||
message = f"::notice file={file_path}::{message}" | ||
print(message, end="\n\n") | ||
|
||
|
||
def print_error(file_path: str, message: str) -> None: | ||
if GITHUB_ACTIONS: | ||
message = f"::error file={file_path}::{message}" | ||
print(message, end="\n\n") | ||
|
||
|
||
def verify_wheel(package_name: str) -> bool: | ||
# Find the package on disk | ||
package_path = next(WHEEL_DIR.glob(f"{package_name}*.whl"), None) | ||
if not package_path: | ||
print_error("", f"Could not find a {package_name} wheel on disk.") | ||
return False | ||
|
||
print(f"Verifying checksum for {package_path}.") | ||
|
||
# Find the version of the package used by ensurepip | ||
package_version_match = re.search( | ||
f'_{package_name.upper()}_VERSION = "([^"]+)', ENSURE_PIP_INIT_PY_TEXT | ||
) | ||
if not package_version_match: | ||
print_error( | ||
package_path, | ||
f"No {package_name} version found in Lib/ensurepip/__init__.py.", | ||
) | ||
return False | ||
package_version = package_version_match[1] | ||
|
||
# Get the SHA 256 digest from the Cheeseshop | ||
try: | ||
raw_text = urlopen(f"https://pypi.org/pypi/{package_name}/json").read() | ||
except (OSError, ValueError): | ||
print_error(package_path, f"Could not fetch JSON metadata for {package_name}.") | ||
return False | ||
|
||
release_files = json.loads(raw_text)["releases"][package_version] | ||
for release_info in release_files: | ||
if package_path.name != release_info["filename"]: | ||
continue | ||
expected_digest = release_info["digests"].get("sha256", "") | ||
break | ||
else: | ||
print_error(package_path, f"No digest for {package_name} found from PyPI.") | ||
return False | ||
|
||
# Compute the SHA 256 digest of the wheel on disk | ||
actual_digest = hashlib.sha256(package_path.read_bytes()).hexdigest() | ||
|
||
print(f"Expected digest: {expected_digest}") | ||
print(f"Actual digest: {actual_digest}") | ||
|
||
if actual_digest != expected_digest: | ||
print_error( | ||
package_path, f"Failed to verify the checksum of the {package_name} wheel." | ||
) | ||
return False | ||
|
||
print_notice( | ||
package_path, | ||
f"Successfully verified the checksum of the {package_name} wheel.", | ||
) | ||
return True | ||
|
||
|
||
if __name__ == "__main__": | ||
exit_status = 0 | ||
for package_name in PACKAGE_NAMES: | ||
if not verify_wheel(package_name): | ||
exit_status = 1 | ||
raise SystemExit(exit_status) |