Public: anyone can read this; the crew can change it.
A preview serving with failed tests does not read green #482
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/118-a-preview-serving-with-failed-tests-does → main 1 commit fork
3 files
changed +42
−7
src/apps/runtime.ts +5 −1
| @@ -123,6 +123,10 @@ const SLEEP_AFTER_MS = { production: 24 * 3_600_000, preview: 30 * 60_000 }; | ||
| 123 | 123 | const SWEEP_EVERY_MS = 60_000; |
| 124 | 124 | const BUSY_GRACE_MS = 45 * 60_000; |
| 125 | 125 | |
| 126 | /** The sentence a serving environment carries while its tests still run; | |
| 127 | * the studio reads the same constant to word its badge. */ | |
| 128 | export const VERIFYING_NOTE = "serving — still verifying its tests"; | |
| 129 | ||
| 126 | 130 | export interface EnvStatus { |
| 127 | 131 | readonly env: EnvName; |
| 128 | 132 | readonly state: EnvState; |
| @@ -455,7 +459,7 @@ export class AppsRuntime { | ||
| 455 | 459 | ...(state.live.deployStartedAt === null |
| 456 | 460 | ? {} |
| 457 | 461 | : { deployStartedAt: state.live.deployStartedAt }), |
| 458 | ...(swapped ? { note: "serving — still verifying its tests" } : {}), | |
| 462 | ...(swapped ? { note: VERIFYING_NOTE } : {}), | |
| 459 | 463 | ...(state.live.testsFailed === undefined |
| 460 | 464 | ? {} |
| 461 | 465 | : { error: `serving · tests failed: ${state.live.testsFailed}` }), |
src/web/ui.ts +9 −6
| @@ -10,7 +10,7 @@ | ||
| 10 | 10 | * reaches for an inline `style` attribute, because the CSP forbids it. |
| 11 | 11 | */ |
| 12 | 12 | |
| 13 | import type { EnvState, EnvStatus } from "../apps/runtime.ts"; | |
| 13 | import { VERIFYING_NOTE, type EnvState, type EnvStatus } from "../apps/runtime.ts"; | |
| 14 | 14 | import type { PreviewData } from "../apps/data.ts"; |
| 15 | 15 | import type { RunKind, RunState } from "../core/runs.ts"; |
| 16 | 16 | import { icon, type IconName } from "./icons.ts"; |
| @@ -327,7 +327,9 @@ export function envTone(state: EnvState | undefined): Tone { | ||
| 327 | 327 | * it came up belongs to `envFacts`, which sits under this and says it once. |
| 328 | 328 | * |
| 329 | 329 | * A serving app is never called down because its tests are red: the words |
| 330 | * say the tests failed, the tone stays the tone of something that answers. | |
| 330 | * say the tests failed, and the tone is not green: it answers, but not | |
| 331 | * verified. While they still run it reads `serving · verifying`, neither | |
| 332 | * green nor failed. | |
| 331 | 333 | */ |
| 332 | 334 | export function envPhrase(env: EnvStatus | undefined): { |
| 333 | 335 | word: string; |
| @@ -342,10 +344,11 @@ export function envPhrase(env: EnvStatus | undefined): { | ||
| 342 | 344 | // behind it, so it is not plain green either. |
| 343 | 345 | if (env.failedDeploy !== undefined) |
| 344 | 346 | return { word: "live · a newer push failed", tone: "attn" }; |
| 345 | return { | |
| 346 | word: env.error === undefined ? "live" : "serving · tests failed", | |
| 347 | tone: "success", | |
| 348 | }; | |
| 347 | if (env.error !== undefined) | |
| 348 | return { word: "serving · tests failed", tone: "attn" }; | |
| 349 | if (env.note === VERIFYING_NOTE) | |
| 350 | return { word: "serving · verifying", tone: "default" }; | |
| 351 | return { word: "live", tone: "success" }; | |
| 349 | 352 | } |
| 350 | 353 | |
| 351 | 354 | export interface EnvFactsOptions { |
test/studio.test.ts +28
| @@ -3194,6 +3194,34 @@ describe("the app's live fragment: /:owner/:name/app/state", () => { | ||
| 3194 | 3194 | expect(red).toContain(runLink); |
| 3195 | 3195 | expect(red).toContain("serving · tests failed: 2 failing"); |
| 3196 | 3196 | expect(red).toContain("live 3.4s after the push"); |
| 3197 | // One badge, not green, and the row still links to the preview. | |
| 3198 | expect(red).toMatch(/data-variant="attn"[^]*?serving · tests failed<\/span/); | |
| 3199 | expect(red).not.toContain('data-variant="success"'); | |
| 3200 | expect(red).not.toContain(">live<"); | |
| 3201 | ||
| 3202 | putEnv(env, { | |
| 3203 | deploying: { | |
| 3204 | run: { id: deployRun.id, commitOid: pull.headOid }, | |
| 3205 | abort: new AbortController(), | |
| 3206 | }, | |
| 3207 | live: { | |
| 3208 | commitOid: pull.headOid, | |
| 3209 | handle: { port: 4324 }, | |
| 3210 | runId: deployRun.id, | |
| 3211 | since: servingAt, | |
| 3212 | servingAt, | |
| 3213 | createdAt, | |
| 3214 | deployStartedAt: createdAt, | |
| 3215 | manifest: { tty: null }, | |
| 3216 | }, | |
| 3217 | }); | |
| 3218 | const verifying = rowOf( | |
| 3219 | await (await get("/alice/vault/app/state", owner)).text(), | |
| 3220 | ); | |
| 3221 | expect(verifying).toContain(open); | |
| 3222 | expect(verifying).toContain("serving · verifying</span"); | |
| 3223 | expect(verifying).not.toContain('data-variant="success"'); | |
| 3224 | expect(verifying).not.toContain('data-variant="attn"'); | |
| 3197 | 3225 | |
| 3198 | 3226 | putEnv(env, { |
| 3199 | 3227 | live: { |
new above
offline