feat: dynamic display_name for triggered runs (#4259)#4375
Open
Mdev303 wants to merge 8 commits into
Open
Conversation
Let callers set a human-readable label on a run at trigger time, so fanned-out child/bulk runs are distinguishable in the dashboard instead of all sharing the generated <readableId>-<timestamp> name. Engine (pkg/repository): - NormalizeDisplayName: trim; empty/whitespace -> unset (generated fallback); truncate to 255 runes (UTF-8/rune-safe). Applied at both SDK and REST ingestion. - Single-task runs -> v1_task.display_name; multi-step DAGs -> v1_dag.display_name (DAG step tasks keep generated names). Excluded from all dedup/idempotency keys, so durable/child re-triggers reuse the first name (first-name-wins). REST: display_name on the trigger endpoint + admin-path normalization. Proto/OpenAPI: display_name added (trigger.proto hatchet-dev#11, workflows.proto hatchet-dev#6) + regen. SDKs (Python, TypeScript, Go, Ruby): display_name on every run surface (run / run_no_wait / aio variants, bulk & run_many per-item, child spawns). Python: carried through _create_workflow_run_request so the value actually reaches gRPC on the real run path. Docs: new "Run Names" guide + cross-links; CHANGELOG entry. Tests: engine unit (NormalizeDisplayName, idempotency-key invariance) + integration (single/DAG/fallback/whitespace/255-rune/run_many/first-name-wins), REST handler, and per-SDK request-builder tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@Mdev303 is attempting to deploy a commit to the Hatchet Team on Vercel. A member of the Team first needs to authorize it. |
Resolve conflicts for hatchet-dev#4375 (dynamic display_name for triggered runs): - workflow_run.yaml: keep both new fields (displayName + return_only_id). - openapi.gen.go: regenerated from merged spec (embedded swagger blob + DisplayName type). - data-contracts.ts: keep both displayName and return_only_id. - 12 *.pb.go: take main's protoc v5.29.6 header, keep merged body (display_name intact). - CHANGELOG.md / sdks/python/CHANGELOG.md: keep both Unreleased entries + main's releases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ay_name) - Run prettier over condition.ts / timestamp.ts, which were regenerated with protoc v7.35.1 (double quotes) but missed the prettier:fix pass, unlike the other v7.35.1-regenerated protoc files. Fixes prettier:check. - Document the new `display_name` param in the 9 run/run_no_wait/create_bulk_run_item docstrings. Fixes pydoclint DOC101/DOC103. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Revert condition.ts / timestamp.ts to origin/main: their only changes were unrelated protoc v3.19.1->v7.35.1 regeneration churn, not part of the display_name feature. Reverting keeps the PR to just the files that must change (trigger.ts / workflows.ts). Verified tsc + lint:check still pass. - Prettier-fix the child-spawning.mdx Callout block added by this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Let callers set a human-readable label on a run at trigger time, so fanned-out child/bulk runs are distinguishable in the dashboard instead of all sharing the generated
<readableId>-<timestamp>name.Engine (
pkg/repository):NormalizeDisplayName: trim; empty/whitespace → unset (generated fallback); truncate to 255 runes (UTF-8/rune-safe). Applied at both SDK and REST ingestion.v1_task.display_name; multi-step DAGs →v1_dag.display_name(DAG step tasks keep generated names). Excluded from all dedup/idempotency keys, so durable/child re-triggers reuse the first name (first-name-wins).REST:
display_nameon the trigger endpoint + admin-path normalization.Proto/OpenAPI:
display_nameadded (trigger.proto#11,workflows.proto#6) + regen.SDKs (Python, TypeScript, Go, Ruby):
display_nameon every run surface (run / run_no_wait / aio variants, bulk & run_many per-item, child spawns). Python: carried through_create_workflow_run_requestso the value actually reaches gRPC on the real run path.Docs: new "Run Names" guide + cross-links; CHANGELOG entries (root + per-SDK).
Description
Adds a dynamic
display_nameto triggered runs. Today, when a parent fans out many child runs in one batch they all render as the identical<readableId>-<timestamp>(same step id, same batch timestamp), forcing you to open each run's input to tell them apart. This lets the caller set a human-readable label at trigger time that the dashboard renders automatically in the runs list, run-detail header, and children list — no frontend change required (the read side already returnsdisplayName).Design spec:
.context/2026-07-07-dynamic-run-display-name-design.md.Fixes #4259
Usage
Same call for single-task and DAG workflows; the engine routes the name (single →
v1_task, DAG →v1_dag). Arrayrun([...], opts)shares one name across the batch — userunMany/run_manyfor distinct per-item names. Not applied to scheduled/cron runs.TypeScript —
displayNameonRunOpts:Python — direct
display_namekwarg:Design decisions & trade-offs
{{ input.company }}-style expressions are a separate, heavier feature deferred for now.display_nameonly changes the display label;step_readable_idand the generated-fallback logic are unchanged.display_nameis silently ignored and does not raiseNonDeterminismError. Editing a cosmetic label must never break a durable run ("first-name-wins").v1_task.display_name/v1_dag.display_namecolumns.display_name(metadata filtering already covers search).Two implementation-time decisions worth calling out:
sdks/gousesWithRunDisplayName(matching itsWithRun*convention) whilepkg/clientusesWithDisplayName(matching itsWithPriority).display_nameis a first-class keyword on every run surface (theoptions=object still works but emits a deprecation warning), and it is threaded through_create_workflow_run_requestso it reaches gRPC on the realrun/run_many/child-spawn path — an adversarial review caught that an earlier version dropped it there.Type of change
Backward compatible: the field is optional; omitting it reproduces today's exact generated-name behavior.
What's Changed
NormalizeDisplayName+ threading throughTriggerTaskData→triggerTuple→createDAGOpts/CreateTaskOpts; single-task →v1_task, DAG →v1_dag.trigger.protoFeat: introduce a scheduling state #11,workflows.protochore(contributing): adapt deps, hardcode generator versions #6) + OpenAPIdisplayName, generated code regenerated.display_name/displayNameon every run surface (run/run_no_wait/aio, bulk & per-item run_many, child spawns).Checklist
Changes have been:
Tested — engine unit (
NormalizeDisplayName, idempotency-key invariance) + integration (single/DAG/fallback/whitespace/255-rune/run_many/first-name-wins), REST handler, per-SDK request-builder tests, plus live end-to-end smoke tests against an engine built from this branch (Python + TypeScript): named top-level runs, per-itemrun_manynames, a named DAG with generated step names, and whitespace→fallback — all read back through the REST API.Linted and formatted
Documented (Run Names guide + cross-links)
Added to CHANGELOG (root + per-SDK) — see Keep a Changelog
I tested manually the the TS and python SDK but not the others.
🤖 AI Disclosure
I acknowledge that an LLM was used in the creation of this Pull Request, in accordance with Hatchet's AI_POLICY.md.
Details: Implemented with Claude Code (Claude Opus 4.8) — engine/SDK/REST implementation, unit + integration + per-SDK tests, docs, changelog entries, an adversarial review pass (which caught the Python gRPC-dropping bug), live e2e smoke verification, and drafting this PR. All changes were run and verified locally.