Repository navigation
Per-stack morca.toml overlays, kept with the stack (#332) - #399
Merged
Merged
Conversation
A project ships one morca.toml; what one stack runs differently goes in an overlay kept with the stack. morca lays it on the file before anything reads it (TomlDoc.merge: a key replaces, a table merges key by key), and refuses an overlay table naming a pipeline the file hasn't. - morca register, config check: --overlay F or MORCA_CONFIG_OVERLAY; config show --file prints the merged file with the overlay's values marked; a registration records the overlay and its hash. - enabled = false: register without binaries skips the pipeline, so a pipeline only one stack runs lives in morca.toml too. - Hetzner: CONFIG_OVERLAY_FILE in hetzner.env is sent as /etc/orca/overlay/morca.overlay.toml, mounted in the scheduler only, checked by the image's morca in plan and apply before anything changes, and is one of the scheduler's files, so a change re-registers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
morca-stack wrote one fixed app.env for every app: the lake, the S3 keys and the UI's PostHog key as POSTHOG_KEY. Now an app's [apps.<name>] says what it gets (port, check, env, lake, secrets, memory_gb), read from the app's own image with the new `morca config apps` (the overlay laid on it), and each app has its own env file, app-<name>.env. - Secrets: a secret's value comes from /etc/orca/secrets/<id>, never printed; SECRETS_FILE may hold any secrets/orca/<id> key, and sync takes them. A missing one stops the deploy at the plan. - APPS=console names the app; a port there is for an app with none in morca.toml, and one that differs is refused. - An undeclared app, or an image without `config apps`, keeps the old fixed env, so today's census images deploy as before. - MORCA_POSTHOG_HOST (POSTHOG_HOST in hetzner.env): where the UI's PostHog snippet goes, a proxy like /ph; PostHog's own host without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
Apps declare their env and secrets in morca.toml (#331)
winding-lines
marked this pull request as ready for review
November 12, 2026 17:59
winding-lines
added a commit
that referenced
this pull request
Nov 12, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #332. Part of census#140.
Targets
main, with #396 (the rename) merged in, and uses the new names. #400 (#331, apps declare their env and secrets) is stacked on this PR.What it does
A project ships one
morca.toml. Whatever one stack runs differently goes in that stack's overlay, a file kept beside itshetzner.envin ops, not in the project.TomlDoc.merge): morca loadsmorca.toml, then lays the overlay on it.env = { A = "1" }keeps the file's other names.[defaults]in an overlay doesn't beat a pipeline's own key in the file, since the overlay merges into each table separately. To change a value a pipeline sets itself, set it in that pipeline's table.overlay:line. A new key,enabled = false, makesmorca register(with no binaries) skip a pipeline. So a pipeline that only one stack runs lives inmorca.toml, and that stack's overlay enables it. The issue didn't ask forenabled, but without itorca.lab.tomlcan't become an overlay: the lab registers onlyballast, and an overlay can't add or remove pipelines. A pipeline that's already registered stays registered, as it does today when a pipeline leaves the file.morca config check [--overlay F]checks the merged result; problems point at the overlay'sfile:line.morca config show --file [<file>] [--overlay F]prints the merged file without a database. Each value the overlay set is marked# overlay F:line.overlayandoverlay_hash.morca config shownames the overlay and gives each value it set as[pipelines.x], overlay F:line.--overlayorMORCA_CONFIG_OVERLAY.--no-configandmorca aws registerdon't use one.CONFIG_OVERLAY_FILEinhetzner.envis read relative to that file's folder, like the other*_FILEsettings, and may be SOPS-encrypted.sync_settingssends it as/etc/orca/overlay/morca.overlay.toml, andsettings.envgetsMORCA_CONFIG_OVERLAY=/etc/orca/overlay/morca.overlay.toml. When it's taken out ofhetzner.env,morca-stack sync --removedeletes the file and the key goes away./etc/orca/overlayis mounted, as a directory so a replaced file shows through, in the scheduler only. That's wheremorca registerruns; the UI doesn't read the config.morca-stack planandapplyhave the new image's morca runconfig checkwith the overlay before anything is paused or replaced. A bad overlay stops the deploy at the plan. So does an image whose morca doesn't printwith <overlay>: a morca from before this PR would quietly register without the overlay.settings: its env file or the overlay changed), so deploy.sh quiesces and registers again. A stack without an overlay gets no new mount and no new spec, so this PR replaces nothing on it.Design notes
CONFIG_OVERLAY_FILE, notMORCA_CONFIG_OVERLAY. It's a path on the laptop, like the other*_FILEsettings, and the server-sideMORCA_CONFIG_OVERLAYis derived from it.src/morca/config.mojogrows to about 1,040 lines, which is over AGENTS.md's 1,000 but under the 1,500 split point. The TOML merge and the display code went intotoml.mojo, and the rest of the change needs ProjectConfig's internals.Census side (its own PR, after morca-mojo 0.25.0)
morca.toml. Add[pipelines.ballast]withmemory_gb = "auto",cpus = "auto"andenabled = false, then deleteorca.dev.tomlandorca.lab.toml. The Dockerfile copies onlymorca.toml.config checkof the dev and lab files.scripts/changelog.sh's check that a run step's pipeline is in both files becomesmorca.tomlonly.ops-secrets side (in the release window)
dev/morca.overlay.toml:fill_order,fill_max_runsandfill_lagstay but do nothing without fills.lab/morca.overlay.toml:dev/hetzner.envandlab/hetzner.env, addCONFIG_OVERLAY_FILE=morca.overlay.toml, and takeORCA_CONFIG=/opt/orca/orca.<stack>.tomlout ofextra.env.settings.envgains a key. Pipelines the lab overlay disables stay registered if they ever were: the lab only hadballast.Tests
Run locally on macOS:
test-toml: a new merge case.test-config: the unit tests (overlay,enabled, locations, refusals) andtests/config.sh. It now covers check, show--fileand register with--overlayandMORCA_CONFIG_OVERLAY, the recorded overlay, and register skipping a disabled pipeline.tests/hetzner.sh: the overlay is sent, checked in the image, mounted only in the scheduler, and a change to it replaces the scheduler and re-registers. A bad overlay and an image without overlay support each stop at the plan, before any pause. Removing the setting removes the overlay.tests/hetzner-stacks.sh: the relative path and the dry run.tests/no-orca.shandmojo format.CI runs the rest.
🤖 Generated with Claude Code
https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6