On this page
Workspace checks (tag: workspace) validating monorepo CI routing, project registration, dev-only boundaries, and inter-project dependency declarations.
#rlsbl.checks.workspace
#rlsbl.checks.workspace
Workspace checks (tag: workspace) validating monorepo CI routing, project registration, dev-only boundaries, and inter-project dependency declarations.
Checks: router-filters-fresh, workspace-ci-router, workspace-ci-synced, workspace-targets, workspace-unregistered, workspace-stale-entries, dev-only-boundary, unversioned-boundary, dead-workspace-packages, subtree-remote-reachable, mirror-required, workspace-unbuildable, layers-violations, deps-unused, deps-undeclared, deps-runtime-test-only, deps-dev-in-lib, deps-stale, root-rlsbl-conflict, test-suite-workspace.
#_closed_release_history_subjects
def _closed_release_history_subjects(root)Names whose release history an operator declared deliberately closed.
Read from the repository-scoped transition record, which is where rlsbl transition record writes both operator-declared kinds. A malformed record raises rather than reading as "nothing is closed": a record that cannot be read is not evidence that no exemption was declared.
#_member_tag_glob
def _member_tag_glob(root, proj)The glob matching the version tags proj would own in this workspace.
A member outside every releasable has no tag_format of its own, so the scheme is the one a member releasing under the workspace's own convention would use: the target's monorepo_tag_glob, and the workspace default {name}@v* for a member with no detectable target.
#_unreleasing_member_state
def _unreleasing_member_state(ctx)Release state on members that release nothing, minus the declared exemptions.
Returns (findings, tags_unreadable). There is one finding per such MEMBER -- not per item -- because the member is the unit the operator acts on: every remedy (move it into a releasable, delete the state, record the history as closed) applies to all of that member's state at once.
tags_unreadable is the reason the local tag namespace could not be read, or None. It is returned rather than swallowed: with the namespace unreadable the tag half of the question was not asked at all, and the caller says so in its outcome instead of reporting the narrower answer as if it were the whole one.
#_listdir
def _listdir(path)Directory entries of path, or nothing when it is not a directory.
#_is_manifestless_root_member
def _is_manifestless_root_member(ctx, proj)Is proj the root member of a repository with no manifest at its root?
The root member is mandatory and owns whatever no other member claims, so a workspace whose root is not itself a package still has one. Such a member has no target and no manifest by construction, and the checks that demand either exempt it -- for every other member, a missing manifest still means a stale or unreleasable entry.
#_committed_router_filters
def _committed_router_filters(router_path)Return (filters_by_member, quantifier, routed_members) from a router.
filters_by_member maps each member name the router's paths-filter step declares to its pattern list (a lone string is normalized to a one-element list). routed_members is the set of members the router routes jobs for, read off the detect job's outputs -- the router's own second statement of the same member set, which is what makes a DELETED filter entry visible: the output stays, the filter it reads stops existing, and the member's if is never true again.
Raises on anything it cannot read: a router whose filter block is unparseable is not a router whose filters can be called fresh.
#_router_filter_drift
def _router_filter_drift(committed, fresh, routed)Name every difference between a committed filters block and a fresh one.
A wholesale comparison of the two blocks, not a walk of the committed entries: an entry deleted by hand is compared against nothing by such a walk, so the one drift that stops a member's CI outright was the one drift the check could not see.
routed restricts the "should exist" side to the members the router actually routes jobs for -- a member with no CI workflow gets no filter entry from monorepo sync, and demanding one would report every such workspace as stale.
#register_workspace_checks
def register_workspace_checks(app)Register workspace-tag checks on app.