Skip to content

CI and release gates

Supported-version evidence

checks.yml is shared by pull requests, pushes to main, and release checks. It runs correctness lint (Ruff E9/F63/F7/F82), mypy, the complete offline pytest suite, branch coverage, strict documentation build, distribution build, strict Twine metadata checks, and wheel-only smoke checks on Python 3.9 through 3.15. The package's >=3.9 requirement is preserved; future Python versions require adding a matrix entry and verification. Python 3.9/3.10 are retained for compatibility despite upstream end of life. Check jobs install .[dev,examples] so the Django/FastAPI offline request examples and their type checks cannot be skipped due to absent optional dependencies. The frameworks remain optional; the installed SDK wheel depends only on HTTPX. The Python 3.9 development extra caps mypy below 1.20: mypy 1.19 is the last version runnable on Python 3.9. The official Python downloads listed 3.15.0 as stable on 2026-10-10. GitHub's runner manifest did not yet contain stable 3.15 binaries. Its matrix job therefore builds the official 3.15.0 source with the SHA-256 published on the release page. It runs the same mandatory checks, without tolerating failures or substituting a prerelease. Replace that temporary source-build step with setup-python once stable binaries are available; update the source version/checksum if a newer patch is needed.

Each successful matrix job uploads coverage-python-VERSION (JSON and XML) and distributions-python-VERSION. Download the coverage artifact from the linked CI run to see measured statements, branches and missing paths. The README badge reports workflow status; it does not claim a fixed coverage percentage.

Measured task-10 baseline on Python 3.14.7: 1,076/1,096 statements (98.18%) and 272/280 branches (97.14%), 97.97% combined coverage. Pytest now enables branch measurement and enforces 97% combined statement/branch coverage, on every matrix interpreter. This leaves less than one percentage point of headroom for interpreter differences while rejecting meaningful coverage loss. It is not a separate 97% branch-only floor. Changes must add behavioral regressions rather than exclude code or chase percentages; providers remain unverified where the contract audit says so.

Wheel isolation

The build makes an sdist, then builds the wheel from that sdist. Both pass strict Twine checks and scripts/release_gate.py, including packaged jukto/py.typed. A fresh virtual environment in a temporary directory installs only the wheel and its runtime dependencies. After leaving the checkout, python -I runs the smoke script: it ignores PYTHONPATH and source-path injection, checks the imported package is under that environment and outside the checkout, verifies its version and typing marker, and exercises an SDK operation using HTTPX MockTransport. No provider traffic occurs.

Publication dependency chain

Only a published GitHub release triggers publish.yml; ordinary pushes and PRs cannot publish. The release event's immutable github.sha is checked out and resolved once; a tag moved while jobs are queued cannot redirect the code being checked. Every check and release-validation checkout uses that SHA. Release validation downloads the exact immutable artifact tested by the Python 3.14 matrix job, rather than rebuilding it, and requires:

  • All supported-version checks to pass.
  • Exactly one wheel and one sdist; matching project names and versions.
  • A tag exactly v plus project.version in pyproject.toml, currently v0.1.0a1.
  • A packaged typing marker and valid distribution metadata.

The publishing job depends on both checks and build, with GitHub's default success condition. Failed, skipped, or cancelled dependencies prevent publication. It downloads only the validated artifact from that same run; it does not check out code or rebuild. Only this final job receives id-token: write, and it uses the pypi environment. No API-token fallback is configured. Release tags should be protected against replacement; old tags containing an older workflow do not gain these gates retroactively. Package versions must be unique on PyPI; these checks do not query PyPI for already-used versions. No release was published to test this pipeline; offline regressions cover rejection and workflow dependency wiring.

External configuration required before a real release

Repository YAML cannot prove account ownership or PyPI/GitHub settings. A project owner must verify the PyPI Trusted Publisher configuration for project jukto:

  • GitHub owner: jukto-sdk.
  • Repository: jukto-python.
  • Workflow filename: publish.yml (not its display name).
  • Environment: pypi, matching the workflow exactly.

Configure the GitHub pypi environment's allowed release tags and, where desired, required reviewers; restrict who can publish releases and modify workflows. Verify repository rules require the matrix checks before merging to main. A matching Trusted Publisher, environment protections, tag protections and branch rules are external settings, not verified by this implementation. OIDC acceptance and actual upload remain untested because this task explicitly forbids publication.

Publishing the prepared 0.1.0a1 alpha

Preparation does not publish a release. Version 0.1.0a1 is an early-access alpha, with experimental SSLCOMMERZ payments and all existing provider verification gaps. Do not mark task 13's external verification gate complete when publishing it.

  1. Sign into PyPI and verify ownership/name availability for jukto. If no project exists yet, add a pending GitHub publisher from your account's Publishing page: project jukto, owner jukto-sdk, repository jukto-python, workflow publish.yml, environment pypi. If you already own the project, use its Publishing settings. Pending publishers do not reserve names; neither ownership nor configuration was verified here.
  2. Verify GitHub Settings → Environments → pypi, allowed release tags and desired reviewer protections. Confirm branch/tag protections and control of workflow changes. No long-lived PyPI token is needed for this workflow.
  3. Pick the prepared commit whose seven CI jobs and strict documentation deployment passed. Record its full SHA, inspect its metadata/version and changelog, and confirm that PyPI has not already used version 0.1.0a1.
  4. Only when you intend to publish, replace VERIFIED_SHA below with that full SHA:
git fetch origin
git tag -a v0.1.0a1 VERIFIED_SHA -m "Jukto 0.1.0a1 early access"
git push origin v0.1.0a1

Tag pushing alone does not publish with the current workflow. Do not replace an existing release tag or reuse an uploaded version. 5. On GitHub Releases → Draft a new release, select v0.1.0a1, title it Jukto 0.1.0a1 — Early access, and check Set as a pre-release. Use the alpha changelog as the body; link the provider/payment audits and explicitly state that sandbox merchant verification is pending. Preview the draft. 6. Publish release triggers the real PyPI upload. It runs the exact-commit checks, validates tag/version identity and uploads the tested Python 3.14 artifacts. Approve the pypi deployment if an environment review is configured. Confirm the final publishing job succeeds; a published GitHub release alone is not proof that the package uploaded successfully. 7. After successful upload, inspect the PyPI README, author/website links and experimental notice. In a fresh environment outside this checkout, install jukto==0.1.0a1 and run the README's MockTransport example. Do not use a real provider operation as a publication smoke test. Record the release and upload outcome, and remove publication-pending wording in subsequent documentation.

The README pins the alpha explicitly because installers normally exclude prereleases unless requested; see Python versioning. TestPyPI uses separate publisher settings and requires a separate workflow; the existing publish.yml targets real PyPI. No tag, GitHub release or upload was created during preparation.