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
vplusproject.versioninpyproject.toml, currentlyv0.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.
- 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: projectjukto, ownerjukto-sdk, repositoryjukto-python, workflowpublish.yml, environmentpypi. If you already own the project, use its Publishing settings. Pending publishers do not reserve names; neither ownership nor configuration was verified here. - 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. - 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. - Only when you intend to publish, replace
VERIFIED_SHAbelow 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.