Runtime Version Management
Framework M enforces reproducible and predictable language execution environments across both backend (Python) and frontend (Node.js) codebases using a declarative configuration file: runtime-config.json.
The m runtime CLI suite provides commands to inspect, synchronize, and automatically upgrade runtime versions across repository configuration files.
1. Principles: Runtimes vs. Package Managers
A central architectural principle of Framework M is the clear separation between language runtimes and package managers:
| Aspect | Runtimes | Package Managers |
|---|---|---|
| Scope | Execution environments (Node.js, Python) | Dependency resolution & installation tools |
| Governed by | runtime-config.json | Project developer preference (pnpm, yarn, bun, npm for JS; uv, poetry, pip for Python) |
| Strategy | Node: Latest Even LTS; Python: Distro-aligned baselines | User-managed lockfiles (pnpm-lock.yaml, uv.lock, etc.) |
:::tip No Forced Package Managers
Framework M does not hardcode package managers into runtime management. When m runtime updates package.json, it updates only devEngines.runtime (node). It preserves the project's existing devEngines.packageManager configuration without overriding it with pnpm.
:::
2. Declarative Configuration: runtime-config.json
The root of any Framework M project or monorepo contains a runtime-config.json file. It specifies the resolution strategy and target files for each language runtime.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"runtimes": [
{
"name": "node",
"strategy": "latest_even",
"feed_url": "https://nodejs.org/dist/index.json",
"targets": [
{
"file": ".gitlab-ci.yml",
"pattern": "(NODE_VERSION:\\s*)\"?\\d+\"?",
"replacement": "$1\"{{version}}\""
},
{
"file": "package.json",
"pattern": "(\"name\":\\s*\"node\",\\s*\"version\":\\s*\">=)\\d+\\.0\\.0\"",
"replacement": "$1{{version}}.0.0\""
}
]
},
{
"name": "python",
"strategy": "distro_aligned",
"min_version": "3.12",
"default_version": "3.12",
"supported_versions": ["3.12", "3.15"],
"distro_matrix": {
"debian": { "12_bookworm": "3.11", "13_trixie": "3.13" },
"ubuntu": { "22.04_lts": "3.10", "24.04_lts": "3.12", "26.04_lts": "3.14" },
"rhel": { "rhel_9": "3.11", "rhel_10": "3.12" }
},
"targets": [
{
"file": ".gitlab-ci.yml",
"pattern": "(PYTHON_VERSION:\\s*)\"?3\\.\\d+\"?",
"replacement": "$1\"{{default_version}}\""
},
{
"file": "pyproject.toml",
"pattern": "(requires-python\\s*=\\s*\">=)3\\.\\d+\"",
"replacement": "$1{{min_version}}\""
}
]
}
]
}
Strategies
latest_even(Node.js): Queries the official release feed and filters for the highest even major version (e.g. Node 24, 26).distro_aligned(Python): Ensures Python baselines align with major enterprise Linux distributions (Debian, Ubuntu LTS, RHEL). Enforces a minimum baseline of>=3.12.fixed: Pin to a specific explicit version.
3. CLI Commands
The m runtime CLI commands are available via the Studio CLI (framework-m-studio).
Check Runtime Versions
Inspect the current runtime configuration, resolve upstream versions, and detect active package managers:
uv run m runtime check
Options:
--root <PATH>: Path to the workspace root directory (default: current directory).
Synchronize Target Files
Apply the resolved or specified runtime versions to all target files declared in runtime-config.json:
uv run m runtime sync
Options:
--root <PATH>: Workspace root directory.--node-version <VER>: Override Node.js target version explicitly (e.g.--node-version 24).
Automated Upgrade & Lockfile Refresh
m runtime upgrade runs the full automated update lifecycle:
- Checks and updates all targets in
runtime-config.json. - Synchronizes
package.jsondevEngines.runtime. - Auto-detects the repository's package managers and refreshes the lockfiles:
- For JS/TS: Runs
pnpm install,yarn install, ornpm installdepending on what is detected. - For Python: Runs
uv lockorpoetry lock.
- For JS/TS: Runs
- Stashes changes in a dedicated git branch (
runtime/upgrade-<timestamp>), commits them with conventional format (chore(runtime): ...), and opens a Merge Request (GitLab) or Pull Request (GitHub) if credentials are provided.
uv run m runtime upgrade
Options:
--root <PATH>: Workspace root directory.--provider <gitlab|github>: Git forge provider (default:gitlab).--token <TOKEN>: Personal access token or CI token.--project-id <ID>: GitLab project ID or GitHubowner/repo.--dry-run: Preview updates without modifying files, committing, or pushing.--skip-branch: Apply updates and refresh lockfiles directly in the current working tree without creating a git branch or commit.
4. CI/CD Integration
In .gitlab-ci.yml, the runtime maintenance job can be triggered on a scheduled pipeline or manually:
runtime-maintenance:
extends: .maintenance-base
stage: test
script:
- uv sync --all-packages --all-extras --all-groups --cache-dir ${UV_CACHE_DIR}
- uv run m runtime upgrade
rules:
- if: $CHECK_RUNTIMES == "true"
when: always
- if: $CI_PIPELINE_SOURCE == "schedule"
when: always
To trigger manually via the GitLab UI:
- Navigate to Pipelines > Run Pipeline.
- Add environment variable:
CHECK_RUNTIMES=true.