Skip to content

Add typed JSON output to theme rename - #8653

Open
gonzaloriestra wants to merge 1 commit into
gonzalo/json-theme-publishfrom
gonzalo/json-theme-rename
Open

gonzaloriestra wants to merge 1 commit into
gonzalo/json-theme-publishfrom
gonzalo/json-theme-rename

Conversation

@gonzaloriestra

@gonzaloriestra gonzaloriestra commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

theme rename has no JSON result contract, so automation must parse terminal output.

Closes shop/issues-develop#23692.

WHAT is this pull request doing?

Return status: "success" and originalName alongside the renamed theme, using the shared mutation success schema. Multiple environments carry these fields inside each successful result, with no overall success claim.

Return the renamed API theme as typed data and move final output into a presenter. Reuse the environment collector from the preceding PR, retaining the name prompt, original theme name, and requested name in terminal output. Add --json, expose the domain-owned schema, and refresh the manifest, README, and generated docs.

Normal output includes:

The theme 'Original' (#1) was renamed to 'Renamed Theme'

Matching JSON:

{
  "status": "success",
  "originalName": "Original",
  "theme": {
    "id": 1,
    "name": "Renamed Theme",
    "role": "unpublished",
    "processing": false,
    "createdAtRuntime": false,
    "shop": "example.myshopify.com"
  }
}

The optional src field is retained when present. Multiple environments return {"environments":[{"environment":"staging","result":...}]} in configured order. Failed or invalid environments are omitted and reported on stderr; total failure returns {"environments":[]}. Existing exit behavior and single-environment presentation are preserved.

How to manually test your changes?

pnpm shopify theme rename --help
pnpm shopify theme rename --json-schema
pnpm shopify theme rename --store "$STORE" --theme "$THEME_ID" --name "Renamed Theme"
pnpm shopify theme rename --store "$STORE" --theme "$THEME_ID" --name "Renamed Theme" --json
pnpm shopify theme rename --environment staging --environment production --theme "$THEME_ID" --name "Renamed Theme" --json

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
  • A single changeset for all theme migrations is added in the last PR, #8682.

@gonzaloriestra
gonzaloriestra added this pull request to stack #8654 September 24, 2026 09:47
@github-actions github-actions Bot added shopify.dev preview Area: @shopify/cli @shopify/cli package issues labels Sep 24, 2026
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from dd58dce to 9606a9a Compare September 24, 2026 10:04
@gonzaloriestra
gonzaloriestra removed this pull request from stack #8654 September 24, 2026 10:04
@gonzaloriestra
gonzaloriestra added this pull request to stack #8655 September 24, 2026 10:05
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 9606a9a to 7336e0a Compare September 24, 2026 10:13
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 7336e0a to 83e17cf Compare September 24, 2026 10:25
@github-actions github-actions Bot added no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. and removed Area: @shopify/cli @shopify/cli package issues labels Sep 24, 2026
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 83e17cf to 32c0974 Compare September 24, 2026 11:56
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 32c0974 to 97f10b5 Compare September 24, 2026 13:46
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch 2 times, most recently from 769c88d to e2e7e23 Compare September 24, 2026 14:36
@gonzaloriestra
gonzaloriestra marked this pull request as ready for review September 24, 2026 14:45
@gonzaloriestra
gonzaloriestra requested review from a team as code owners September 24, 2026 14:45
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from e2e7e23 to fb17cc3 Compare September 25, 2026 12:27
@gonzaloriestra
gonzaloriestra removed this pull request from stack #8655 September 25, 2026 12:28
@gonzaloriestra
gonzaloriestra added this pull request to stack #8673 September 25, 2026 12:29
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch 2 times, most recently from 79b50fd to 7975e76 Compare September 28, 2026 10:25
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 7975e76 to 904a7d0 Compare September 28, 2026 11:39
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 904a7d0 to 888a95b Compare September 28, 2026 11:51
import {zod} from '@shopify/cli-kit/node/schema'
import type {Theme} from '@shopify/cli-kit/node/themes/types'

const ThemeRenameResultSchema = zod.object({theme: ThemeMutationThemeSchema})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this schema should include at least status: success (outside of the theme object).
And maybe also the original name?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added top-level status: "success" using the shared mutation schema, plus originalName. The theme object contains the updated name returned by the API. Both fields are also included in each successful environment result.

@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 888a95b to 9502887 Compare September 29, 2026 10:28
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 9502887 to 4461326 Compare September 29, 2026 11:11
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-theme-rename branch from 4461326 to 28dfeb4 Compare September 29, 2026 11:38
@github-actions

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

packages/cli-kit/dist/private/node/ui/tasks.d.ts
import { TokenizedString } from '../../../public/node/output.js';
export interface Task<TContext = unknown> {
    title: string | TokenizedString;
    task: (ctx: TContext, task: Task<TContext>) => Promise<void | Task<TContext>[]>;
    retry?: number;
    retryCount?: number;
    errors?: Error[];
    skip?: (ctx: TContext) => boolean;
}
export declare function runTasks<TContext>(tasks: Task<TContext>[], onTask?: (task: Task<TContext>) => void): Promise<TContext>;

Existing type declarations

packages/cli-kit/dist/public/common/command-events.d.ts
@@ -23,14 +23,14 @@ export declare const commandDiagnosticEventSchema: z.ZodObject<{
 export declare const commandProgressEventSchema: z.ZodObject<{
     type: z.ZodLiteral<"progress">;
     timestamp: z.ZodString;
-    status: z.ZodEnum<["started", "updated", "completed"]>;
+    status: z.ZodEnum<["started", "updated", "retrying", "completed", "failed"]>;
     operation: z.ZodString;
     message: z.ZodOptional<z.ZodString>;
     current: z.ZodOptional<z.ZodNumber>;
     total: z.ZodOptional<z.ZodNumber>;
 }, "strict", z.ZodTypeAny, {
     type: "progress";
-    status: "started" | "updated" | "completed";
+    status: "started" | "updated" | "retrying" | "completed" | "failed";
     timestamp: string;
     operation: string;
     message?: string | undefined;
@@ -38,7 +38,7 @@ export declare const commandProgressEventSchema: z.ZodObject<{
     total?: number | undefined;
 }, {
     type: "progress";
-    status: "started" | "updated" | "completed";
+    status: "started" | "updated" | "retrying" | "completed" | "failed";
     timestamp: string;
     operation: string;
     message?: string | undefined;
@@ -67,14 +67,14 @@ export declare const commandEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
 }>, z.ZodObject<{
     type: z.ZodLiteral<"progress">;
     timestamp: z.ZodString;
-    status: z.ZodEnum<["started", "updated", "completed"]>;
+    status: z.ZodEnum<["started", "updated", "retrying", "completed", "failed"]>;
     operation: z.ZodString;
     message: z.ZodOptional<z.ZodString>;
     current: z.ZodOptional<z.ZodNumber>;
     total: z.ZodOptional<z.ZodNumber>;
 }, "strict", z.ZodTypeAny, {
     type: "progress";
-    status: "started" | "updated" | "completed";
+    status: "started" | "updated" | "retrying" | "completed" | "failed";
     timestamp: string;
     operation: string;
     message?: string | undefined;
@@ -82,7 +82,7 @@ export declare const commandEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
     total?: number | undefined;
 }, {
     type: "progress";
-    status: "started" | "updated" | "completed";
+    status: "started" | "updated" | "retrying" | "completed" | "failed";
     timestamp: string;
     operation: string;
     message?: string | undefined;
packages/cli-kit/dist/public/node/base-command.d.ts
@@ -35,6 +35,7 @@ declare abstract class BaseCommand extends Command {
         argv: string[];
     }>;
     protected environmentsFilename(): string | undefined;
+    protected validateNonTTYFlags(flags: FlagOutput): void;
     protected failMissingNonTTYFlags(flags: FlagOutput, requiredFlags: string[]): void;
     private failMissingNonTTYFlagRequirements;
     private applicableNonTTYFlagRequirements;
packages/cli-kit/dist/public/node/command-events.d.ts
@@ -29,14 +29,14 @@ export declare const commandEventOutputSchema: import("./json-output-schema.js")
 }>, import("zod").ZodObject<{
     type: import("zod").ZodLiteral<"progress">;
     timestamp: import("zod").ZodString;
-    status: import("zod").ZodEnum<["started", "updated", "completed"]>;
+    status: import("zod").ZodEnum<["started", "updated", "retrying", "completed", "failed"]>;
     operation: import("zod").ZodString;
     message: import("zod").ZodOptional<import("zod").ZodString>;
     current: import("zod").ZodOptional<import("zod").ZodNumber>;
     total: import("zod").ZodOptional<import("zod").ZodNumber>;
 }, "strict", import("zod").ZodTypeAny, {
     type: "progress";
-    status: "started" | "updated" | "completed";
+    status: "started" | "updated" | "retrying" | "completed" | "failed";
     timestamp: string;
     operation: string;
     message?: string | undefined;
@@ -44,7 +44,7 @@ export declare const commandEventOutputSchema: import("./json-output-schema.js")
     total?: number | undefined;
 }, {
     type: "progress";
-    status: "started" | "updated" | "completed";
+    status: "started" | "updated" | "retrying" | "completed" | "failed";
     timestamp: string;
     operation: string;
     message?: string | undefined;
packages/cli-kit/dist/public/node/ui.d.ts
@@ -318,6 +318,8 @@ export declare function renderTasks<TContext>(tasks: Task<TContext>[], { renderO
 export interface RenderSingleTaskOptions<T> {
     title: TokenizedString;
     task: (updateStatus: (status: TokenizedString) => void) => Promise<T>;
+    /** The number of additional attempts after a failure. Defaults to zero. */
+    retry?: number;
     onAbort?: () => void;
     renderOptions?: RenderOptions;
 }
@@ -326,12 +328,13 @@ export interface RenderSingleTaskOptions<T> {
  * @param options - Configuration object
  * @param options.title - The initial title to display with the loading bar
  * @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.
+ * @param options.retry - The number of additional attempts after a failure. Defaults to zero.
  * @param options.renderOptions - Optional render configuration
  * @returns The result of the task
  * @example
  * Loading app ...
  */
-export declare function renderSingleTask<T>({ title, task, onAbort, renderOptions, }: RenderSingleTaskOptions<T>): Promise<T>;
+export declare function renderSingleTask<T>({ title, task, retry, onAbort, renderOptions, }: RenderSingleTaskOptions<T>): Promise<T>;
 export interface RenderTextPromptOptions extends Omit<TextPromptProps, 'onSubmit'> {
     renderOptions?: RenderOptions;
 }
packages/cli-kit/dist/private/node/ui/components/Tasks.d.ts
@@ -1,14 +1,7 @@
 import { AbortSignal } from '../../../../public/node/abort.js';
-import { TokenizedString } from '../../../../public/node/output.js';
+import { Task } from '../tasks.js';
 import React from 'react';
-export interface Task<TContext = unknown> {
-    title: string | TokenizedString;
-    task: (ctx: TContext, task: Task<TContext>) => Promise<void | Task<TContext>[]>;
-    retry?: number;
-    retryCount?: number;
-    errors?: Error[];
-    skip?: (ctx: TContext) => boolean;
-}
+export type { Task } from '../tasks.js';
 interface TasksProps<TContext> {
     tasks: Task<TContext>[];
     silent?: boolean;

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

no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. shopify.dev preview

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants