Skip to content

feat(seitask): add provision-node for follower SeiNode fleets#419

Merged
bdchatham merged 1 commit into
mainfrom
feat/seitask-provision-node
Jun 18, 2026
Merged

feat(seitask): add provision-node for follower SeiNode fleets#419
bdchatham merged 1 commit into
mainfrom
feat/seitask-provision-node

Conversation

@bdchatham

Copy link
Copy Markdown
Collaborator

What

New seitask provision-node subcommand: provisions N follower SeiNode CRs (<base>-0..N-1), peer-wires them to a genesis SeiNetwork, waits for readiness, and publishes their endpoints into workflow-vars for the chaos suite. The genesis path (provision-snd → SeiNetwork) is untouched — this is purely additive.

Why

The migration off SeiNodeDeployment split provisioning into genesis (SeiNetwork, already done by provision-snd) and the follower/RPC fleet (SeiNode), which had no provisioning path. The chaos suite needs an EVM load target that is a follower — genesis validators run ModeValidator and don't serve EVM.

Design

  • Fan-out N SeiNodes; stamp sei.io/role=node (+ sei.io/seinetwork=<net> when --network) on each CR object — byte-identical to seictl node apply, so node list -l sei.io/seinetwork=<net>,sei.io/role=node resolves followers regardless of which tool created them. (Controller ResourceLabels only stamps pods, never the CR.)
  • Readiness before publish: PhaseRunning → TM /status height>0 → per-node eth_blockNumber 200. The EVM listener binds after Running (status is discoverability, not serve-readiness) and no downstream step probes EVM, so the gate lives here.
  • Publishes 5 workflow-vars keys (byte-identical names): <ROLE>_EVM_RPC_LIST (N-node CSV), _EVM_RPC (node-0 scalar), _TM_RPC (node-0), _REST (node-0), CHAIN_ID.

⚠️ Hard dependency — RBAC must land with-or-before this

provision-node needs seinodes create + seinodes/status get on the seitask-runner Role. Current grant is get/list/watch only. The grant must be added to both clusters/harbor/nightly/major-upgrade/rbac.yaml and the vendored runner/rbac.yaml (kept-in-sync) — see the platform-side migration (WS-C). Do not wire provision-node into a nightly workflow before that grant merges, or every fan-out step 403s on create.

Tests

Fan-out naming, object-label stamping (incl. no-network case omits the network label), readiness gating (publish blocked while the EVM dial fails even at TM height>0), workflow-vars assembly, empty-guards. provisionnode 81% coverage. make manifests generate → no diff (CLI/runtime only). Idiom review: clean, no correctness findings.

Provenance

Design + cross-review in the migration workspace (WS-B LLD; xreview ledger RESOLVED R1→R2, dissent lifted). Pairs with the seictl network/node split (WS-A).

🤖 Generated with Claude Code

New `seitask provision-node` subcommand provisions N follower SeiNode CRs
(named <base>-0..N-1), peer-wires them to a genesis SeiNetwork, waits for
readiness, and publishes their endpoints into workflow-vars for the chaos
suite. Genesis path (provision-snd) is untouched.

- Fan-out N SeiNodes; stamp sei.io/role=node (+ sei.io/seinetwork when
  --network) on each CR object, byte-identical to seictl node apply, so
  node-list selectors resolve followers regardless of which tool created them.
- Readiness before publish: PhaseRunning -> TM /status height>0 -> per-node
  eth_blockNumber 200 (the EVM listener binds after Running; no downstream
  step probes EVM, so the gate lives here).
- Publish 5 workflow-vars keys: <ROLE>_EVM_RPC_LIST (N-node CSV), _EVM_RPC
  (node-0), _TM_RPC (node-0), _REST (node-0), CHAIN_ID.

Runtime RBAC: requires seinodes create + seinodes/status get on the
seitask-runner Role (both major-upgrade/rbac.yaml and the vendored
runner/rbac.yaml) — must land with-or-before this ships.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cursor

cursor Bot commented Jun 18, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Creates cluster SeiNodes and publishes RPC URLs used by test workflows; behavior is well-tested but depends on matching RBAC and correct readiness gating before downstream steps run.

Overview
Adds seitask provision-node, a new workflow task that fans out N follower SeiNode CRs from a Go template, wires them to a genesis network when --network is set, and publishes role-scoped RPC endpoints into workflow-vars for downstream chaos/load steps.

The runtime in internal/seitask/provisionnode renders one manifest per replica (injecting .ORDINAL / .NODE_NAME), stamps workflow ownerRefs, object labels aligned with seictl node apply, optional label-based peer sources, then waits for Running, TM /status height > 0, and per-node EVM eth_blockNumber before writing CHAIN_ID and <ROLE>_EVM_RPC_LIST (plus node-0 scalars). Re-runs tolerate AlreadyExists and warn on spec drift instead of force-applying.

provision-snd, runner, and tests are touched only to share flagTemplate / flagVar constants and to assert SeiNode is registered on taskScheme. Broad unit coverage covers readiness gating (publish blocked if EVM never binds), label/peer stamping, and workflow-vars assembly.

Deploy note: the task creates SeiNode resources; seitask-runner RBAC must grant create (and status read) before wiring this into nightly workflows, or fan-out will 403.

Reviewed by Cursor Bugbot for commit ad94291. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ad94291. Configure here.


if err := c.Create(ctx, node, fieldOwner); err != nil {
if !apierrors.IsAlreadyExists(err) {
return Result{}, taskruntime.Infra(fmt.Errorf("creating SeiNode %s/%s: %w", node.Namespace, node.Name, err))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runner RBAC missing SeiNode create

High Severity

The new provision-node path calls Create on SeiNode CRs, but runner/rbac.yaml still grants only get, list, and watch on seinodes. Any workflow step that runs this subcommand gets HTTP 403 on fan-out create and the task fails before readiness or workflow-vars publish.

Fix in Cursor Fix in Web

Triggered by learned rule: Scenario workflows must have matching runner RBAC permissions

Reviewed by Cursor Bugbot for commit ad94291. Configure here.

@bdchatham bdchatham merged commit 15f5dc7 into main Jun 18, 2026
5 checks passed
@bdchatham bdchatham deleted the feat/seitask-provision-node branch June 18, 2026 19:56
bdchatham added a commit that referenced this pull request Jun 20, 2026
…de RBAC (#420)

* feat(seitask): WS-C — rpc scenario templates → SeiNode + provision-node RBAC

- runner/rbac.yaml: grant seitask-runner `seinodes` create (provision-node's
  first act is c.Create(SeiNode); without it every rpc-fleet step 403s) +
  seinodes/status get (forward-compat, matches the /status pattern).
- scenarios/{load-test,release-test}/rpc.yaml.tmpl: rewrite from a dead second
  `kind: SeiNetwork` (replicas:2) to a single `kind: SeiNode` fullNode follower;
  name/ns/ownerRef/labels/peers stamped by provision-node at runtime.

Pairs with platform WS-C (chaos workflows → provision-node) and consumes the
merged provision-node (#419) + SeiNode.status.endpoint (#418).

HARD GATE before merge: dry-run the rendered SeiNode template against the
DEPLOYED CRD (`seictl node apply … --dry-run`) — envtest only covers the
repo CRD, not the live one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(seitask): move rpc.yaml.tmpl render-clean guard to provisionnode

The WS-C rewrite of scenarios/{load-test,release-test}/rpc.yaml.tmpl from
kind: SeiNetwork to kind: SeiNode broke provisionsnd's
TestBundledTemplates_RenderClean, which strict-unmarshals every bundled
template as a SeiNetwork (rendered SeiNode has top-level spec.chainId, an
unknown field on SeiNetworkSpec).

- provisionsnd test: drop the rpc.yaml.tmpl case — it only owns the
  SeiNetwork genesis/validator templates now.
- provisionnode test: add TestBundledTemplates_RenderClean covering both
  rpc.yaml.tmpl, asserting they render + strict-unmarshal as a SeiNode
  (spec.chainId set, spec.fullNode present).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant