Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .agents/skills/obol-stack-dev/references/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,20 @@ When `OBOL_DEVELOPMENT=true`, `obol stack up` creates k3d pull-through caches an

Caveats:

- Pull-through caches do **not** speed up local-build flows (`docker build` runs on the host daemon, `k3d image import` bypasses registries). Use the local push target (`just dev-frontend` does this).
- Pull-through caches do **not** speed up local-build flows (`docker build` runs on the host daemon). `just dev-frontend` pushes to `localhost:54103` **and** runs `k3d image import` so k3s picks up the new `:dev` digest (`imagePullPolicy: IfNotPresent` otherwise serves a stale image).
- Registry config is only set up at cluster create. If `obol stack up` is starting an existing cluster, registry setup is skipped — recreate (`obol stack down && obol stack up`) once to pick up new entries.

### Local frontend (`obol-stack-front-end`)

```bash
# From obol-stack — use .envrc.local so OBOL_CONFIG_DIR points at ~/.config/obol (one cluster)
source .envrc.local
FRONTEND_DIR=../obol-stack-front-end just dev-frontend-rebuild
open http://obol.stack:8080
```

- `dev-frontend` — build (may use Docker cache) + push + import + rollout
- `dev-frontend-rebuild` — same with `--no-cache` (use after editing frontend source)
- `dev-frontend-reset` — restore released chart image

Host `pnpm run dev` on `:3000` is optional for HMR; see frontend repo `.env.example` for kubeconfig/Prometheus port-forwards.
27 changes: 11 additions & 16 deletions .envrc.local.example
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
# Local environment overrides (copy to .envrc.local)
# This file is for local development customizations and is gitignored
# Local environment overrides (copy to .envrc.local, then: source .envrc.local)
# This file is gitignored. Use direnv (`direnv allow`) for auto-load in this repo.

# Recommended when your stack lives in ~/.config/obol but you build obol from this repo:
# --- Recommended: dev-build obol CLI against your real stack (single cluster) ---
# Without OBOL_CONFIG_DIR, OBOL_DEVELOPMENT=true alone uses .workspace/config and
# creates a SECOND k3d cluster (new petname stack ID). Point at ~/.config/obol instead.
#
# export OBOL_DEVELOPMENT=true
# export OBOL_CONFIG_DIR="${HOME}/.config/obol"
# export OBOL_DATA_DIR="${HOME}/.local/share/obol"
# export OBOL_STATE_DIR="${HOME}/.local/state/obol"
# export OBOL_BIN_DIR="${PWD}/.workspace/bin"
# PATH_add .workspace/bin
#
# Without OBOL_CONFIG_DIR, OBOL_DEVELOPMENT=true uses .workspace/config and may
# create a second k3d cluster (separate stack ID from your real install).
# if type PATH_add >/dev/null 2>&1; then PATH_add .workspace/bin; else export PATH="${PWD}/.workspace/bin:${PATH}"; fi

# Example: Override development mode
# export OBOL_DEVELOPMENT=false

# Example: Override config directories
# Example: custom paths
# export OBOL_CONFIG_DIR=/custom/config/path
# export OBOL_BIN_DIR=/custom/bin/path
# export OBOL_STATE_DIR=/custom/state/path

# Example: Set custom XDG directories
# export XDG_CONFIG_HOME=/custom/xdg/config
# export XDG_DATA_HOME=/custom/xdg/data
23 changes: 22 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,28 @@ k3d: 1 server, ports `80:80` + `8080:80` + `443:443` + `8443:443`, image `ranche

Generated k3d registry config written to `$OBOL_CONFIG_DIR/registries.yaml`. Cache data under `~/.local/state/obol/registry-cache/` by default, or under `OBOL_REGISTRY_CACHE_DIR` when set.

Local push target: `just dev-frontend` swaps layered diffs into cluster via `docker push localhost:54103/...` (deployment image `localhost:54103/...:dev`) — only changed layers transfer, vs. `k3d image import`'s full-tarball round-trip.
Local push target: `just dev-frontend` builds `obol-stack-front-end`, pushes `localhost:54103/obol-stack-front-end:dev`, **imports into the active k3d cluster** (`k3d image import` — required because `imagePullPolicy: IfNotPresent` caches the `:dev` tag), and restarts the frontend pod. Use `just dev-frontend-rebuild` after code changes (forces `docker build --no-cache`). Reset: `just dev-frontend-reset`.

### Local frontend development

**Two ways to run the UI:**

| Mode | URL | When |
|------|-----|------|
| In-cluster (recommended) | `http://obol.stack:8080` | Stable Prometheus/disk metrics; no port-forwards |
| Host `pnpm run dev` | `http://obol.stack:3000` | Fast React HMR; needs kubeconfig + optional Prometheus/eRPC port-forwards (see frontend `.env.example`) |

**Single cluster when dev-building from this repo** — copy `.envrc.local.example` → `.envrc.local` and `source` it (or `direnv allow`). This sets `OBOL_CONFIG_DIR=$HOME/.config/obol` so `obol kubectl` / `just dev-frontend` hit your real stack instead of spawning a second `.workspace` cluster.

```bash
cd obol-stack && source .envrc.local
FRONTEND_DIR=../obol-stack-front-end just dev-frontend-rebuild # after UI code changes
open http://obol.stack:8080
```

**k3d vs `obol stack up`:** `k3d cluster start` only powers Docker containers + API. `obol stack up` deploys Helm infra, agents, tunnel replay, etc. Use k3d directly only for loadbalancer/port emergencies; otherwise `obol stack up`.

**Stale frontend image symptoms:** build log shows all `CACHED` layers → use `dev-frontend-rebuild`; rollout succeeds but UI unchanged → `k3d image import` (now automatic in `just dev-frontend`).

Caveats:
- Pull-through caches don't help host `docker build` flows — `k3d image import` bypasses registries entirely. The local push target is what speeds up local-build redeploys.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ OBOL_DEVELOPMENT=true ./obolup.sh

Development mode uses `.workspace/` instead of XDG directories and runs `go run` on every `obol` invocation — no build step needed.

**Already have a stack in `~/.config/obol`?** Copy `.envrc.local.example` → `.envrc.local` and `source` it so dev commands use that cluster (avoids a second k3d stack in `.workspace/config`). **Frontend in-cluster:** `FRONTEND_DIR=../obol-stack-front-end just dev-frontend-rebuild` → `http://obol.stack:8080` (see `CLAUDE.md` → Local frontend development).

Networks are embedded at `internal/embed/networks/`. Each uses annotated Go templates that auto-generate CLI flags:

```yaml
Expand Down
17 changes: 16 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ dev_image := "localhost:54103/obol-stack-front-end:dev"
# Build frontend from local source, push to local registry, and restart the pod
dev-frontend: (_dev-frontend-build "false" "true")

# Rebuild and hot-swap frontend (skip docker cache for faster iteration)
# Rebuild and hot-swap frontend (forces docker --no-cache; use after code changes)
dev-frontend-rebuild: (_dev-frontend-build "true" "false")

# Internal: build the frontend dev image, push it, and roll out the deployment.
Expand Down Expand Up @@ -103,6 +103,21 @@ _dev-frontend-build no_cache set_image:
docker build "${build_args[@]}" -t {{ dev_image }} {{ frontend_dir }}
echo "→ Pushing {{ dev_image }} to local registry"
docker push {{ dev_image }}

# k3s caches images by tag (imagePullPolicy: IfNotPresent). Pushing a new
# digest to :dev does not replace the node's copy — import forces the update.
cfg_dir="${OBOL_CONFIG_DIR:-}"
if [ -z "$cfg_dir" ] && [ "${OBOL_DEVELOPMENT:-}" = "true" ]; then
cfg_dir="{{ justfile_directory() }}/.workspace/config"
fi
if [ -z "$cfg_dir" ]; then
cfg_dir="${XDG_CONFIG_HOME:-$HOME/.config}/obol"
fi
stack_id="$(cat "$cfg_dir/.stack-id")"
cluster="obol-stack-${stack_id}"
echo "→ Importing {{ dev_image }} into ${cluster}"
k3d image import {{ dev_image }} -c "${cluster}"

echo "→ Restarting frontend deployment"
if [ "{{ set_image }}" = "true" ]; then
obol kubectl set image deployment/obol-frontend-obol-app \
Expand Down
Loading