From 646836040d755b603d4269059cdf52c4c5dfc6cb Mon Sep 17 00:00:00 2001 From: Karl Waldman Date: Tue, 11 Aug 2026 07:34:10 -0400 Subject: [PATCH] fix: validate wheel from build-only environment --- CHANGELOG.md | 8 ++++++++ MANIFEST.in | 15 --------------- oilpriceapi/version.py | 2 +- pyproject.toml | 2 +- scripts/clean-wheel-smoke.sh | 13 +++++++++++-- tests/sdk_audit_test.py | 2 ++ tests/test_release_readiness.py | 9 +++++++++ 7 files changed, 32 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 367d072..e594edf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.12.1] - 2026-08-11 + +### Fixed + +- Read release metadata without importing the uninstalled source package, so + the trusted publisher can validate the exact wheel from a build-only clean + environment before PyPI upload. + ## [1.12.0] - 2026-08-11 ### Added diff --git a/MANIFEST.in b/MANIFEST.in index 0dfc9f7..bc90398 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,18 +11,3 @@ include .env.example # Include type information recursive-include oilpriceapi py.typed - -# Exclude unnecessary files -global-exclude *.pyc -global-exclude *.pyo -global-exclude __pycache__ -global-exclude .DS_Store -global-exclude *.so - -# Exclude test and development files -exclude test_sdk_live.py -exclude generate_*.py -exclude data_validation_comparison.py -prune tests -prune docs/_build -prune htmlcov \ No newline at end of file diff --git a/oilpriceapi/version.py b/oilpriceapi/version.py index a933c70..20fb3af 100644 --- a/oilpriceapi/version.py +++ b/oilpriceapi/version.py @@ -5,6 +5,6 @@ Used in __init__.py, client.py, and async_client.py. """ -__version__ = "1.12.0" +__version__ = "1.12.1" SDK_VERSION = __version__ SDK_NAME = "oilpriceapi-python" diff --git a/pyproject.toml b/pyproject.toml index f1ba1e9..7e42b9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "oilpriceapi" -version = "1.12.0" +version = "1.12.1" description = "Official Python SDK for source-timestamped OilPriceAPI energy data" authors = [ {name = "OilPriceAPI", email = "support@oilpriceapi.com"} diff --git a/scripts/clean-wheel-smoke.sh b/scripts/clean-wheel-smoke.sh index 7f67447..60c6f49 100755 --- a/scripts/clean-wheel-smoke.sh +++ b/scripts/clean-wheel-smoke.sh @@ -4,8 +4,17 @@ set -euo pipefail root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" wheel="$(find "$root_dir/dist" -maxdepth 1 -name '*.whl' -print -quit)" expected_version="$( - cd "$root_dir" - python -c 'from oilpriceapi.version import SDK_VERSION; print(SDK_VERSION)' + python -c ' +import pathlib +import re +import sys + +project = pathlib.Path(sys.argv[1]).read_text() +match = re.search(r"(?m)^version = \"([^\"]+)\"$", project) +if match is None: + raise SystemExit("project version not found") +print(match.group(1)) +' "$root_dir/pyproject.toml" )" if [[ -z "$wheel" ]]; then diff --git a/tests/sdk_audit_test.py b/tests/sdk_audit_test.py index e506d0e..3e891c9 100644 --- a/tests/sdk_audit_test.py +++ b/tests/sdk_audit_test.py @@ -33,6 +33,8 @@ @dataclass class TestResult: """Test result container""" + __test__ = False + name: str passed: bool error: str = None diff --git a/tests/test_release_readiness.py b/tests/test_release_readiness.py index d617ec0..0cbf3bd 100644 --- a/tests/test_release_readiness.py +++ b/tests/test_release_readiness.py @@ -26,10 +26,12 @@ def test_examples_use_the_canonical_free_quota() -> None: def test_publish_gate_audits_and_installs_the_built_wheel() -> None: workflow = (ROOT / ".github" / "workflows" / "publish.yml").read_text() + smoke = (ROOT / "scripts" / "clean-wheel-smoke.sh").read_text() assert "pip-audit" in workflow assert "scripts/clean-wheel-smoke.sh" in workflow assert "continue-on-error: true" not in workflow + assert "from oilpriceapi.version import SDK_VERSION" not in smoke def test_packaging_configuration_remains_compatible_with_supported_python() -> None: @@ -41,3 +43,10 @@ def test_packaging_configuration_remains_compatible_with_supported_python() -> N assert 'license = {file = "LICENSE"}' in project assert 'requires-python = ">=3.8"' in project assert "[tool.ruff.lint]" in project + + +def test_manifest_has_no_noop_exclusion_patterns() -> None: + manifest = (ROOT / "MANIFEST.in").read_text() + + for stale in ("global-exclude", "exclude test_sdk_live.py", "prune "): + assert stale not in manifest