feat: link the original run from replayed runs (#2262)

* Add ID of the replayedFrom run to the TaskRun schema

* Propagate the replayedFrom run ID in the replay flow

* Link the replayed run in the run details pane
This commit is contained in:
Saadi Myftija
2025-07-14 16:57:54 +02:00
committed by GitHub
parent 630e9556b0
commit b78b3dceb2
10 changed files with 27 additions and 0 deletions
@@ -218,6 +218,7 @@ export class SpanPresenter extends BasePresenter {
friendlyId: true,
},
},
replayedFromTaskRunFriendlyId: true,
},
where: span.originalRun
? {
@@ -331,6 +332,7 @@ export class SpanPresenter extends BasePresenter {
runtime: run.lockedToVersion?.runtime,
runtimeVersion: run.lockedToVersion?.runtimeVersion,
isTest: run.isTest,
replayedFromTaskRunFriendlyId: run.replayedFromTaskRunFriendlyId,
environmentId: run.runtimeEnvironment.id,
idempotencyKey: run.idempotencyKey,
idempotencyKeyExpiresAt: run.idempotencyKeyExpiresAt,
@@ -63,6 +63,7 @@ import {
v3DeploymentVersionPath,
v3RunDownloadLogsPath,
v3RunPath,
v3RunRedirectPath,
v3RunSpanPath,
v3RunsPath,
v3SchedulePath,
@@ -592,6 +593,20 @@ function RunBody({
{run.isTest ? <CheckIcon className="size-4 text-text-dimmed" /> : ""}
</Property.Value>
</Property.Item>
{run.replayedFromTaskRunFriendlyId && (
<Property.Item>
<Property.Label>Replayed from</Property.Label>
<Property.Value>
<TextLink
to={v3RunRedirectPath(organization, project, {
friendlyId: run.replayedFromTaskRunFriendlyId,
})}
>
{run.replayedFromTaskRunFriendlyId}
</TextLink>
</Property.Value>
</Property.Item>
)}
{environment && (
<Property.Item>
<Property.Label>Environment</Property.Label>
@@ -264,6 +264,7 @@ export class RunEngineTriggerTaskService {
spanId: event.spanId,
parentSpanId:
options.parentAsLinkType === "replay" ? undefined : event.traceparent?.spanId,
replayedFromTaskRunFriendlyId: options.replayedFromTaskRunFriendlyId,
lockedToVersionId: lockedToBackgroundWorker?.id,
taskVersion: lockedToBackgroundWorker?.version,
sdkVersion: lockedToBackgroundWorker?.sdkVersion,
@@ -87,6 +87,7 @@ export class ReplayTaskRunService extends BaseService {
{
spanParentAsLink: true,
parentAsLinkType: "replay",
replayedFromTaskRunFriendlyId: existingTaskRun.friendlyId,
traceContext: {
traceparent: `00-${existingTaskRun.traceId}-${existingTaskRun.spanId}-01`,
},
@@ -33,6 +33,7 @@ export type TriggerTaskServiceOptions = {
scheduleInstanceId?: string;
queueTimestamp?: Date;
overrideCreatedAt?: Date;
replayedFromTaskRunFriendlyId?: string;
};
export class OutOfEntitlementError extends Error {
@@ -427,6 +427,7 @@ export class TriggerTaskServiceV1 extends BaseService {
parentAttempt?.taskRun.id ??
dependentBatchRun?.dependentTaskAttempt?.taskRun.rootTaskRunId ??
dependentBatchRun?.dependentTaskAttempt?.taskRun.id,
replayedFromTaskRunFriendlyId: options.replayedFromTaskRunFriendlyId,
batchId: dependentBatchRun?.id ?? parentBatchRun?.id,
resumeParentOnCompletion: !!(dependentAttempt ?? dependentBatchRun),
depth,
@@ -0,0 +1 @@
ALTER TABLE "TaskRun" ADD COLUMN "replayedFromTaskRunFriendlyId" TEXT;
@@ -648,6 +648,8 @@ model TaskRun {
logsDeletedAt DateTime?
replayedFromTaskRunFriendlyId String?
/// This represents the original task that that was triggered outside of a Trigger.dev task
rootTaskRun TaskRun? @relation("TaskRootRun", fields: [rootTaskRunId], references: [id], onDelete: SetNull, onUpdate: NoAction)
rootTaskRunId String?
@@ -372,6 +372,7 @@ export class RunEngine {
tags,
parentTaskRunId,
rootTaskRunId,
replayedFromTaskRunFriendlyId,
batch,
resumeParentOnCompletion,
depth,
@@ -451,6 +452,7 @@ export class RunEngine {
oneTimeUseToken,
parentTaskRunId,
rootTaskRunId,
replayedFromTaskRunFriendlyId,
batchId: batch?.id,
resumeParentOnCompletion,
depth,
@@ -126,6 +126,7 @@ export type TriggerParams = {
tags: { id: string; name: string }[];
parentTaskRunId?: string;
rootTaskRunId?: string;
replayedFromTaskRunFriendlyId?: string;
batch?: {
id: string;
index: number;