Skip to content

Commit eba7df3

Browse files
[cli] Fix false "data expired" warning in CLI for non-expired runs (#1736)
* fix cli expiredAt check * fix cli expiredAt check * fix cli expiredAt check
1 parent ac09f40 commit eba7df3

3 files changed

Lines changed: 80 additions & 6 deletions

File tree

.changeset/many-peas-jog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@workflow/cli": patch
3+
---
4+
5+
Fix false "data expired" warning for runs with future expiredAt
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { describe, expect, it } from 'vitest';
2+
import type { WorkflowRun } from '@workflow/world';
3+
import { formatTableValue, hasExpiredData } from './output.js';
4+
5+
const makeRun = (overrides: Partial<WorkflowRun> = {}): WorkflowRun =>
6+
({
7+
runId: 'run-1',
8+
status: 'running',
9+
deploymentId: 'dep-1',
10+
workflowName: 'workflow//./src/workflows/test//myWorkflow',
11+
input: undefined,
12+
output: undefined,
13+
error: undefined,
14+
createdAt: new Date('2025-01-01'),
15+
updatedAt: new Date('2025-01-01'),
16+
completedAt: undefined,
17+
startedAt: undefined,
18+
expiredAt: undefined,
19+
specVersion: 2,
20+
executionContext: {},
21+
...overrides,
22+
}) as unknown as WorkflowRun;
23+
24+
describe('hasExpiredData', () => {
25+
it('returns false when expiredAt is undefined', () => {
26+
expect(hasExpiredData(makeRun({ expiredAt: undefined }))).toBe(false);
27+
});
28+
29+
it('returns false when expiredAt is in the future', () => {
30+
const future = new Date(Date.now() + 24 * 60 * 60 * 1000);
31+
expect(hasExpiredData(makeRun({ expiredAt: future }))).toBe(false);
32+
});
33+
34+
it('returns true when expiredAt is in the past', () => {
35+
const past = new Date(Date.now() - 24 * 60 * 60 * 1000);
36+
expect(hasExpiredData(makeRun({ expiredAt: past }))).toBe(true);
37+
});
38+
});
39+
40+
describe('formatTableValue expired data handling', () => {
41+
it('returns input value when expiredAt is in the future', () => {
42+
const future = new Date(Date.now() + 24 * 60 * 60 * 1000);
43+
const item = { expiredAt: future.toISOString(), input: 'hello' };
44+
const result = formatTableValue('input', 'hello', {}, undefined, item);
45+
expect(result).not.toContain('expired');
46+
});
47+
48+
it('returns expired message when expiredAt is in the past', () => {
49+
const past = new Date(Date.now() - 24 * 60 * 60 * 1000);
50+
const item = { expiredAt: past.toISOString(), output: 'hello' };
51+
const result = formatTableValue('output', 'hello', {}, undefined, item);
52+
expect(String(result)).toContain('data expired');
53+
});
54+
55+
it('returns input value when expiredAt is not present', () => {
56+
const item = { input: 'hello' };
57+
const result = formatTableValue('input', 'hello', {}, undefined, item);
58+
expect(String(result)).not.toContain('expired');
59+
});
60+
});

packages/cli/src/lib/inspect/output.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ const formatIdField = (
276276
return idStr;
277277
};
278278

279-
const formatTableValue = (
279+
export const formatTableValue = (
280280
prop: string,
281281
value: unknown,
282282
opts: InspectCLIOptions = {},
@@ -318,8 +318,12 @@ const formatTableValue = (
318318
}
319319

320320
if (prop === 'output' || prop === 'input' || prop === 'error') {
321-
// Check if data has expired
322-
if (item && 'expiredAt' in item && item.expiredAt != null) {
321+
if (
322+
item &&
323+
'expiredAt' in item &&
324+
item.expiredAt != null &&
325+
new Date(item.expiredAt as string | number | Date) < new Date()
326+
) {
323327
return EXPIRED_DATA_MESSAGE;
324328
}
325329
return inlineFormatIO(value);
@@ -490,10 +494,15 @@ const showInspectInfoBox = (resource: string) => {
490494
const EXPIRED_DATA_MESSAGE = chalk.gray('<data expired>');
491495

492496
/**
493-
* Checks if a run has expired data storage (run-level expiredAt field)
497+
* Checks if a run has expired data storage (run-level expiredAt field).
498+
* Only returns true when `expiredAt` is in the past.
494499
*/
495-
const hasExpiredData = (run: WorkflowRun): boolean => {
496-
return 'expiredAt' in run && run.expiredAt != null;
500+
export const hasExpiredData = (run: WorkflowRun): boolean => {
501+
return (
502+
'expiredAt' in run &&
503+
run.expiredAt != null &&
504+
new Date(run.expiredAt) < new Date()
505+
);
497506
};
498507

499508
/**

0 commit comments

Comments
 (0)