Skip to content

Releases: stricttools/rlsbl

v0.134.0

Choose a tag to compare

@smm-h smm-h released this 14 Oct 21:37

Retiring a releasable now takes it out of the workspace in one commit (declarations, release hooks, scaffold state, and CI entries), several releasables retire together with a repeated --subject, and rlsbl release retract retracts released Go versions. A never-released releasable is unreleased until the owner records it active, on-hold is renamed non-releasing, the confidential-term list is found through the family settings file, and several commands require flags they used to fill in.

Breaking

  • A releasable that has never been released is unreleased, and its releases are refused until the owner records it active. The status is derived, never recorded: with no lifecycle period in effect, a releasable is active when its release archives record a release and unreleased when they do not. release run, release resume, release retry, and monorepo release init refuse an unreleased releasable, naming rlsbl transition lifecycle --subject <name> --status active, which allows its first release. monorepo init, monorepo add, monorepo absorb, and migrate records no longer open an active lifecycle period for a releasable; transition lifecycle --status unreleased is refused; and status, monorepo status, and transition show print each releasable's lifecycle status, recorded or derived.
  • Breaking. rlsbl release edit requires the version argument; rlsbl changelog amend requires --user-facing or --no-user-facing; rlsbl dev install requires --uninstall or --no-uninstall; rlsbl discover requires --mine or --no-mine; and rlsbl secrets sync-npm-token requires --all or --no-all. None of them is filled in when left out.
  • Breaking. The lifecycle status that refuses a releasable's releases is non-releasing, no longer on-hold: rlsbl transition lifecycle --status non-releasing, rlsbl status --json, and every refusal name it, and a lifecycle-and-license record holding on-hold is refused.
  • Breaking. The confidential-term list is read from the path the confidential_term_list setting names in the family's settings file, stricttools/config.toml under the user's configuration directory, instead of a fixed place under the home directory. A missing settings file or setting refuses only what reads the list (the confidential-terms check, a release, the commands that rewrite a GitHub Release, and transition declassify), naming what to write; a missing list at that path still holds no terms.

Features

  • The lifecycle-and-license guide and the release workflow describe the derived unreleased status.
  • The help of monorepo release init, release retry, and release resume, and the monorepo guide, name the unreleased refusal.
  • Retracted versions in the release record. A release archive may record retracted_by (and the retraction version's own archive retracts): a retracted version keeps its tags, has no GitHub Release (unpublished-refs and release reconcile demand none, and a history rewrite writes none), is marked retracted in CHANGELOG.md, and does not count as a release, so a releasable whose every version is retracted is unreleased and its first release ships the version files' version. A bump landing on a retracted number is refused, naming the version-files value that bumps past it.
  • rlsbl release retract --versions <version> --reason <text> retracts released versions of a Go module through the next free version: it commits one retract [low, new] go.mod line on the release branch, records every covered version retracted, tags the new version and pushes only its tags (no branch, no GitHub Release), and deletes the retracted versions' GitHub Releases, keeping their tags. It works on an unreleased releasable, asks no registry about any version, and a run that stops is finished by running it again.
  • rlsbl release retract requests the retraction version from the Go module proxy right after pushing its tag, and reports success only once the proxy returns it, so the retraction is published to every consumer; a run the proxy stopped is finished by running the same command again.
  • Retiring a releasable takes it out of the workspace in one commit. rlsbl transition lifecycle --subject <releasable> --status retired now also removes the releasable and its members from releasables.toml, closes their open identities, deletes their release hooks, drops their files from the scaffold state, and regenerates the routers and the root CHANGELOG.md; its changelog and release history stay in place and are no longer reported as residue. Retiring a standalone repository's releasable is refused: archive the repository instead.
  • rlsbl transition lifecycle --status retired takes a repeated --subject. --subject a --subject b retires several declared releasables of a workspace in one commit, regenerating the routers once for what remains, so two releasables whose directories are both gone, each blocking the other's retirement, retire together. A repeated --subject with active or non-releasing, or naming a member or an undeclared subject, is refused.

Fixes

  • rlsbl monorepo remove accepts a retired member, and its refusal names the retirement. A member with open lifecycle-and-license entries is refused with rlsbl transition lifecycle --subject <member> --status retired as the fix; once retired, the remove goes through.

v0.133.0

Choose a tag to compare

@smm-h smm-h released this 10 Oct 21:44

Releases scan what they push and publish against the age-encrypted confidential-term list, report every hit at once, and refuse a hit until it is judged a false positive or approved by the owner with the new confidential commands; the archive records each resolution used. The machine-local confidential-name index and transition public-client are gone.

Context

Confidential terms now live in one encrypted list outside every repository instead of being derived from lifecycle-and-license records into a machine-local index. Commits are never refused for a term; only what is published is checked, so a false positive never interrupts work and every hit of a release is judged together.

Breaking

  • Releases scan for the confidential-term list, and every hit is judged. The confidential-names check is now confidential-terms: a release scans what it pushes and publishes against the age-encrypted confidential-term list (a missing list has no terms), reports every hit at once with an id, its location, and the text around it, and refuses while a hit has no resolution. rlsbl confidential judge-false-positive records a false positive judged at 70% certainty or more, rlsbl confidential approve-hit (consequential) records the owner's approval, and the release archive records the resolutions it used under confidential_hits. The machine-local confidential-name index is gone: no command reads or writes it, transition public-client is removed, and the record refuses codenames, distinctive_terms, and public_clients.

Features

  • A confidential repository's packed artifacts are scanned for confidential terms. A registry is public whatever the repository is, so a release from a confidential repository scans the artifacts it publishes, and records the resolutions it used.

v0.132.1

Choose a tag to compare

@smm-h smm-h released this 09 Oct 15:46

rlsbl release scrub finishes in a repository with versions released before it kept changelog files, keeping their GitHub Releases' own notes.

Fixes

  • rlsbl release scrub finishes in a repository with versions released before it kept changelog files: their GitHub Releases keep their own notes, with the rlsbl-ci-sha marker moved to the rewritten release commit, where the scrub refused to write them and stopped.

v0.132.0

Choose a tag to compare

@smm-h smm-h released this 09 Oct 14:33

rlsbl rewritten in Go: one binary, published to npm and PyPI as per-platform packages and wheels and installable with go install, with the release record in the .strictmetadata layout. The Python package is gone.

Context

The stricttools projects are moving to Go; the source checks rlsbl ran moved to strictcode.

Breaking

  • rlsbl is rewritten in Go. One rlsbl binary replaces the Python package. It is distributed as the Go module github.com/stricttools/rlsbl, as npm packages under the existing rlsbl name (the binary in one package per platform, rlsbl-linux-x64, rlsbl-linux-arm64, rlsbl-darwin-x64, and rlsbl-darwin-arm64, selected through optionalDependencies), and as PyPI wheels under the existing rlsbl name. There are no Windows packages, and rlsbl's Python modules can no longer be imported.
  • rlsbl's records move to .strictmetadata/. rlsbl reads nothing of the old layout (.rlsbl/, .rlsbl-monorepo/, and each member's .rlsbl/). Run rlsbl migrate records once in every repository, with --dry-run first: it converts the declarations, changelogs, release files and archives, batch release files, transition record, scaffold state, hook scripts, and options entries, writes the lifecycle-and-license record (--licenses states a license the manifests do not), removes the old layout through saferm, and commits. rlsbl monorepo cleanup removes old-layout residue, in a standalone repository too.
  • One declarations file. config.json, workspace.toml, and releasable.toml are replaced by .strictmetadata/releasables/releasables.toml, declaring the layout, release branches, releasables, members, targets, pipelines, hooks, and checks; its [timeouts] table (push_seconds, ci_seconds, check_seconds, hook_seconds) replaces the push_timeout, ci_timeout, check_timeout, and hook_timeout keys, and behavior switches are options entries in .strictmetadata/options/, written with rlsbl options set. rlsbl migrate records writes both.
  • The release targets are go, npm, and pypi. The spec target is removed, and rlsbl migrate records refuses a configuration naming any target other than go, npm, and pypi, naming the hand edit.
  • Changelog format version 2. Each releasable's changelog lives in .strictmetadata/changelog/<releasable>/, every entry carries an id, and an entry naming more commits than the per-entry limit carries its reason through rlsbl changelog add --batch-reason, which replaces --allow-batch and the batch_limits exclusions; rlsbl migrate records restamps existing entries.
  • The pre-release channel is removed. Versions are MAJOR.MINOR.PATCH: a release file carrying preid, blog, or bump = "prerelease" is refused, and rlsbl migrate records folds a pre-release's changelog entries into the stable version it preceded.
  • Removed subsystems. Member layering (the [layers] key and the layers-violations check), deploy configuration (a server releasable declares a deploy_command instead), subtree mirror publication, the launcher artifact, local asset upload (assets and custom_assets; the publish workflow builds and attaches release archives in CI), the Cloudflare Pages pipeline (selfdoc deploys documentation sites), blog-on-release, and the requires-services (with the services and test_env keys), private-hook-stale, and mixed-tag-schemes checks are removed.
  • Removed commands and flags. rlsbl deploy, rlsbl prs, rlsbl pre-push-check, rlsbl monorepo mirror, rlsbl monorepo snapshot, rlsbl monorepo snapshot-check (rlsbl monorepo graph --json gives the same inventory on demand), rlsbl transition record, rlsbl release undo --target, and rlsbl changelog amend --id are removed.
  • Source checks move to strictcode. The lint, format, and type-check tool options, the dependency-declaration checks, and the dead-modules, circular-deps, library-lint, dead-workspace-packages, ruff-lint, and strictspec certificate checks leave rlsbl; the rlsbl:strictcode option (error by default) runs strictcode analyze as a release check and refuses a missing strictcode, and rlsbl migrate records moves their settings into strictcode.toml.
  • The lifecycle-and-license record. Each repository's .strictmetadata/lifecycle-and-license/lifecycle-and-license.toml holds each releasable's dated lifecycle, license, and identities. A release or resume of a releasable on hold or retired is refused; a proprietary releasable requires a private repository and refuses every public output (registry packages, attestations, the Go module proxy, public docs); a Go library target on a private repository is refused; and rlsbl monorepo init, rlsbl monorepo add, and rlsbl monorepo absorb creating a releasable require --license.
  • Changed flags. rlsbl release reconcile takes --mode plan or --mode apply instead of --plan and --apply; rlsbl monorepo release init requires --releasables or --all, writing no table for every releasable unasked; and rlsbl monorepo graph requires --format.
  • Preflight checks always run. A declared pre_release hook replaces only a member's built-in tests, never the preflight checks, and customized hook scripts become hooks declared in releasables.toml, moved by rlsbl migrate records to .strictmetadata/release-hooks/.
  • A release refuses an origin remote whose host is a domain other than github.com; SSH host aliases without a dot are accepted.
  • A release file whose exclude names a target a pipeline publishes is refused, naming the pipeline: every pipeline publishes on every release, so the excluded target was published anyway. Delete the pipeline from releasables.toml to release without publishing that target.
  • rlsbl is a Go binary. The npm and PyPI packages rlsbl now install the Go binary, through per-platform packages (rlsbl-linux-x64, rlsbl-linux-arm64, rlsbl-darwin-x64, rlsbl-darwin-arm64 on npm, platform wheels on PyPI) for Linux and macOS on x64 and arm64; there is no Windows build. go install github.com/stricttools/rlsbl/cmd/rlsbl@v0 and the archives on each GitHub Release install it too. The Python package and its python -m rlsbl entry point are gone.

Features

  • New rlsbl transition public-client --subject <name> --reason <text> declares that a subject of a confidential repository has a public client, taking its registry names and the repository's names out of the confidential-name index; transition show lists the declarations, and the index no longer holds releasable names or identity values, nor matches a name inside a URL or a dotted hostname
  • New rlsbl transition commands keep the lifecycle-and-license record: transition show prints the record with every rule's verdict, transition lifecycle, transition license, transition identity, and transition unversioned-tag record periods and tags, transition classify makes a releasable proprietary, transition declassify squashes the proprietary history and takes a repository public, and transition init-minimal-record writes a minimal record into a repository rlsbl does not manage.
  • Confidential names stay out of public output. The confidential-names check refuses a tracked file or changelog entry of a public repository carrying a name from the machine-local confidential-name index, every GitHub Release body rlsbl writes is scanned the same way, and every mutating command keeps the index in step with the lifecycle-and-license record.
  • A release refuses a packed artifact (an npm tarball, a wheel, or a Go module zip) carrying a file from outside the releasable's members, naming each file.
  • rlsbl monorepo graph --json prints the dependency graph as a document: the members in topological order with their versions, targets, releasables, flags, dependencies, and dependents, and the edges in the same order.
  • npm ships Go binaries. A go binary pipeline publishes to npm as one package per platform, selected through the main package's optionalDependencies by os and cpu, with no postinstall script.
  • rlsbl rewrite project-name records each renamed identity in the lifecycle-and-license record as a pending identity, one per registry carrying the name, which takes effect with the next release.
  • rlsbl release deprecate and rlsbl release yank accept the latest release, which they used to refuse in favor of rlsbl release undo.
  • rlsbl scaffold refuses to write a new VERSION that would disagree with a target's version.

Fixes

  • Commands that create a .strictmetadata directory's manifest.toml while writing a record (rlsbl release backfill, rlsbl release abandon) now commit the manifest with the record instead of leaving it uncommitted
  • A refusing command prints no partial report: rlsbl status refusing a member with several targets and no --target no longer prints an empty status block before the error
  • transition show holds the confidential-names rule for a confidential repository whose public-client declarations leave it no name to protect, expecting no index entry, instead of calling it public
  • After a three-way merge conflict is resolved, the next rlsbl scaffold commits the resolved file and its new merge base, which it used to leave uncommitted.
  • The npm-token-synced check runs inside rlsbl check, rlsbl failing-checks, and a release's --dry-run; it failed there because listing the npm tokens was not an allowed read.
  • A go binary pipeline whose main package is not at the module root gets a .goreleaser.yml and archives named after that package (./cmd/tool builds tool), not after the module path's last element; and rlsbl scaffold keeps the version.go it wrote into the main package instead of removing it on the next run and writing it again on the one after.
  • rlsbl scaffold writes a stub go.mod into the .strictmetadata/ of a Go module below ...
Read more

v0.131.0

Choose a tag to compare

@smm-h smm-h released this 07 Oct 13:07

Releases build against the release checkout's own committed go.work, and every release gets a private RLSBL_RELEASE_BIN directory for its own builds of tools

Context

The release checkout sits inside the live repository, so Go found the working tree's uncommitted go.work from there and selfdoc's release failed. Releases now pin GOWORK to the checkout, the dep-locks check stops its go.work.sum search at the repository root, and a hook can build an unreleased tool into RLSBL_RELEASE_BIN without installing it for every other session.

Breaking

  • In a workspace, batch_limits.exclusions in a member's own .rlsbl/config.json is now a hard error. Exclusions name lines of the releasable's changelog, so they belong in the releasable's .rlsbl-monorepo/releasables/<name>/config.json, where changelog add --allow-batch writes them and the release removes stale ones. A member list silently replaced the releasable's and was never cleaned at release. Move the entries to the releasable's config and delete the member's exclusions key.
  • The strictcli schema dump moved to .strictmetadata/.cli-schema/schema.json. The release writes a strictcli program's help --json document there instead of .strictcli/schema.json, and rlsbl rewrite go-module-path rewrites the project_id of dumps at the new location only; a dump left at .strictcli/schema.json is no longer read or rewritten. Move it with selfdoc layout migrate (run --dry-run first). rlsbl's own test coverage now follows strictcli's source-tree root layout, .strictmetadata/.cli-test-coverage/.
  • Only the go, npm, pypi, and spec release targets remain. The dart, deno, docker, flutter, hex, maven, native-android, native-ios, pgdesign, plain, swift, swift-apple, and zig targets are removed, along with their scaffold templates, the deno, hex, maven, maven-central, and docker pipeline types, the maven-central-metadata and mirror-required checks and their options, and the Dart and JVM import analysis. A targets entry in .rlsbl/config.json or in a releasable's config that names a target rlsbl does not register is now a hard error naming the config file and the supported targets, where it used to print a warning while the release went on without it: delete the entry or name a supported target, and delete the pipeline entries of a removed type. The Flutter delivery mode is removed with flutter, so a release file's [targets.<name>] table and a changelog line's release_type field now fail validation as unknown keys: delete the table or the field.

Features

  • A release can run its own unreleased build of a tool. Every release gets a private, empty directory for binaries, named to every hook as RLSBL_RELEASE_BIN and placed first on PATH for the hooks and every step rlsbl runs. A pre-checks.sh that builds a tool there (GOBIN="$RLSBL_RELEASE_BIN" go install .) has the selfdoc steps and later hooks run that build, without installing it for every other session on the machine.

Fixes

  • The npm lockfile step in rlsbl scaffold next steps now says to commit package-lock.json before releasing, not before pushing: releases are the only push.
  • rlsbl scaffold no longer crashes with unresolved template variables: goreleaserMain, brewsSection on an npm+go project whose first registry is npm: every scaffolded file now renders with its own target's values, whichever registry is primary.
  • A release no longer builds against the working tree's uncommitted go.work. The release checkout sits inside the live repository, so Go found the working tree's gitignored go.work from there: a hook's go install . failed with "main module does not contain package", and where it did not fail the release built against unreleased local modules. Every process a release starts now runs with the checkout's own committed go.work when the repository root tracks one, and with GOWORK=off otherwise.
  • The dep-locks check no longer accepts sums from a go.work.sum outside the repository. Its search for a Go workspace's sums now stops at the repository root, so in the release checkout the working tree's uncommitted go.work.sum can no longer vouch for a module whose own go.sum is missing entries.
  • rlsbl changelog add --allow-batch in a workspace now names the releasable's config.json it writes the batch exclusion to (.rlsbl-monorepo/releasables/<name>/config.json), in both the dry-run and the write message, instead of claiming .rlsbl/config.json.
  • dead-modules no longer reports Go test helpers and go run programs as dead. An internal package imported by another package's _test.go files (a test helper such as internal/cli/clitest) now counts as used, and an internal package main directory is treated as an entry point. A package's own tests and files under testdata/ still never keep it alive.
  • Every batch_limits message (the changelog add refusal over the commit limit, the changelog-batch-commits hint, and the invalid batch_limits errors) now names the config file the setting was actually read from. In a workspace that is the releasable's .rlsbl-monorepo/releasables/<name>/config.json unless the member's own .rlsbl/config.json declares the setting; before, every message named .rlsbl/config.json.
  • rlsbl changelog add --allow-batch no longer crashes with FileNotFoundError in a workspace whose releasable has no config.json of its own; it creates the file with the exclusion.
  • releasable-residue no longer fails on rlsbl scaffold's own output in Go members. The stub .rlsbl/go.mod scaffold writes into a Go member is accepted while its content is the stub's; any other go.mod there is still reported.
  • The rlsbl changelog add refusal for an entry over max_commits_per_entry no longer suggests adding an exclusion by hand, which never cleared it; it names the fixes that work: split the entry, or re-run with --allow-batch, which records the exclusion in the config file it names.
  • At a workspace root, changelog-batch-commits and changelog-batch-entries now check each releasable's changelog against that releasable's own batch_limits instead of the root's.
  • releasable-residue no longer promises that rlsbl monorepo cleanup removes every per-package finding: each finding says whether cleanup removes it or it needs removing by hand, and the summary counts both.
  • A release no longer runs the npm package's own install scripts when it refreshes package-lock.json. A wrapper package whose postinstall downloads the release asset of the version being released failed the release before its candidate was pushed. The refresh, and the dep-locks fix it names, are now npm install --package-lock-only --ignore-scripts.
  • rlsbl now requires strictcli 0.46.0 or later. Its command definitions declare their source-tree root to strictcli, which older strictcli versions refuse with a TypeError when rlsbl is imported.
  • The release workflow page, the README, and the check reference no longer say the release writes the project's new version to .rlsbl/version or that version-consistency compares it: the file names the rlsbl that last scaffolded or released the project.

v0.130.0

Choose a tag to compare

@smm-h smm-h released this 29 Sep 21:02

Forks, rlsbl release abandon, every check as an option, nested workspace members, a refusal of uploads carrying private paths, releases run in a detached checkout of the committed commit (--allow-dirty removed), and rlsbl secrets sync-npm-token with the npm-token-synced check.

Context

Every release now runs in a release checkout, a detached checkout of the
release branch's committed tip, so nothing it builds or tests reads the working
tree; --allow-dirty had nothing left to waive and was removed. Nested workspace
members are supported across ownership, tags, CI filters, test runners, uploads
and Go requires. A registry keeps every upload permanently, so a release now
refuses an upload carrying planning notes, release metadata, agent files or
secrets, and scaffold writes each ecosystem's exclusions. An expired npm token
broke CI publishes after tagging, so rlsbl secrets sync-npm-token copies the
~/.npmrc token into NPM_TOKEN secrets and the npm-token-synced check blocks a
release whose secret predates the token. rlsbl now requires strictcli 0.44.0
and strictspec 0.5.0.

Breaking

  • rlsbl claim-name --force-publish is removed. claim-name always respects its availability check: a name the check reports as taken exits 1, and a check that ended in an error or returned a status it does not define exits 2, without publishing. Passing --force-publish is now refused as an unknown flag.
  • Every check is an option, rlsbl:<check name>. An error check ranks error > warn > off and a warning check warn > off, defaulting to its registered severity, and the checks strictcli registers into rlsbl are options too. rlsbl options set <id> --current <value> --ideal <value> --reason <text> [--scope <member>] writes the entry into .strictmetadata/options/<subject>.toml at the git root (creating the directory and its strictspec-owned manifest.toml), validates it with strictspec before writing, and commits it with the Autogenerated trailer; rlsbl options registry prints the registry, as data with --json. Every check run and every release apply the entries -- off does not run the check, warn reports without blocking -- and rlsbl check --list shows each check's value and where it came from. Invalid entries stop every check run and every release. dep-floors, lint, format, type-check, and strictspec-certificate-gate stay off until their options are switched on, and rlsbl:test-sandbox decides whether the sandboxed test runner is rendered. Declaring internal_dep_floors, a checks.<name> block, strictspec_gate, or test_sandbox no longer turns anything on: each setting is required while its option is on and refused by config-schema and every release while it is off, and the refusal names both fixes, including the exact rlsbl options set command. These options take a path scope, so a workspace can switch one on for a single member (--scope cli); the scope guards skip while their check is off, and testisolation-floor counts the floor as adopted when rlsbl:test-sandbox is on or the testisolation plugin is declared. To keep what a repository runs today, write the entry for every such setting its config carries. changelog_format_version_enforced is retired, and the changelog-format-version check is removed. The changelog-format-version-gate check runs on every repository, and its option rlsbl:changelog-format-version-gate decides whether a line without format_version blocks: error by default, and at warn the check still runs and reports. config-schema and every release refuse a config still carrying the key; delete it, and when the repository wants the gate off, also write the entry the refusal names: rlsbl options set rlsbl:changelog-format-version-gate --current off --ideal error --reason "...".
  • The pre-push hook runs rlsbl failing-checks --hook pre-push, and blocks only on error-level failures. rlsbl's checks.toml declares [hooks.pre-push] (the prepush tag) and [hooks.pre-release] (the preflight tag), so the installed hook names only its hook and a check an options entry softened to warn no longer blocks a push; rlsbl check stays the full report and still fails on warnings. rlsbl check --hook <name> and rlsbl failing-checks (same selection flags, including --releasable) run a declared hook's selection. Run rlsbl scaffold to upgrade an installed hook: it recognizes the previous rlsbl check --tag prepush hook and rewrites it; a hand-written hook is left alone and must be changed by hand.
  • A release blocks only on error-level check failures, for every bump type. A check at warn, registered that way or softened by an options entry, is printed as a WARN line and no longer stops a patch, minor, major, or prerelease release. The at-least-one-user-facing-entry rule is now release validation: every release except infra refuses to run without a user-facing changelog entry, naming bump = "infra" for a release with only infrastructure changes.
  • The pgdesign target reads pgdesign check --tag validation --json instead of passing --ignore-warnings. A check with status fail fails the release and its errors are named; warnings are printed and never block. The output must be strictcli's machine envelope, which pgdesign 0.27.1 prints: an older pgdesign whose --json prints a bare result array, a validation tag that selects no check, or a nonzero exit with no failure or warning to show fails the build.
  • --allow-dirty is removed from rlsbl release run and rlsbl monorepo release run: every release runs in a detached checkout of the committed commit. The release checks the release branch's tip out into .git/rlsbl/release-checkout (reused across releases, submodules initialized) and runs the producers, tests, hooks, local builds, version bump, and release commits there, so uncommitted work never reaches a release. The branch advances only by compare-and-swap from where the release left it -- a branch another session moved is refused, naming the commits -- and only the files the release's own commits change are written into the working tree. An uncommitted change to a path the release writes (its release state, version files, changelog, or a file it generates) refuses the release, naming the path; every other uncommitted change is listed and left alone, and --dry-run reports both instead of refusing. A release that fails before its candidate push leaves the branch and the working tree as they were: there is no git reset --hard anymore, and a refused candidate push takes its branch advance back the same way. Drop --allow-dirty/--no-allow-dirty from every invocation.
  • Workspace member paths are accepted in one spelling only. A member path in workspace.toml is repository-relative and /-separated, with no ., .., or empty segment, no leading or trailing /, and no backslash, and the repository root is .. Any other spelling (draw/cmd/, ./draw, draw//cmd) used to be tidied at load, and some spellings owned no files at all; it is now refused at load and by rlsbl monorepo add and rlsbl monorepo absorb. The load refusal lists every such path at once, each with the line to change in .rlsbl-monorepo/workspace.toml (path = "python/" becomes path = "python"), so a workspace written with trailing slashes is fixed in one pass.
  • Two new release-blocking Go tag checks. path-tag-format-go-member refuses a releasable whose tag_format is a Go path tag (<path>/v{version}) naming a path none of its own Go members lives at: such a tag would permanently publish a version of another module, or of none. It names {name}@v{version} and each Go member's own path as the formats to write. go-module-major-suffix refuses a go.mod module path ending in /v2 or a higher major, naming the rlsbl rewrite go-module-path invocation that drops the suffix. Both run in a release's preflight, so an affected workspace stops releasing until it is fixed.
  • workspace-unregistered finds an undeclared project at any depth. It looked only at top-level directories, so a go.mod or package.json nested inside a member (tools/extra/go.mod) passed, and its files silently fell to the enclosing member. Every manifest git lists is now read. Manifests under a tests/, testdata/, or fixtures/ folder and inside a scratch directory at a member's root are skipped, and a package.json marked private, or the undeclared parent directory of a declared member, is no longer exempt. Declare each flagged directory as a member, or remove its manifest.
  • rlsbl rewrite go-module-path renames only the module it names. Renaming M/draw also renamed M/draw/cmd, a module nested under it with a go.mod of its own, including when run as the fix rlsbl monorepo extract prints. A nested module's path and its packages' imports are now left alone (its references to the renamed module still move), the plan names every nested module it leaves, and each is renamed by an invocation of its own.
  • A release hook may not run inside a member nested in the member that declares it. A config-driven hook's dir pointing into a nested member (sdk's hook with "dir": "python", where sdk/python is a member) is refused when it would run, naming the member that owns the directory and the config file to declare the hook in instead. A releasable-level hook may still name any of its own releasable's members, and a dir with a .. segment or an absolute path is refused.
  • Go modules in one workspace must require each other's released versions, and may not use replace. rlsbl never raised a Go module's require line after a sibling module released, and go install <module>@<version> rejects a module carrying a replace, so a released module could ship pinned to a superseded sibling or unusable from outside. go-workspace-require-current refuses a require below the s...
Read more

v0.129.0

Choose a tag to compare

@smm-h smm-h released this 25 Sep 23:08

Rename commits are left to changelog coverage, which now decides whether the closing message prints an entry line, and rewrite project-name refuses when a Go target's latest release is marked unrecoverable.

Context

rlsbl rewrite project-name and rlsbl monorepo rename-releasable no longer
mark their rename commits as autogenerated, so changelog coverage judges them
like any other commit. Each closing message prints its runnable
rlsbl changelog add --type breaking line only when coverage asks an entry for
that commit, derived from the same exemption and scope rules the
changelog-coverage check applies: a releasable rename whose tag format carries
{name} changes the publish workflow and needs one, while a name-only rename
touches only files rlsbl owns and needs none.

rlsbl rewrite project-name used to rename a project with a Go target without
recording a go-module-path event when its latest release was marked
unrecoverable. It now refuses before writing anything: rlsbl's record cannot
establish the Go module path that release published, and no command can
establish that honestly, so the refusal names none.

Fixes

  • rlsbl rewrite project-name no longer marks its rename commit as autogenerated, so changelog coverage asks for the breaking entry the closing message prints (its runnable rlsbl changelog add line names that commit); the transition-record commit stays autogenerated.
  • rlsbl monorepo rename-releasable no longer marks its rename commit as autogenerated, so changelog coverage decides whether that commit needs an entry. When it does (a {name} tag format, whose rename changes the publish workflow), the closing message prints a runnable (cd <member> && rlsbl changelog add ... --type breaking) line naming that commit, which clears it; a name-only rename touches only files rlsbl owns, needs no entry, and prints nothing about the changelog.
  • rlsbl rewrite project-name now refuses, before writing anything, when there is a Go target and the latest release's archive is marked unrecoverable, instead of renaming with no go-module-path event: rlsbl's record cannot establish the Go module path that release published, so the event the rename must record cannot be written. The refusal names no command, because none can establish that commit honestly.

v0.128.0

Choose a tag to compare

@smm-h smm-h released this 25 Sep 21:27

New rlsbl rewrite project-name command renames a standalone project's published identity: npm and PyPI package names, the Go module path, and the identity-transition record.

Context

A standalone project could not rename its published identity through rlsbl:
monorepo rename-releasable covers releasables and rewrite go-module-path covers
a Go module path, but nothing renamed the package names in the manifests or
recorded the change. The new command renames the package name in every target
manifest whose target renames it, moves the Go module path to one ending in the
new name, and records one identity-transition event per changed identity. The
Go event starts from the module path the latest release published, read from
go.mod at that release's commit. Every event's effective version is the version
the next release ships, decided by the same rule the release flow applies. The
rename and the record are two commits, so a re-run completes an interrupted
rename. Every release target now declares whether rlsbl renames its package
name, and where that name is declared.

Features

  • New command rlsbl rewrite project-name --from <old> --to <new>. Renames a standalone project's published identity: the package name in its npm and PyPI manifests and, for a Go target, the module path's last element. It records one identity-transition event per changed identity, effective from the version the next release ships (the Go event starts from the module path the latest release published), commits the rename and the record separately so a re-run completes an interrupted one, and lists the remaining steps: source directories, install_paths, rlsbl scaffold, command names, the GitHub repository, and a breaking changelog entry. Every release target now declares whether rlsbl renames its package name.

v0.127.3

Choose a tag to compare

@smm-h smm-h released this 25 Sep 18:50

Re-running rename-releasable repairs a renamed releasable without failing

Context

0.127.2 made re-running rlsbl monorepo rename-releasable the repair that records shipped_as on a releasable renamed before the rename did. On a real repository the re-run failed: it staged the removal of the tracked publish cache, sync rewrote it unchanged, and the rename commit was refused as empty. Its alias step could also record and push an alias for a version released after the rename.

Fixes

  • Re-running rlsbl monorepo rename-releasable works on a completed rename. The re-run that records shipped_as on an already-renamed releasable no longer fails with an empty commit after dropping and regenerating the publish cache, and no longer records or pushes an alias for a version released after the rename.

v0.127.2

Choose a tag to compare

@smm-h smm-h released this 25 Sep 18:37

A renamed releasable's past releases keep the tags they shipped under

Context

rlsbl monorepo rename-releasable's own rule is that historical releases stay under the old prefix, but the ref authority made the current scheme's spelling every archived version's primary ref, and the rename never recorded the spelling its past releases shipped under. In a renamed workspace, rlsbl release reconcile therefore planned to push new-name tags and create a second GitHub Release for every version whose Release already stands under its old tag.

The archive's shipped_as field now decides a version's primary ref, rename-releasable writes it, and re-running rename-releasable repairs a workspace renamed before it did. This reverses the earlier rule under which reconcile minted the current spelling for such versions; a tag or GitHub Release it already minted stays explained and counts as the version's own.

Fixes

  • A renamed releasable's past releases keep the tags they shipped under. rlsbl release reconcile no longer plans new-name tags and duplicate GitHub Releases for versions released before rlsbl monorepo rename-releasable: a version whose archive records shipped_as keeps that tag as its primary ref, and a tag or Release under the current name still counts where one exists. rename-releasable now records shipped_as on every past release, and re-running it repairs a releasable renamed before it did. release edit, deprecate, yank, and retry find such a version's GitHub Release under its shipped tag.