scripts.provision_worktree_env

Reference › scripts › provision_worktree_env

scripts/provision_worktree_env.py materialises a .env file in whichever git worktree the caller is standing in, idempotently, so a new worktree can run the code and gates that need its environment (the RUL-021 worktree-environment rule; see check_worktree_envs and worktrees). A human or a worktree-creation step runs it; it has no internal imports.

current_worktree and primary_worktree locate the worktrees with git (through _git). provision ensures that worktree/.env exists and returns whether it is present plus a short reason. It obtains the file either by decrypting the committed ciphertext (_decrypt_from_ciphertext) or by copying from the primary worktree (_copy_from_primary). Options: --worktree (default the worktree containing the current directory), --check (report only and exit non-zero when .env is absent; provisions nothing), --force (re-materialise even when one exists) and --quiet (print only on failure). Outside a git worktree it prints that there is nothing to do and exits 0.

At a glance

Source scripts/provision_worktree_env.py
Lines of code 202
Classes 0
Functions 7
Imports (internal) none
Imported by none
Tests that import it none

Class diagram

No classes; see Functions.

Dependency diagram

No internal imports and no importers.

API

Functions

Function Signature Summary
_git _git(**args: str, cwd: Path | None = None) -> str | None Run git and return stripped stdout, or None if git failed.
current_worktree current_worktree(start: Path | None = None) -> Path | None The worktree we are standing in (its top level), or None outside a repo.
primary_worktree primary_worktree(start: Path | None = None) -> Path | None The FIRST worktree git lists, which is always the primary checkout.
_decrypt_from_ciphertext _decrypt_from_ciphertext(worktree: Path, dest: Path) -> str | None Try source 1: the tracked SOPS artifact.
_copy_from_primary _copy_from_primary(worktree: Path, dest: Path) -> str | None Try source 2: the primary worktree's plaintext.
provision provision(worktree: Path, *, force: bool = False) -> tuple[bool, str] Ensure worktree/.env exists.
main main(argv: list[str] | None = None) -> int

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/scripts/provision_worktree_env.py

#!/usr/bin/env python3
"""Materialise ``.env`` in whichever worktree we are standing in — idempotently.

WHY THIS EXISTS (measured 2026-08-12, session 262). A builder agent working in
``.claude/worktrees/agent-aad6ad8280c27cf26`` reported 8 test modules failing with
``SystemExit: neither KG_ROUTING_URI nor MEMGRAPH_URI is set`` and dispositioned them
as "a pre-existing environment/config gap unrelated to this packet". They were not
pre-existing: the same modules pass in the primary worktree in 8 seconds. The worktree
simply had **no ``.env`` file at all**, and the failing tests read the ``.env`` FILE
from disk (``dotenv_values(_ENV_FILE)``) rather than ``os.environ`` — so a fully
populated shell environment did not help them.

That is the expensive shape of this defect: it does not present as "missing config",
it presents as **product tests failing**, which invites a wrong diagnosis and burns an
agent's whole budget chasing it. ``scripts/check_worktree_envs.py`` gated ``.venv`` and
never looked for ``.env``, so RUL-021 ("every damn feature branch gets a full env") was
enforced for half the env.

WHY A SEPARATE SCRIPT rather than logic inside a hook: worktrees are created by at
least two paths that do not share code — ``scripts/worktrees.py`` (the project's own
lifecycle manager) and the Claude Code harness's ``isolation: worktree`` (which never
calls project code). The only thing BOTH paths run is git's ``post-checkout`` hook,
which ``git worktree add`` fires in the new worktree (verified empirically, not
assumed). Keeping the logic here means the hook is a one-line trigger and every other
caller — provisioner, gate, CI, a human — invokes the identical code path.

SOURCE PRECEDENCE, most trustworthy first:
  1. Decrypt the tracked SOPS artifact, when an age identity is available. This is the
     real answer: the ciphertext travels with the repo, so a worktree (or a fresh
     clone) reconstructs its own secrets.
  2. Copy the primary worktree's ``.env``. Same machine, same user, same secrets that
     are already on this disk — this is a convenience, not a security boundary, and it
     is what makes worktrees work TODAY on a machine whose key is already present.
  3. Neither available -> report and EXIT 0.

**Never blocks a checkout.** A hook that can fail a ``git worktree add`` or a branch
switch converts a missing convenience into a broken repository. Every failure path here
is a printed line and exit 0; only ``--check`` reports absence as non-zero, because a
GATE is exactly the place where absence should be loud.
"""

from __future__ import annotations

import argparse
import os
import shutil
import subprocess
import sys
from pathlib import Path

ENV_FILENAME = ".env"
CIPHERTEXT_RELPATH = Path("secrets") / "env.sops.env"

#: Exit codes. ``--check`` is the only mode that reports a missing ``.env`` as a
#: failure; the hook path is always 0 (see the module docstring).
OK = 0
MISSING = 1


def _git(*args: str, cwd: Path | None = None) -> str | None:
    """Run git and return stripped stdout, or None if git failed."""
    try:
        done = subprocess.run(
            ["git", *args],
            cwd=str(cwd) if cwd else None,
            capture_output=True,
            text=True,
            check=True,
        )
    except subprocess.CalledProcessError, OSError:
        return None
    return done.stdout.strip()


def current_worktree(start: Path | None = None) -> Path | None:
    """The worktree we are standing in (its top level), or None outside a repo."""
    top = _git("rev-parse", "--show-toplevel", cwd=start)
    return Path(top) if top else None


def primary_worktree(start: Path | None = None) -> Path | None:
    """The FIRST worktree git lists, which is always the primary checkout.

    ``git worktree list --porcelain`` emits the primary first; every linked worktree
    follows. Deriving it this way (rather than assuming a path shape like
    ``.claude/worktrees/*``) keeps this correct for worktrees created anywhere.
    """
    listing = _git("worktree", "list", "--porcelain", cwd=start)
    if not listing:
        return None
    for line in listing.splitlines():
        if line.startswith("worktree "):
            return Path(line[len("worktree ") :].strip())
    return None


def _decrypt_from_ciphertext(worktree: Path, dest: Path) -> str | None:
    """Try source 1: the tracked SOPS artifact. Returns a description on success."""
    ciphertext = worktree / CIPHERTEXT_RELPATH
    if not ciphertext.is_file():
        return None
    secrets_cli = worktree / "scripts" / "secrets_cli.py"
    if not secrets_cli.is_file():
        return None
    try:
        done = subprocess.run(
            [sys.executable, str(secrets_cli), "decrypt", "--dest", str(dest)],
            cwd=str(worktree),
            capture_output=True,
            text=True,
        )
    except OSError:
        return None
    if done.returncode != OK or not dest.is_file():
        return None
    return f"decrypted from {CIPHERTEXT_RELPATH}"


def _copy_from_primary(worktree: Path, dest: Path) -> str | None:
    """Try source 2: the primary worktree's plaintext. Returns a description."""
    primary = primary_worktree(worktree)
    if primary is None or primary.resolve() == worktree.resolve():
        return None
    source = primary / ENV_FILENAME
    if not source.is_file():
        return None
    # Copy through a temp file + replace so an interrupted copy cannot leave a
    # truncated .env that would fail in a far more confusing way than an absent one.
    tmp = dest.with_name(dest.name + ".provision.tmp")
    try:
        shutil.copyfile(source, tmp)
        os.chmod(tmp, 0o600)
        os.replace(tmp, dest)
    except OSError:
        tmp.unlink(missing_ok=True)
        return None
    return f"copied from the primary worktree ({primary})"


def provision(worktree: Path, *, force: bool = False) -> tuple[bool, str]:
    """Ensure ``worktree/.env`` exists. Returns (present, human-readable reason)."""
    dest = worktree / ENV_FILENAME
    if dest.is_file() and not force:
        return True, "already present"

    for attempt in (_decrypt_from_ciphertext, _copy_from_primary):
        detail = attempt(worktree, dest)
        if detail is not None:
            return True, detail

    return False, (
        "no source available — no decryptable secrets/env.sops.env and no readable "
        ".env in the primary worktree"
    )


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--worktree",
        default=None,
        help="Worktree to provision (default: the one containing the cwd)",
    )
    parser.add_argument(
        "--check",
        action="store_true",
        help="Report only; exit non-zero when .env is absent. Provisions nothing.",
    )
    parser.add_argument(
        "--force",
        action="store_true",
        help="Re-materialise even when a .env is already present",
    )
    parser.add_argument("--quiet", action="store_true", help="Print only on failure")
    args = parser.parse_args(argv)

    start = Path(args.worktree).resolve() if args.worktree else None
    worktree = current_worktree(start) if start is None else start
    if worktree is None:
        print("[worktree-env] not a git worktree — nothing to do")
        return OK

    if args.check:
        present = (worktree / ENV_FILENAME).is_file()
        state = "present" if present else "MISSING"
        print(f"[worktree-env] {worktree}: .env {state}")
        return OK if present else MISSING

    present, reason = provision(worktree, force=args.force)
    if present:
        if not args.quiet or reason != "already present":
            print(f"[worktree-env] {worktree}: .env {reason}")
        return OK

    # Deliberately exit 0: see the module docstring. A checkout must never fail
    # because a convenience file could not be created.
    print(f"[worktree-env] {worktree}: .env NOT created — {reason}", file=sys.stderr)
    return OK


if __name__ == "__main__":
    raise SystemExit(main())