Skip to content

v0.114.0

Choose a tag to compare

@smm-h smm-h released this 14 Aug 04:07
· 2929 commits to main since this release

The check system gains an observe-ability purity model backed by a written read-only-command standard, plus path-capable lint, format and type-check built-ins that replace the structured external-check adapter. Machine output on status, unreleased, check-name and monorepo graph/impact moves to strictcli's envelope, the scrub flow now requires safegit 0.27.0, and the test-suite and dev-status checks stop wiping and misreporting dev-sync overlays.

Context

The framework dependency moves onto released strictcli 0.40.0: the machine-mode
API this release is built on (ctx.json, ctx.payload, payload_schema and the
envelope) ships there, so the floor is raised to >=0.40.0 and the local
development overlay onto the strictcli checkout is retired. rlsbl now resolves
strictcli from PyPI like any consumer does.

The machine-output change is BREAKING for anything parsing rlsbl's --json.
rlsbl status --json, rlsbl unreleased --json, rlsbl check-name --json,
rlsbl monorepo graph --json and rlsbl monorepo impact --json no longer print
their own bare JSON document. Each now emits exactly one envelope whose
payload member carries what the command used to print at the top level, so a
consumer reads .payload where it previously read the document root. The same
move is why rlsbl release scrub requires safegit 0.27.0 or newer: it reads
safegit's --json through the envelope only, and older safegit does not emit
one.

The check-system work behind the headline is a redefinition rather than a new
feature bolted on. Purity now means "starts only allowlisted read-only
programs", which is a property the check itself can be audited against, so the
changelog validators, the two pre-push checks, workspace-unregistered and
go-companion-tags execute during --dry-run instead of reporting themselves
as would-run and checking nothing.

Breaking

  • BREAKING: external_checks entries with kind: "structured" are rejected. The tool-plus-paths shape is now the built-in lint / format / type-check checks configured under the top-level checks key. The error names the replacing check and renders the migrated block. Freeform entries are unaffected. Separately, release run --dry-run in a repo with a customized pre-release hook now runs the preflight checks it can instead of listing every external check and executing none.
  • BREAKING: --json output is now strictcli's envelope. status, unreleased, check-name, monorepo graph and monorepo impact no longer print their own JSON document: machine mode emits exactly one envelope carrying the command's data under payload, alongside the exit code, the structured preview and every diagnostic. Each command declares its payload's JSON Schema, which rlsbl --dump-schema publishes. Consumers read .payload; nothing else about the data changed. monorepo impact loses its --format flag, and monorepo graph's drops json and now defaults to text.
  • BREAKING: rlsbl release scrub now requires safegit 0.27.0 or newer. safegit's --json moved onto the strictcli framework's machine mode, where stdout carries exactly one document -- the envelope -- and safegit's own data is its payload member. The scrub flow reads that shape only: the whole stream is parsed as one document (the partial decode that tolerated a trailing would-do log is gone), the data comes from payload, and a scrub with nothing to rewrite is a null payload rather than empty output. An older safegit is refused by name, naming the version to install; there is no dual support and no fallback parse.

Features

  • Shorter, more readable help for rlsbl dev install and rlsbl monorepo rename-releasable.
  • A preview now validates your changelog. rlsbl release run --dry-run used to list the changelog validators as "would run" and check nothing. They spawn only read-only git, so they are now classified pure and execute in a preview -- a broken commit hash, an uncovered commit or an orphaned entry is reported before you release rather than after. The same reclassification covers the two pre-push checks, workspace-unregistered and go-companion-tags.
  • New built-in checks: lint, format and type-check. Each runs one Python tool (ruff / mypy) over a path list you declare in a top-level checks block in .rlsbl/config.json, invoked through the project's own environment with uv run. Each is paired with a competing-scope guard that hard-errors when the tool's own config carries scope that would silently override or narrow those paths. An unconfigured check skips.
  • The sandboxed test runner honours rlsbl dev sync overlays. When a sibling checkout is overlaid onto a uv project's environment, the runner binds that checkout read-only into the sandbox and installs it editable offline, so the sandboxed suite tests the same source the bare suite does instead of the locked registry wheel. Repos with no overlay declared are unaffected, and every run prints which dependency source it used.

Fixes

  • A failing linter no longer aborts the whole check run. An external check whose tool separates findings with blank lines (ruff, mypy) reported an internal problem text must be a non-empty string error with no attribution instead of the tool's actual findings. Blank lines are now filtered before reporting, and an exception raised with no message no longer produces the same failure.
  • gh auth token no longer runs anywhere. rlsbl used to ask gh to print a live GitHub credential to stdout and capture it, in three code paths (private-repo detection, GitHub topic tagging, rlsbl discover). Those now let gh apply the credential inside its own process (gh api), so no raw token ever transits an rlsbl pipe, buffer or log.
  • rlsbl watch re-dispatches a failed run again. The auto-retry called gh run rerun, which the effects layer refused because the command was misdeclared read_only; the refusal was swallowed into "retry trigger failed" and the retry silently gave up. watch is now correctly declared mutating (it does not prompt), and gh run watch is an allowlisted read so a preview reports the real verdict.
  • The release CI gate reads check runs under --dry-run again. The paginated gh api call omitted --method GET, so it matched no allowlisted read and was recorded instead of performed -- the gate then parsed a placeholder where it expected JSON.
  • config-schema probes the right directory. When a Go pipeline was missing artifact, the suggested value came from running go list in the process's current directory instead of the project root -- so in a monorepo, or from any subdirectory, the suggestion described the wrong project.
  • dep-floors sees dev-group dependencies. An internal_dep_floors entry whose dependency is declared in a PEP 735 [dependency-groups] table was dropped silently -- the check produced no verdict for it at all, however far behind its declared floor was. Test-infrastructure dependencies live exactly there, so the check was inert for them.
  • The gh authentication check names its host. rlsbl now runs gh auth status --hostname github.com instead of the bare gh auth status, and the observe allowlist is pinned to exactly that argv -- so no token-printing variant (--show-token, -t) can execute under --dry-run on the strength of an entry written for the token-free form.
  • Fix. --json on status, check-name and unreleased is now the framework-owned flag: it is recognised anywhere in the argument list rather than only after the command word, and its behaviour is otherwise unchanged.
  • rlsbl dev status no longer reports an installed overlay as missing. A uv workspace keeps one environment, at the workspace root, so an overlay installed for a member project read as [MISSING] and dev-overlay-drift failed on a perfectly healthy environment. The environment is now resolved the way uv resolves it (workspace root, UV_PROJECT_ENVIRONMENT), and whether an install is editable is read from the PEP 610 direct_url.json record through importlib.metadata -- never from the file layout, which an editable install does not populate with a package directory.
  • The test-suite check no longer uninstalls dev overlays. rlsbl check -- and with it the release preflight and the pre-push hook -- ran a bare uv sync, which reinstalled the locked registry wheels over an active rlsbl dev sync overlay without a word: the suite then tested released code, and dev-overlay-drift failed on the wipe the check itself had caused. When the overlay declaration and the sentinel agree, the sync now carries --inexact --no-install-package per overlay and the suite runs with uv run --no-sync (the shape the sandboxed runner already used), and a workspace sync excludes every member's overlaid packages. Files that disagree are a hard error naming both.