Repository navigation
Releases: stricttools/rlsbl
Release list
v0.134.0
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, andmonorepo release initrefuse an unreleased releasable, namingrlsbl transition lifecycle --subject <name> --status active, which allows its first release.monorepo init,monorepo add,monorepo absorb, andmigrate recordsno longer open an active lifecycle period for a releasable;transition lifecycle --status unreleasedis refused; andstatus,monorepo status, andtransition showprint each releasable's lifecycle status, recorded or derived. - Breaking.
rlsbl release editrequires the version argument;rlsbl changelog amendrequires--user-facingor--no-user-facing;rlsbl dev installrequires--uninstallor--no-uninstall;rlsbl discoverrequires--mineor--no-mine; andrlsbl secrets sync-npm-tokenrequires--allor--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 longeron-hold:rlsbl transition lifecycle --status non-releasing,rlsbl status --json, and every refusal name it, and a lifecycle-and-license record holdingon-holdis refused. - Breaking. The confidential-term list is read from the path the
confidential_term_listsetting names in the family's settings file,stricttools/config.tomlunder 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 (theconfidential-termscheck, a release, the commands that rewrite a GitHub Release, andtransition 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
unreleasedstatus. - The help of
monorepo release init,release retry, andrelease resume, and the monorepo guide, name theunreleasedrefusal. - Retracted versions in the release record. A release archive may record
retracted_by(and the retraction version's own archiveretracts): a retracted version keeps its tags, has no GitHub Release (unpublished-refsandrelease reconciledemand none, and a history rewrite writes none), is marked retracted inCHANGELOG.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 oneretract [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 retractrequests 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 retirednow also removes the releasable and its members fromreleasables.toml, closes their open identities, deletes their release hooks, drops their files from the scaffold state, and regenerates the routers and the rootCHANGELOG.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 retiredtakes a repeated--subject.--subject a --subject bretires 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--subjectwithactiveornon-releasing, or naming a member or an undeclared subject, is refused.
Fixes
rlsbl monorepo removeaccepts a retired member, and its refusal names the retirement. A member with open lifecycle-and-license entries is refused withrlsbl transition lifecycle --subject <member> --status retiredas the fix; once retired, the remove goes through.
v0.133.0
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-namescheck is nowconfidential-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-positiverecords 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 underconfidential_hits. The machine-local confidential-name index is gone: no command reads or writes it,transition public-clientis removed, and the record refusescodenames,distinctive_terms, andpublic_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
rlsbl release scrub finishes in a repository with versions released before it kept changelog files, keeping their GitHub Releases' own notes.
Fixes
rlsbl release scrubfinishes in a repository with versions released before it kept changelog files: their GitHub Releases keep their own notes, with therlsbl-ci-shamarker moved to the rewritten release commit, where the scrub refused to write them and stopped.
v0.132.0
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
rlsblbinary replaces the Python package. It is distributed as the Go modulegithub.com/stricttools/rlsbl, as npm packages under the existingrlsblname (the binary in one package per platform,rlsbl-linux-x64,rlsbl-linux-arm64,rlsbl-darwin-x64, andrlsbl-darwin-arm64, selected throughoptionalDependencies), and as PyPI wheels under the existingrlsblname. 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/). Runrlsbl migrate recordsonce in every repository, with--dry-runfirst: 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 (--licensesstates a license the manifests do not), removes the old layout through saferm, and commits.rlsbl monorepo cleanupremoves old-layout residue, in a standalone repository too. - One declarations file.
config.json,workspace.toml, andreleasable.tomlare 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 thepush_timeout,ci_timeout,check_timeout, andhook_timeoutkeys, and behavior switches are options entries in.strictmetadata/options/, written withrlsbl options set.rlsbl migrate recordswrites both. - The release targets are go, npm, and pypi. The
spectarget is removed, andrlsbl migrate recordsrefuses 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 throughrlsbl changelog add --batch-reason, which replaces--allow-batchand thebatch_limitsexclusions;rlsbl migrate recordsrestamps existing entries. - The pre-release channel is removed. Versions are
MAJOR.MINOR.PATCH: a release file carryingpreid,blog, orbump = "prerelease"is refused, andrlsbl migrate recordsfolds 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 adeploy_commandinstead), subtree mirror publication, the launcher artifact, local asset upload (assetsandcustom_assets; the publish workflow builds and attaches release archives in CI), the Cloudflare Pages pipeline (selfdoc deploys documentation sites), blog-on-release, and therequires-services(with theservicesandtest_envkeys),private-hook-stale, andmixed-tag-schemeschecks 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 --jsongives the same inventory on demand),rlsbl transition record,rlsbl release undo --target, andrlsbl changelog amend --idare 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:strictcodeoption (error by default) runsstrictcode analyzeas a release check and refuses a missing strictcode, andrlsbl migrate recordsmoves their settings intostrictcode.toml. - The lifecycle-and-license record. Each repository's
.strictmetadata/lifecycle-and-license/lifecycle-and-license.tomlholds 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; andrlsbl monorepo init,rlsbl monorepo add, andrlsbl monorepo absorbcreating a releasable require--license. - Changed flags.
rlsbl release reconciletakes--mode planor--mode applyinstead of--planand--apply;rlsbl monorepo release initrequires--releasablesor--all, writing no table for every releasable unasked; andrlsbl monorepo graphrequires--format. - Preflight checks always run. A declared
pre_releasehook replaces only a member's built-in tests, never the preflight checks, and customized hook scripts become hooks declared inreleasables.toml, moved byrlsbl migrate recordsto.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
excludenames 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 fromreleasables.tomlto release without publishing that target. - rlsbl is a Go binary. The npm and PyPI packages
rlsblnow install the Go binary, through per-platform packages (rlsbl-linux-x64,rlsbl-linux-arm64,rlsbl-darwin-x64,rlsbl-darwin-arm64on 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@v0and the archives on each GitHub Release install it too. The Python package and itspython -m rlsblentry 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 showlists 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 transitioncommands keep the lifecycle-and-license record:transition showprints the record with every rule's verdict,transition lifecycle,transition license,transition identity, andtransition unversioned-tagrecord periods and tags,transition classifymakes a releasable proprietary,transition declassifysquashes the proprietary history and takes a repository public, andtransition init-minimal-recordwrites a minimal record into a repository rlsbl does not manage. - Confidential names stay out of public output. The
confidential-namescheck 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 --jsonprints 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
optionalDependenciesbyosandcpu, with no postinstall script. rlsbl rewrite project-namerecords 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 deprecateandrlsbl release yankaccept the latest release, which they used to refuse in favor ofrlsbl release undo.rlsbl scaffoldrefuses to write a newVERSIONthat would disagree with a target's version.
Fixes
- Commands that create a
.strictmetadatadirectory'smanifest.tomlwhile 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 statusrefusing a member with several targets and no--targetno longer prints an empty status block before the error transition showholds 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 scaffoldcommits the resolved file and its new merge base, which it used to leave uncommitted. - The
npm-token-syncedcheck runs insiderlsbl 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.ymland archives named after that package (./cmd/toolbuildstool), not after the module path's last element; andrlsbl scaffoldkeeps theversion.goit wrote into the main package instead of removing it on the next run and writing it again on the one after. rlsbl scaffoldwrites a stubgo.modinto the.strictmetadata/of a Go module below ...
v0.131.0
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.exclusionsin a member's own.rlsbl/config.jsonis 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, wherechangelog add --allow-batchwrites 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'sexclusionskey. - The strictcli schema dump moved to
.strictmetadata/.cli-schema/schema.json. The release writes a strictcli program'shelp --jsondocument there instead of.strictcli/schema.json, andrlsbl rewrite go-module-pathrewrites theproject_idof dumps at the new location only; a dump left at.strictcli/schema.jsonis no longer read or rewritten. Move it withselfdoc layout migrate(run--dry-runfirst). 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-metadataandmirror-requiredchecks and their options, and the Dart and JVM import analysis. Atargetsentry in.rlsbl/config.jsonor 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'srelease_typefield 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_BINand placed first onPATHfor the hooks and every step rlsbl runs. Apre-checks.shthat 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 scaffoldnext steps now says to commit package-lock.json before releasing, not before pushing: releases are the only push. rlsbl scaffoldno longer crashes withunresolved template variables: goreleaserMain, brewsSectionon 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 gitignoredgo.workfrom there: a hook'sgo 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 committedgo.workwhen the repository root tracks one, and withGOWORK=offotherwise. - The
dep-lockscheck no longer accepts sums from ago.work.sumoutside 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 uncommittedgo.work.sumcan no longer vouch for a module whose owngo.sumis missing entries. rlsbl changelog add --allow-batchin 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-modulesno longer reports Go test helpers andgo runprograms as dead. An internal package imported by another package's_test.gofiles (a test helper such asinternal/cli/clitest) now counts as used, and an internalpackage maindirectory is treated as an entry point. A package's own tests and files undertestdata/still never keep it alive.- Every
batch_limitsmessage (thechangelog addrefusal over the commit limit, thechangelog-batch-commitshint, and the invalidbatch_limitserrors) now names the config file the setting was actually read from. In a workspace that is the releasable's.rlsbl-monorepo/releasables/<name>/config.jsonunless the member's own.rlsbl/config.jsondeclares the setting; before, every message named.rlsbl/config.json. rlsbl changelog add --allow-batchno longer crashes with FileNotFoundError in a workspace whose releasable has noconfig.jsonof its own; it creates the file with the exclusion.releasable-residueno longer fails on rlsbl scaffold's own output in Go members. The stub.rlsbl/go.modscaffold writes into a Go member is accepted while its content is the stub's; any othergo.modthere is still reported.- The
rlsbl changelog addrefusal for an entry overmax_commits_per_entryno 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-commitsandchangelog-batch-entriesnow check each releasable's changelog against that releasable's ownbatch_limitsinstead of the root's. releasable-residueno longer promises thatrlsbl monorepo cleanupremoves 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 whosepostinstalldownloads the release asset of the version being released failed the release before its candidate was pushed. The refresh, and thedep-locksfix it names, are nownpm 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/versionor thatversion-consistencycompares it: the file names the rlsbl that last scaffolded or released the project.
v0.130.0
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-publishis 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-publishis now refused as an unknown flag.- Every check is an option,
rlsbl:<check name>. An error check rankserror > warn > offand a warning checkwarn > 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>.tomlat the git root (creating the directory and its strictspec-ownedmanifest.toml), validates it with strictspec before writing, and commits it with the Autogenerated trailer;rlsbl options registryprints the registry, as data with--json. Every check run and every release apply the entries --offdoes not run the check,warnreports without blocking -- andrlsbl check --listshows each check's value and where it came from. Invalid entries stop every check run and every release.dep-floors,lint,format,type-check, andstrictspec-certificate-gatestay off until their options are switched on, andrlsbl:test-sandboxdecides whether the sandboxed test runner is rendered. Declaringinternal_dep_floors, achecks.<name>block,strictspec_gate, ortest_sandboxno longer turns anything on: each setting is required while its option is on and refused byconfig-schemaand every release while it is off, and the refusal names both fixes, including the exactrlsbl options setcommand. 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, andtestisolation-floorcounts the floor as adopted whenrlsbl:test-sandboxis 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_enforcedis retired, and thechangelog-format-versioncheck is removed. Thechangelog-format-version-gatecheck runs on every repository, and its optionrlsbl:changelog-format-version-gatedecides whether a line withoutformat_versionblocks:errorby default, and atwarnthe check still runs and reports.config-schemaand 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](theprepushtag) and[hooks.pre-release](thepreflighttag), so the installed hook names only its hook and a check an options entry softened towarnno longer blocks a push;rlsbl checkstays the full report and still fails on warnings.rlsbl check --hook <name>andrlsbl failing-checks(same selection flags, including--releasable) run a declared hook's selection. Runrlsbl scaffoldto upgrade an installed hook: it recognizes the previousrlsbl check --tag prepushhook 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 aWARNline 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 exceptinfrarefuses to run without a user-facing changelog entry, namingbump = "infra"for a release with only infrastructure changes. - The pgdesign target reads
pgdesign check --tag validation --jsoninstead of passing--ignore-warnings. A check with statusfailfails 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--jsonprints 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-dirtyis removed fromrlsbl release runandrlsbl 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-runreports both instead of refusing. A release that fails before its candidate push leaves the branch and the working tree as they were: there is nogit reset --hardanymore, and a refused candidate push takes its branch advance back the same way. Drop--allow-dirty/--no-allow-dirtyfrom every invocation.- Workspace member paths are accepted in one spelling only. A member path in
workspace.tomlis 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 byrlsbl monorepo addandrlsbl monorepo absorb. The load refusal lists every such path at once, each with the line to change in.rlsbl-monorepo/workspace.toml(path = "python/"becomespath = "python"), so a workspace written with trailing slashes is fixed in one pass. - Two new release-blocking Go tag checks.
path-tag-format-go-memberrefuses a releasable whosetag_formatis 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-suffixrefuses ago.modmodule path ending in/v2or a higher major, naming therlsbl rewrite go-module-pathinvocation that drops the suffix. Both run in a release's preflight, so an affected workspace stops releasing until it is fixed. workspace-unregisteredfinds an undeclared project at any depth. It looked only at top-level directories, so ago.modorpackage.jsonnested 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 atests/,testdata/, orfixtures/folder and inside a scratch directory at a member's root are skipped, and apackage.jsonmarkedprivate, 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-pathrenames only the module it names. RenamingM/drawalso renamedM/draw/cmd, a module nested under it with a go.mod of its own, including when run as the fixrlsbl monorepo extractprints. 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
dirpointing into a nested member (sdk's hook with"dir": "python", wheresdk/pythonis 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 adirwith 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'srequireline after a sibling module released, andgo install <module>@<version>rejects a module carrying areplace, so a released module could ship pinned to a superseded sibling or unusable from outside.go-workspace-require-currentrefuses a require below the s...
v0.129.0
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-nameno longer marks its rename commit as autogenerated, so changelog coverage asks for the breaking entry the closing message prints (its runnablerlsbl changelog addline names that commit); the transition-record commit stays autogenerated.rlsbl monorepo rename-releasableno 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-namenow refuses, before writing anything, when there is a Go target and the latest release's archive is markedunrecoverable, instead of renaming with nogo-module-pathevent: 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
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 oneidentity-transitionevent 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
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-releasableworks on a completed rename. The re-run that recordsshipped_ason 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
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 reconcileno longer plans new-name tags and duplicate GitHub Releases for versions released beforerlsbl monorepo rename-releasable: a version whose archive recordsshipped_askeeps that tag as its primary ref, and a tag or Release under the current name still counts where one exists.rename-releasablenow recordsshipped_ason every past release, and re-running it repairs a releasable renamed before it did.release edit,deprecate,yank, andretryfind such a version's GitHub Release under its shipped tag.