orchestrata_ultimate.promotion.promoter_targets

Reference › orchestrata_ultimate › promotion › promoter_targets

The per-target parts of Promoter.promote: where each environment's code lives, and what promoting to the test environment means.

deploy_context(promoter, target) loads the target's profile and builds the DeployContext. The target tree is deliberately not the checkout being edited (RUL-027). ORCHESTRATA_DEPLOY_ROOT in the profile sets it; without it prod falls back to /opt/orchestrata (ADR-0062) and other environments to ~/<env>/orchestrata-ultimate. The workspace comes from ORCHESTRATA_WORKSPACE or ~/workspace.

promote_test_container(promoter, execute) handles the test environment, which has no host tree to advance: its services run in the app container of the Incus test project against a read-only mount of this checkout. It runs the provisioning script deploy/orchestrata-test/provision_app_container.sh, then scripts/start_test_services.py --status under the test profile, and succeeds only when the services answer. Provisioning is not counted as promotion: a failure at either step records FAIL with the failing step in the ledger and raises PromotionError. Success records the sha and target. A dry run prints what it would run.

At a glance

Source src/orchestrata_ultimate/promotion/promoter_targets.py
Lines of code 119
Classes 0
Functions 2
Imports (internal) orchestrata_ultimate.promotion.env_profile, orchestrata_ultimate.promotion.promoter, orchestrata_ultimate.promotion.stages
Imported by orchestrata_ultimate.promotion.promoter
Tests that import it tests/scripts/test_promote_env_reexports.py

Class diagram

No classes; see Functions.

Dependency diagram

Dependency diagram orchestrata_ultimate.promotion.promoter_targets

API

Functions

Function Signature Summary
promote_test_container promote_test_container(promoter: Promoter, *, execute: bool = True) -> int Promotion to the TEST environment — the containerized services.
deploy_context deploy_context(promoter: Promoter, target: str) -> DeployContext Where this environment's code lives, and what it deploys from.

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/src/orchestrata_ultimate/promotion/promoter_targets.py

"""Target-specific promotion bodies lifted out of ``Promoter`` (RUL-021 file
budget). Each function takes the owning ``Promoter`` instance and does
exactly what the corresponding private method used to do — a plain
extract-function split, no behaviour change.
"""

from __future__ import annotations

import os
import subprocess
import sys
from pathlib import Path
from typing import TYPE_CHECKING

from orchestrata_ultimate.promotion.env_profile import PromotionError
from orchestrata_ultimate.promotion.stages import DeployContext

if TYPE_CHECKING:
    from orchestrata_ultimate.promotion.promoter import Promoter


def promote_test_container(promoter: Promoter, *, execute: bool = True) -> int:
    """Promotion to the TEST environment — the containerized services.

    The test env has NO host tree to advance: its kernel + gateway run in
    the ``app`` container of the Incus ``orchestrata-test`` project against
    a READ-ONLY bind-mount of this checkout (deploy/orchestrata-test/
    README.md — the isolation that closed the host/test split-brain). The
    generic ``deploy()`` path would try to advance
    ``~/test/orchestrata-ultimate`` — a tree that has never existed on this
    machine (measured 2026-08-14); every promote to test was a guaranteed
    failure against a phantom target.

    Promotion here means: (re)provision the container idempotently, then
    REFUSE success unless the services actually answer on the test fleet.
    """
    script = (
        promoter.repo_root
        / "deploy"
        / "orchestrata-test"
        / "provision_app_container.sh"
    )
    verify_cmd = [
        sys.executable,
        str(promoter.repo_root / "scripts" / "start_test_services.py"),
        "--status",
    ]
    if not execute:
        print(f"DRY: would run {script}")
        print(f"DRY: would verify via {' '.join(verify_cmd)}")
        return 0
    if not script.is_file():
        raise PromotionError(f"test provisioner missing: {script}")
    proc = subprocess.run(["bash", str(script)], cwd=promoter.repo_root)
    if proc.returncode != 0:
        promoter.record("test", "promote", {"result": "FAIL", "stage": "provision"})
        raise PromotionError(
            f"test container provisioning FAILED (rc={proc.returncode})"
        )
    check = subprocess.run(
        verify_cmd,
        env={**os.environ, "ORCHESTRATA_ENV_PROFILE": "test"},
        cwd=promoter.repo_root,
    )
    if check.returncode != 0:
        promoter.record("test", "promote", {"result": "FAIL", "stage": "verify"})
        raise PromotionError(
            "test services did not answer on the test fleet after "
            f"provisioning (rc={check.returncode}) — provisioned is not "
            "promoted"
        )
    sha = subprocess.run(
        ["git", "rev-parse", "HEAD"],
        cwd=promoter.repo_root,
        capture_output=True,
        text=True,
    ).stdout.strip()
    promoter.record(
        "test",
        "promote",
        {"result": "PASS", "sha": sha, "target": "orchestrata-test/app"},
    )
    print(f"PASS promote test: container services live on 10.53.2.13 @ {sha[:12]}")
    return 0


def deploy_context(promoter: Promoter, target: str) -> DeployContext:
    """Where this environment's code lives, and what it deploys from.

    The target tree is deliberately NOT this checkout (RUL-027): prod must
    never be the working copy someone is editing. ``ORCHESTRATA_DEPLOY_ROOT``
    in the profile overrides the convention when a host lays things out
    differently.

    prod's fallback is ``/opt/orchestrata`` itself (ADR-0062: prod is a
    pinned checkout owned by the deploying user, not a per-env directory
    under ``~``) -- ``env/prod.env``'s own ``ORCHESTRATA_DEPLOY_ROOT``
    still wins whenever it is set; this is only what a profile missing
    that key falls back to.
    """
    profile = promoter.load_profile(target)
    default_root = (
        Path("/opt/orchestrata")
        if target == "prod"
        else Path.home() / target / "orchestrata-ultimate"
    )
    target_root = Path(
        profile.get("ORCHESTRATA_DEPLOY_ROOT", str(default_root))
    ).expanduser()
    workspace = Path(
        profile.get("ORCHESTRATA_WORKSPACE", str(Path.home() / "workspace"))
    ).expanduser()
    return DeployContext(
        env=target,
        profile=profile,
        repo_root=promoter.repo_root,
        target_root=target_root,
        workspace=workspace,
    )