Skip to content

OilPriceAPI Python SDK v1.12.7 #18

OilPriceAPI Python SDK v1.12.7

OilPriceAPI Python SDK v1.12.7 #18

Workflow file for this run

name: Publish to PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
verify:
name: Verify release candidate
if: github.event.release.prerelease == false
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: "3.12"
- name: Install verification dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e '.[dev]' pip-audit build 'jsonschema>=4.17,<4.24'
- name: Verify release tag matches package version and protected main
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
PACKAGE_VERSION="$(python scripts/package_version.py)"
if [ "$RELEASE_TAG" != "v$PACKAGE_VERSION" ]; then
echo "::error::Release tag $RELEASE_TAG does not match package version $PACKAGE_VERSION"
exit 1
fi
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
RELEASE_COMMIT="$(git rev-parse "$RELEASE_TAG^{commit}")"
if [ "$RELEASE_COMMIT" != "$(git rev-parse HEAD)" ]; then
echo "::error::Checked-out commit does not match $RELEASE_TAG"
exit 1
fi
if ! git merge-base --is-ancestor "$RELEASE_COMMIT" origin/main; then
echo "::error::$RELEASE_TAG is not reachable from protected main"
exit 1
fi
- name: Lint source with ruff
run: ruff check oilpriceapi/
- name: Run unit tests
run: pytest tests/ --ignore=tests/integration --ignore=tests/contract -m 'not slow' --cov=oilpriceapi -v
- name: Audit installed dependencies
run: pip-audit
- name: Validate public storefront claims
run: python scripts/validate_storefront_claims.py
- name: Build package
run: python -m build
- name: Install and import the exact built wheel
run: ./scripts/clean-wheel-smoke.sh
- name: Build signed snippet manifest
run: |
python scripts/generate_snippet_manifest.py \
--source-commit "$(git rev-parse HEAD)" \
--output artifacts/snippets/oilpriceapi-python-snippets-v1.json
- name: Prepare checksummed release artifact
run: |
set -euo pipefail
ARTIFACT_DIR="$RUNNER_TEMP/release-artifact"
mkdir -p "$ARTIFACT_DIR/dist" "$ARTIFACT_DIR/snippets"
cp dist/* "$ARTIFACT_DIR/dist/"
cp artifacts/snippets/* "$ARTIFACT_DIR/snippets/"
PACKAGE_VERSION="$(python scripts/package_version.py)"
printf 'PACKAGE_VERSION=%s\n' "$PACKAGE_VERSION" > "$ARTIFACT_DIR/release.env"
(
cd "$ARTIFACT_DIR"
find dist snippets -type f -print0 \
| sort -z \
| xargs -0 sha256sum > artifact.sha256
sha256sum release.env >> artifact.sha256
)
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: verified-pypi-package
path: ${{ runner.temp }}/release-artifact/
if-no-files-found: error
retention-days: 1
publish:
name: Publish verified package to PyPI
needs: verify
if: github.event.release.prerelease == false
runs-on: ubuntu-latest
timeout-minutes: 15
environment: pypi
permissions:
contents: read
id-token: write
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: verified-pypi-package
path: ${{ runner.temp }}/release-artifact
- name: Verify exact artifact checksums
working-directory: ${{ runner.temp }}/release-artifact
run: |
set -euo pipefail
manifest_files="$RUNNER_TEMP/manifest-files"
actual_files="$RUNNER_TEMP/actual-files"
sed -n 's/^[0-9a-f]\{64\} //p' artifact.sha256 \
| LC_ALL=C sort > "$manifest_files"
{
find dist snippets -type f -print
printf '%s\n' release.env
} | LC_ALL=C sort > "$actual_files"
if [ -n "$(find dist snippets -type l -print -quit)" ]; then
echo "::error::Verified release artifact contains a symlink"
exit 1
fi
if ! cmp -s "$manifest_files" "$actual_files"; then
echo "::error::Checksum manifest does not cover the exact release files"
exit 1
fi
sha256sum -c artifact.sha256
- name: Publish exact verified distributions
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 2026-07-28
with:
packages-dir: ${{ runner.temp }}/release-artifact/dist/
skip-existing: true
readback:
name: Verify public PyPI artifact hashes
needs: publish
if: github.event.release.prerelease == false
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: verified-pypi-package
path: ${{ runner.temp }}/release-artifact
- name: Verify exact public PyPI hashes
working-directory: ${{ runner.temp }}/release-artifact
run: |
set -euo pipefail
sha256sum -c artifact.sha256
PACKAGE_VERSION="$(sed -n 's/^PACKAGE_VERSION=//p' release.env)"
if ! printf '%s' "$PACKAGE_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "::error::Invalid package version in verified artifact"
exit 1
fi
for attempt in $(seq 1 24); do
curl --fail --silent --show-error --max-time 10 \
"https://pypi.org/pypi/oilpriceapi/$PACKAGE_VERSION/json" \
> "$RUNNER_TEMP/pypi.json" || true
all_present=true
for file in dist/*; do
filename="$(basename "$file")"
expected="$(sha256sum "$file" | cut -d' ' -f1)"
actual="$(jq -r --arg filename "$filename" \
'[.urls[]? | select(.filename == $filename) | .digests.sha256][0] // empty' \
"$RUNNER_TEMP/pypi.json" 2>/dev/null || true)"
if [ -z "$actual" ]; then
all_present=false
elif [ "$actual" != "$expected" ]; then
echo "::error::PyPI $filename has an unexpected immutable hash"
exit 1
fi
done
if [ "$all_present" = true ]; then
echo "Verified every public oilpriceapi $PACKAGE_VERSION distribution hash."
exit 0
fi
if [ "$attempt" -lt 6 ]; then
sleep_seconds=$((attempt * 2))
else
sleep_seconds=10
fi
sleep "$sleep_seconds"
done
echo "::error::PyPI public readback did not expose every verified distribution"
exit 1
release_assets:
name: Attach verified release assets
needs: readback
if: github.event.release.prerelease == false
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: verified-pypi-package
path: ${{ runner.temp }}/release-artifact
- name: Attach checksummed snippet manifest
working-directory: ${{ runner.temp }}/release-artifact
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
sha256sum -c artifact.sha256
gh release upload "$RELEASE_TAG" snippets/* artifact.sha256 --clobber