On this page
Project configuration loading with layered precedence (CLI > project > user), plus publish, deploy, changelog validation, and asset size limit helpers.
#rlsbl.config
#rlsbl.config
Project configuration loading with layered precedence.
Layers (highest to lowest priority):
- Per-package config.json
- Releasable config.json
CLI flags override project-level .rlsbl/config.json which overrides user-level defaults.
#merge_config
def merge_config(base, overlay)Merge two config dicts with shallow-replace, deep-merge for nested dicts.
Top-level keys in overlay replace those in base, except when both values are dicts -- in that case the nested dict is merged recursively (overlay nested keys merge into base nested keys).
Keys present in base but absent in overlay are preserved.
Returns a new dict; neither input is mutated.
#load_env_file
def load_env_file(path)Load KEY=VALUE pairs from a file into os.environ.
Supports ~ expansion. Ignores comments (#) and blank lines. Strips surrounding quotes from values.
#_project_config
def _project_config(project_root)Resolve project config path at call time.
Returns an absolute path based on project_root.
#read_json_config
def read_json_config(path)Safely read a JSON file, returning {} on missing.
#should_tag
def should_tag(flags, config)Returns True if tagging is enabled, checking flag > project > user > default.
config is the project config dict (already loaded). User-level config is still read from disk.
#read_project_config
def read_project_config(project_root, releasable_config_dir=None)Read project config with optional releasable-level inheritance.
When releasable_config_dir is provided (path to a releasable's state directory, e.g. .rlsbl-monorepo/releasables/www/), config is loaded with 2-level precedence:
- Per-package config.json (highest)
- Releasable config.json (lowest)
When releasable_config_dir is None, loads only the per-package level.
#read_deploy_config
def read_deploy_config(config)Read and validate deploy targets from project config dict. Returns (targets, errors).
#get_changelog_validation_config
def get_changelog_validation_config(config)Read changelog validation config from a project config dict.
Returns the batch_limits section as a dict like {"max_commits_per_entry": 5, "max_entries_per_commit": 2, "exclusions": [{"reason": "...", "commits": [...], "entries": [{"version": "...", "line": N}]}]}.
Each exclusion object has a required "reason" string for audit purposes; "commits" and "entries" are optional lists silencing the corresponding batch_size_commits and batch_size_entries violations.
Returns an empty dict if no config or malformed.
#get_release_mode
def get_release_mode(config)Return the release mode from config, defaulting to "imperative".
Reads config["release"]["mode"] if present, otherwise returns "imperative". Does NOT validate -- call validate_release_mode for that.
#validate_release_mode
def validate_release_mode(config)Validate the release.mode config key if present.
Valid values: "imperative" (default) and "pr". Raises ConfigError if the value is invalid or the structure is wrong.
#validate_pipelines_config
def validate_pipelines_config(config)Validate the pipelines section of a project config.
Raises ConfigError if:
pipelinesis present but not a dict- An entry is not a dict
- An entry is missing
type(str) orlocal(bool) typeis not a registered pipeline typeassetsis true butmax_asset_size_mbis missing or not a positive intcustom_assetsis present butmax_asset_size_mbis missing or not a positive intcustom_assetsentries are malformed (missingnameorbuild)
#_read_unreleased_commits
def _read_unreleased_commits(config_path)Read commit hashes from unreleased.jsonl adjacent to config_path.
Returns a set of commit hash strings found in the "commits" arrays of all entries in unreleased.jsonl. Returns an empty set if the file does not exist or is empty.
#clean_stale_exclusions
def clean_stale_exclusions(config_path)Remove stale batch_limits exclusions after release finalization.
Two kinds of exclusions become stale:
- Entry-level (have
"entries"withversion="unreleased"):
after finalization renames unreleased.jsonl to X.Y.Z.jsonl, these are dead references.
- Commit-level (have
"commits"but no"entries"): stale when
ALL referenced commits are no longer in unreleased.jsonl (they were moved to a versioned file during finalization).
Returns the number of exclusions removed. Returns 0 and does not write to disk if nothing changed.
#update_last_build_release
def update_last_build_release(project_dir, version)Store last_build_release version in .rlsbl/config.json for OTA validation.
#write_project_config
def write_project_config(key, value, project_root)Write or update a key in .rlsbl/config.json (creates dir if needed).
Returns the updated config dict after writing to disk.