Skip to content

Add shopify app import channel-config for partner channel spec import - #8360

Open
suzkiee wants to merge 7 commits into
Shopify:mainfrom
suzkiee:suzkiee/channel-spec-generate-command
Open

suzkiee wants to merge 7 commits into
Shopify:mainfrom
suzkiee:suzkiee/channel-spec-generate-command

Conversation

@suzkiee

@suzkiee suzkiee commented Aug 21, 2026

Copy link
Copy Markdown

WHY are these changes introduced?

Legacy channel apps need a migration path onto partner-owned channel_config extension specs. Shopify already has app-level FrozenRecord fallback specs for some legacy channels. Partners need a safe way to receive a deployable, partner-owned copy of the public parts of that spec.

The CLI team reviewed the proposal (thread) and approved this as a new import namespace under app:

start implementing this as import channel-config in Shopify CLI and we will work on a PR to stack on that moves the existing commands.

This PR adds app import channel-config and introduces the app import topic. A follow-up PR from the CLI team will migrate the existing import-extensions / import-custom-data-definitions commands into the same namespace.

WHAT is this pull request doing?

Adds a new command:

shopify app import channel-config [--stdout] [--overwrite]

Flow:

  1. Resolves the app from local context via linkedAppContext (standard --path / --client-id / --config / --reset flags).
  2. Calls a thin transport (services/import-channel-config/fetch.ts) that delegates to the canonical Channels-owned exporter (Channels::PartnerChannelSpecExport). The CLI never transforms or validates spec fields — the backend response is the deployable artifact.
  3. Writes extensions/channel-config/specifications/<handle>.toml (creates directories as needed).

Behavior details:

  • Refuses to overwrite an existing file unless --overwrite is passed.
  • --stdout prints only the TOML to stdout (pipeable); warnings go to stderr.
  • Backend warnings ({code, message}, e.g. automatic_product_feed_management) render out-of-band — never written into the TOML.
  • Failure reason codes map to partner-facing guidance: no_exportable_frozen_record, multiple_exportable_records, not_allowlisted, contains_no_public_fields, invalid_public_schema.
  • Never deploys; success output points at shopify app deploy as the next step.

Files:

File Purpose
packages/app/src/cli/commands/app/import/channel-config.ts oclif command (app:import:channel-config)
packages/app/src/cli/services/import-channel-config/import.ts file/stdout UX + failure mapping
packages/app/src/cli/services/import-channel-config/fetch.ts transport + response parsing
packages/app/src/cli/services/import-channel-config/import.test.ts 11 service tests (real temp dirs)
packages/app/src/cli/services/import-channel-config/fetch.test.ts 10 transport tests (GID URL, status handling, malformed bodies)
packages/app/src/cli/index.ts command registration
packages/cli/package.json new app:import topic description
Generated files oclif manifest, README, dev-docs data

Transport / backend contract

The command calls GET app_management/unstable/organizations/:orgId/apps/:id/channel_spec_export.json:

  • Success: {handle, filename, toml, warnings}
  • Well-formed failure: 422 {error: "not_exportable_yet", reason}
  • 404 is reserved for "endpoint unavailable / app not found" and surfaces as an abort.

The corresponding App Management endpoint is being added in shop/world (rework of shop/world#2051080).

Design constraints

  • Export is app-level and shop-independent — app-owner/collaborator auth only; no shop/admin/runtime auth contexts.
  • Internal-only fields are omitted entirely server-side via a public-field allowlist. Generated TOML must pass the public channel_config validation contract; the exporter fails closed otherwise.
  • Single-spec legacy apps only for MVP (multi-spec apps out of scope). A --specification-handle <handle> flag is reserved for future multi-spec support and intentionally not included here.
  • No comments, provenance, or warnings inside the TOML file.

@suzkiee suzkiee changed the title [Prototype] Add shopify app channel-spec generate for partner channel spec export Add shopify app import channel-config for partner channel spec import Sep 14, 2026
Comment on lines +52 to +55
const response = await shopifyFetch(url, {
method: 'GET',
headers: appManagementHeaders(token),
})

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Should this mirror other App Management only operations and have the HTTP call be moved in a DeveloperPlatformClient method?

@suzkiee
suzkiee marked this pull request as ready for review September 16, 2026 14:51
@suzkiee
suzkiee requested review from a team as code owners September 16, 2026 14:51
Generates a deployable channel_config spec TOML from the Shopify-authored
default channel specification. The TOML is produced and validated server-side
by the Channels-owned exporter; the CLI handles app context, transport, and
local file UX only.

- shopify app channel-spec generate writes extensions/channel-config/specifications/<handle>.toml
- --stdout prints only the TOML (warnings go to stderr)
- --overwrite required to replace an existing file
- Backend warnings ({code, message}) are rendered out-of-band, never into the TOML
- Failure reason codes map to partner-facing guidance
…el spec fetch

- A 404 is not part of the export contract (failures are 422 with a
  reason code), so stop mapping it to no_exportable_frozen_record and
  abort with an endpoint-unavailable message instead.
- Validate that backend warnings are {code, message} objects before
  rendering them, dropping malformed entries.
Per CLI team feedback, the command previously named `shopify app
channel-spec generate` is now `shopify app import channel-config`:

- Move commands/app/channel-spec/generate.ts to
  commands/app/import/channel-config.ts and rename the class to
  ImportChannelConfig (path mirrors the new oclif ID
  app:import:channel-config for lazy loading).
- Rename services/channel-spec/ to services/import-channel-config/ and
  generateChannelSpec to importChannelConfig.
- Register the new command ID in packages/app/src/cli/index.ts and add
  the "app:import" oclif topic in packages/cli/package.json.
- Regenerate oclif.manifest.json, README.md, and dev docs JSON.

Assisted-By: devx/3abb0030-fdc9-44fb-8c5f-e2f47d8caf39
@suzkiee
suzkiee force-pushed the suzkiee/channel-spec-generate-command branch from 791e783 to 6082b1e Compare September 17, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant