From 6ac3a7e2523cdebdd128452b8fabc94937c61381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Wed, 3 Jun 2026 12:16:24 +0200 Subject: [PATCH] Fix app env pull absolute env-file paths --- .changeset/fix-app-env-pull-absolute-path.md | 5 ++ .../app/src/cli/commands/app/env/pull.test.ts | 61 +++++++++++++++++++ packages/app/src/cli/commands/app/env/pull.ts | 4 +- 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-app-env-pull-absolute-path.md create mode 100644 packages/app/src/cli/commands/app/env/pull.test.ts diff --git a/.changeset/fix-app-env-pull-absolute-path.md b/.changeset/fix-app-env-pull-absolute-path.md new file mode 100644 index 00000000000..6b975c07b20 --- /dev/null +++ b/.changeset/fix-app-env-pull-absolute-path.md @@ -0,0 +1,5 @@ +--- +'@shopify/app': patch +--- + +Fix `app env pull --env-file` with absolute paths. diff --git a/packages/app/src/cli/commands/app/env/pull.test.ts b/packages/app/src/cli/commands/app/env/pull.test.ts new file mode 100644 index 00000000000..c765171a3cf --- /dev/null +++ b/packages/app/src/cli/commands/app/env/pull.test.ts @@ -0,0 +1,61 @@ +import EnvPull from './pull.js' +import {linkedAppContext} from '../../../services/app-context.js' +import {pullEnv} from '../../../services/app/env/pull.js' +import {testAppLinked, testOrganization, testOrganizationApp} from '../../../models/app/app.test-data.js' +import {outputResult} from '@shopify/cli-kit/node/output' +import {joinPath, resolvePath} from '@shopify/cli-kit/node/path' +import {describe, expect, test, vi} from 'vitest' + +vi.mock('../../../services/app-context.js') +vi.mock('../../../services/app/env/pull.js') +vi.mock('@shopify/cli-kit/node/output', async (importOriginal) => { + const actual = await importOriginal() + return {...actual, outputResult: vi.fn()} +}) + +describe('app env pull command', () => { + test('uses absolute --env-file paths as-is', async () => { + const app = testAppLinked({ + directory: joinPath('F:', 'Project', 'cherhomeliving.shopify', 'shopify-app'), + configPath: joinPath('F:', 'Project', 'cherhomeliving.shopify', 'shopify-app', 'shopify.app.toml'), + }) + const remoteApp = testOrganizationApp() + const organization = testOrganization() + const envFile = joinPath(app.directory, '.env') + + vi.mocked(linkedAppContext).mockResolvedValue({app, remoteApp, organization} as Awaited< + ReturnType + >) + vi.mocked(pullEnv).mockResolvedValue('Created env file') + + await EnvPull.run(['--path', app.directory, '--env-file', envFile], import.meta.url) + + expect(pullEnv).toHaveBeenCalledWith({ + app, + remoteApp, + organization, + envFile, + }) + expect(outputResult).toHaveBeenCalledWith('Created env file') + }) + + test('resolves relative --env-file paths from the app directory', async () => { + const app = testAppLinked({directory: '/tmp/my-app', configPath: '/tmp/my-app/shopify.app.toml'}) + const remoteApp = testOrganizationApp() + const organization = testOrganization() + + vi.mocked(linkedAppContext).mockResolvedValue({app, remoteApp, organization} as Awaited< + ReturnType + >) + vi.mocked(pullEnv).mockResolvedValue('Created env file') + + await EnvPull.run(['--path', app.directory, '--env-file', 'config/.env'], import.meta.url) + + expect(pullEnv).toHaveBeenCalledWith({ + app, + remoteApp, + organization, + envFile: resolvePath(app.directory, 'config/.env'), + }) + }) +}) diff --git a/packages/app/src/cli/commands/app/env/pull.ts b/packages/app/src/cli/commands/app/env/pull.ts index 4e437f2a261..2689bd336bd 100644 --- a/packages/app/src/cli/commands/app/env/pull.ts +++ b/packages/app/src/cli/commands/app/env/pull.ts @@ -6,7 +6,7 @@ import {linkedAppContext} from '../../../services/app-context.js' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' import {outputResult} from '@shopify/cli-kit/node/output' -import {joinPath} from '@shopify/cli-kit/node/path' +import {resolvePath} from '@shopify/cli-kit/node/path' export default class EnvPull extends AppLinkedCommand { static summary = 'Pull app and extensions environment variables.' @@ -36,7 +36,7 @@ export default class EnvPull extends AppLinkedCommand { forceRelink: flags.reset, userProvidedConfigName: flags.config, }) - const envFile = joinPath(app.directory, flags['env-file'] ?? getDotEnvFileName(app.configPath)) + const envFile = resolvePath(app.directory, flags['env-file'] ?? getDotEnvFileName(app.configPath)) outputResult(await pullEnv({app, remoteApp, organization, envFile})) return {app} }