Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ updates:
patterns:
- "*"

- package-ecosystem: uv
directory: "/docker/runtime-python"
open-pull-requests-limit: 2
schedule:
interval: weekly
labels:
- dependencies
- python:uv
groups:
all-version-updates:
patterns:
- "*"
all-security-updates:
applies-to: security-updates
patterns:
- "*"

- package-ecosystem: docker
directory: "/"
open-pull-requests-limit: 2
Expand Down
6 changes: 4 additions & 2 deletions .github/github.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"roles": "docs/roles.md",
"workspaceCli": "docs/tooling/workspace-cli.md",
"artifactInputs": "docs/tooling/artifact-inputs.md",
"buildToolUpgrades": "docs/tooling/build-tool-upgrades.md",
"commandPatterns": "docs/tooling/command-patterns.md",
"tenantOverlay": "docs/tooling/tenant-overlay.md"
},
Expand All @@ -16,7 +17,8 @@
"default": "uv sync --locked"
},
"test": {
"default": "uv run python -m unittest discover -s tests"
"default": "uv run python -m unittest discover -s tests",
"runtimePythonLock": "uv lock --check --offline --no-config --project docker/runtime-python"
},
"format": {
"default": "uv run ruff format --check ."
Expand Down Expand Up @@ -59,7 +61,7 @@
"Dependency Graph",
"Dependabot Updates"
],
"requiredStatusChecks": ["test"],
"requiredStatusChecks": ["test", "runtime-python-lock"],
"codeScanningMergeProtection": {
"ruleset": "Require code scanning results",
"tool": "CodeQL",
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ permissions:
contents: read

jobs:
runtime-python-lock:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7

- name: Install uv
uses: astral-sh/setup-uv@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.13"

- name: Verify runtime Python lock
run: uv lock --check --offline --no-config --project docker/runtime-python

test:
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ lanes live in `launchplane`.
command surface and generated-output contract.
- [tooling/artifact-inputs.md](tooling/artifact-inputs.md) for the repo-owned
runtime and publish source-input contract.
- [tooling/build-tool-upgrades.md](tooling/build-tool-upgrades.md) for central
build-tool ownership and atomic tenant pin synchronization.
- [tooling/command-patterns.md](tooling/command-patterns.md) for concrete
workspace command examples.
- [tooling/tenant-overlay.md](tooling/tenant-overlay.md) for the thin tenant
Expand Down
61 changes: 61 additions & 0 deletions docs/tooling/build-tool-upgrades.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Build-Tool Upgrades

## Ownership

`docker/runtime-python/pyproject.toml` is the devkit-owned catalog for Python
build tools that must be available at exact versions during tenant artifact
assembly. Its independent `uv.lock` records the approved artifacts. Tenant and
shared-addon projects retain exact `[build-system].requires` declarations so
the publish provenance check can prove that every requested backend is present
in either the support/runtime catalog or the tenant catalog.

Dependabot monitors `docker/runtime-python` separately from the devkit root
project. The `runtime-python-lock` CI job rejects catalog changes whose lock is
not current.

## Tenant Synchronization

Plan a tenant update from a devkit checkout and an exact candidate commit:

```bash
uv run python -m odoo_devkit.build_tool_sync \
--tenant-root ../odoo-tenant-opw \
--devkit-root . \
--devkit-ref <40-character-devkit-commit>
```

Add `--check` to exit nonzero when any synchronized value differs,
`--check-build-tools` to ignore unrelated devkit-ref movement and fail only on
centrally managed addon pin drift, or `--apply` to update the tenant's
`workspace.toml` devkit/runtime refs and matching addon build-tool pins as one
transaction. Apply mode reparses every changed TOML file, verifies the exact
catalog contract, and runs the tenant's offline uv lock check. Any failure
restores every touched file.

The command owns deterministic file transformation and validation only.
Launchplane owns repository inventory, credentials, branch creation, pull
requests, merge ordering, retries, and audited rollout state.

## Rollout Order

1. Pin each tenant to its current known-good devkit commit.
2. Open and validate the devkit catalog/lock update.
3. Run the synchronization command against the devkit candidate commit to
preview and validate the downstream changes.
4. Merge the devkit update and capture the resulting commit on `main`.
5. Rerun synchronization with that final commit, then merge the green tenant
updates. Do not permanently pin a pull-request head that may be replaced by
squash or rebase merge.

Tenant Dependabot may ignore centrally owned build tools only after the
runtime-python Dependabot lane, lock validation, and synchronization path are
operational. Security updates then originate from the central catalog and use
the same downstream rollout. Tenants should also run a scheduled sync check
against devkit `main` so a centrally available update cannot remain silent.

## Recovery

A failed tenant rollout leaves its tracked files unchanged. A merged tenant can
roll back by restoring its prior devkit commit and addon build-tool pins through
the same synchronization command. Never weaken the exact catalog check or use
a floating branch ref as a transition mechanism.
Loading