feature:release

Release a feature. Auto-infer its contract, bump version, tag, publish to GitHub and PyPI, and create a versioned cache snapshot.


Table of contents

  1. Usage
  2. Examples
    1. With the semver wizard (recommended)
    2. With an explicit version
    3. Release and attach to the active product
  3. Description
  4. Automatic contract inference
  5. Requirements
  6. Result
  7. Notes
  8. See also

Usage

splent feature:release <feature_name> [<version>] [--attach] [--skip-checks]
                      [--no-github] [--no-pypi] [--allow-unfinished]
Argument / Option Description
<feature_name> Feature to release (splent_feature_auth or splent-io/splent_feature_auth).
<version> Optional. Version to release (e.g. v1.2.7). If omitted, the semver wizard runs.
--attach After release, attach the new version to the active product.
--skip-checks Bypass the pre-release gate (lint + tests), for emergencies only. It does not bypass the channel gate.
--no-github Publish to PyPI only. Nothing at all is pushed to GitHub for this version, so the commit and the tag stay on this machine and no cache snapshot is created.
--no-pypi Publish to GitHub only. The feature will not exist on PyPI for this version, and a production build cannot install it.
--allow-unfinished Release even though the previous version never finished publishing. The older version stays broken.

Releasing a feature needs no account and no token beyond your own GitHub and PyPI credentials. There is nothing to log in to, and the git tag is the publication.

The release refuses to start unless every channel it publishes to would accept it right now, so a version number is never burned on a credential that was going to fail.


Examples

Omit the version and the wizard fetches the current tag from GitHub, shows the three semver options, and asks you to choose.

splent feature:release splent_feature_auth
  Fetching current version from GitHub...
  Current version: v1.2.6

  Bump type:
    [1] patch  v1.2.7   bug fixes, no new features
    [2] minor  v1.3.0   new features, backward compatible
    [3] major  v2.0.0   breaking changes
    [4] cancel

  Choice: 1

  Will release as v1.2.7
  Proceed? [y/N]: y

  Releasing splent_io/splent_feature_auth v1.2.7

  Release gate (channels)
  github   ready, splent-io/splent_feature_auth accepts push, tag and release as drorganvidez
  pypi     ready, credentials accepted, splent_feature_auth exists so this is a new version

  contract updating from source code...
  contract written to pyproject.toml
  version  1.2.7 written to pyproject.toml
  commit   changes committed
  pypi     building package...
  pypi     upload complete
  tag      v1.2.7 created
  tag      v1.2.7 pushed to origin
  github   release created: https://github.com/...
  snapshot splent_feature_auth@v1.2.7 (read-only)

  splent_io/splent_feature_auth v1.2.7 released.

With an explicit version

splent feature:release splent_feature_auth v1.2.7

Release and attach to the active product

splent feature:release splent_feature_auth --attach

Description

Performs a full release pipeline.

  1. Validates environment credentials.
  2. Channel gate, pass one. Proves every enabled channel would accept this exact version, before anything is spent on tests.
  3. Pre-release gate. Runs ruff lint + feature:test on the feature. Aborts with no changes if either fails. Skip with --skip-checks.
  4. Channel gate, pass two. The binding one, so the verdict acted on is seconds old rather than minutes.
  5. Updates [project].version to <version>.
  6. Infers the feature contract from source code (see below) and writes it to [tool.splent.contract].
  7. Stages and commits, locally.
  8. Cleans build artifacts, builds, and uploads the package to PyPI.
  9. Pushes main, creates and pushes the Git tag, creates the GitHub Release.
  10. Compiles frontend assets (delegates to feature:compile) and creates a versioned snapshot in .splent_cache (read-only).
  11. Asks whether to attach the released version to the active product (defaults to yes). Use --attach to skip the prompt and attach automatically.

PyPI is published before anything is pushed, because a PyPI version can never be replaced or removed while an unpushed tag costs nothing. If step 9 fails after step 8 succeeded, the run says the channels have diverged and prints the release:resume command that finishes the job without bumping the version.

The cache snapshot is a clone of the tag from GitHub, so with --no-github there is no tag on the remote and no snapshot is created. The command says so rather than failing.


Automatic contract inference

Before any versioning step, feature:release delegates to feature:contract --write to scan the feature’s source code and rewrite [tool.splent.contract] in pyproject.toml. Both commands use the same update_contract() function, ensuring consistent inference whether done during development or at release time.

[tool.splent.contract]
description = "Authentication feature"   # ← preserved if already set

[tool.splent.contract.provides]
routes       = ["/auth/login", "/auth/logout", "/auth/register"]
blueprints   = ["auth_bp"]
models       = ["User"]
commands     = []
hooks        = ["layout.anonymous_sidebar", "layout.authenticated_sidebar"]
services     = ["AuthService"]
docker       = []
signals      = ["user_registered", "user_logged_in"]
translations = ["en", "es"]

[tool.splent.contract.requires]
features  = []
env_vars  = ["SECRET_KEY", "MAIL_SERVER"]
signals   = ["profile_updated"]

[tool.splent.contract.extensible]
hooks    = true
signals  = true

What is scanned.

Field Source file What is detected
provides.routes routes.py @<bp>.route(...) decorator paths
provides.blueprints __init__.py BaseBlueprint / Blueprint variable names
provides.models models.py class <Name>(db.Model) definitions
provides.commands commands.py @click.command("name") decorators in commands.py
provides.hooks hooks.py register_template_hook("slot", func) slot names
provides.services services.py class <Name>(BaseService) definitions
provides.docker feature root docker-compose*.yml / docker-compose*.yaml files
provides.signals signals.py define_signal() calls in signals.py
provides.translations translations/ Locale directories in translations/
requires.features all .py files Imports of other splent_feature_* packages
requires.env_vars all .py files os.getenv(...) and os.environ[...] calls
requires.signals signals.py connect_signal() calls in signals.py

The developer’s description field is preserved across releases. Everything else is regenerated from source.

Run splent feature:release after every meaningful change to keep the contract accurate. Other products and product:validate rely on this data.


Requirements

Environment variables.

Variable Purpose
SPLENT_APP Active product (required for --attach)
TWINE_USERNAME / PYPI_USERNAME PyPI authentication
TWINE_PASSWORD / PYPI_PASSWORD PyPI authentication
GITHUB_TOKEN Required for creating GitHub Releases and for the semver wizard to fetch the current version without rate limits

Result

After a successful release.

  • The feature contract in pyproject.toml is up to date.
  • A Git tag is pushed.
  • A GitHub Release is created.
  • The package is published to PyPI.
  • A versioned snapshot exists at this path.
<workspace>/.splent_cache/features/<namespace>/<feature_name>@<version>/

If --attach is used, the feature version is also linked to the active product and recorded in splent.manifest.json with state declared.


Notes

  • The feature must be in editable (non-versioned) state at workspace root. Use feature:unlock first to convert a versioned snapshot.
  • The semver wizard fetches the latest GitHub tag to compute the next version. If no tags exist yet, it starts from v0.0.0 and suggests v0.0.1 / v0.1.0 / v1.0.0.
  • The wizard offers patch, minor, major, and cancel. Choosing cancel aborts immediately. The wizard also ends with a Proceed? confirmation before doing anything irreversible.
  • Passing an explicit <version> skips the wizard entirely, useful in CI or when you know exactly what to release.
  • Build artifacts (__pycache__, dist/, build/) are cleaned automatically before the PyPI build to prevent stale files or permission issues from causing build failures.

See also


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es