Skip to content

Commit 78ad480

Browse files
committed
Allow theme commands to take glob pattern for environments
1 parent 6d0d24b commit 78ad480

File tree

6 files changed

+40
-12
lines changed

6 files changed

+40
-12
lines changed

.changeset/wet-bats-glow.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'@shopify/cli-kit': patch
3+
'@shopify/theme': patch
4+
'@shopify/app': patch
5+
---
6+
7+
Updated the environment flag to support glob patterns
8+
9+
For commands that support multiple environments you can now use glob patterns
10+
to specify the environments, e.g. `--environment "*-production"`. It's important
11+
to wrap any glob patterns in quotes to ensure your shell does not expand the
12+
value before passing it to the CLI.
13+
14+
This comes with a side effect that environments will be deduplicated.

packages/cli-kit/src/public/node/base-command.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,12 @@ describe('applying environments', async () => {
203203
outputMock.clear()
204204

205205
// When
206-
await MockCommand.run(['--path', tmpDir, '--environment', 'validEnvironment', '--environment', 'validEnvironment'])
206+
await MockCommand.run(['--path', tmpDir, '--environment', 'validEnvironment', '--environment', 'validEnvironment2'])
207207

208208
// Then
209209
expect(testResult).toEqual({
210210
path: resolvePath(tmpDir),
211-
environment: ['validEnvironment', 'validEnvironment'],
211+
environment: ['validEnvironment', 'validEnvironment2'],
212212
someStringWithDefault: 'default stringy',
213213
})
214214
expect(outputMock.info()).toEqual('')

packages/cli-kit/src/public/node/base-command.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {errorHandler, registerCleanBugsnagErrorsFromWithinPlugins} from './error-handler.js'
2-
import {loadEnvironment, environmentFilePath} from './environments.js'
2+
import {loadEnvironment, environmentFilePath, expandEnvironmentPatterns} from './environments.js'
33
import {isDevelopment} from './context/local.js'
44
import {addPublicMetadata} from './metadata.js'
55
import {AbortError} from './error.js'
@@ -146,16 +146,22 @@ This flag is required in non-interactive terminal environments, such as a CI env
146146
const environmentFileExists = await environmentFilePath(environmentsFileName, {from: flags.path})
147147

148148
// Handle both string and array cases for environment flag
149-
let environments: string[] = []
149+
let environmentPatterns: string[] = []
150150
if (flags.environment) {
151-
environments = Array.isArray(flags.environment) ? flags.environment : [flags.environment]
151+
environmentPatterns = Array.isArray(flags.environment) ? flags.environment : [flags.environment]
152152
}
153153

154-
const environmentSpecified = environments.length > 0
154+
const environmentSpecified = environmentPatterns.length > 0
155155

156156
// Noop if no environment file exists and none was specified
157157
if (!environmentFileExists && !environmentSpecified) return originalResult
158158

159+
// Theme commands can have environment names with glob patterns, in order
160+
// to check if there are multiple environments being specified we need to
161+
// expand them before continuing even if other commands might not support
162+
// multi environment behaviour.
163+
const environments = await expandEnvironmentPatterns(environmentPatterns, environmentsFileName)
164+
159165
// Noop if multiple environments were specified (let commands handle this)
160166
if (environmentSpecified && environments.length > 1) return originalResult
161167

packages/theme/src/cli/flags.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {resolvePath, cwd} from '@shopify/cli-kit/node/path'
44
import {fileExistsSync} from '@shopify/cli-kit/node/fs'
55
import {renderError} from '@shopify/cli-kit/node/ui'
66

7+
const globQuotesDescription = "Wrap the value in double quotes if you're using wildcards."
8+
79
/**
810
* An object that contains the flags that
911
* are shared across all the theme commands.
@@ -44,14 +46,12 @@ export const themeFlags = {
4446
}),
4547
environment: Flags.string({
4648
char: 'e',
47-
description: 'The environment to apply to the current command.',
49+
description: `The environment to apply to the current command. ${globQuotesDescription}`,
4850
env: 'SHOPIFY_FLAG_ENVIRONMENT',
4951
multiple: true,
5052
}),
5153
}
5254

53-
const globQuotesDescription = "Wrap the value in double quotes if you're using wildcards."
54-
5555
export const globFlags = (action: 'download' | 'upload') => ({
5656
only: Flags.string({
5757
char: 'o',

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {ensureThemeStore} from './theme-store.js'
33
import {describe, vi, expect, test, beforeEach} from 'vitest'
44
import {Config, Flags} from '@oclif/core'
55
import {AdminSession, ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session'
6-
import {loadEnvironment} from '@shopify/cli-kit/node/environments'
6+
import {loadEnvironment, expandEnvironmentPatterns} from '@shopify/cli-kit/node/environments'
77
import {fileExistsSync} from '@shopify/cli-kit/node/fs'
88
import {AbortError} from '@shopify/cli-kit/node/error'
99
import {resolvePath} from '@shopify/cli-kit/node/path'
@@ -137,6 +137,7 @@ describe('ThemeCommand', () => {
137137
vi.mocked(ensureThemeStore).mockReturnValue('test-store.myshopify.com')
138138
vi.mocked(ensureAuthenticatedThemes).mockResolvedValue(mockSession)
139139
vi.mocked(fileExistsSync).mockReturnValue(true)
140+
vi.mocked(expandEnvironmentPatterns).mockImplementation(async (patterns) => patterns)
140141
})
141142

142143
describe('run', () => {

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {hashString} from '@shopify/cli-kit/node/crypto'
55
import {Input} from '@oclif/core/interfaces'
66
import Command, {ArgOutput, FlagOutput, noDefaultsOptions} from '@shopify/cli-kit/node/base-command'
77
import {AdminSession, ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session'
8-
import {loadEnvironment} from '@shopify/cli-kit/node/environments'
8+
import {loadEnvironment, expandEnvironmentPatterns} from '@shopify/cli-kit/node/environments'
99
import {
1010
renderWarning,
1111
renderConcurrent,
@@ -75,7 +75,14 @@ export default abstract class ThemeCommand extends Command {
7575
const {args, flags} = await this.parse(klass)
7676
const commandRequiresAuth = 'password' in klass.flags
7777

78-
const environments = (Array.isArray(flags.environment) ? flags.environment : [flags.environment]).filter(Boolean)
78+
const environmentPatterns = (Array.isArray(flags.environment) ? flags.environment : [flags.environment]).filter(
79+
Boolean,
80+
)
81+
82+
const environments =
83+
environmentPatterns.length > 0
84+
? await expandEnvironmentPatterns(environmentPatterns, 'shopify.theme.toml', {from: flags.path as string})
85+
: []
7986

8087
// Single environment or no environment
8188
if (environments.length <= 1) {

0 commit comments

Comments
 (0)