diff --git a/.changeset/fix-codespaces-custom-tunnel.md b/.changeset/fix-codespaces-custom-tunnel.md new file mode 100644 index 00000000000..e1dc11a0df5 --- /dev/null +++ b/.changeset/fix-codespaces-custom-tunnel.md @@ -0,0 +1,5 @@ +--- +'@shopify/app': patch +--- + +Respect `--tunnel-url` when running `shopify app dev` in GitHub Codespaces. diff --git a/packages/app/src/cli/services/dev/urls.test.ts b/packages/app/src/cli/services/dev/urls.test.ts index e21ec3aff65..30b3d6925dc 100644 --- a/packages/app/src/cli/services/dev/urls.test.ts +++ b/packages/app/src/cli/services/dev/urls.test.ts @@ -410,6 +410,19 @@ describe('generateFrontendURL', () => { expect(got).toEqual({frontendUrl: 'https://my-tunnel-provider.io', frontendPort: 4242, usingLocalhost: false}) }) + test('returns tunnelUrl when running in a codespace environment', async () => { + // Given + vi.mocked(codespaceURL).mockReturnValue('codespace.url.fqdn.com') + vi.mocked(codespacePortForwardingDomain).mockReturnValue('app.github.dev') + const options = {...defaultOptions, tunnelUrl: 'https://my-tunnel-provider.io:4242'} + + // When + const got = await generateFrontendURL(options) + + // Then + expect(got).toEqual({frontendUrl: 'https://my-tunnel-provider.io', frontendPort: 4242, usingLocalhost: false}) + }) + test('generates a tunnel url with cloudflare when there is no tunnelUrl and use cloudflare is true', async () => { // Given const options: FrontendURLOptions = { diff --git a/packages/app/src/cli/services/dev/urls.ts b/packages/app/src/cli/services/dev/urls.ts index 8db28d4a880..e1b18f7a184 100644 --- a/packages/app/src/cli/services/dev/urls.ts +++ b/packages/app/src/cli/services/dev/urls.ts @@ -47,10 +47,10 @@ interface FrontendURLResult { /** * The tunnel creation logic depends on 7 variables: - * - If a Codespaces environment is detected, then the URL is built using the codespaces hostname. No need for tunnel - * - If a Gitpod environment is detected, then the URL is built using the gitpod hostname. No need for tunnel - * No need for tunnel. In case problems with that configuration, the flags Tunnel or Custom Tunnel url could be used * - If a tunnelUrl is provided, that takes preference and is returned as the frontendURL + * - If a Codespaces environment is detected, then the URL is built using the codespaces hostname. No need for tunnel + * - If a Gitpod environment is detected, then the URL is built using the gitpod hostname. + * In case problems with that configuration, the Custom Tunnel URL flag could be used * - If noTunnel is true, that takes second preference and localhost is used * - Otherwise, a tunnel is created. (by default using cloudflare) * @@ -69,17 +69,6 @@ export async function generateFrontendURL(options: FrontendURLOptions): Promise< let frontendUrl = '' const usingLocalhost = options.noTunnelUseLocalhost - if (codespaceURL()) { - frontendUrl = `https://${codespaceURL()}-${frontendPort}.${codespacePortForwardingDomain()}` - return {frontendUrl, frontendPort, usingLocalhost} - } - - if (gitpodURL()) { - const defaultUrl = gitpodURL()?.replace('https://', '') - frontendUrl = `https://${frontendPort}-${defaultUrl}` - return {frontendUrl, frontendPort, usingLocalhost} - } - if (options.tunnelUrl) { const matches = options.tunnelUrl.match(/(https:\/\/[^:]+):([0-9]+)/) if (!matches) { @@ -91,6 +80,17 @@ export async function generateFrontendURL(options: FrontendURLOptions): Promise< return {frontendUrl, frontendPort, usingLocalhost} } + if (codespaceURL()) { + frontendUrl = `https://${codespaceURL()}-${frontendPort}.${codespacePortForwardingDomain()}` + return {frontendUrl, frontendPort, usingLocalhost} + } + + if (gitpodURL()) { + const defaultUrl = gitpodURL()?.replace('https://', '') + frontendUrl = `https://${frontendPort}-${defaultUrl}` + return {frontendUrl, frontendPort, usingLocalhost} + } + if (options.tunnelClient) { frontendPort = options.tunnelClient.port frontendUrl = await pollTunnelURL(options.tunnelClient)