Skip to content

Commit 5188073

Browse files
committed
Fix issue with single environment calls in theme commands
1 parent 48e3eb4 commit 5188073

File tree

2 files changed

+63
-27
lines changed

2 files changed

+63
-27
lines changed

.changeset/itchy-houses-kick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/theme': patch
3+
---
4+
5+
fix the way we detect single or non environments & improve output for multienvironment commands

packages/theme/src/cli/utilities/theme-command.ts

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import {ArgOutput, FlagOutput, Input} from '@oclif/core/lib/interfaces/parser.js
44
import Command from '@shopify/cli-kit/node/base-command'
55
import {AdminSession, ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session'
66
import {loadEnvironment} from '@shopify/cli-kit/node/environments'
7-
import {renderWarning} from '@shopify/cli-kit/node/ui'
7+
import {renderWarning, renderConcurrent} from '@shopify/cli-kit/node/ui'
88
import {AbortError} from '@shopify/cli-kit/node/error'
9+
import {AbortController} from '@shopify/cli-kit/node/abort'
10+
import {Writable} from 'stream'
911

1012
export interface FlagValues {
1113
[key: string]: boolean | string | string[] | number | undefined
@@ -36,7 +38,11 @@ export default abstract class ThemeCommand extends Command {
3638
return configurationFileName
3739
}
3840

39-
async command(_flags: FlagValues, _session: AdminSession): Promise<void> {}
41+
async command(
42+
_flags: FlagValues,
43+
_session: AdminSession,
44+
_context?: {stdout?: Writable; stderr?: Writable},
45+
): Promise<void> {}
4046

4147
async run<
4248
TFlags extends FlagOutput & {path?: string; verbose?: boolean},
@@ -50,20 +56,38 @@ export default abstract class ThemeCommand extends Command {
5056
const requiredFlags = klass.multiEnvironmentsFlags
5157
const {flags} = await this.parse(klass)
5258

53-
// Single environment
54-
if (!flags.environment) {
59+
// No environment provided
60+
if (!flags.environment?.length) {
5561
const session = await this.ensureAuthenticated(flags)
62+
5663
await this.command(flags, session)
64+
5765
return
5866
}
5967

60-
// Synchronously authenticate all environments
61-
const sessions: {[storeFqdn: string]: AdminSession} = {}
6268
// OCLIF parses flags.environment as an array when using the --environment & -e flag but
6369
// as a string when using the direct environment variable SHOPIFY_FLAG_ENVIRONMENT
6470
// This handles both cases
6571
const environments = Array.isArray(flags.environment) ? flags.environment : [flags.environment]
6672

73+
// If only one environment is specified, treat it as single environment mode
74+
if (environments.length === 1) {
75+
const environmentConfig = await loadEnvironment(environments[0], 'shopify.theme.toml', {from: flags.path})
76+
const environmentFlags = {
77+
...flags,
78+
...environmentConfig,
79+
environment: environments,
80+
}
81+
82+
const session = await this.ensureAuthenticated(environmentConfig as FlagValues)
83+
await this.command(environmentFlags, session)
84+
85+
return
86+
}
87+
88+
// Multiple environments
89+
const sessions: {[storeFqdn: string]: AdminSession} = {}
90+
6791
// Authenticate on all environments sequentially to avoid race conditions,
6892
// with authentication happening in parallel.
6993
for (const environmentName of environments) {
@@ -73,27 +97,34 @@ export default abstract class ThemeCommand extends Command {
7397
sessions[environmentName] = await this.ensureAuthenticated(environmentConfig as FlagValues)
7498
}
7599

76-
// Concurrently run commands
77-
await Promise.all(
78-
environments.map(async (environment: string) => {
79-
const environmentConfig = await loadEnvironment(environment, 'shopify.theme.toml', {from: flags.path})
80-
const environmentFlags = {
81-
...flags,
82-
...environmentConfig,
83-
environment: [environment],
84-
}
85-
86-
if (!this.validConfig(environmentConfig as FlagValues, requiredFlags, environment)) return
87-
88-
const session = sessions[environment]
89-
90-
if (!session) {
91-
throw new AbortError(`No session found for environment ${environment}`)
92-
}
93-
94-
return this.command(environmentFlags, session)
95-
}),
96-
)
100+
// Use renderConcurrent for multi-environment execution
101+
const abortController = new AbortController()
102+
103+
await renderConcurrent({
104+
processes: environments.map((environment: string) => ({
105+
prefix: environment,
106+
action: async (stdout: Writable, stderr: Writable, _signal) => {
107+
const environmentConfig = await loadEnvironment(environment, 'shopify.theme.toml', {from: flags.path})
108+
const environmentFlags = {
109+
...flags,
110+
...environmentConfig,
111+
environment: [environment],
112+
}
113+
114+
if (!this.validConfig(environmentConfig as FlagValues, requiredFlags, environment)) return
115+
116+
const session = sessions[environment]
117+
118+
if (!session) {
119+
throw new AbortError(`No session found for environment ${environment}`)
120+
}
121+
122+
await this.command(environmentFlags, session, {stdout, stderr})
123+
},
124+
})),
125+
abortSignal: abortController.signal,
126+
showTimestamps: true,
127+
})
97128
}
98129

99130
private async ensureAuthenticated(flags: FlagValues) {

0 commit comments

Comments
 (0)