Outpost

We have a problem. The stagecoach tool is designed to run on the FASRC cluster, and it relies on the sheriff to run a citizenship test (i.e. determine that you are bought in to use The Frontier). This means that if you want to run stagecoach outside of FASRC, you need to have those documents, which will be a barrier for many users.

Here, we introduce the outpost module, which will temporarily scaffold a fake Frontier directory that the sheriff will accept as valid. This will allow users to run stagecoach on their local machines, without needing to have the actual citizenship documents.

We’re going ot implement this as a CLI flag, --outpost, which will trigger the creation of this fake directory. Additionally, ChatGPT recommends using the contextlib module to create a context manager that will handle the setup and teardown of this fake directory, ensuring that it is cleaned up after use.

The outpost module will have a create_outpost function context.

from __future__ import annotations

from contextlib import contextmanager
from pathlib import Path
from tempfile import TemporaryDirectory
import os
import yaml


@contextmanager
def create_outpost(
    *,
    mode: str = "outpost",
    frontier_dirname: str = "frontier",
    frontier_file: str = "frontier.yml",
):
    """
    Create a temporary mock Frontier file and point THE_FRONTIER at it.

    This does not grant access to real Frontier resources. It only satisfies
    Sheriff's file-based citizenship check for commands that need to run
    outside the assigned Frontier, such as `stagecoach hail --outpost`.
    """
    old_the_frontier = os.environ.get("THE_FRONTIER")

    with TemporaryDirectory(prefix="stagecoach-outpost-") as tmp:
        root = Path(tmp)
        frontier_root = root / frontier_dirname
        frontier_root.mkdir(parents=True, exist_ok=True)

        frontier_path = frontier_root / frontier_file

        mock_frontier = {
            "frontier": {
                "mode": mode,
                "kind": "mock",
                "created_by": "stagecoach.forger",
                "purpose": "temporary citizenship scaffold",
            }
        }

        frontier_path.write_text(
            yaml.safe_dump(mock_frontier, sort_keys=False),
            encoding="utf-8",
        )

        os.environ["THE_FRONTIER"] = str(frontier_path)

        try:
            yield frontier_path
        finally:
            if old_the_frontier is None:
                os.environ.pop("THE_FRONTIER", None)
            else:
                os.environ["THE_FRONTIER"] = old_the_frontier