On this page
Extract and absorb operations for moving packages in and out of monorepos.
#rlsbl.commands.monorepo.extract
#rlsbl.commands.monorepo.extract
Extract and absorb operations for moving packages in and out of monorepos.
Provides:
- require_filter_repo(): dependency check for git-filter-repo
- cmd_extract(): extract a package from a monorepo into a new repository
- cmd_absorb(): absorb an external repository as a package in the monorepo
- cmd_extract_releasable(): extract all member packages of a releasable
#ExtractError
Error during extract or absorb operations.
#require_filter_repo
def require_filter_repo()Raise if git-filter-repo is not installed.
Checks that the git-filter-repo command is available on PATH. Raises ExtractError with install instructions if missing.
#_run_git
def _run_git(cwd, *args)Run a git command and return stdout. Raises subprocess.CalledProcessError on failure.
#_find_project
def _find_project(projects, package_name)Find a project by name in the workspace project list.
Returns the WorkspaceProject or raises ExtractError.
#_get_default_branch
def _get_default_branch(cwd)Detect the default branch name (main or master) of a repo.
#_filter_changelog_entries
def _filter_changelog_entries(entries, package_path, repo_root)Filter changelog entries to those touching a specific package path.
An entry matches if:
- It has a
packagesfield containing the package name, OR - Any of its commits touch files under the package path (checked via
git diff-tree if repo_root is provided and the commit exists).
When we cannot determine relevance (e.g. no packages field and commits are not resolvable), the entry is included (conservative approach).
#_migrate_changelog_to_new_repo
def _migrate_changelog_to_new_repo(source_changes_dir, target_changes_dir, package_path, repo_root)Migrate changelog entries relevant to a package into a new repo's changes dir.
Reads unreleased.jsonl and all versioned JSONL files from source_changes_dir, filters entries to those relevant to the package, and writes them into target_changes_dir.
Returns (files_written, entries_migrated) tuple.
#_create_rlsbl_config
def _create_rlsbl_config(target_path, source_config_path=None)Create a .rlsbl/ config in the target repo.
If source_config_path is provided and exists, copies relevant config. Otherwise creates a minimal config.
#_remove_project_from_workspace
def _remove_project_from_workspace(workspace_root, package_name, projects)Remove a project from workspace.toml by name.
Returns the updated project list.
#validate_extract_preconditions
def validate_extract_preconditions(workspace_root, package_name, target_repo_path)Validate that extraction can proceed.
Checks:
- Package exists in workspace.toml
- Target path does not already exist
- git-filter-repo is installed
Returns (projects, project) tuple.
#cmd_extract
def cmd_extract(workspace_root, package_name, target_repo_path, *, dry_run=False)Extract a package from the monorepo into a new repository.
Steps:
- Validate package exists in workspace.toml
- Clone the monorepo to target_repo_path
- Run
git filter-repo --pathon the clone to keep only
that package's history
- Migrate changelog: filter JSONL entries to those touching the
extracted package
- Create
.rlsbl/config in the new repo - Update source monorepo: remove project from workspace.toml
Args:
workspace_root: path to the monorepo root.package_name: name of the package to extract.target_repo_path: path where the new repo will be created.dry_run: if True, validate but do not perform the extraction.
Returns:
- A dict with extraction details: package_name, target_path,
- entries_migrated, files_written.
#validate_absorb_preconditions
def validate_absorb_preconditions(workspace_root, source_repo_path, package_name)Validate that absorption can proceed.
Checks:
- Source repo exists and is a git repo
- Package name is not already in workspace.toml
Returns projects list.
#_migrate_changelog_from_source
def _migrate_changelog_from_source(source_repo_path, target_changes_dir)Migrate changelog entries from a source repo into the monorepo's changes dir.
Reads .rlsbl/changes/ from the source repo and writes entries into target_changes_dir, appending to existing files.
Returns (files_written, entries_migrated) tuple.
#cmd_absorb
def cmd_absorb(workspace_root, source_repo_path, package_name, releasable_name=None, *, dry_run=False)Absorb an external repository as a package in the monorepo.
Steps:
- Run
git subtree add --prefix= - Add project to workspace.toml with the specified releasable
- Migrate changelog: read source repo's
.rlsbl/changes/, write to
the package's changelog in the monorepo
- Return details for the caller to regenerate CI
Args:
workspace_root: path to the monorepo root.source_repo_path: path to the external repository.package_name: name for the package in the monorepo.releasable_name: optional releasable to assign the package to.dry_run: if True, validate but do not perform the absorption.
Returns:
- A dict with absorption details: package_name, source_path,
- entries_migrated, files_written.
#cmd_extract_releasable
def cmd_extract_releasable(workspace_root, releasable_name, target_repo_path, *, dry_run=False)Extract all member packages of a releasable into a new repository.
If the releasable has one member, the result is a single-project repo. If it has multiple members, the result is a monorepo with workspace.toml.
Steps:
- Resolve releasable members from workspace.toml
- Clone the monorepo
- Run
git filter-repo --path--path ... for all
member paths
- Migrate changelog for each member
- Create appropriate config (single-project or monorepo)
- Update source monorepo: remove all member projects from workspace.toml
Args:
workspace_root: path to the monorepo root.releasable_name: name of the releasable to extract.target_repo_path: path where the new repo will be created.dry_run: if True, validate but do not perform the extraction.
Returns:
- A dict with extraction details.