Skip to content

feat: add step facts for named values and links - #17

Merged
piekstra merged 2 commits into
mainfrom
piekstra/step-facts
Oct 26, 2026
Merged

piekstra merged 2 commits into
mainfrom
piekstra/step-facts

Conversation

@piekstra

@piekstra piekstra commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

What

A step can declare facts: named values and links that tell the reader what the step created or touched, such as a record id and a link to it in another app.

- id: create_order
  run: ./create-order.sh
  outputs: { id: self.json.id }
  facts:
    - label: Order
      value: ${{ self.outputs.id }}
      href: https://shop.example.com/admin/orders/${{ self.outputs.id }}
  • Spec: facts: [{label, value?, href?}] on any step. A fact needs a value, an href, or both. Templates may use self, like artifacts.
  • Runner: evaluated in finish_step after the step runs, whatever its result, and skipped with the step. Values and links are redacted. A link that resolves to anything other than http or https is dropped with a warning while the value is kept.
  • Validation: label required, value or href required, templates checked with self in scope. A literal href that is not http or https is an error.
  • Report: a new facts list on the step report. artifacts stays file-only, so lest bundle and other file consumers are unchanged. Both lest schema flow and lest schema report include it.
  • CLI: lest run prints label: value href under the finished step.
  • UI: the step's Artifacts tab and the run's side panel show facts above the files. Links open in a new tab with rel="noopener noreferrer". Steps that declare only facts now appear in the side panel.

Why a separate field instead of value artifacts

Making artifacts entries polymorphic (path or value or link) would make the report's Artifact fields optional and every file consumer (bundle, the artifact grid, demo video lookup) would need to branch. A separate facts list keeps both shapes strict.

Testing

  • make check: lint, typecheck, UI tests (43) and build pass. In the full cargo test, parallel_group_runs_concurrently and cancel_stops_steps_but_runs_finally_and_cleanup fail when the machine is under heavy load (load average 15 to 20 during this run). They fail the same way on unmodified main under that load and pass when run alone on this branch.
  • New tests: runner (values, links, redaction, non-web link dropped with a warning, skipped step has none), validation (missing value and href, bad scheme, secrets and forward references rejected), CLI line format, UI side-panel grouping for a facts-only step.
  • Ran a sample flow with the release binary; lest run printed Order: 42 https://shop.example.com/orders/42 and the report carried the fact.

A step can declare facts: a label with a value, an http(s) link, or both, evaluated after the step runs with self in scope. They are redacted, recorded on the step report, printed under the step by lest run and shown with the step's artifacts in the app.
@piekstra

Copy link
Copy Markdown
Member Author

Review of the diff (self-review; a separate review agent was not available in this run), with dispositions:

  • Empty value rendered as an empty link (RunView.tsx FactList): a value that interpolates to "" used ??, so the link had no text. Fixed in 4cfc3a0 (|| falls back to the href).
  • Facts on resumed runs (runner/mod.rs seeding with --from): earlier steps are seeded from the previous report wholesale (prev.clone()), so their facts carry over. No change needed.
  • Facts on a failed step whose outputs did not parse: the fact's template fails and becomes a run warning naming the fact, the same way a failing artifact path does. Kept: the warning tells the author the fact could not be built, and the result is unaffected.
  • Secrets in facts: validation rejects secrets.* in facts (facts use the non-secret scope, like artifacts), and resolved values are passed through the redactor in case an output carries one. No change needed.
  • Facts in agent context, JUnit properties and lest explain: not added. They are not needed for the fact to be visible in the report, CLI and app; left out of this PR to keep it to one capability.

@piekstra piekstra closed this Oct 26, 2026
@piekstra piekstra reopened this Oct 26, 2026
@piekstra
piekstra marked this pull request as ready for review October 26, 2026 17:38
@piekstra
piekstra merged commit 0ade497 into main Oct 26, 2026
9 of 10 checks passed
@piekstra
piekstra deleted the piekstra/step-facts branch October 26, 2026 17:39
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