Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Releasing

Workspace wiring gives you a monorepo-style development experience: cross-repo imports resolve locally, no version bumps needed during development. rwv lock captures the exact cross-repo state — the lock file is the project’s version.

For repos that are only consumed within the project, this is the whole story. The lock file pins exact revisions, semver is optional, and you never need to publish to a registry. sha256sum rwv.lock is the project fingerprint — two machines with the same checksum have identical source.

Some repos are also consumed outside the project — published as packages on npm, crates.io, PyPI, etc. These repos need tagged releases and semver. The workspace wiring still eliminates the development-time version dance, but at release time you tag, publish, and update downstream version pins. The decision is per-repo: a project can have repos on the light internal path alongside repos that publish with full semver.

Locking

When you’re ready to capture the current state:

rwv lock

Reads the HEAD revision from each repo and writes projects/web-app/rwv.lock. If a tag exists at HEAD, the lock records the tag name; otherwise the revision ID.

cd projects/web-app
git add rwv.lock && git commit -m "lock: payment feature"
git push

For the internal model, this is the whole release: the committed lock file pins every repo to an exact revision. Reproduce it anywhere with rwv fetch --locked.

Publishing: what workspace wiring gives you

During development, workspace wiring eliminates the development-time version dance: edit B, test A — no bump, no publish, no install. The iteration loop is just edit and test, across repos, like a monorepo.

At release time, the steps are: bump version, tag, publish, install. But most of these are simpler than they seem, because ecosystem tools and version constraints do the heavy lifting.

Constraint checking during development

When you bump a package version in the workspace, most ecosystem tools immediately tell you if consumers’ constraints are incompatible:

EcosystemCatches constraint mismatch in workspace?Details
CargoYescargo check fails: “failed to select a version for the requirement”
GoYesModule path convention (v2 = different path) forces explicit migration
npmYesnpm install fails: “No matching version found”
uv/PythonNoworkspace = true silently overrides constraints — version mismatch only surfaces outside the workspace

This means you discover constraint incompatibilities during development, before publishing — except in Python where you need to be more careful.

The common case: compatible bumps

If B bumps from 1.0.0 to 1.1.0 and A depends on B ^1.0, no constraint update is needed. The release sequence is just:

rwv lock                                          # capture tested state
cd github/chatly/protocol
git tag v1.1.0 && git push origin v1.1.0          # tag and publish
cd ../server
git tag v2.1.0 && git push origin v2.1.0          # A picks up new B on next install

No reference edits. The ecosystem lock file (Cargo.lock, package-lock.json) resolves the range to the new version at install time.

Breaking changes: constraint updates

If B bumps to 2.0.0 (major/breaking) and A depends on B ^1.0, the ecosystem tool catches this in the workspace. Update A’s constraint, then release in dependency order:

# During development: bump B, ecosystem tool flags A's constraint
# Fix A's constraint to ^2.0
rwv lock
cd github/chatly/protocol
git tag v2.0.0 && git push origin v2.0.0
cd ../server
# Cargo.toml already updated to ^2.0 during development
git tag v3.0.0 && git push origin v3.0.0

Per-ecosystem release sequences

Each ecosystem has its own publish command. The pattern is the same — tag, publish, move on — but the exact invocations differ:

Cargo (crates.io):

cd github/chatly/protocol
cargo publish                       # publishes from Cargo.toml version
git tag v1.1.0 && git push origin v1.1.0

Go (module proxy):

cd github/chatly/protocol
git tag v1.1.0 && git push origin v1.1.0
# consumers: go get github.com/chatly/protocol@v1.1.0

npm:

cd github/chatly/web
npm version 1.1.0                   # bumps package.json, creates git tag
npm publish
git push origin v1.1.0

Python (PyPI):

cd github/chatly/ml-service
# bump version in pyproject.toml
git tag v1.1.0 && git push origin v1.1.0
uv build && uv publish

What the lock file tells you

The lock file format itself encodes release state: entries with tag names (e.g., v1.5.0) are already released; entries with revision IDs are unreleased. Read rwv.lock to see what needs attention:

repositories:
  github/chatly/protocol:
    version: v1.5.0              # released
  github/chatly/server:
    version: e1f2a3b4c5d6...     # unreleased — needs a tag
WhatWho knows
Which repos need a releaserwv.lock — tag = released, revision ID = unreleased
Which repos depend on whichEcosystem manifests (Cargo.toml, package.json, go.mod)
Whether a version bump is compatibleEcosystem tools — Cargo, Go, npm catch mismatches in the workspace
How to update version pinsEcosystem tools (cargo update, npm install, go get)
What was tested togetherrwv.lock — the cross-ecosystem snapshot

repoweave owns the first and last rows — which repos, and the cross-repo snapshot. The middle rows are the ecosystem’s job. In a multi-ecosystem project — a Go service using protobufs that a TypeScript frontend also uses — no single ecosystem tool sees all the repos that were tested together. The lock file is the only artifact that captures that cross-ecosystem state.