Files
computer-playbook/cli/deploy/development/profile.py
T
kevinveenbirkenbachandClaude Opus 4.7 94936f198b feat(compose): gate registry-cache to local dev only via Profile class
Move the registry-cache pull-through proxy out of the always-on `ci`
profile into its own `cache` profile, and select it based on the runtime
environment instead of statically.

Why
   The proxy only earns its keep when image pulls amortize across many
   runs on the same host. That holds on developer machines (cross-run
   image dedup, persistent host disk) but not on GitHub-hosted runners
   (fresh disk per job), where the proxy startup overhead is net loss
   without the corresponding payoff.

How
* Compose: split `registry-cache` into its own `cache` profile;
  `infinito.depends_on.registry-cache` gets `required: false` so Compose
  does not auto-start the proxy via the dependency when the profile is
  inactive; the systemd drop-in bind-mount source is gated by the new
  `INFINITO_REGISTRY_CACHE_PROXY_CONF` env var with `/dev/null` default,
  so dockerd loads an empty drop-in (no `HTTP_PROXY`, no `ExecStartPre`)
  when the proxy is not running and pulls images directly.
* New `cli/deploy/development/profile.py` `Profile` class is the SPOT
  for which compose profiles activate. KISS + SRP: `is_ci()` reads the
  three CI signals (`GITHUB_ACTIONS`, `RUNNING_ON_GITHUB`, `CI`),
  `registry_cache_active()` is its strict inverse, and `args()` returns
  the matching `--profile ...` flag list.
* `Compose` and `down.py` consume the same `Profile` so up/down cannot
  drift on which services are part of the stack.
* Documentation under `compose/registry-cache/README.md`,
  `docs/contributing/artefact/files/compose.yml.md` and
  `docs/contributing/environment/variables.md` describes the new toggle
  and the `INFINITO_REGISTRY_CACHE_PROXY_CONF` env var. Pre-existing
  documentation.md violations in those files (one SPOT self-label, one
  em dash, two path-as-link-text instances) corrected in the same pass
  per the fix-nearby rule.
* Tests: 14 new `Profile` unit tests in `test_profile.py` plus two
  scenario tests in `test_compose.py` that lock down the
  `--profile ci` (CI runner) vs `--profile ci --profile cache` (local)
  argument shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:25:44 +02:00

56 lines
2.0 KiB
Python

"""Compose-profile selection for the dev/CI stack.
Single source of truth for which `docker compose --profile ...` flags
the dev tooling passes through. Lives in its own module so callers
(`Compose` in compose.py, `_compose_run` in down.py) cannot drift on
which services belong to a given run.
The decision is based on the runtime environment, not on the call
site:
* ``ci`` - always active. Carries `coredns`, `infinito` and any
other future "always present" service.
* ``cache``- active on developer machines, inactive on CI runners.
Carries `registry-cache`. Local hosts amortize the proxy
across many runs (cross-run image dedup); CI runners
get a fresh disk per job, so the proxy adds startup
latency without payoff.
"""
from __future__ import annotations
import os
class Profile:
"""Decide which docker compose profiles to activate."""
def is_ci(self) -> bool:
"""True when running on a CI runner (GitHub-hosted or generic).
Conservative on purpose: if any of the standard CI signals are
set, treat the environment as CI. ``act`` runs locally but
sets ``GITHUB_ACTIONS=true`` to mimic the runner; for the
registry-cache decision that is the same answer either way.
"""
return (
os.environ.get("GITHUB_ACTIONS") == "true"
or os.environ.get("RUNNING_ON_GITHUB") == "true"
or os.environ.get("CI") == "true"
)
def registry_cache_active(self) -> bool:
"""True iff the `cache` profile should be activated.
Inverse of ``is_ci``: developer machines benefit from the
proxy's cross-run image dedup, CI runners do not.
"""
return not self.is_ci()
def args(self) -> list[str]:
"""The ``--profile ...`` flag list to pass to docker compose."""
out = ["--profile", "ci"]
if self.registry_cache_active():
out += ["--profile", "cache"]
return out