Skip to content

ci: distinguish unusable smoke credentials from CLI regressions - #251

Merged
nicknisi merged 20 commits into
nicknisi/installer-tuifrom
ci/smoke-auth-preflight
Sep 25, 2026
Merged

nicknisi merged 20 commits into
nicknisi/installer-tuifrom
ci/smoke-auth-preflight

Conversation

@nicknisi

Copy link
Copy Markdown
Member

Summary

Split the independent CI work out of #250 so installer URL fixes can be reviewed on their own.

  • Preflight the smoke credential with one direct, read-only API request.
  • HTTP 200 enables the existing authenticated CLI checks; their failures remain fatal.
  • Missing credentials or HTTP 401 report live checks as NOT RUN, with an explicit warning and summary.
  • Other HTTP statuses or transport failures fail CI. The probe does not follow redirects or log credentials or response bodies.

Validation

  • bun install --frozen-lockfile passed.
  • bun run test scripts/smoke-auth-preflight.spec.ts: 15 passed, using localhost fixtures only.
  • No live authenticated smoke run was performed as part of this split.

This branch contains only the workflow, preflight script, and its tests.

The `--dashboard` installer mode and hidden `workos dashboard` command were
unmaintained. Remove them along with the Ink/React components, the
DashboardAdapter, the eval harness's Ink live view, and the ink, react,
@types/react, and react-devtools-core dependencies.

The installer now uses HeadlessAdapter in JSON mode and CLIAdapter otherwise.
Evals always use sequential logging (`--no-dashboard` is gone).

BREAKING CHANGE: `workos install --dashboard` / `-d` and `workos dashboard`
are removed. Use `workos install`.
Groundwork for the full-screen installer. Nothing imports these yet.
react-devtools-core is a build-only devDependency: Ink's reconciler statically
imports it behind a DEV gate, and `bun build --compile` must resolve it.
Task labels, walkthrough copy, tips, and announcements live in one bundled,
data-only JSON file validated by a zod schema. Walkthrough keys must be real
installer events with only the placeholders each event supplies; tips and
announcements can target frameworks, and announcements take a date window.
Adds a runtime INSTALLER_EVENT_NAMES list that the compiler keeps in sync
with InstallerEvents.
setUiHost() routes every ui line (with its log level), spinner status, and
confirm/select/text/password prompt to a host such as the full-screen
installer. The --json and non-TTY guards and the one-prompt-at-a-time chain
still apply in front of the host. With no host registered, output is
byte-for-byte unchanged.
A plain subscribe/getSnapshot store over InstallerEventEmitter. It maps
machine phases to the task list (settling a task on the next phase's enter,
so a failure never flashes "completed"), narrates events with the content
copy, and records agent status lines, file changes, and commands. It also
holds the pending prompt, spinner status, notices, the outcome, and the tips
and announcements for the detected framework. No Ink dependency; tests drive
the real installer machine.
In an interactive terminal of at least 80x24, `workos install` now opens a
full-screen Ink view: the WorkOS logomark (Arc's raster, precomputed), a task
list driven by installer events, a plain-English walkthrough, a rotating tips
and news card, and every question asked inline. When it closes, the terminal
is restored and the same output a plain run prints is replayed into the
scrollback, ending with the completion summary.

TuiAdapter wraps CLIAdapter, so every event is still handled and every prompt
answered by the same code; it only redirects ui output and prompts through
setUiHost() and captures stray console output. ctrl-c goes down the existing
SIGINT path, esc/ctrl-c in a prompt cancel it as in the plain CLI, and an
exit hook restores the terminal on any process.exit.

Adapter selection is a pure, tested function. JSON stays headless; CI/agent
modes, piped stdio, TERM=dumb, small terminals, and --no-tui keep the plain
CLI adapter. Telemetry reports installer.mode 'tui'. Also drops a leftover
`dashboard` arg type and stops the adapter if the environment picker throws.
…and add a top margin

Callers print what a question is about and then ask ("You have uncommitted
or untracked files:" + the list, then "Continue anyway?"). With a UI host,
ui.ts now attaches the lines printed in the same synchronous run to the
prompt as `context`, and the full-screen view shows them right above the
question. The list collapses to "… N more" when the terminal is short, so
the question and its answer line always stay on screen.

The view also leaves a blank row at the top, matching the blank row at the
bottom and the one-column side margins.
The CLI drew two brand marks: the full-screen installer uses the WorkOS
logomark, while the plain CLI (and the scrollback replayed after the full
screen) used a lock mascot whose face showed the outcome.

- The install opener draws the compact logomark in WorkOS indigo beside the
  wordmark, or one plain line without Unicode.
- The install summary and `workos doctor`'s summary box lead with a title
  line that carries the outcome (✔ green, ! yellow, ✗ red). An error detail
  under a failed install's title reads "›" instead of repeating the ✗.
- After the full-screen view closes, the replay skips the opener: you just
  saw the logo, so the scrollback starts with what happened.

The logomark raster moves to src/utils/logomark.ts so both surfaces share it;
lock-art.ts is gone.
The full-screen installer can now tick off the dashboard's AuthKit checklist
as the installer works through it, instead of one "Configure WorkOS" row.

- `config:step`: the configure step (before the agent) reports "Add
  environment variables", and for React Router and TanStack Start the
  redirect URI and CORS origin as each REST write settles; without an API key
  those two are reported as not set, with the reason.
- `app-urls:step`: for Next.js, the redirect, initiate login, and sign-out
  URIs that #244 sets on the AuthKit application once the agent's routes
  exist. `reportAppUrlSetup` wraps `configureAuthkitApplication` without
  changing it: a throw still fails the install; an unverified result flags
  both URLs with its reason.

Plain and JSON output are unchanged.
…ight

- "Configure WorkOS" expands into the dashboard's items it sets while it
  runs, in the dashboard's order and words, and collapses once they land.
- New "Connect your app's URLs" step (Next.js) after the agent, where the
  redirect, initiate login, and sign-out URIs are actually set. Items that
  weren't set or verified stay open with a `!`, and items sharing a reason
  share one walkthrough line.
- "Complete your first sign-up" ends the list as the next step (→). The
  run's closing line says so when a setting still needs a look.
- The walkthrough is on the left and the checklist on the right. Below
  100x30 the walkthrough keeps the room and the checklist becomes one
  progress line.
…crollback

On exit the full-screen view replayed everything the plain CLI would have
printed, so the scrollback filled with every command and file the agent
touched. It now keeps the answers, the settings rows, warnings and errors
(including any from the agent's run), validation, and the summary, and
points to the installer log for the step-by-step.
Ink re-subscribes input handlers after each render, so a key arriving
before that reached a handler holding the previous state:
- a fast ↓ then enter in a select picked the option from before the move
  (continue on the current branch became "create a branch")
- a text or password answer pasted with its trailing newline was inserted as
  text and never submitted, and typing ahead lost characters

The select keeps its focus in a ref, and text/password prompts use a small
line input whose value and cursor live in a ref; a newline anywhere in a chunk
submits what precedes it, as the plain CLI's prompts do. It edits by
character (an emoji is one step), ignores keys Ink delivers as raw escape
sequences (Home, End), and shows a validator that throws as the prompt's
error instead of crashing the installer.
…screen view

From review of the stack:
- A terminating signal emits no 'exit' event, so `kill` or a closed terminal
  left the alternate screen up and the tty raw. The view now restores the
  terminal on SIGTERM/SIGHUP and then dies of the signal.
- Redirected stderr (`2> errors.log`) now keeps the plain CLI, so errors stay
  on stderr; previously only the interaction mode implied this.
- A setting whose write failed while the install carried on no longer ends
  the run on "All done": it counts as needing a look, like one not set.
The note on where the hidden agent lines went printed just before "Agent completed", so the scrollback read backwards. It now follows the next line.
A finished task with a setting left to check showed a green ✔ above its ! items and counted toward "N of M done", so a run that ends on "setup required" read 8 of 8 done. The task now shares the ! and stays out of the count.
When authenticated command smoke fails, issue a single GET /connections using the same smoke credential and configured API host through curl instead of the compiled CLI. Discard the body, do not follow redirects, and log only HTTP status, curl exit status, and the request ID. Keep the original failed check red.
Preflight live smoke with one direct read-only API request. Missing credentials or direct HTTP401 report live checks NOT RUN with an explicit warning/summary instead of misclassifying a CLI regression. HTTP200 enables the unchanged authenticated CLI checks, whose failures still fail CI. All other HTTP or transport failures remain fatal. Localhost-only tests cover status handling, non-disclosure, no redirects, and propagation of CLI failures.
@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[High risk] Changes CI authentication check and smoke test flow.

The PR appears safe to merge; no actionable failure was established in the new smoke gate.

Summary

This PR adds a direct, read-only credential preflight before authenticated CLI smoke checks.

  • HTTP 200 enables the existing checks, whose failures remain fatal.
  • Missing credentials or HTTP 401 mark live checks as NOT RUN; other probe failures fail CI.
  • Localhost tests cover response handling, credential redaction, and workflow gating.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Preflight credential] --> B{Result}
  B -->|HTTP 200| C[Run authenticated CLI smoke]
  B -->|Missing key or HTTP 401| D[Warn: NOT RUN]
  B -->|Other status or transport failure| E[Fail CI]
  C -->|Smoke failure| E
Loading

Reviews (1) · Last reviewed commit: "ci: warn explicitly when smoke credentia..."

@nicknisi
nicknisi force-pushed the nicknisi/installer-tui branch from d201fd5 to 5737030 Compare September 25, 2026 10:00
@nicknisi
nicknisi merged commit ecca26a into nicknisi/installer-tui Sep 25, 2026
5 checks passed
@nicknisi
nicknisi deleted the ci/smoke-auth-preflight branch September 25, 2026 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant