Skip to content

Feat(workflow): loops in the studio, the run view and pipelines (23/23) - #978

Merged
briankane merged 2 commits into
mainfrom
stack/23-workflow-loops
Oct 16, 2026
Merged

briankane merged 2 commits into
mainfrom
stack/23-workflow-loops

Conversation

@briankane

@briankane briankane commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Stack 23/23 · after #977 · last in the stack

Targets main but builds on #977, so the earlier stack commits show here too: review the last commit only. Merge after #977.

Description of your changes

A workflow step or step group with forEach runs once per item (kubevela/pkg#142, kubevela/workflow#261, kubevela/kubevela#7396), and can name each item by a key (kubevela/pkg#154, kubevela/workflow#273, kubevela/kubevela#7468). VelaUX dropped forEach when it copied steps, so a loop synced from the cluster ran once on the next deploy, and a run's passes matched nothing it knew. VelaUX now keeps loops, records them, and lets you build and follow them.

Run view. A loop is a stacked card: a segment per item when closed, a lane per item when open, labelled by the item, with Approve on a waiting pass.

23-run-open

23-run-closed

Studio. Loop in the Add menu (greyed inside a group, since only a top-level step takes forEach), Repeat on a card's tools, and a strip on each loop with its items and mode.

23-studio

23-studio-add-loop

The wizard gains an Items stage: a list typed in (a table, or YAML), an earlier step's output, or, in an application, a $( ) expression; one item at a time or all at once. Steps in a loop are offered each.item, each.index and each item key as inputs.

23-wizard-items

A key names each item's passes after values in the item (rollout-us-east-deploy rather than rollout-0-deploy). The Items stage takes one, offered from the list's columns and checked as the controller checks it; a keyed loop's lanes are labelled by their keys.

23-wizard-key

23-keyed-run

Pipelines get the same studio and run view.

23-pipeline-run

Server side:

  • Sync, deploy and the API keep forEach, including key.
  • A loop's run record starts with no sub-steps and takes its passes from the status, each with the item it ran for (the engine's own IterationIndex) and the alias of the body step it repeats (IterationTemplate). The items, and a keyed loop's labels, are the ones the engine stored in the workflow context. Before this, a looped group's record kept its body once, never started.
  • A pipeline run carries the same per loop (loops on the run and its status), and no longer pads a loop with its body steps.

Fixes #

I have:

  • Read and followed KubeVela's contribution process.
  • Related Docs updated properly. In a new feature or configuration option, an update to the documentation is necessary.
  • Run yarn lint to ensure the frontend changes are ready for review.
  • Run make reviewableto ensure the server changes are ready for review.
  • Added backport release-x.y labels to auto-backport this PR if necessary.

How has this code been tested

  • Go: forEach round trips through sync, deploy and the API; loop run records (inline steps and a referenced Workflow); pipeline run loops and the padding fix. Each bug had a failing test first.
  • UI: lanes, lane specs, progress, item labels, withLoops, loop edits and item validation (299 tests).
  • On k3d with a controller from KubeVela master: an Application looping a group over three regions (records, run view, approving one pass with ?step=), the same keyed by name (passes rollout-us-east-*, labels in the record, key kept through sync), and a pipeline looping a step over three items all at once, on a workflow controller from workflow main.

Special notes for your reviewer

  • Over 50 typed-in items warns rather than blocks: 50 is the controller's default --max-for-each-items, which a cluster can raise.
  • The Expression source shows only in an application's studio; pipelines have no expressions.

briankane and others added 2 commits October 16, 2026 17:41
forEach landed in pkg and workflow after both moved to Go 1.27.1 and
k8s 0.37 (controller-runtime 0.25), so the loop work needs that line.
Pins: pkg a754071 and workflow 53204a3 (which add forEach keys, pkg#154
and workflow#273), and prism dba7491 (its own 1.27 bump, which no longer needs the
apiserver-runtime replace). The replace block is the union of ours and
KubeVela master's. KubeVela itself stays on the fork commit the stack
pins, which carries the expression APIs this branch's features use.

controller-runtime 0.25 adds Apply to client.Client and to the
sub-resource clients. Both of our wrappers embed the client, so Apply
went straight through: the project query guard, meant to be read-only,
could write with it, and the impersonating auth client sent it as VelaUX
rather than the user. Both now override Apply, with tests.

CI and the Dockerfiles build with Go 1.27.1; envtest runs k8s 1.37.0;
staticcheck is v0.8.2 and golangci-lint v2.14.0 (the config was already
in the v2 format), installed with go install. ReverseProxy.Director is
deprecated from Go 1.26; its four uses stay, marked, since Rewrite
changes which headers reach the upstream.

golangci-lint v2 reads the v2 config velaux already had, so it reports
what 1.60 never could: 43 findings, about half already on main. Repeated
strings become constants named for what they are (datastore sort and
filter keys, the permission templates' scopes, effect, actions and View
permission names, the definition type and data-flow kind "source"), or
the existing ones where they mean the same (the expression type kinds).
Three WriteString(fmt.Sprintf) become fmt.Fprintf, and DefinitionBase's
deprecation notice gets its own paragraph; VelaUX still fills that
field for clients that read it, marked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7yvmmhDdoDfVVe4b5EpYY
Signed-off-by: Brian Kane <briankane1@gmail.com>
A workflow step or step group with forEach runs once per item. VelaUX
dropped forEach when it copied steps, and drew a loop's passes as
nothing it knew. It now keeps forEach everywhere, records each loop's
items and passes on the run, and edits and shows loops.

- Sync, deploy and the API keep forEach. A loop's run record starts with
  no sub-steps and takes its passes from the status, each with the item
  it ran for (the engine's IterationIndex) and the alias of the body
  step it repeats; the items, and a keyed loop's labels, come from the
  workflow context. A pipeline run carries the same per loop, and no
  longer pads a loop with its body.
- Studio: Loop in the Add menu, Repeat on a card, a loop strip with its
  items and mode. The wizard gains an Items stage: a list typed in (a
  table or YAML), an earlier step's output, or, in an application, a $( )
  expression; one item at a time or all at once; and a key naming each
  item, checked against typed-in items as the controller checks it.
  Steps in a loop are offered each.item, each.index, each.key and each
  item key as inputs.
- Run view: a loop is a stacked card, a segment per item when closed and
  a lane per item when open, labelled by the item or its key, with
  Approve on a waiting pass. The same on the pipeline run page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7yvmmhDdoDfVVe4b5EpYY
Signed-off-by: Brian Kane <briankane1@gmail.com>
@briankane
briankane force-pushed the stack/23-workflow-loops branch from cf33c7e to 8144d61 Compare October 16, 2026 16:42
@briankane
briankane merged commit eca7137 into main Oct 16, 2026
11 checks passed
@briankane
briankane deleted the stack/23-workflow-loops branch October 16, 2026 17:47
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.

2 participants