OXYGENHUB

Coverage / src/flowview.ts 91.8%

90 of 98 lines run, 10 of 10 functions, 32 of 40 branches · run #23 on main · run missed

10×
// OxygenFlow in the editor, without VS Code: how runs and jobs look (icon,
20×
// colour, labels) and which runs just finished. Shared by the Flow view, the
30×
// status bar item and the tests.
41×
5
import type { FlowRun } from "./hubapi";
61×
70×
/** A codicon and a theme colour id for a run's or job's status. */
8
export interface Look {
9
  /** Codicon id; `~spin` makes it turn. */
10
  icon: string;
11
  /** A theme colour id, e.g. `testing.iconPassed`. */
12
  color: string;
13
  /** A short word for screen readers and tooltips. */
14
  word: string;
15
}
161×
176×
export function look(status: string): Look {
186×
  switch (status) {
196×
    case "passed":
206×
      return { icon: "pass-filled", color: "testing.iconPassed", word: "passed" };
216×
    case "failed":
226×
      return { icon: "error", color: "testing.iconFailed", word: "failed" };
236×
    case "error":
246×
      return { icon: "warning", color: "testing.iconErrored", word: "could not run" };
256×
    case "running":
266×
      return { icon: "sync~spin", color: "oxygenhub.flowRunning", word: "running" };
276×
    case "queued":
286×
      return { icon: "clock", color: "testing.iconQueued", word: "queued" };
296×
    case "skipped":
306×
      return { icon: "debug-step-over", color: "testing.iconSkipped", word: "skipped" };
316×
    default:
326×
      return { icon: "circle-large-outline", color: "descriptionForeground", word: status };
336×
  }
346×
}
351×
361×
export function live(status: string): boolean {
378×
  return status === "queued" || status === "running";
382×
}
392×
402×
/** "3.2 s", "4 min 10 s". */
412×
export function duration(ms: number): string {
422×
  const s = Math.max(0, ms) / 1000;
432×
  if (s < 60) {
441×
    return `${s.toFixed(1)} s`;
451×
  }
462×
  return `${Math.floor(s / 60)} min ${Math.floor(s % 60)} s`;
472×
}
481×
491×
/** "just now", "5 minutes ago", as the hub says it. */
501×
export function ago(ms: number, now = Date.now()): string {
513×
  const s = Math.max(0, Math.floor((now - ms) / 1000));
523×
  const unit = (n: number, w: string) => `${n} ${w}${n === 1 ? "" : "s"} ago`;
533×
  if (s < 45) {
541×
    return "just now";
551×
  }
563×
  if (s < 90) {
570×
    return "a minute ago";
580×
  }
593×
  if (s < 2700) {
601×
    return unit(Math.ceil(s / 60), "minute");
611×
  }
623×
  if (s < 5400) {
630×
    return "an hour ago";
640×
  }
651×
  if (s < 79200) {
661×
    return unit(Math.ceil(s / 3600), "hour");
671×
  }
683×
  return unit(Math.ceil(s / 86400), "day");
693×
}
701×
711×
/** What a run ran on: its bookmark, or the change for a run on one change. */
721×
export function subject(run: FlowRun): string {
732×
  return run.bookmark || `change ${(run.heads[0] ?? "").slice(0, 12)}`;
742×
}
752×
762×
/** "#12 main". */
772×
export function runLabel(run: FlowRun): string {
782×
  return `#${run.number} ${subject(run)}`;
792×
}
802×
812×
/** "passed in 2 min 3 s · push by andy · 5 minutes ago". */
822×
export function runDescription(run: FlowRun, now = Date.now()): string {
832×
  const took = run.finished_ms ? ` in ${duration(run.finished_ms - run.created_ms)}` : "";
842×
  const queued = run.status === "queued" && run.queue_position ? ` (#${run.queue_position} in line)` : "";
852×
  const trigger = run.trigger.startsWith("rerun:") ? `re-run of #${run.trigger.slice(6)}` : run.trigger;
862×
  return `${look(run.status).word}${took}${queued} · ${trigger} by ${run.actor} · ${ago(run.created_ms, now)}`;
872×
}
881×
891×
/**
901×
 * Runs that were live at the last look and are finished now, so the editor
911×
 * can say so once. `before` maps a run's key to its last status.
921×
 */
931×
export function newlyFinished(before: Map<string, string>, runs: { key: string; run: FlowRun }[]): { key: string; run: FlowRun }[] {
941×
  return runs.filter(({ key, run }) => {
954×
    const was = before.get(key);
964×
    return was !== undefined && live(was) && !live(run.status);
971×
  });
981×
}