Compare commits

...

2 Commits

Author SHA1 Message Date
8185d16c07 Merge branch 'rig-work' 2026-09-28 10:04:31 -03:00
f00055033e proper docs and .version 2026-09-28 10:02:55 -03:00
13 changed files with 94 additions and 214 deletions

9
rig/.gitignore vendored
View File

@@ -6,14 +6,7 @@ def
.env.local .env.local
ctrl/.env ctrl/.env
# generated: the .dot is a build artifact rendered from arch/*.json, never hand-edited. # the manifests the air-gapped installer image unpacks (docs/notes/Dockerfile.deps.md)
# The .svg IS committed — onboarding material should render in a repo browser.
arch/*.dot
# ctrl/Tiltfile.gen was here for a generator that no longer exists. ctrl/Tiltfile
# is now a real, committed file that derives its values when Tilt parses it, so
# there is nothing generated to ignore.
# binaries pulled by `make deps-bundle` for the air-gapped installer image
vendor vendor
# Overlays that live with no version control of their own, or clones of their own # Overlays that live with no version control of their own, or clones of their own

1
rig/.version Normal file
View File

@@ -0,0 +1 @@
0.1.1

View File

@@ -83,9 +83,8 @@ fetches with `curl`. A stock `debian:trixie-slim` has no curl — detection runs
fine, then the first download dies with `curl: command not found` and an exit fine, then the first download dies with `curl: command not found` and an exit
code of 127. That is the bootstrap paradox `ctrl/Dockerfile.deps` exists code of 127. That is the bootstrap paradox `ctrl/Dockerfile.deps` exists
to kill — the installer carries its own toolchain so the host needs only Docker — to kill — the installer carries its own toolchain so the host needs only Docker —
but building the image and running it are two different things, and only the but `make deps image` only builds the image; running it is the step below.
build has a Makefile target today. **On a genuinely bare machine, run it by **On a genuinely bare machine, run it by hand:**
hand:**
```bash ```bash
make deps image # builds rig-deps:deps make deps image # builds rig-deps:deps
@@ -207,13 +206,13 @@ never tracks it), or keep it anywhere else and name it by path.
## Run it ## Run it
```bash ```bash
make kind-up # idempotent create, then selects the context make cluster up # idempotent create, then selects the context
make tilt-up # context + your assigned port make tilt # context + your assigned port
``` ```
`tilt-up` passes `--context kind-<name>` every time, which is the point of going `make tilt` passes `--context kind-<name>` every time, which is the point of going
through `make` at all: tilt cannot deploy into whichever cluster you last looked through `make` at all: tilt cannot deploy into whichever cluster you last looked
at. at.
`make tilt-down` and `make kind-down` close the loop, and `make kind-reset` is `make tilt down` and `make cluster down` close the loop, and `make cluster reset` is
delete-and-recreate for when a cluster wedges. delete-and-recreate for when a cluster wedges.

View File

@@ -1,200 +1,99 @@
# rig # rig
A runnable local model of a large, regulated estate — legacy and new side by rig builds a disposable Kubernetes environment on your machine, so you can see how a system
side. Its job is onboarding and exploration, not a production replica: most fits together without access to any of it. It is for **onboarding and exploration**, not a
services are deliberately mocked, because what has to be faithful is the production replica.
topology, not the workloads.
## Prerequisite Most services in it are **not real**. What has to be faithful is the topology: names, ports,
dependency order, who can reach whom, and how it fails. That is what makes a whole estate fit on
**Docker.** Nothing else — no curl, no jq, no python, no apt repositories. a laptop. A real 20-service platform does not fit once in 14 GB; stubs of about 30 MB each fit
three times.
### Starting from plain Windows
Everything here is bash and runs *inside* a Linux shell, so on a Windows machine
that means WSL. Nothing in rig installs WSL, and nothing will: `wsl --install`
enables Windows features and requires a reboot, which is not something a script
should do to a machine on your behalf — and there is no tested undo for it.
From an elevated PowerShell or Command Prompt, once:
```powershell Under the hood it is a kind cluster, a local image registry and a Tilt dev loop, each with its
wsl --install own name and ports, so several environments run side by side. What runs on it is an
``` **overlay**: a folder outside rig that holds one use case.
Then reboot and open the Linux shell it installed. ## Using rig from a project
**If you cloned this on the Windows side, copy it into WSL before carrying on.** You don't need to read rig to use it. Get a release (`rig-<version>.tar.gz`, or a checkout at
WSL can reach the Windows drives at `/mnt/c`, and working from there mostly the tag `rig-<version>`), extract it anywhere, and point the project at it (`RIG_DIR`). Then run
functions — slowly — but file watching does not: that filesystem raises no `make check`: it says what the machine still lacks and which command comes next. `.version`
inotify events, so anything watching for edits silently stops seeing them. names the release; a project records the one it was last run against. See
[`docs/notes/overlay.md`](docs/notes/overlay.md).
```bash ## Prerequisite
cp -r /mnt/c/Users/<you>/rig ~/rig
cd ~/rig
```
`make deps` reports it if you are running from `/mnt/...`. Then carry on below. **Docker.** Nothing else: no curl, jq, python or apt repositories.
If it fails, the usual causes give unhelpful messages: On Windows, rig runs inside WSL. Run `wsl --install` once, from an elevated shell, then reboot.
Work inside the Linux filesystem, not `/mnt/c`: file watching doesn't work there, and
`make deps` warns about it. Git Bash, MSYS and Cygwin don't work (no `/proc`, no docker socket).
| symptom | cause | | symptom | cause |
| --- | --- | | --- | --- |
| "the virtual machine could not be started" | virtualization disabled in BIOS/UEFI | | "the virtual machine could not be started" | virtualization disabled in BIOS/UEFI |
| the command is not recognised | Windows build too old — needs 2004 or later | | the command is not recognised | Windows build too old (needs 2004 or later) |
| the install starts, then nothing works | a reboot is still pending | | the install starts, then nothing works | a reboot is still pending |
Running the scripts from **Git Bash, MSYS or Cygwin does not work** — those look On a machine with nothing but Docker, [BOOTSTRAP.md](BOOTSTRAP.md) runs the toolchain through
close enough to a Linux shell to get started and then fail without `/proc` or a the installer container.
docker socket. `ctrl/deps.sh` detects that and says so rather than letting you
find out the slow way.
## Read the docs first
```bash
make docs # serves on localhost, prints the URL
```
They run before anything is installed, which matters because they are the
instructions for everything else. No cluster and no toolchain required.
Why the code is the way it is — the reasoning, measurements and gotchas — lives
in [`docs/notes/`](docs/notes/), one file per script, so the code keeps short comments.
## Then
```bash
make check # is this machine ready? short; `make check all` for every detail
make deps # install the toolchain (add `core` on a managed machine)
make cluster up # cluster + registry + the profile's addons
```
That is the whole setup. `make cluster up` also starts this environment's local ## What it does
registry and wires it into the node, so an image built locally is pullable by the
cluster without going near docker.io. `make check` shows its port, among
everything else:
```bash | command | does |
make check # ... registry localhost:<port> (running) | --- | --- |
docker build -t localhost:<port>/app:1 . | `make docs` | serves the docs locally; works before anything is installed |
docker push localhost:<port>/app:1 | `make check` | is this machine ready? memory, toolchain, cluster, the next command (`check all` for every detail) |
kubectl --context kind-$(basename $PWD) run app --image=localhost:<port>/app:1 | `make deps` | installs the pinned toolchain (`deps core` on a managed machine) |
``` | `make cluster up` | the cluster, its registry and the configured addons (`down`, `reset`, `list`, `free`) |
| `make tilt` | the dev loop: rig's part, then the overlay's Tiltfile |
| `make selftest` | checks rig itself |
| `make help` | every target |
The port block is derived from the directory name, so two copies of rig never Every verb is a `Makefile` target calling one script in `ctrl/`. The aliases (`kind-up`,
collide — nothing to configure. `make check all` lists it; `bash ctrl/ports.sh persist` `tilt-up`, …) call the same scripts.
pins it into `ctrl/.env` if you want it fixed:
```bash ## Overlays
make cluster list # every cluster on this machine, with memory
make cluster free # stop the others if memory is tight
make cluster down # remove this cluster and its registry
```
**The verbs are yours to change.** `cluster` is the script — `ctrl/cluster.sh` — An overlay holds its settings (`rig.env`), its manifests (`k8s/overlays/dev`), its Tiltfile and
and every spelling above is a `Makefile` target that calls it. `make kind-up` is images, its addons, and its kind config if it needs one. rig reads it and never writes into it.
an alias for `make cluster up`, kept because the other projects on this machine
answer to that spelling and muscle memory spans repos rather than stopping at
one. Nothing outside the `Makefile` reads these names, so rename them, drop the
ones you never type, or add whatever your own projects already say: each alias
is two lines at the bottom of the file, calling the same script the canonical
target does.
**`make tilt` works on a fresh copy, unedited.** rig's `ctrl/Tiltfile` does
rig's part — identity, context guard, registry, the manifests — and then includes
the overlay's own Tiltfile. With no overlay named that is `examples/starter`, so
the dev loop comes up with its two examples running and nothing to configure.
It hardcodes nothing. It asks `ctrl/ports.sh active` for this environment's
cluster name, kube context, ports and paths — the same values every other rig
script resolves through `ctrl/lib/config.sh` — so a copied and renamed rig, or a
moved overlay, deploys into its own cluster with no edits.
`make help` lists every target. `make selftest` checks rig itself, the installer's
detection included; `make selftest install` runs the installer on clean containers
([`docs/notes/installer-testing.md`](docs/notes/installer-testing.md)).
On a machine where Docker really is the only thing installed, `make deps` has
nothing to download with — see [BOOTSTRAP.md](BOOTSTRAP.md), which runs the
toolchain through the installer container and carries on to scaffolding and running
a new project.
## What runs is an overlay
rig is the machine: toolchain, cluster, registry, port block, the dev loop's
plumbing. What runs on it is an **overlay** — one folder, outside rig's version
control, holding a use case: its settings (`rig.env`), its manifests
(`k8s/overlays/dev`), its images and Tiltfile, its addons, its kind config if it
needs its own. rig reads it and never writes into it. See
[`docs/notes/overlay.md`](docs/notes/overlay.md).
```bash ```bash
cp -r examples/starter local/myenv # local/ is gitignored cp -r examples/starter local/myenv # local/ is ignored
OVERLAY=local/myenv make cluster up # or OVERLAY=local/myenv in ctrl/.env OVERLAY=local/myenv make cluster up
OVERLAY=local/myenv make tilt OVERLAY=local/myenv make tilt
``` ```
An overlay can also be a repo of its own, anywhere, or a project folder that With no overlay named, rig runs `examples/starter`. [`examples/data`](examples/data/) adds
carries rig at `<project>/rig/` with a three-line forwarding Makefile. postgres, redis and airflow as plain manifests. A project can carry rig at `./rig`, or keep it
anywhere and name it with `RIG_DIR`.
## One environment per folder The cluster name, context, image tags and ports derive from the overlay folder's name (rig's
own, with no overlay), so environments never collide, and one's teardown never touches another.
Cluster name, kubectl context, image tags and the host port block all derive ## Configuration
from a folder name — the overlay's when one is named, else rig's own — so copies
never collide and neither one's teardown can touch the other. Two overlays run
side by side from one rig; two copies of rig do too.
## Profiles Layers, weakest first: built-in defaults < `ctrl/versions.env` < the profile < the overlay's
`rig.env` < `ctrl/.env` < the command line. A profile (`ctrl/env.d/`) is optional and says how
this machine reaches the world: `mirror` (a pull-through cache) and `offline` (air-gapped) ship
as examples. The cluster itself is one kind template: the overlay's, or rig's one-node default.
**rig needs no profile.** With none named it runs on built-in defaults: one node, rig's own addons make the cluster work: `metallb` (LoadBalancer addresses), `cert-manager` (a
no addons, a local registry, the newest Kubernetes version it pins. A profile is local CA), `metrics-server` (`kubectl top`). A workload's database, cache or scheduler belongs to
an optional file in `ctrl/env.d/`, named by `PROFILE`, that says how this machine its overlay. There is no ingress controller: services are reached through LoadBalancer
reaches the world. rig ships two as **examples**; copy one to use it (the copy is addresses, or through the overlay's own gateway on the environment's HTTP port.
gitignored):
| example | what it changes | ## Where things are
| --- | --- |
| `mirror.env.example` | images through a pull-through cache of an internal registry |
| `offline.env.example` | air-gapped: everything from a preloaded local registry |
```bash
cp ctrl/env.d/mirror.env.example ctrl/env.d/mirror.env
PROFILE=mirror make cluster up
``` ```
Makefile the verbs
The layers, weakest first: built-in defaults < `ctrl/versions.env` < the profile .version this release: patch and minor steps are edits here; milestones get a tag
< the overlay's `rig.env` < `ctrl/.env` < your command line. ctrl/ one script per verb; lib/config.sh (settings and layers); Tiltfile (rig's
half of the dev loop); k8s/kind-config.yaml.tpl; addons/; env.d/; versions.env
The **cluster itself** is one file: the overlay's `kind-config.yaml.tpl` if it has docs/ index.html (make docs); notes/, one per script: why the code is as it is
one, else rig's `ctrl/k8s/kind-config.yaml.tpl` (one node). To change it — more examples/ starter (the default overlay), data (postgres, redis, airflow)
nodes, other port mappings, mounts — edit it and `make cluster reset`. The node standalone/ single-file kits generated from ctrl/ (make standalone); never edited by hand
count is read back out of it, so there is nothing to drift. tests/ the installer's host fixtures
BOOTSTRAP.md from a bare machine with only Docker
## Addons STALE.md assumptions withdrawn, each checked by selftest
Each addon is its own idempotent script, and `ADDONS` names the ones to install,
in order. Adding one is adding a file — there is no dispatcher to edit. An
overlay's `addons/<name>.sh` is found before rig's own.
**There is no ingress controller, deliberately.** They pin a narrow window of
Kubernetes versions, so depending on one would constrain which k8s a rig can be
built with — and running a trailing-edge control plane is often the point.
Services are reached through MetalLB and `type: LoadBalancer`, which carries no
such constraint and is also what a real cluster does.
rig's own addons make the cluster work:
| Addon | Does |
| --- | --- |
| `metallb` | gives `type: LoadBalancer` an address it can actually reach |
| `cert-manager` | a local CA, so TLS works offline |
| `metrics-server` | makes `kubectl top` work on kind |
What a workload needs — a database, a cache, a scheduler — belongs to its
overlay. [`examples/data`](examples/data/) carries postgres, redis and airflow as
plain manifests (no helm: a chart repo is a network dependency), with passwords
generated on first install and kept across re-runs:
```bash
OVERLAY=examples/data make cluster up
``` ```

View File

@@ -1 +0,0 @@
0.1.0

View File

@@ -1,5 +1,5 @@
# Machine-local config. Copy to ctrl/.env (gitignored) and edit. # Machine-local config. Copy to ctrl/.env (gitignored) and edit.
# Cluster SHAPE: an optional profile in ctrl/env.d/. Architecture MODEL: arch/<name>.json. # Cluster SHAPE: an optional profile in ctrl/env.d/.
# Notes: docs/notes/env.md # Notes: docs/notes/env.md
# A profile in ctrl/env.d/ to build. Empty means rig's built-in defaults, which # A profile in ctrl/env.d/ to build. Empty means rig's built-in defaults, which

View File

@@ -386,7 +386,8 @@ docker load &lt; rig.tgz &amp;&amp; make cluster up PROFILE=offline <span clas
derived from the cluster's Docker network at install time, because Docker picks derived from the cluster's Docker network at install time, because Docker picks
that subnet and it differs between machines.</p> that subnet and it differs between machines.</p>
<p>Those addresses are reachable from the Linux side, including inside WSL. A <p>Those addresses are reachable from the Linux side, including inside WSL. A
browser on Windows has no route to them: use the ingress host ports instead.</p> browser on Windows has no route to them: use the environment's HTTP port instead, where
an overlay's gateway listens (its kind config maps it to the host).</p>
<h3>Networking and memory</h3> <h3>Networking and memory</h3>
<p>The cluster uses kind's built-in networking, which does enforce standard <p>The cluster uses kind's built-in networking, which does enforce standard
@@ -417,9 +418,9 @@ OVERLAY=local/myenv make cluster up
</code></pre> </code></pre>
<p>With none named, rig runs its own <code>examples/starter</code>. <p>With none named, rig runs its own <code>examples/starter</code>.
<code>examples/data</code> carries postgres, redis and airflow as an overlay's own <code>examples/data</code> carries postgres, redis and airflow as an overlay's own
addons. A project can also carry rig at <code>&lt;project&gt;/rig/</code> and be addons. A project can carry rig at <code>./rig</code>, or keep it anywhere and name
the overlay itself, with a three-line forwarding Makefile — see it with <code>RIG_DIR</code>. <code>.version</code> names the release; the project
<code>docs/notes/overlay.md</code>.</p> records the one it was last run against. See <code>docs/notes/overlay.md</code>.</p>
<h3>What runs in it</h3> <h3>What runs in it</h3>
<p>Each component is one of three things, and switching between them is a <p>Each component is one of three things, and switching between them is a

View File

@@ -15,7 +15,7 @@ docker build -f ctrl/Dockerfile.deps --target deps -t <slug>-deps .
docker build -f ctrl/Dockerfile.deps --target deps-full -t <slug>-deps:full . docker build -f ctrl/Dockerfile.deps --target deps-full -t <slug>-deps:full .
``` ```
`deps-full` bakes every pinned binary in at build time, and the manifests rig's own addons apply (metallb, cert-manager, metrics-server). `docker save` it and you have the whole installer as one file to carry into an air-gapped network. There, put the manifests where the addons look for them: `make deps image full` builds the second. `deps-full` bakes every pinned binary in at build time, and the manifests rig's own addons apply (metallb, cert-manager, metrics-server). `docker save` it and you have the whole installer as one file to carry into an air-gapped network. There, put the manifests where the addons look for them:
``` ```
docker run --rm -v "$PWD/vendor:/out/vendor" rig-deps:full manifests --to /out/vendor/manifests docker run --rm -v "$PWD/vendor:/out/vendor" rig-deps:full manifests --to /out/vendor/manifests

View File

@@ -31,7 +31,7 @@ Read positionally, so the order is a contract; ctrl/selftest.sh pins it. The two
`OVERLAY` and `CLUSTER` given as make arguments (`make tilt OVERLAY=local/x`) are handed to that `$(shell ...)` explicitly. Before make 4.4, `$(shell)` runs with make's own environment and does not see command-line variables, while the recipes do: tilt would then be told one context and the Tiltfile would guard on another. An overlay's forwarder avoids the question by putting `OVERLAY` in the environment. `OVERLAY` and `CLUSTER` given as make arguments (`make tilt OVERLAY=local/x`) are handed to that `$(shell ...)` explicitly. Before make 4.4, `$(shell)` runs with make's own environment and does not see command-line variables, while the recipes do: tilt would then be told one context and the Tiltfile would guard on another. An overlay's forwarder avoids the question by putting `OVERLAY` in the environment.
This used to be sed over ctrl/.env plus a slug computed in the Makefile, which is a SECOND derivation of values lib/config.sh already owns, and the two could disagree about the port after `ports.sh persist`, or about the name for any directory whose sanitised form differs from its raw one. One source now; the Tiltfile reads the same line. One source: lib/config.sh owns these values, and the Tiltfile reads the same line. A second derivation in the Makefile could disagree about the port after `ports.sh persist`, or about the name of any directory whose sanitised form differs from its raw one.
## CLUSTER / KCTX fallback ## CLUSTER / KCTX fallback
@@ -39,7 +39,7 @@ The fallback matters: ports.sh sources config.sh, and if a profile or .env is br
## ARGS as .PHONY ## ARGS as .PHONY
Words after the target become the script's subcommand; each gets a no-op rule so make does not treat them as goals. They are also marked PHONY, because some of those words name real directories. `cfg`, `ctrl`, `docs`, `gen` and `init` all exist at this level, and make considers a target that is an existing directory already built, so `make build ctrl` ran the build and then printed "make: 'ctrl' is up to date". The empty rule is not enough on its own; only .PHONY stops make consulting the filesystem. Words after the target become the script's subcommand; each gets a no-op rule so make does not treat them as goals. They are also marked PHONY, because some of those words name real directories (`ctrl`, `docs`, `examples`), and make considers a target that is an existing directory already built: without it, `make docs ctrl` would print "make: 'ctrl' is up to date". The empty rule is not enough on its own; only .PHONY stops make consulting the filesystem.
## tilt: --port guard ## tilt: --port guard

View File

@@ -54,7 +54,7 @@ switch for the host part, so the standalone `rigdeps.sh detect` is short too.
rig knows what a node costs (NODE_MB), not what a workload does, so the parts come from the rig knows what a node costs (NODE_MB), not what a workload does, so the parts come from the
overlay's rig.env: `MEMORY_BUDGET="name=MB ..."`, in the order listed; a 0 is left out, and an overlay's rig.env: `MEMORY_BUDGET="name=MB ..."`, in the order listed; a 0 is left out, and an
entry that is not `name=MB` is a `!` line. rig.env is sourced, so an overlay can size a part by entry that is not `name=MB` is a `!` line. rig.env is sourced, so an overlay can size a part by
its own knob (poc_rig's airflow follows its mode). When one part outweighs the rest together its own knob (an airflow sized by the mode the overlay runs it in). When one part outweighs the rest together
(and is at least 1 GB), check names it as the first thing to switch off; `MEMORY_BUDGET_TIP` (and is at least 1 GB), check names it as the first thing to switch off; `MEMORY_BUDGET_TIP`
says how, in the overlay's words. No budget: one `?` row says where to add it. says how, in the overlay's words. No budget: one `?` row says where to add it.

View File

@@ -2,7 +2,7 @@
## ctrl/.env.example: header ## ctrl/.env.example: header
Machine-local config. Copy to ctrl/.env (gitignored) and edit. The cluster SHAPE is an optional profile in ctrl/env.d/ — see the *.env.example there. The architecture MODEL lives in arch/<name>.json — not in .env either. Machine-local config. Copy to ctrl/.env (gitignored) and edit. The cluster SHAPE is an optional profile in ctrl/env.d/ — see the *.env.example there.
## ctrl/.env.example: CLUSTER ## ctrl/.env.example: CLUSTER

View File

@@ -168,13 +168,16 @@ No search path: an unset `RIG_DIR` means `./rig`, and nothing else is tried. Mov
changes nothing in the cluster's name, context or ports; moving or renaming the overlay changes nothing in the cluster's name, context or ports; moving or renaming the overlay
folder does. folder does.
`VERSION`, at rig's top, names the rig. It travels with the folder, vendored, a `.version`, at rig's top, names the rig. It travels with the folder, vendored, a
worktree or a plain copy, and needs no git. A project records the one it was last run worktree, a plain copy or a `git archive` release, and needs no git. Patch and minor
against and warns on another; it does not refuse: steps are edits to that file, with no tag; a `rig-<version>` tag marks a milestone only.
A project records the version it was last run against and warns on another; it does not
refuse. Releases before 0.1.1 carry `VERSION` instead, so the project reads that as a
fallback:
```make ```make
RIG_REF := 0.1.0 RIG_REF := 0.1.1
RIG_AT := $(strip $(shell cat '$(RIG_DIR)/VERSION' 2>/dev/null)) RIG_AT := $(strip $(shell cat '$(RIG_DIR)/.version' 2>/dev/null || cat '$(RIG_DIR)/VERSION' 2>/dev/null))
ifneq ($(RIG_AT),$(RIG_REF)) ifneq ($(RIG_AT),$(RIG_REF))
$(warning rig at $(RIG_DIR) is $(or $(RIG_AT),unversioned); this overlay was last run against rig $(RIG_REF)) $(warning rig at $(RIG_DIR) is $(or $(RIG_AT),unversioned); this overlay was last run against rig $(RIG_REF))
endif endif
@@ -183,18 +186,3 @@ endif
`rig.env` holds no secrets, by this contract. A repository whose `.gitignore` has a `rig.env` holds no secrets, by this contract. A repository whose `.gitignore` has a
broad `*.env` (a common secrets rule) would still hide it, so an overlay living in broad `*.env` (a common secrets rule) would still hide it, so an overlay living in
such a repo re-includes it in its own `.gitignore`: `!rig.env`. such a repo re-includes it in its own `.gitignore`: `!rig.env`.
## Moving a copied rig to an overlay
A rig copied into a project and edited there splits cleanly:
| was, in the copy | goes to |
| --- | --- |
| `ctrl/k8s/base`, `ctrl/k8s/overlays` | `k8s/` |
| the workload parts of `ctrl/Tiltfile` | `Tiltfile` (paths now relative to the overlay) |
| `ctrl/env.d/<name>.env` | `rig.env` |
| edits to `ctrl/k8s/kind-config.yaml.tpl` | `kind-config.yaml.tpl` (`${HOST_WORKDIR}` → `${OVERLAY_DIR}`) |
| workload addons | `addons/` |
| Dockerfiles for the workload | beside the Tiltfile |
| `ctrl/.env` | `rig/ctrl/.env` (this machine's; drop a `MANIFESTS_DIR=ctrl/k8s/overlays/dev` line) |
| everything else of rig's | replaced by rig as it is |

View File

@@ -28,7 +28,7 @@ So the loop is generated FROM the list: add a key to `CONFIG_OVERRIDABLE` and th
## one derivation, not three ## one derivation, not three
The Makefile used to compute the cluster name itself and sed `TILT_PORT` out of `ctrl/.env`: a second derivation of values `lib/config.sh` already owns, which could disagree with it after `ports.sh persist`. It now reads `ports.sh active`. Nothing structurally prevents the sed coming back, so the agreement is asserted against the real `make -n` output rather than against the source. The Makefile reads `ports.sh active` rather than deriving the cluster name and `TILT_PORT` itself: a second derivation of values `lib/config.sh` already owns could disagree with it after `ports.sh persist`. Nothing structurally prevents one coming back, so the agreement is asserted against the real `make -n` output rather than against the source.
`--no-print-directory` and a grep, not `tail -1`: run from `make selftest` this is a RECURSIVE make, and the "Entering/Leaving directory" lines go to STDOUT. `tail -1` then reads "make[1]: Leaving directory ..." and both checks fail, but only when invoked through make, never when the script is run directly. A test that passes one way and fails the other is worse than no test. `--no-print-directory` and a grep, not `tail -1`: run from `make selftest` this is a RECURSIVE make, and the "Entering/Leaving directory" lines go to STDOUT. `tail -1` then reads "make[1]: Leaving directory ..." and both checks fail, but only when invoked through make, never when the script is run directly. A test that passes one way and fails the other is worse than no test.