Skip to content

Commit

Permalink
fix: never repeat current stage in CI mode
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Oct 24, 2024
1 parent 81529c6 commit 05f9ecd
Showing 1 changed file with 27 additions and 28 deletions.
55 changes: 27 additions & 28 deletions src/multi-stage-output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,14 @@ export type MultiStageOutputOptions<T extends Record<string, unknown>> = {
}

class CIMultiStageOutput<T extends Record<string, unknown>> {
private readonly completedStages: Set<string> = new Set()
private data?: Partial<T>
private readonly design: RequiredDesign
private readonly hasElapsedTime?: boolean
private readonly hasStageTime?: boolean
private lastUpdateTime: number
private readonly messageTimeout = Number.parseInt(env.SF_CI_MESSAGE_TIMEOUT ?? '5000', 10) ?? 5000
private readonly postStagesBlock?: InfoBlock<T>
private readonly preStagesBlock?: InfoBlock<T>
private readonly seenInfo: Set<string> = new Set()
private readonly seenStages: Set<string> = new Set()
private readonly stages: readonly string[] | string[]
private readonly stageSpecificBlock?: StageInfoBlock<T>
private readonly startTime: number | undefined
Expand Down Expand Up @@ -134,7 +132,6 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
this.stageSpecificBlock = stageSpecificBlock
this.timerUnit = timerUnit ?? 'ms'
this.data = data
this.lastUpdateTime = Date.now()

if (title) ux.stdout(`───── ${title} ─────`)
ux.stdout('Stages:')
Expand All @@ -152,8 +149,8 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
public stop(stageTracker: StageTracker): void {
this.update(stageTracker)
ux.stdout()
this.printInfo(this.preStagesBlock, 0, true)
this.printInfo(this.postStagesBlock, 0, true)
this.maybePrintInfo(this.preStagesBlock, 0, true)
this.maybePrintInfo(this.postStagesBlock, 0, true)
if (this.startTime) {
const elapsedTime = Date.now() - this.startTime
ux.stdout()
Expand All @@ -167,7 +164,7 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {

for (const [stage, status] of stageTracker.entries()) {
// no need to re-render completed, failed, or skipped stages
if (this.seenStages.has(stage)) continue
if (this.completedStages.has(stage)) continue

switch (status) {
case 'pending': {
Expand All @@ -177,15 +174,13 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {

case 'current': {
if (!this.startTimes.has(stage)) this.startTimes.set(stage, Date.now())
if (Date.now() - this.lastUpdateTime < this.messageTimeout) break
this.lastUpdateTime = Date.now()
ux.stdout(`${this.design.icons.current.figure} ${stage}…`)
this.printInfo(this.preStagesBlock, 3)
this.printInfo(
this.maybeStdout(`${this.design.icons.current.figure} ${stage}…`)
this.maybePrintInfo(this.preStagesBlock, 3)
this.maybePrintInfo(
this.stageSpecificBlock?.filter((info) => info.stage === stage),
3,
)
this.printInfo(this.postStagesBlock, 3)
this.maybePrintInfo(this.postStagesBlock, 3)
break
}

Expand All @@ -196,28 +191,28 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
case 'async':
case 'warning':
case 'completed': {
this.seenStages.add(stage)
this.completedStages.add(stage)
if (this.hasStageTime && status !== 'skipped') {
const startTime = this.startTimes.get(stage)
const elapsedTime = startTime ? Date.now() - startTime : 0
const displayTime = readableTime(elapsedTime, this.timerUnit)
ux.stdout(`${this.design.icons[status].figure} ${stage} (${displayTime})`)
this.printInfo(this.preStagesBlock, 3)
this.printInfo(
this.maybeStdout(`${this.design.icons[status].figure} ${stage} (${displayTime})`)
this.maybePrintInfo(this.preStagesBlock, 3)
this.maybePrintInfo(
this.stageSpecificBlock?.filter((info) => info.stage === stage),
3,
)
this.printInfo(this.postStagesBlock, 3)
this.maybePrintInfo(this.postStagesBlock, 3)
} else if (status === 'skipped') {
ux.stdout(`${this.design.icons[status].figure} ${stage} - Skipped`)
this.maybeStdout(`${this.design.icons[status].figure} ${stage} - Skipped`)
} else {
ux.stdout(`${this.design.icons[status].figure} ${stage}`)
this.printInfo(this.preStagesBlock, 3)
this.printInfo(
this.maybeStdout(`${this.design.icons[status].figure} ${stage}`)
this.maybePrintInfo(this.preStagesBlock, 3)
this.maybePrintInfo(
this.stageSpecificBlock?.filter((info) => info.stage === stage),
3,
)
this.printInfo(this.postStagesBlock, 3)
this.maybePrintInfo(this.postStagesBlock, 3)
}

break
Expand All @@ -229,19 +224,23 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
}
}

private printInfo(infoBlock: InfoBlock<T> | StageInfoBlock<T> | undefined, indent = 0, force = false): void {
const spaces = ' '.repeat(indent)
private maybePrintInfo(infoBlock: InfoBlock<T> | StageInfoBlock<T> | undefined, indent = 0, force = false): void {
if (infoBlock?.length) {
for (const info of infoBlock) {
const formattedData = info.get ? info.get(this.data as T) : undefined
if (!formattedData) continue
const str = info.type === 'message' ? formattedData : `${info.label}: ${formattedData}`
if (!force && this.seenInfo.has(str)) continue
ux.stdout(`${spaces}${str}`)
this.seenInfo.add(str)
this.maybeStdout(str, indent, force)
}
}
}

private maybeStdout(str: string, indent = 0, force = false): void {
const spaces = ' '.repeat(indent)
if (!force && this.seenInfo.has(str)) return
ux.stdout(`${spaces}${str}`)
this.seenInfo.add(str)
}
}

class MultiStageOutputBase<T extends Record<string, unknown>> implements Disposable {
Expand Down

0 comments on commit 05f9ecd

Please sign in to comment.