Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wp-now: Update Playground and PHP WASM dependencies #350

Merged
merged 25 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
394594b
Update playground dependencies in package
sejas Aug 1, 2024
af4c5cc
Update playground dependencies
eliot-akira Aug 22, 2024
a35b512
Start updating PHP instantiation, mount and request handler
eliot-akira Aug 22, 2024
46f13cf
Update to new interface for managing PHP runtime instances, request h…
eliot-akira Aug 27, 2024
84e3b78
Update Playground dependencies to 0.9.32
eliot-akira Aug 27, 2024
a44742b
Update `executeWpCli` based on fork of `wp-now` in Automattic/studio
eliot-akira Sep 7, 2024
bc0d15f
Update Playground dependencies to 0.9.37
eliot-akira Sep 7, 2024
a8edcab
Add `@php-wasm/util` as dependency
eliot-akira Sep 7, 2024
602a594
Update Playground dependencies to 0.9.39
eliot-akira Sep 11, 2024
45c5820
Lint
eliot-akira Sep 11, 2024
fc61a8c
Replace NodePHP with PHP
eliot-akira Sep 11, 2024
482b7e6
Use index mode for PHP CLI
eliot-akira Sep 11, 2024
9e30b39
Update executeWPCli to accept options for PHP version and project path
eliot-akira Sep 11, 2024
a96df21
Lint
eliot-akira Sep 11, 2024
2ab6c92
Simplify wp-cli test: Remove consoleSpy
eliot-akira Sep 12, 2024
2ad15cc
Update startWPNow based on Studio fork: Rewrite rules, file not found…
eliot-akira Sep 12, 2024
f9e5690
Lint: Remove unused variables and code
eliot-akira Sep 12, 2024
a97a483
Make project path required for executeWPCli
eliot-akira Sep 12, 2024
46191a5
Remove patch that made PHP CLI only run index mode
eliot-akira Sep 12, 2024
a9069cf
Lint
eliot-akira Sep 12, 2024
42150fd
Update Playground dependencies to 1.0.2
eliot-akira Oct 13, 2024
2dbb1a5
force execute php cli to always work in index mode
sejas Oct 16, 2024
a73938c
fix tests express compressing assets
sejas Oct 16, 2024
34ec26b
Merge branch 'trunk' of github.com:WordPress/playground-tools into up…
sejas Oct 17, 2024
1235519
add type to codeEditorMode on wp playground block package
sejas Oct 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,558 changes: 1,477 additions & 81 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@
"@codemirror/state": "6.4.1",
"@codemirror/theme-one-dark": "6.1.2",
"@codemirror/view": "6.28.1",
"@php-wasm/node": "0.6.16",
"@php-wasm/progress": "0.6.16",
"@php-wasm/universal": "0.6.16",
"@php-wasm/web": "0.6.16",
"@php-wasm/node": "1.0.2",
"@php-wasm/progress": "1.0.2",
"@php-wasm/universal": "1.0.2",
"@php-wasm/util": "1.0.2",
"@php-wasm/web": "1.0.2",
"@uiw/react-codemirror": "4.22.2",
"@webcontainer/env": "1.1.1",
"@wp-playground/blueprints": "0.6.16",
"@wp-playground/blueprints": "1.0.2",
"classnames": "^2.3.2",
"comlink": "^4.4.1",
"compressible": "2.0.18",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {

export default async function downloadZippedPackage(
client: PlaygroundClient,
codeEditorMode
codeEditorMode: string
) {
const docroot = await client.documentRoot;

Expand Down
10 changes: 5 additions & 5 deletions packages/wp-now/src/execute-php.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useHostFilesystem } from '@php-wasm/node';
import startWPNow from './wp-now';
import { WPNowOptions } from './config';
import { WPNowMode, WPNowOptions } from './config';
import { disableOutput } from './output';
import * as path from 'path';
import fs from 'fs-extra';
Expand All @@ -23,14 +24,13 @@ export async function executePHP(
);
}
disableOutput();
const { phpInstances, options: wpNowOptions } = await startWPNow({
const { php, options: wpNowOptions } = await startWPNow({
...options,
numberOfPhpInstances: 2,
mode: WPNowMode.INDEX,
});
const [, php] = phpInstances;

try {
php.useHostFilesystem();
useHostFilesystem(php);
if (!path.isAbsolute(phpArgs[1])) {
const maybePhpFile = path.join(
wpNowOptions.projectPath,
Expand Down
130 changes: 104 additions & 26 deletions packages/wp-now/src/execute-wp-cli.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,121 @@
import startWPNow from './wp-now';
import { downloadWPCLI } from './download';
import { disableOutput } from './output';
import { rootCertificates } from 'tls';
import getWpCliPath from './get-wp-cli-path';
import getWpNowConfig from './config';
import { DEFAULT_PHP_VERSION, DEFAULT_WORDPRESS_VERSION } from './constants';
import { dirname } from 'path';
import { phpVar } from '@php-wasm/util';
import { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';
import {
PHP,
MountHandler,
writeFiles,
setPhpIniEntries,
} from '@php-wasm/universal';
import { readFileSync } from 'fs';

const isWindows = process.platform === 'win32';

/**
* This is an unstable API. Multiple wp-cli commands may not work due to a current limitation on php-wasm and pthreads.
* @param args The arguments to pass to wp-cli.
*/
export async function executeWPCli(args: string[]) {
export async function executeWPCli(
projectPath: string,
args: string[],
{ phpVersion }: { phpVersion?: string } = {}
): Promise<{ stdout: string; stderr: string; exitCode: number }> {
await downloadWPCLI();
disableOutput();
const options = await getWpNowConfig({
php: DEFAULT_PHP_VERSION,
php: phpVersion || DEFAULT_PHP_VERSION,
wp: DEFAULT_WORDPRESS_VERSION,
path: process.env.WP_NOW_PROJECT_PATH || process.cwd(),
path: projectPath,
});
const { phpInstances, options: wpNowOptions } = await startWPNow({
...options,
numberOfPhpInstances: 2,

const id = await loadNodeRuntime(options.phpVersion);
const php = new PHP(id);
php.mkdir(options.documentRoot);
await php.mount(
options.documentRoot,
createNodeFsMountHandler(projectPath) as unknown as MountHandler
);

eliot-akira marked this conversation as resolved.
Show resolved Hide resolved
//Set the SAPI name to cli before running the script
await php.setSapiName('cli');

php.mkdir('/tmp');

const wpCliPath = '/tmp/wp-cli.phar';
const stderrPath = '/tmp/stderr';
const runCliPath = '/tmp/run-cli.php';
const createFiles = {
[wpCliPath]: readFileSync(getWpCliPath()),
[stderrPath]: '',
[runCliPath]: `<?php
// Set up the environment to emulate a shell script
// call.

// Set SHELL_PIPE to 0 to ensure WP-CLI formats
// the output as ASCII tables.
// @see https://github.com/wp-cli/wp-cli/issues/1102
putenv( 'SHELL_PIPE=0' );

// When running PHP on Playground, the value of constant PHP_OS is set to Linux.
// This implies that platform-specific logic won't work as expected. To solve this,
// we use an environment variable to ensure WP-CLI runs the Windows-specific logic.
putenv( 'WP_CLI_TEST_IS_WINDOWS=${isWindows ? 1 : 0}' );

// Set the argv global.
$GLOBALS['argv'] = array_merge([
"${wpCliPath}",
"--path=${options.documentRoot}"
], ${phpVar(args)});

// Provide stdin, stdout, stderr streams outside of
// the CLI SAPI.
define('STDIN', fopen('php://stdin', 'rb'));
define('STDOUT', fopen('php://stdout', 'wb'));
define('STDERR', fopen('${stderrPath}', 'wb'));

// Force disabling WordPress debugging mode to avoid parsing issues of WP-CLI command result
define('WP_DEBUG', false);
// Filter out errors below ERROR level to avoid parsing issues of WP-CLI command result
error_reporting(E_ERROR);

// WP-CLI uses this argument for checking updates. Seems it's not defined by Playground
// when running a script, so we explicitly set it.
// Reference: https://github.com/wp-cli/wp-cli/blob/main/php/WP_CLI/Runner.php#L1889
$_SERVER['argv'][0] = '${wpCliPath}';

require( '${wpCliPath}' );`,
['/internal/shared/ca-bundle.crt']: rootCertificates.join('\n'),
};

await writeFiles(php, '/', createFiles);

await setPhpIniEntries(php, {
'openssl.cafile': '/internal/shared/ca-bundle.crt',
});
const [, php] = phpInstances;

try {
const vfsWpCliPath = '/wp-cli/wp-cli.phar';
php.mount(dirname(getWpCliPath()), dirname(vfsWpCliPath));
await php.cli([
'php',
vfsWpCliPath,
`--path=${wpNowOptions.documentRoot}`,
...args,
]);
} catch (resultOrError) {
const success =
resultOrError.name === 'ExitStatus' && resultOrError.status === 0;
if (!success) {
throw resultOrError;
}
php.chdir(options.documentRoot);
const result = await php.run({
scriptPath: runCliPath,
});
const stderr = php
.readFileAsText(stderrPath)
.replace('PHP.run() output was: #!/usr/bin/env php', '')
.trim();
return {
stdout: result.text.replace('#!/usr/bin/env php', '').trim(),
stderr,
exitCode: result.exitCode,
};
} catch (error) {
const stderr = php
.readFileAsText(stderrPath)
.replace('PHP.run() output was: #!/usr/bin/env php', '')
.trim();
return { stdout: '', stderr: stderr, exitCode: 1 };
} finally {
php.exit();
}
}
9 changes: 4 additions & 5 deletions packages/wp-now/src/start-server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import fs from 'fs';
import { WPNowOptions } from './config';
import { HTTPMethod } from '@php-wasm/universal';
import { HTTPMethod, PHP } from '@php-wasm/universal';
import express from 'express';
import compression from 'compression';
import compressible from 'compressible';
import { portFinder } from './port-finder';
import { NodePHP } from '@php-wasm/node';
import { isWebContainer } from '@webcontainer/env';
import startWPNow from './wp-now';
import { output } from './output';
Expand All @@ -24,7 +23,7 @@ const requestBodyToBytes = async (req): Promise<Uint8Array> =>

export interface WPNowServer {
url: string;
php: NodePHP;
php: PHP;
options: WPNowOptions;
stopServer: () => Promise<void>;
}
Expand All @@ -44,7 +43,7 @@ export async function startServer(
);
}
const app = express();
app.use(compression({ filter: shouldCompress }));
app.use(compression({ filter: shouldCompress, threshold: 0 }));
app.use(addTrailingSlash('/wp-admin'));
const port = await portFinder.getOpenPort();
const { php, options: wpNowOptions } = await startWPNow(options);
Expand Down Expand Up @@ -77,7 +76,7 @@ export async function startServer(
data.headers['origin'] = options.absoluteUrl;
}

const resp = await php.request(data);
const resp = await php.requestHandler.request(data);
res.statusCode = resp.httpStatusCode;
Object.keys(resp.headers).forEach((key) => {
res.setHeader(key, resp.headers[key]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test Page that should be compressed</title>
</head>
</html>
26 changes: 5 additions & 21 deletions packages/wp-now/src/tests/wp-now.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ describe('Test starting different modes', () => {
* Test that startServer compresses the text files correctly.
*/
test.each([
['html', ''],
['html', '/wp-content/themes/theme-with-assets/page.html'],
['css', '/wp-content/themes/theme-with-assets/style.css'],
[
'javascript',
Expand Down Expand Up @@ -753,7 +753,7 @@ describe('Test starting different modes', () => {
`${php.documentRoot}/print-constants.php`,
`<?php echo WP_DEBUG_LOG;`
);
const result = await php.request({
const result = await php.requestHandler.request({
method: 'GET',
url: '/print-constants.php',
});
Expand All @@ -774,7 +774,7 @@ describe('Test starting different modes', () => {
`${php.documentRoot}/print-constants.php`,
`<?php echo WP_SITEURL;`
);
const result = await php.request({
const result = await php.requestHandler.request({
method: 'GET',
url: '/print-constants.php',
});
Expand Down Expand Up @@ -819,22 +819,6 @@ describe('Test starting different modes', () => {
* Test wp-cli command.
*/
describe('wp-cli command', () => {
let consoleSpy;
let output = '';

beforeEach(() => {
function onStdout(outputLine: string) {
output += outputLine;
}
consoleSpy = vi.spyOn(console, 'log');
consoleSpy.mockImplementation(onStdout);
});

afterEach(() => {
output = '';
consoleSpy.mockRestore();
});

beforeAll(async () => {
await downloadWithTimer('wp-cli', downloadWPCLI);
});
Expand All @@ -848,7 +832,7 @@ describe('wp-cli command', () => {
* We don't need the WordPress context for this test.
*/
test('wp-cli displays the version', async () => {
await executeWPCli(['cli', 'version']);
expect(output).toMatch(/WP-CLI (\d\.?)+/i);
const { stdout } = await executeWPCli('.', ['--version']);
expect(stdout).toMatch(/WP-CLI (\d\.?)+/i);
});
});
Loading
Loading