From f2f21da9a89627ca18354a1827982d18c93f4910 Mon Sep 17 00:00:00 2001 From: Antonio Sejas Date: Thu, 1 Jun 2023 13:16:46 +0100 Subject: [PATCH] wp now: add codespaces support (#41) Allow running `wp-now` in GitHub codespaces --- packages/wp-now/src/config.ts | 9 ++++- packages/wp-now/src/github-codespaces.ts | 15 ++++++++ packages/wp-now/src/run-cli.ts | 8 ++++- packages/wp-now/src/start-server.ts | 3 +- .../src/tests/github-codespaces.spec.ts | 35 +++++++++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 packages/wp-now/src/github-codespaces.ts create mode 100644 packages/wp-now/src/tests/github-codespaces.spec.ts diff --git a/packages/wp-now/src/config.ts b/packages/wp-now/src/config.ts index c03dcc2a..52b8af60 100644 --- a/packages/wp-now/src/config.ts +++ b/packages/wp-now/src/config.ts @@ -3,6 +3,7 @@ import { SupportedPHPVersionsList, } from '@php-wasm/universal'; import crypto from 'crypto'; +import { getCodeSpaceURL, isGitHubCodespace } from './github-codespaces'; import { inferMode } from './wp-now'; import { portFinder } from './port-finder'; import { isValidWordPressVersion } from './wp-playground-wordpress'; @@ -64,6 +65,9 @@ export interface WPEnvOptions { async function getAbsoluteURL() { const port = await portFinder.getOpenPort(); + if (isGitHubCodespace) { + return getCodeSpaceURL(port); + } return `http://localhost:${port}`; } @@ -83,7 +87,10 @@ function getWpContentHomePath(projectPath: string, mode: string) { export default async function getWpNowConfig( args: CliOptions ): Promise { - const port = args.port || (await portFinder.getOpenPort()); + if (args.port) { + portFinder.setPort(args.port); + } + const port = await portFinder.getOpenPort(); const optionsFromCli: WPNowOptions = { phpVersion: args.php as SupportedPHPVersion, projectPath: args.path as string, diff --git a/packages/wp-now/src/github-codespaces.ts b/packages/wp-now/src/github-codespaces.ts new file mode 100644 index 00000000..ba2e1074 --- /dev/null +++ b/packages/wp-now/src/github-codespaces.ts @@ -0,0 +1,15 @@ +/* + * True if the current environment is a GitHub Codespace + */ +export const isGitHubCodespace = Boolean( + process.env.CODESPACE_NAME && + process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN +); + +/* + * Returns the URL in the current GitHub Codespace + * e.g: https://sejas-fluffy-space-eureka-wrj7r95qhvq4x-8881.preview.app.github.dev + */ +export function getCodeSpaceURL(port: number): string { + return `https://${process.env.CODESPACE_NAME}-${port}.${process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}`; +} diff --git a/packages/wp-now/src/run-cli.ts b/packages/wp-now/src/run-cli.ts index dcfb6b45..72429c1f 100644 --- a/packages/wp-now/src/run-cli.ts +++ b/packages/wp-now/src/run-cli.ts @@ -7,6 +7,7 @@ import getWpNowConfig, { CliOptions } from './config'; import { spawn, SpawnOptionsWithoutStdio } from 'child_process'; import { executePHP } from './execute-php'; import { output } from './output'; +import { isGitHubCodespace } from './github-codespaces'; function startSpinner(message: string) { process.stdout.write(`${message}...\n`); @@ -123,6 +124,9 @@ export async function runCli() { } function openInDefaultBrowser(url: string) { + if (isGitHubCodespace) { + return; + } let cmd: string, args: string[] | SpawnOptionsWithoutStdio; switch (process.platform) { case 'darwin': @@ -141,5 +145,7 @@ function openInDefaultBrowser(url: string) { output?.log(`Platform '${process.platform}' not supported`); return; } - spawn(cmd, args); + spawn(cmd, args).on('error', function (err) { + console.error(err.message); + }); } diff --git a/packages/wp-now/src/start-server.ts b/packages/wp-now/src/start-server.ts index 8fc13360..a0c9692a 100644 --- a/packages/wp-now/src/start-server.ts +++ b/packages/wp-now/src/start-server.ts @@ -101,8 +101,7 @@ export async function startServer( output?.trace(e); } }); - - const url = `http://localhost:${port}/`; + const url = options.absoluteUrl; app.listen(port, () => { output?.log(`Server running at ${url}`); }); diff --git a/packages/wp-now/src/tests/github-codespaces.spec.ts b/packages/wp-now/src/tests/github-codespaces.spec.ts new file mode 100644 index 00000000..c9f9b0f9 --- /dev/null +++ b/packages/wp-now/src/tests/github-codespaces.spec.ts @@ -0,0 +1,35 @@ +import getWpNowConfig from '../config'; +import * as codespaces from '../github-codespaces'; + +describe('Test GitHub Codespaces', () => { + let processEnv; + beforeAll(() => { + processEnv = process.env; + process.env = {}; + }); + + afterAll(() => { + process.env = processEnv; + }); + + test('getAbsoluteURL returns the localhost URL', async () => { + vi.spyOn(codespaces, 'isGitHubCodespace', 'get').mockReturnValue(false); + const options = await getWpNowConfig({ port: 7777 }); + + expect(options.absoluteUrl).toBe('http://localhost:7777'); + vi.resetAllMocks(); + }); + + test('getAbsoluteURL returns the codespace URL', async () => { + vi.spyOn(codespaces, 'isGitHubCodespace', 'get').mockReturnValue(true); + process.env.CODESPACE_NAME = 'my-codespace-name'; + process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN = + 'preview.app.github.dev'; + const options = await getWpNowConfig({ port: 7777 }); + + expect(options.absoluteUrl).toBe( + 'https://my-codespace-name-7777.preview.app.github.dev' + ); + vi.resetAllMocks(); + }); +});