Skip to content

Share replay watch logic and fix watcher startup - #9108

Draft
isaacroldan wants to merge 1 commit into
codex/function-replay-jsonfrom
codex/function-replay-shared-watch
Draft

isaacroldan wants to merge 1 commit into
codex/function-replay-jsonfrom
codex/function-replay-shared-watch

Conversation

@isaacroldan

@isaacroldan isaacroldan commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Text Function replay has its own watch loop, and shared watcher startup can report readiness before the initial scan or a startup rebuild finishes. A rebuild failure during that scan can also be hidden by an older successful build result.

WHAT is this pull request doing?

Use the replay loop introduced by #9056 for both text and JSON presentation. Keep text input, output, logs, and instruction statistics, continue after recoverable failures, and stop the UI on fatal runner failures.

Enable scan readiness and command context retention by default for the shared watcher. Wait for pending startup file events and include their latest extension build results before emitting ready. Cancellation during startup prevents dev preview upload. Preserve the explicit readiness opt-out.

This follow-up contains the text UI refactor, generic watcher readiness and startup state machinery, and raw replay loop tests extracted from #9056. #9056 remains independently mergeable. Active process and build shutdown changes stay in #9057, which follows this PR.

How to manually test your changes?

Use a test app with a Function and a saved Function log.

  1. Run pnpm shopify app function replay --path <function-directory> --log <log-id>.
  2. Edit the Function, introduce a build error, then fix it. Check the input, output, logs, and instruction statistics. A completed Function failure should keep watching; a fatal runner error should exit with code 1.
  3. Press q to quit. Repeat with --json --no-input to check that the JSON records retain their contract.
  4. Run pnpm shopify app dev --path <app-directory> in a test app with many watched files. Edit an extension during startup. Check that preview startup uses the latest completed build result.
  5. Introduce a startup build failure. Check that the known failure prevents preview upload. Cancel during the initial scan and check that preview startup does not proceed.

Validation

  • 391 related Function, replay UI, watcher, startup, and dev session tests passed on this head.
  • The startup tests cover failure, recovery, an in-flight rebuild, and further file events received during startup. Native context and readiness opt-out tests passed.
  • App type checking, scoped ESLint, formatting, and diff checks passed.
  • Local checks ran on macOS ARM with Node 24.22.1. Full hosted CI is separate from this validation.

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've considered analytics changes to measure impact
  • The change is user-facing and has changesets.

@github-actions github-actions Bot added the Area: @shopify/cli @shopify/cli package issues label Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

We found no new type declarations in this PR

Existing type declarations

packages/cli-kit/dist/private/node/dev-instance-output.d.ts
@@ -2,18 +2,18 @@ import { zod } from '../../public/node/schema.js';
 import { Writable, type WritableOptions } from 'stream';
 export declare const devInstanceLogOutputSchema: import("../../public/node/json-output-schema.js").JsonOutputSchema<zod.ZodObject<{
     timestamp: zod.ZodString;
-    source: zod.ZodOptional<zod.ZodString>;
+    source: zod.ZodString;
     level: zod.ZodOptional<zod.ZodEnum<["debug", "info", "warning", "error"]>>;
     message: zod.ZodString;
 }, "strict", zod.ZodTypeAny, {
+    source: string;
     message: string;
     timestamp: string;
-    source?: string | undefined;
     level?: "info" | "error" | "debug" | "warning" | undefined;
 }, {
+    source: string;
     message: string;
     timestamp: string;
-    source?: string | undefined;
     level?: "info" | "error" | "debug" | "warning" | undefined;
 }>>;
 /** One line of a dev instance's JSON Lines log. */
@@ -30,7 +30,7 @@ export declare function createDevInstanceOutput({ logFile, logOutput, isActive,
         timestamp?: string;
     }) => Promise<void>;
     tee: (target: Writable, { source, stringWritesAreMessages }: {
-        source?: string;
+        source: string;
         stringWritesAreMessages?: boolean;
     }) => DevInstanceOutput;
     flush: () => Promise<PromiseSettledResult<void>[]>;
packages/cli-kit/dist/private/node/output-context.d.ts
@@ -2,8 +2,6 @@ export interface ConcurrentOutputContext {
     outputPrefix?: string;
     /** Controls ANSI stripping for terminal output. JSON diagnostics are always unstyled. */
     stripAnsi?: boolean;
-    /** Captures console messages before the terminal renderer handles them. */
-    consoleWarn?: (message: string) => void;
 }
 export declare function useConcurrentOutputContext<T>(context: ConcurrentOutputContext, callback: () => T): T;
 /** Returns the source and styling context for the current output write. */
packages/cli-kit/dist/public/node/dev-instance.d.ts
@@ -80,8 +80,7 @@ export interface DevInstance {
      * The returned stream forwards the original bytes to `target` unchanged.
      */
     tee: (target: Writable, options: {
-        /** Omit the source field when the stream does not need to distinguish producers. */
-        source?: string;
+        source: string;
         /** Treat each string write as a complete message. Byte writes remain buffered into lines. */
         stringWritesAreMessages?: boolean;
     }) => Writable;
packages/cli-kit/dist/public/node/upgrade.d.ts
@@ -5,11 +5,9 @@ export { getAutoUpgradeEnabled, setAutoUpgradeEnabled };
  * Utility function for generating an install command for the user to run
  * to install an updated version of Shopify CLI.
  *
- * @param version - The version or dist-tag to install. Homebrew can't
- * install a specific version, so it always upgrades to the formula's current version.
  * @returns A string with the command to run, or undefined if the package manager cannot be determined.
  */
-export declare function cliInstallCommand(version: string): string | undefined;
+export declare function cliInstallCommand(): string | undefined;
 /**
  * Options for {@link runCLIUpgrade}.
  */
@@ -21,13 +19,6 @@ export interface RunCLIUpgradeOptions {
      * their `package.json` / lockfile in the background.
      */
     autoupgrade?: boolean;
-    /**
-     * The exact version to install. The auto-upgrade hook passes the version it already
-     * vetted, such as one that isn't a major version change, so the install can't drift to
-     * whatever `latest` points at by the time the package manager runs. When omitted, the
-     * CLI installs `latest`.
-     */
-    version?: string;
 }
 /**
  * Runs the CLI upgrade using the appropriate package manager.
packages/cli-kit/dist/private/node/api/status-checks.d.ts
@@ -2,6 +2,6 @@
  * Checks whether an HTTP status indicates a gateway-level failure.
  *
  * @param status - The HTTP status to check.
- * @returns Whether the status is 502, 503, 504, or a Cloudflare edge error from 520 to 524.
+ * @returns Whether the status is 502, 503, or 504.
  */
 export declare function isGatewayErrorStatus(status: number | undefined): boolean;
\ No newline at end of file

@isaacroldan
isaacroldan added this pull request to stack #9109 November 9, 2026 12:50
@isaacroldan
isaacroldan force-pushed the codex/function-replay-shared-watch branch from a21fc33 to 7a563b8 Compare November 9, 2026 14:49
@isaacroldan
isaacroldan removed this pull request from stack #9109 November 9, 2026 17:12
@isaacroldan
isaacroldan force-pushed the codex/function-replay-shared-watch branch from 7a563b8 to 76ad225 Compare November 9, 2026 17:13
@isaacroldan
isaacroldan added this pull request to stack #9110 November 9, 2026 17:13

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/cli @shopify/cli package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant