Skip to content

Unify launch secrets across Kubernetes and Docker - #3473

Draft
morganmcg1 wants to merge 7 commits into
mainfrom
codex/unified-secrets
Draft

Unify launch secrets across Kubernetes and Docker#3473
morganmcg1 wants to merge 7 commits into
mainfrom
codex/unified-secrets

Conversation

@morganmcg1

@morganmcg1 morganmcg1 commented Jul 18, 2026

Copy link
Copy Markdown
Member

Why

Credential handling had grown into several unrelated paths: launch-time keys came from shell state, .env, or gh; W&B used a separately managed cluster Secret; the scout workflow carried literal placeholders; and Docker had no equivalent launch path. That made setup hard to explain, rotation inconsistent, and accidental drift likely.

This PR makes the gitignored root .env the single operator-facing credential source for every supported launch path.

What changed

  • adds one root launch.py for Kubernetes and Docker, backed by one shared package-level CLI
  • removes the legacy k8s/launch.py entrypoint and keeps all launcher Python code under senpai/launch/
  • loads and validates all credentials from .env, secures it to mode 0600, and preflights GitHub, Anthropic, Exa, and W&B before launch
  • keeps settings in senpai.yaml or launch arguments and fails clearly if .env would override a runtime setting
  • accepts arbitrary additional workload credentials without launcher changes
  • creates one launch-scoped Kubernetes Secret over stdin and injects it with envFrom
  • adds a Docker Compose backend that uses native file-mounted Compose secrets; generated Compose files contain names and references, never values
  • routes scout-only infrastructure credentials only to the CoreWeave scout workflow
  • removes the old shared senpai-secrets dependency and literal secret template
  • protects .env and sibling backup files from Git and Docker build contexts
  • documents a four-command quick start, rotation, dry runs, Kubernetes cleanup, and Docker-on-AWS usage

Security and operations

The operator now copies example.env to .env and fills in the four required values. Real launches no longer fall back to ambient shell variables or gh auth token; this intentional boundary makes the active credential set visible and reproducible. WANDB_API_KEY is now launch-scoped and preflighted instead of coming from a manually maintained shared Secret.

Kubernetes values are sent to kubectl apply through stdin. Updating a Secret deliberately does not restart existing pods because that could interrupt long-running training. The launcher warns when a tag already has deployments and prints the explicit kubectl rollout restart command to use when interruption is safe. Existing pods keep their current credentials until they restart; new or restarted pods load the updated values.

Docker passes values only to the Compose client, which mounts secret files under /run/secrets; the worker exports them only inside the container because the underlying CLIs require environment variables. Re-running a Docker launch uses --force-recreate, so containers load rotated values.

Validation

  • uv run --with pytest pytest tests/test_launch_credentials.py tests/test_docker_backend.py tests/test_kubernetes_backend.py -q — 12 passed
  • uvx ruff check ... — passed
  • python -m py_compile ... — passed
  • root launcher Docker and Kubernetes advisor/student dry runs — passed
  • docker compose config --quiet against generated output — passed
  • native Compose secret mount smoke test — passed

@github-actions

Copy link
Copy Markdown


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants