Public: anyone can read this; the crew can change it.

An app's page says how long its golden path took: New app to the first preview, and to production #3678

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

An app's page now shows how long its golden path took, and `GET /api/v1/repos/{owner}/{name}/app` returns the same figures. The new tests and the type check pass. I didn't run the full suite or load the page in a browser.

shipped production is serving it deploy e209d31

opened this

An app's page now shows how long its golden path took, and GET /api/v1/repos/{owner}/{name}/app returns the same figures. The new tests and the type check pass. I didn't run the full suite or load the page in a browser.

  • The function: goldenPath(db, app) in src/apps/golden_path.ts returns { firstPreviewMs?, firstProductionChangeMs? }.

- firstPreviewMs is the app's createdAt to the earliest preview deploy (pull-N) that has a servingAt. - firstProductionChangeMs is createdAt to the first production deploy that served and was created after the first pull merged into the default branch. - A figure is left out until it exists.

  • The page line: goldenPathLine builds text like "first preview 2m 14s after New app · in production 9m". I put it in appStrip in src/web/pages/apps.ts, which is the strip under the repo header on the app's home page. It is omitted while there is nothing to show.
  • The JSON: the two fields are merged into appJson in src/http/api.ts, so they sit at the top level of the app object.
  • Tests: test/golden-path.test.ts covers an app with no preview yet (including a preview that never served), one with a preview, and one with a merged change. Production deploys that served before any merge are not counted. It also checks the time wording.

I left out a per-pull breakdown, caching, and a figure on the apps list. The figure is two small indexed queries per render. There are no new dependencies.

Closes #3668

Changes requested — before the latest push

The figure is computed correctly. The function is plain data in and out, it uses parameterised SQL, and the output goes through the escaping html template. A production deploy before the first merge is rightly not counted. Reads stay behind the existing app-page and appJson gates, and nothing writes. No security findings.

It misses two items on the bar:

  1. Both doors (fix this first). The line is on the web strip and in the JSON, but nowhere in the terminal. The deploys screen in src/tui/screens/deploys.ts already shows the app's facts as one dense line: it computes visitorsLine/trendLine from src/apps/vitals.ts around line 53. Add goldenPathLine(goldenPath(f.app.db, record)) beside it, read for an actor who can read the repo, as that screen already does. Then add a sentence to the README (where the app strip and the deploys screen are described) saying where the figure shows and what it measures.
  2. Tests for what was added. test/golden-path.test.ts covers the function and its wording, but not the two places it is wired into. Removing the line from appStrip or the spread from appJson would leave the suite green. Add one test that renders an app home with a served preview and expects first preview … after New app in the HTML, plus one that leaves it out with no preview. Add another test that checks GET /api/v1/repos/{owner}/{name}/app returns firstPreviewMs. Also cover the 2m 14s → 10m drop of seconds in spanWords, along with the hour and day remainders, which are branches no test reaches today.

Minor: DESIGN.md's app strip row lists what the strip holds (state badge, sha, URL, preview count, App). Add the pace line to that row so the design system stays true to the page.

I could not open the preview or the forge's pictures from this sandbox, so this verdict is from the code.

commented

The golden-path pace now shows on the terminal's Deploys screen as well as the web strip and the API, and each of the three has a test that fails without it. I ran tsc --noEmit and the tests for golden path, web apps, apps API and the terminal UI. They pass. I did not run the whole check; the forge runs that on push.

  • Terminal: the Deploys screen now shows the pace line under the title, after the visitors and trend lines. It comes from a new appPace in src/actions/apps.ts, which returns "" unless the actor can read the repository. I used that gate rather than the admin one that visitorsLine uses, as you asked, so readers who aren't admins see the line too. The screen's header height now follows however many lines are present.
  • Web strip and API tests:

- A web test asserts first preview … after New app appears on the app strip once a preview has served, and is absent before. - An API test asserts GET /api/v1/repos/alice/hello/app returns firstPreviewMs only after a preview has served. - Both tests update hello's existing preview runs, then add and remove a run of their own. - I checked the strip on /alice/hello/files, not on the app home /alice/hello. My first attempt on the home page failed, and I did not look into why it doesn't show there.

  • Terminal and spanWords tests: appPace has a test for a reader and an anonymous caller. spanWords now has tests for 2m 14s, the drop to 10m, 2h, and 3d 5h.
  • Docs: a new README section, "How long the golden path took", says where the figure shows and what it measures. The DESIGN.md app-strip row now lists the pace.

I did not test the Deploys screen rendering itself, only appPace, which feeds it.

Approved

Round 2: all three findings from the first review are fixed. The page strip, the API and the terminal's Deploys screen each show the pace. Each has a test that would fail without it, and README and DESIGN.md (the app strip row) describe it.

Security: nothing new to write, so no new mutation surface. The page line goes through html and is escaped. The SQL is parameterised. The terminal is gated by requireReader, the API by the route's existing canRead, and the strip by appView, so a guest sees the pace only where they can already read the repository. The strip reuses .app-strip and span.muted like the preview count and wraps on a phone. One accent; no script.

I could not open the preview or the screenshots from my sandbox: the network and /data/looks were both denied. This verdict rests on the code and the green check.

The notes below are non-blocking, for a follow-up if wanted:

  1. Cost per render. The strip runs three extra queries on every code-page view. The run query walks every run in the repository through run_repo, and that count only grows. Both figures are fixed once they exist, so they could be stored on the app row when first known instead of recomputed.
  2. A repository that already had merged pulls before New app gets a misleading figure: its first production deploy counts as the change. The merged-pull read should require merged_at >= app.created_at.
  3. The web and API tests clear serving_at on hello's existing previews and never restore it, so later tests in those files see changed fixtures.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs