Skip to content

Commit 84e2fac

Browse files
committed
refactor(tooling): keep SERVERS in the workflows, drop it only from devnet.env
Narrows the previous commit: replacing the `for h in $SERVERS` loops with an inline inventory query per command went further than intended. Which hosts a command runs against is the caller's to pass, and `SERVERS` is how they pass it, so the workflows are back to taking it from the caller and the query that fills it stays documented where inventory.sh is introduced. What devnet.env loses stands: no script reads SERVERS or SSH_USER, so storing them there only created a host list to keep in step with devnet.inventory.
1 parent 6471452 commit 84e2fac

5 files changed

Lines changed: 24 additions & 29 deletions

File tree

.claude/skills/multi-server-devnet/SKILL.md

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,19 @@ B owns `k+1..N-1`). Everything below still applies with three changes, and
4040

4141
Nothing about the servers is hardcoded. Establish these from the operator:
4242

43-
- The hosts: one row each in `scripts/devnet.inventory` (below), queried with
44-
`scripts/inventory.sh`. There is no second host list to hold in step with it.
43+
- `SERVERS`: the SSH targets for the operation at hand (any count, any names),
44+
one devnet each. A working set taken FROM the inventory below, not a second
45+
list of hosts to keep in step with it.
4546
- `SSH_USER`: login user. `docker` is invoked with `sudo`.
4647
- Per-devnet `NODES` (validators on that server) and `SUBNETS`
4748
(`ATTESTATION_COMMITTEE_COUNT`); these can differ between servers.
4849
- A central host for Grafana + the federating Prometheus (often one of the
4950
servers); each server's per-host Prometheus remote-writes to it.
5051

51-
Put the non-host values in `scripts/devnet.env` (copy `scripts/devnet.env.example`;
52-
gitignored) instead of retyping them: the operator-side scripts source it via
52+
`SERVERS`/`SSH_USER` are the caller's to pass per command: no script reads them, so
53+
which hosts a command runs against is decided at the call rather than stored. The
54+
rest goes in `scripts/devnet.env` (copy `scripts/devnet.env.example`; gitignored)
55+
instead of being retyped: the operator-side scripts source it via
5356
`scripts/devnet-env.sh`, and an env var exported in the shell still wins over the
5457
file. It is the one place a deployment's urls and Grafana ids live.
5558

@@ -62,8 +65,8 @@ than reading it by hand:
6265
bash scripts/inventory.sh --tag devnet-ab --field ip # ips, for a loop
6366
bash scripts/inventory.sh --tag devnet-ab --tag aggregator # AND across tags
6467
bash scripts/inventory.sh --tag validator # derived, see below
65-
hosts=$(bash scripts/inventory.sh --tag devnet-ab --field name) || exit
66-
for h in $(echo $hosts); do ssh "$SSH_USER@$h" uptime; done # splits in bash + zsh
68+
SERVERS=$(bash scripts/inventory.sh --field name) || exit # exit 2 = typo'd tag
69+
SERVERS=${SERVERS//$'\n'/ } # newlines -> spaces
6770
```
6871

6972
Tag conventions: a `devnet-*` tag names the chain a host's nodes belong to (two
@@ -152,20 +155,13 @@ redirect must run under sudo).
152155

153156
## Workflows
154157

155-
Examples assume `SSH_USER` is set and `$h` is one host. Per server you pass its own
156-
`NODES`/`SUBNETS`. Keep the host query and the loop in ONE command, since a shell's
157-
variables don't outlive it, and `|| exit` so a typo'd tag can't leave a loop that
158-
does nothing and reports success:
159-
160-
```bash
161-
hosts=$(bash scripts/inventory.sh --tag <devnet> --field name) || exit
162-
for h in $(echo $hosts); do ...; done # $(echo ...) splits under bash and zsh
163-
```
158+
Examples assume `SSH_USER` is set and you iterate over `SERVERS`. Per server you
159+
pass its own `NODES`/`SUBNETS`. `for h in $SERVERS` splits under bash; zsh does not
160+
split parameter expansions, so there write `for h in $(echo $SERVERS)`.
164161

165162
### Pull the latest images on all servers
166163
```bash
167-
hosts=$(bash scripts/inventory.sh --tag <devnet> --field name) || exit
168-
for h in $(echo $hosts); do ssh "$SSH_USER@$h" 'sudo docker pull ghcr.io/lambdaclass/ethlambda:devnet5'; done
164+
for h in $SERVERS; do ssh "$SSH_USER@$h" 'sudo docker pull ghcr.io/lambdaclass/ethlambda:devnet5'; done
169165
```
170166
`devnet5` is the current devnet tag; it tracks the chain's leanVM/proof format,
171167
so it (and the other clients' tags in `references/clients.md`) move together on a

.claude/skills/multi-server-devnet/references/operations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ SKILL.md has the workflows; this file has the depth and the failure modes.
66

77
## Topology model
88

9-
- SSH targets come from `scripts/devnet.inventory`, queried with
10-
`scripts/inventory.sh` (any count, any names); the operator supplies `SSH_USER`
11-
and `docker` runs under `sudo`. No host count, address, or spec is assumed.
9+
- Operator supplies SSH targets via `SERVERS` (any count, any names) and
10+
`SSH_USER`; `docker` runs under `sudo`. No host count, address, or spec is
11+
assumed.
1212
- **Each server runs its own complete devnet** — its own genesis, GENESIS_TIME,
1313
fork choice, and finality. No cross-server peering: every ENR is pinned to
1414
`127.0.0.1`, so discovery never leaves the host even though all devnets share

.claude/skills/multi-server-devnet/scripts/devnet-env.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ devnet_load_env() {
6464
esac
6565
# Quotes, when present, DELIMIT the value, so a '#' or a trailing space inside
6666
# them survives. Unquoted, a `# comment` tail is dropped: it used to end up
67-
# inside the value, and for METRICS_HOST that means ssh-ing to 'host # ssh'.
67+
# inside the value, and for SERVERS that means sweep.sh ssh-ing to a host '#'.
6868
case $val in
6969
\"*) val=${val#\"}; val=${val%%\"*} ;;
7070
\'*) val=${val#\'}; val=${val%%\'*} ;;
@@ -73,8 +73,8 @@ devnet_load_env() {
7373
esac
7474
# File provides defaults only: keep an already-set value. No eval anywhere --
7575
# `${!key}` is bash indirect expansion, and `export` gets ONE quoted
76-
# name=value word, so a multi-word value (a quoted path with a space, say)
77-
# arrives whole and nothing in it is ever reparsed as shell.
76+
# name=value word, so a multi-word value (SERVERS="host-a host-b") arrives
77+
# whole and nothing in it is ever reparsed as shell.
7878
[ -n "${!key:-}" ] || export "$key=$val"
7979
done < "$file"
8080
echo "loaded deployment env from $file" >&2

.claude/skills/multi-server-devnet/scripts/devnet.env.example

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
# Loaded by the operator-side scripts via devnet-env.sh; an env var already set in
55
# your shell overrides the value here.
66

7-
# --- ssh ---------------------------------------------------------------------
8-
# WHICH hosts exist is devnet.inventory's business, not this file's: query it with
9-
# scripts/inventory.sh instead of keeping a second host list here to hold in step.
10-
SSH_USER=user # login user; docker is invoked with sudo
7+
# Only what a script actually reads lives here. SERVERS/SSH_USER don't: which hosts
8+
# a command runs against is the caller's to pass per invocation, and which hosts
9+
# EXIST is devnet.inventory's record, queried with scripts/inventory.sh.
1110

1211
# --- central metrics / logs stack -------------------------------------------
1312
# sweep.sh reads CENTRAL_PROM_URL; the other two are args you pass to

.claude/skills/multi-server-devnet/scripts/devnet.inventory.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# bash scripts/inventory.sh --tag devnet-ab --field ip # ips, for a loop
1313
# bash scripts/inventory.sh --tag devnet-ab --tag aggregator # AND: both needed
1414
# bash scripts/inventory.sh --tag validator # derived, see TAGS
15-
# hosts=$(bash scripts/inventory.sh --tag devnet-ab --field name) || exit
16-
# for h in $(echo $hosts); do ssh "$SSH_USER@$h" uptime; done # bash + zsh
15+
# SERVERS=$(bash scripts/inventory.sh --field name) || exit # exit 2 = typo'd tag
16+
# SERVERS=${SERVERS//$'\n'/ } # newlines -> spaces
1717
#
1818
# FORMAT: whitespace-separated columns, aligned however you like. Blank lines and
1919
# lines whose first non-space character is '#' are ignored. Five columns:

0 commit comments

Comments
 (0)