fix: restore watcher elapsed status updates
This commit is contained in:
@@ -134,18 +134,48 @@ Check the run.
|
|||||||
} as any,
|
} as any,
|
||||||
phase: 'waiting',
|
phase: 'waiting',
|
||||||
checkedAt: '2026-03-19T07:02:10.000Z',
|
checkedAt: '2026-03-19T07:02:10.000Z',
|
||||||
|
statusStartedAt: '2026-03-19T07:00:00.000Z',
|
||||||
nextRun: '2026-03-19T07:04:10.000Z',
|
nextRun: '2026-03-19T07:04:10.000Z',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(rendered).toContain('CI 감시 중: GitHub Actions run 123456');
|
expect(rendered).toContain('CI 감시 중: GitHub Actions run 123456');
|
||||||
expect(rendered).toContain('- 상태: 대기 중');
|
expect(rendered).toContain('- 상태: 대기 중');
|
||||||
expect(rendered).toContain('- 마지막 확인: 16시 02분 10초');
|
expect(rendered).toContain('- 마지막 확인: 16시 02분 10초');
|
||||||
|
expect(rendered).toContain('- 경과 시간: 2분 10초');
|
||||||
expect(rendered).toContain('- 확인 간격: 1분');
|
expect(rendered).toContain('- 확인 간격: 1분');
|
||||||
expect(rendered).toContain('- 다음 확인: 16시 04분 10초');
|
expect(rendered).toContain('- 다음 확인: 16시 04분 10초');
|
||||||
expect(rendered).not.toContain('16:02:10');
|
expect(rendered).not.toContain('16:02:10');
|
||||||
expect(rendered).not.toContain('16:04:10');
|
expect(rendered).not.toContain('16:04:10');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('omits watcher elapsed time when tracking has not started yet', () => {
|
||||||
|
const prompt = `
|
||||||
|
[BACKGROUND CI WATCH]
|
||||||
|
|
||||||
|
Watch target:
|
||||||
|
GitHub Actions run 123456
|
||||||
|
|
||||||
|
Task ID:
|
||||||
|
task-123
|
||||||
|
|
||||||
|
Check instructions:
|
||||||
|
Check the run.
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
const rendered = renderWatchCiStatusMessage({
|
||||||
|
task: {
|
||||||
|
prompt,
|
||||||
|
schedule_type: 'interval',
|
||||||
|
schedule_value: '60000',
|
||||||
|
} as any,
|
||||||
|
phase: 'checking',
|
||||||
|
checkedAt: '2026-03-19T07:02:10.000Z',
|
||||||
|
statusStartedAt: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(rendered).not.toContain('- 경과 시간:');
|
||||||
|
});
|
||||||
|
|
||||||
it('computeNextRun anchors interval tasks to scheduled time to prevent drift', () => {
|
it('computeNextRun anchors interval tasks to scheduled time to prevent drift', () => {
|
||||||
const scheduledTime = new Date(Date.now() - 2000).toISOString(); // 2s ago
|
const scheduledTime = new Date(Date.now() - 2000).toISOString(); // 2s ago
|
||||||
const task = {
|
const task = {
|
||||||
|
|||||||
@@ -140,10 +140,28 @@ function formatWatchIntervalLabel(
|
|||||||
return minutes > 0 ? `${hours}시간 ${minutes}분` : `${hours}시간`;
|
return minutes > 0 ? `${hours}시간 ${minutes}분` : `${hours}시간`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatElapsedLabel(startedAtIso: string, checkedAtIso: string): string {
|
||||||
|
const elapsedMs = Math.max(
|
||||||
|
0,
|
||||||
|
new Date(checkedAtIso).getTime() - new Date(startedAtIso).getTime(),
|
||||||
|
);
|
||||||
|
const totalSeconds = Math.floor(elapsedMs / 1000);
|
||||||
|
const hours = Math.floor(totalSeconds / 3600);
|
||||||
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||||
|
const seconds = totalSeconds % 60;
|
||||||
|
|
||||||
|
const parts: string[] = [];
|
||||||
|
if (hours > 0) parts.push(`${hours}시간`);
|
||||||
|
if (minutes > 0) parts.push(`${minutes}분`);
|
||||||
|
parts.push(`${seconds}초`);
|
||||||
|
return parts.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
export function renderWatchCiStatusMessage(args: {
|
export function renderWatchCiStatusMessage(args: {
|
||||||
task: Pick<ScheduledTask, 'prompt' | 'schedule_type' | 'schedule_value'>;
|
task: Pick<ScheduledTask, 'prompt' | 'schedule_type' | 'schedule_value'>;
|
||||||
phase: WatcherStatusPhase;
|
phase: WatcherStatusPhase;
|
||||||
checkedAt: string;
|
checkedAt: string;
|
||||||
|
statusStartedAt?: string | null;
|
||||||
nextRun?: string | null;
|
nextRun?: string | null;
|
||||||
}): string {
|
}): string {
|
||||||
const target = extractWatchCiTarget(args.task.prompt) || 'CI watcher';
|
const target = extractWatchCiTarget(args.task.prompt) || 'CI watcher';
|
||||||
@@ -165,6 +183,11 @@ export function renderWatchCiStatusMessage(args: {
|
|||||||
`- 상태: ${statusLabel}`,
|
`- 상태: ${statusLabel}`,
|
||||||
`- 마지막 확인: ${formatTimeLabel(args.checkedAt)}`,
|
`- 마지막 확인: ${formatTimeLabel(args.checkedAt)}`,
|
||||||
];
|
];
|
||||||
|
if (args.statusStartedAt) {
|
||||||
|
lines.push(
|
||||||
|
`- 경과 시간: ${formatElapsedLabel(args.statusStartedAt, args.checkedAt)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
const intervalLabel = formatWatchIntervalLabel(args.task);
|
const intervalLabel = formatWatchIntervalLabel(args.task);
|
||||||
if (intervalLabel) {
|
if (intervalLabel) {
|
||||||
lines.push(`- 확인 간격: ${intervalLabel}`);
|
lines.push(`- 확인 간격: ${intervalLabel}`);
|
||||||
@@ -290,6 +313,7 @@ async function runTask(
|
|||||||
task,
|
task,
|
||||||
phase,
|
phase,
|
||||||
checkedAt,
|
checkedAt,
|
||||||
|
statusStartedAt,
|
||||||
nextRun,
|
nextRun,
|
||||||
});
|
});
|
||||||
const payload = `${TASK_STATUS_MESSAGE_PREFIX}${text}`;
|
const payload = `${TASK_STATUS_MESSAGE_PREFIX}${text}`;
|
||||||
|
|||||||
Reference in New Issue
Block a user