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
16 changes: 16 additions & 0 deletions .github/github.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
{
"defaultBranch": "main",
"projectType": "odoo-workspace-devkit",
"commands": {
"dependencies": {
"inspect": {
"command": "uv run platform dependencies inspect --manifest <workspace.toml>",
"mutates": false
},
"check": {
"command": "uv run platform dependencies check --manifest <workspace.toml>",
"mutates": false
},
"normalize": {
"command": "uv run platform dependencies normalize --manifest <workspace.toml> [--output-dir <directory>]",
"mutates": true
}
}
},
"docs": {
"index": "docs/README.md",
"overview": "README.md",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ uv run platform workspace clean --manifest /path/to/workspace.toml
uv run platform workspace run --manifest /path/to/workspace.toml -- pwd
uv run platform dependencies inspect --manifest /path/to/workspace.toml
uv run platform dependencies check --manifest /path/to/workspace.toml
uv run platform dependencies normalize --manifest /path/to/workspace.toml
uv run platform runtime select --manifest /path/to/workspace.toml
uv run platform runtime build --manifest /path/to/workspace.toml --no-cache
uv run platform runtime up --manifest /path/to/workspace.toml --build
Expand Down
29 changes: 29 additions & 0 deletions docs/tooling/workspace-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ uv run platform workspace clean --manifest /path/to/workspace.toml
uv run platform workspace run --manifest /path/to/workspace.toml -- pwd
uv run platform dependencies inspect --manifest /path/to/workspace.toml
uv run platform dependencies check --manifest /path/to/workspace.toml
uv run platform dependencies normalize --manifest /path/to/workspace.toml
uv run platform dependencies normalize --manifest /path/to/workspace.toml \
--output-dir /path/to/normalization-output
uv run platform runtime select --manifest /path/to/workspace.toml
uv run platform runtime build --manifest /path/to/workspace.toml --no-cache
uv run platform runtime up --manifest /path/to/workspace.toml --build
Expand Down Expand Up @@ -140,6 +143,32 @@ Purpose
- `inspect` prints structured JSON. `check` prints the same report and exits
nonzero when `current` is false.

## `dependencies normalize`

Purpose

- Regenerate the canonical tenant root `uv.lock` inside the same staged
tenant/shared-addon workspace used by dependency inspection, then atomically
copy only the verified lock back to the tenant repo.
- Preserve strict tenant CI: normalization proceeds only when the workspace is
already publishable or stale lock state is its sole finding, and the written
lock must pass the existing offline, no-config publishability check.
- Run `uv lock --python <manifest-python> --no-config` without broad upgrade
flags. Pinning the manifest's Python version keeps canonical lock generation
stable across hosts while the existing lock continues to constrain
unaffected packages.
- Produce the frozen export shape used by tenant CI with `uv export --frozen
--all-packages --no-emit-workspace --no-default-groups --no-config`. The
export is verified and hashed on every run; pass `--output-dir` to retain it
as `tenant-requirements.txt`.
- Emit sorted JSON with source input hashes, tenant/shared source commits and
dirty-state flags, uv version and arguments, final artifact hashes, strict
post-check results, and `changed = false` for a measured no-change run.
Output omits credentials, repository URLs, and machine-specific source paths.
- Restore the original tenant `uv.lock` if the strict post-check or retained
export write fails. Tenant manifests, addon metadata, shared-addon sources,
and CI workflows remain owned by their existing repositories.

## `workspace scaffold-cockpit-root`

Purpose
Expand Down
22 changes: 21 additions & 1 deletion odoo_devkit/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from dataclasses import replace
from pathlib import Path

from .dependency_workspace import inspect_dependency_workspace
from .dependency_workspace import inspect_dependency_workspace, normalize_dependency_workspace
from .manifest import WorkspaceManifest, load_workspace_manifest
from .runtime import (
run_native_runtime_build,
Expand Down Expand Up @@ -105,6 +105,20 @@ def build_parser() -> argparse.ArgumentParser:
)
dependencies_check_parser.set_defaults(handler=_handle_dependencies_check)

dependencies_normalize_parser = _add_manifest_argument(
dependencies_subparsers.add_parser(
"normalize",
help="Regenerate the canonical tenant lock and frozen dependency export",
)
)
dependencies_normalize_parser.add_argument(
"--output-dir",
type=Path,
default=None,
help="Retain tenant-requirements.txt in this directory",
)
dependencies_normalize_parser.set_defaults(handler=_handle_dependencies_normalize)

runtime_parser = subparsers.add_parser("runtime", help="Run local runtime workflows via the workspace manifest")
runtime_subparsers = runtime_parser.add_subparsers(dest="runtime_command")

Expand Down Expand Up @@ -367,6 +381,12 @@ def _handle_dependencies_check(arguments: argparse.Namespace) -> None:
raise SystemExit(1)


def _handle_dependencies_normalize(arguments: argparse.Namespace) -> None:
manifest = _load_manifest(arguments.manifest)
result = normalize_dependency_workspace(manifest=manifest, output_directory=arguments.output_dir)
print(json.dumps(result.to_dict(), indent=2, sort_keys=True))


def _handle_runtime_select(arguments: argparse.Namespace) -> None:
manifest = _load_runtime_manifest(arguments)
exit_code = _run_runtime_handler(lambda: run_native_runtime_select(manifest=manifest))
Expand Down
Loading