Skip to content
rlsbl.context
On this page

ProjectContext dataclass holding project_root, monorepo_root, and config for threading explicit paths through rlsbl command flows.

#rlsbl.context

#rlsbl.context

Project context for general command use.

#ProjectContext

Context object carrying project root, optional workspace root, and loaded config.

#find_member_for_root

python
def find_member_for_root(root: Path, workspace_root: Path, projects) -> 'WorkspaceProject | None'

Return the workspace member whose declared path IS root, or None.

The one place a directory is matched to a member, so the member a context reports and the releasable config its config was merged from can never disagree.

#_resolve_releasable_config_dir

python
def _resolve_releasable_config_dir(root: Path, workspace_root: Path, *, projects, releasables, resolve_releasable_for_project_fn, get_releasable_dir_fn) -> str | None

Find the releasable config directory for a package in a monorepo.

Receives pre-loaded workspace data via parameters to avoid importing from workspace.py (breaks the context->workspace circular dep edge).

Returns None if the project is not in the workspace, is not releasable, or if the workspace could not be loaded.

#resolve_releasable_config_dir

python
def resolve_releasable_config_dir(root: Path, workspace_root: Path) -> str | None

Convenience wrapper: load workspace data and resolve the releasable config dir.

External callers (release_state, sync) use this instead of calling _resolve_releasable_config_dir directly. The lazy workspace import happens here, keeping the inner function import-free.

#create_context

python
def create_context(root: Path, workspace_root: Path | None=None, project: WorkspaceProject | None=None) -> ProjectContext

Create a ProjectContext, loading config via read_project_config().

When in a monorepo with [[releasables]], automatically detects releasable membership and applies config inheritance (releasable-level config as base, per-package config on top).

A caller that does not name project gets the member whose declared path is root -- the same match the releasable config directory comes from. A context that carried no member could not resolve that directory a second time, so a member configured only by its releasable (a root member, which may not have a .rlsbl/ of its own) read an empty config from every caller that asked the context rather than the path.

Returns an empty dict for config if no config.json exists.

#resolve_release_scope

python
def resolve_release_scope(root)

Resolve the release/changelog context of the project at root.

Returns (project, tag_glob, changes_dir, scope):

  • project is the WorkspaceProject (None in standalone mode).
  • tag_glob scopes tag-namespace questions to this project's own

releases.

  • changes_dir is the releasable-aware JSONL directory, and therefore

also names the release record (.../releases/) that records what this project released. A releasable member's entries live under .rlsbl-monorepo/releasables/<name>/, NOT under the member package -- resolving it per-package made every releasable member report "JSONL changelog not set up" and read an empty release record.

  • scope is the ownership scope commits are attributed against: the

whole releasable -- its members plus its own state directory -- when the project is in one, the single member otherwise, and None outside a workspace.

Shared by every command that answers a question about this project's releases -- listing unreleased commits, labelling a watched commit with the release it is -- so they all read the same directory and the same tag scheme for the same checkout.

The per-package fallback answers exactly ONE question: this checkout is not inside a workspace, or is inside one that does not claim it. Both are plain returns below. Everything past them is a workspace that exists and claims this project, so a loader or validation failure there is a hard error and propagates: degrading it to the fallback would answer with the member package's own (empty) changes directory and no tag scheme, and the caller would report a coverage figure and an unreleased range for a project it had in fact failed to identify.

More tools from this site

  • claudestream Drive Claude Code from Python: run it as a subprocess and read its output as typed events, with async and sync sessions, sandbox policies, and tools you define in Python
  • claudewheel A TUI Claude Code Launcher that lets you have more than one profile, manage sessions lifecycle, pick the exact CC version, model to use (even older unlisted ones), pick which GitHub account to use, etc.
  • dirstat Fast, single-binary directory statistics CLI: every file under a tree grouped by format, with counts, sizes, and lines of code, as a colored terminal table or as JSON
  • fastware A batteries-included ASGI framework: msgspec JSON, a managed Granian server, dependency injection, SSE, WebSockets, auth, and a test client
  • go-toml-edit Zero-dep TOML editing library for Go with comment preservation
  • howmuchleft The fastest Claude Code statusline: context window, 5-hour, and weekly limit usage as three customizable gradient bars, rendering in about 6 ms
  • orxtra
  • pgdesign
  • predraw Declarative rendering pipeline: describe a scene in JSON and get SVG, PNG and WebP out, with light and dark style tokens, reusable components and text converted to path outlines
  • reposummary Turn a git repository's history into a Markdown journal: pick a time window or revision range and get a readable digest of what changed, optionally narrated by an LLM
  • safegit git wrapper CLI that gives each commit its own temporary index and retries ref updates on conflict, so concurrent agents share one repository
  • saferm Command-line replacement for rm that archives every deletion with a mandatory reason and the context it ran in, so deleted files can be listed, inspected and restored
  • selfdoc Static Site Generator that builds a project's documentation site directly from its source code, so the docs can never drift from the code they describe, with SEO/AEO, first-class blog, search, and cross-project linking built in
  • strictcli
  • stricttest An always-on test-isolation floor: a pytest plugin and a Go env-hygiene module that make a test suite structurally unable to reach real credentials, the real HOME, the network, or the development repository.
  • wesktop A Python framework that turns an ASGI web app into a desktop application, serving it from a local Granian server and displaying it in a native OS window via pywebview
Search