Skip to content

Latest commit

 

History

History
110 lines (83 loc) · 4.1 KB

File metadata and controls

110 lines (83 loc) · 4.1 KB

Contributing to fastsaver

Thanks for taking the time to contribute! This document explains how to set up a development environment, run the checks, and ship a release.

Development setup

The project uses uv for environment management and hatchling as the build backend (src layout).

git clone https://github.com/coder2077/fastsaver.git
cd fastsaver

# Create .venv and install the package (editable) plus the "dev" dependency group
uv sync

# Run the checks
.venv/bin/python -m pytest tests
.venv/bin/ruff check src tests examples
.venv/bin/ruff format --check src tests examples
.venv/bin/mypy

uv run <cmd> works as well (for example uv run pytest). To test against a specific interpreter use uv sync --python 3.9 (the package supports 3.9–3.14).

Auto-format before committing:

.venv/bin/ruff format src tests examples
.venv/bin/ruff check --fix src tests examples

Running the live tests

The regular test-suite is fully mocked with respx and needs no network access. tests/test_live.py talks to the real API and is skipped unless both of the following environment variables are set:

export FASTSAVER_API_KEY="fs_sk_..."   # your own key from https://api.fastsaver.io
export FASTSAVER_LIVE=1
.venv/bin/python -m pytest tests/test_live.py

Live tests call balance() (free) and perform a single fetch(), which costs a couple of credits. Never paste a real key into source code, fixtures or CI logs — tests use fake keys such as fs_sk_test_....

Pull request guidelines

  • Open an issue first for larger changes so we can agree on the design.
  • Keep pull requests focused; one topic per PR.
  • Add or update tests for every behaviour change (sync and async where applicable).
  • Make sure pytest, ruff check, ruff format --check and mypy all pass locally; CI runs the same commands on Python 3.9–3.14.
  • Keep the public API in sync between FastSaver and AsyncFastSaver.
  • Models must parse leniently (missing keys -> None/empty, unknown keys ignored).
  • Code comments, docstrings and docs are written in English.
  • Update CHANGELOG.md under the [Unreleased] heading.
  • Use from __future__ import annotations and Python 3.9 compatible syntax.

Release process

  1. Bump the version in src/fastsaver/_version.py.

  2. Move the [Unreleased] entries in CHANGELOG.md under a new ## [X.Y.Z] - YYYY-MM-DD heading and update the comparison links at the bottom.

  3. Commit and push to main, then tag and push the tag:

    git tag vX.Y.Z
    git push origin vX.Y.Z
  4. Create a GitHub Release from the vX.Y.Z tag (copy the changelog entry into the release notes). Publishing the release triggers .github/workflows/publish.yml, which builds the sdist/wheel with uv build, verifies them with twine check and uploads them to PyPI using Trusted Publishing (OIDC) — no API token is stored in the repository.

One-time PyPI Trusted Publisher setup

Trusted Publishing has to be configured once on PyPI so that GitHub Actions is allowed to upload the fastsaver project:

  1. Log in to https://pypi.org and open the project page for fastsaver (for the very first release use https://pypi.org/manage/account/publishing/ and add a pending publisher — the project is created on the first upload).
  2. Under Publishing -> Add a new publisher choose GitHub and fill in:
    • Owner: coder2077
    • Repository name: fastsaver
    • Workflow name: publish.yml
    • Environment name: pypi
  3. In the GitHub repository go to Settings -> Environments, create an environment called pypi and (recommended) add required reviewers so a human approves every upload.

The workflow requests id-token: write permission, which is all pypa/gh-action-pypi-publish needs to exchange the GitHub OIDC token for a short-lived PyPI upload token.

Code of conduct

Be kind and constructive. Harassment or disrespectful behaviour is not tolerated.

Questions?

Open a GitHub Discussion/Issue, join the Telegram channel https://t.me/fastsaverapi or e-mail support@fastsaver.io.