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
3 changes: 3 additions & 0 deletions control_plane/contracts/product_environment_read_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,8 @@ def _product_action_authorization_context(
return ""
if action.route_path == "/v1/drivers/generic-web/prod-promotion-workflow":
return _lane_context_for_instance(profile=profile, preferred_instances=("testing", "prod"))
if action.route_path == "/v1/drivers/generic-web/prod-rollback-plan":
return _lane_context_if_present(profile=profile, instance="prod")
if action.route_path in {
"/v1/drivers/odoo/prod-backup-gate",
"/v1/drivers/odoo/prod-promotion",
Expand Down Expand Up @@ -1331,6 +1333,7 @@ def _action_support_reason(
return ""
if action.route_path in {
"/v1/drivers/generic-web/prod-promotion-workflow",
"/v1/drivers/generic-web/prod-rollback-plan",
"/v1/drivers/odoo/prod-backup-gate",
"/v1/drivers/odoo/prod-promotion",
"/v1/drivers/odoo/prod-rollback",
Expand Down
45 changes: 45 additions & 0 deletions tests/test_product_environment_read_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ def action_allowed(action: str, product: str, context: str) -> bool:
in {
"generic_web_prod_promotion.dispatch",
"generic_web_prod_promotion.execute",
"generic_web_prod_rollback.plan",
}
and context == "example-site-prod"
)
Expand All @@ -565,8 +566,52 @@ def action_allowed(action: str, product: str, context: str) -> bool:
actions = {action.action_id: action for action in overview.available_actions}
self.assertTrue(actions["prod_promotion_workflow"].enabled)
self.assertTrue(actions["prod_promotion"].enabled)
self.assertTrue(actions["prod_rollback_plan"].enabled)
self.assertFalse(actions["preview_refresh"].enabled)

def test_odoo_product_site_overview_uses_prod_context_for_inherited_rollback_plan(
self,
) -> None:
profile = LaunchplaneProductProfileRecord.model_validate(_odoo_profile_payload())
seen_contexts: list[tuple[str, str]] = []

def action_allowed(action: str, _product: str, context: str) -> bool:
if action == "generic_web_prod_rollback.plan":
seen_contexts.append((action, context))
return context == "cm"
return True

overview = build_product_site_overview(
record_store=_PreviewRecordStore(profile, ()),
product=profile.product,
action_allowed=action_allowed,
)

actions = {action.action_id: action for action in overview.available_actions}
self.assertEqual(
actions["prod_rollback_plan"].route_path,
"/v1/drivers/generic-web/prod-rollback-plan",
)
self.assertTrue(actions["prod_rollback_plan"].enabled)
self.assertTrue(seen_contexts)
self.assertEqual({context for _action, context in seen_contexts}, {"cm"})

def test_inherited_rollback_plan_is_disabled_without_prod_lane(self) -> None:
payload = _odoo_profile_payload()
lanes = cast(tuple[dict[str, object], ...], payload["lanes"])
payload["lanes"] = tuple(lane for lane in lanes if lane["instance"] != "prod")
profile = LaunchplaneProductProfileRecord.model_validate(payload)

overview = build_product_site_overview(
record_store=_PreviewRecordStore(profile, ()),
product=profile.product,
action_allowed=lambda *_: True,
)

actions = {action.action_id: action for action in overview.available_actions}
self.assertFalse(actions["prod_rollback_plan"].enabled)
self.assertIn("prod lane", actions["prod_rollback_plan"].disabled_reasons[0])

def test_product_site_overview_uses_testing_context_for_deploy_actions(self) -> None:
profile = LaunchplaneProductProfileRecord.model_validate(
_site_profile_payload(preview_enabled=False)
Expand Down