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
9 changes: 7 additions & 2 deletions docs/tooling/workspace-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,10 @@ Notes
- When Launchplane supplies `ODOO_DEVKIT_RUNTIME_ENVIRONMENT_JSON`, publish can
synthesize the selected manifest context from that explicit payload instead of
requiring every Launchplane-owned product context to be listed in the shared
devkit stack. Unknown contexts still fail closed without the explicit payload.
devkit stack. Synthesized contexts do not inherit stack-level install-module
lists; their artifact install intent comes from the managed-instance required
modules plus any repo-owned `website-bootstrap.toml` modules. Unknown contexts
still fail closed without the explicit payload.
- Publish-time GHCR credentials can be split by purpose. Private base image
reads prefer `GHCR_READ_TOKEN`, artifact image pushes prefer `GHCR_TOKEN`,
and private source checkout secrets still belong in the transient runtime
Expand All @@ -274,7 +277,9 @@ Notes
Repo-owned source selection belongs in the dedicated artifact-input manifest.
- Artifact manifests preserve selector intent in `addon_selectors` while
keeping `addon_sources` as the resolved exact-SHA runtime truth consumed by
control-plane release and deploy flows.
control-plane release and deploy flows. They also include the resolved
`odoo_install_modules` list so promotion/deploy orchestration can preserve
tenant module activation intent when it rewrites a live target environment.
- `platform runtime odoo-shell` follows the same local-only rule. It can run
interactively, consume a `--script` file, and optionally tee output into a
`--log-file`, but it is still a manifest-backed local helper rather than a
Expand Down
3 changes: 3 additions & 0 deletions odoo_devkit/local_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ def publish_runtime_artifact(
runtime_repo_commit=runtime_commit,
artifact_source_entries=artifact_source_entries,
source_selector_entries=artifact_source_selectors,
odoo_install_modules=runtime_context.selection.effective_install_modules,
openupgrade_addon_repository=runtime_values.get("OPENUPGRADE_ADDON_REPOSITORY", ""),
openupgradelib_install_spec=runtime_values.get("OPENUPGRADELIB_INSTALL_SPEC", ""),
addon_skip_flags=parse_csv_values(runtime_values.get("ODOO_PYTHON_SYNC_SKIP_ADDONS", "")),
Expand Down Expand Up @@ -2378,6 +2379,7 @@ def build_runtime_artifact_manifest_payload(
runtime_repo_commit: str,
artifact_source_entries: tuple[dict[str, str], ...],
source_selector_entries: tuple[dict[str, str], ...],
odoo_install_modules: tuple[str, ...],
openupgrade_addon_repository: str,
openupgradelib_install_spec: str,
addon_skip_flags: tuple[str, ...],
Expand All @@ -2402,6 +2404,7 @@ def build_runtime_artifact_manifest_payload(
"enterprise_base_digest": enterprise_base_digest,
"addon_sources": list(artifact_source_entries),
"addon_selectors": list(source_selector_entries),
"odoo_install_modules": list(odoo_install_modules),
"openupgrade_inputs": {
"addon_repository": openupgrade_addon_repository,
"install_spec": openupgradelib_install_spec,
Expand Down
20 changes: 20 additions & 0 deletions tests/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,10 @@ def fake_run_command(
self.assertEqual(payload["enterprise_base_digest"], "sha256:" + "2" * 64)
self.assertEqual(payload["build_flags"]["values"]["build_target"], "production")
self.assertEqual(payload["image"]["tags"], ["opw-20260416-abcdef"])
self.assertEqual(
payload["odoo_install_modules"],
["launchplane_settings", "disable_odoo_online", "opw_custom"],
)
self.assertEqual(payload["output_file"], str(output_file.resolve()))
written_payload = json.loads(output_file.read_text(encoding="utf-8"))
self.assertEqual(written_payload["artifact_id"], payload["artifact_id"])
Expand Down Expand Up @@ -1184,6 +1188,10 @@ def fake_run_command(
}
],
)
self.assertEqual(
payload["odoo_install_modules"],
["launchplane_settings", "disable_odoo_online", "opw_custom"],
)
self.assertNotIn("odoo_addon_repository_selectors", payload["build_flags"]["values"])

def test_registry_auth_splits_base_image_read_and_artifact_push_tokens(self) -> None:
Expand Down Expand Up @@ -1384,6 +1392,10 @@ def fake_run_command(
}
],
)
self.assertEqual(
payload["odoo_install_modules"],
["launchplane_settings", "disable_odoo_online", "opw_custom"],
)

def test_native_runtime_publish_rejects_invalid_artifact_inputs_manifest(self) -> None:
with tempfile.TemporaryDirectory() as temporary_directory:
Expand Down Expand Up @@ -1685,6 +1697,10 @@ def fake_run_command(
{"repository": "cbusillo/disable_odoo_online", "ref": exact_ref.rsplit("@", 1)[1]},
payload["addon_sources"],
)
self.assertEqual(
payload["odoo_install_modules"],
["launchplane_settings", "disable_odoo_online", "opw_custom"],
)

def test_native_runtime_publish_rejects_unknown_context_without_explicit_runtime_payload(self) -> None:
with tempfile.TemporaryDirectory() as temporary_directory:
Expand Down Expand Up @@ -1836,6 +1852,10 @@ def fake_run_command(
self.assertTrue(payload["artifact_id"].startswith("artifact-cm_website-"))
self.assertEqual(payload["image"]["repository"], "ghcr.io/example/cm-website-runtime")
self.assertEqual(payload["image"]["tags"], ["cm_website-20260606-abcdef"])
self.assertEqual(
payload["odoo_install_modules"],
["launchplane_settings", "disable_odoo_online", "cm_website"],
)
self.assertIn(
"ODOO_ADDON_REPOSITORIES=cbusillo/disable_odoo_online@411f6b8e85cac72dc7aa2e2dc5540001043c327d",
captured_build_args,
Expand Down