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

A Playground server package #1056

Open
bgrgicak opened this issue Feb 26, 2024 · 7 comments
Open

A Playground server package #1056

bgrgicak opened this issue Feb 26, 2024 · 7 comments
Labels
[Focus] Developer Tools [Type] Developer Experience [Type] Enhancement New feature or request [Type] Exploration An exploration that may or may not result in mergable code [Type] Idea

Comments

@bgrgicak
Copy link
Collaborator

Playground currently has a Node package that is used by products like wp-now.
Would it be useful to add a @wp-playground/server package that starts an Express (or similar) server with Playground?

This would work similarly to the wp-now server. The server could use a selected folder as a root of the WordPress server and serve it like Apache or Nginx.

The goal of this would be to create an easy-to-run Apache and Nginx alternative for hosting WordPress.

@bgrgicak bgrgicak added [Type] Enhancement New feature or request [Type] Developer Experience [Focus] Developer Tools [Type] Exploration An exploration that may or may not result in mergable code [Type] Idea labels Feb 26, 2024
@adamziel
Copy link
Collaborator

adamziel commented Mar 6, 2024

There could be:

  • A @php-wasm/server package in Playground repo
  • A @wp-playground/server package that consumes the above and runs Blueprints.

Other notes:

  • Standardized way of spinning a Blueprint – the same for the server and an in-browser Playground. Also GitHub repos in a standard path. Also WP.org plugins SVN repos
  • Useful features: Multiple Blueprints, additional static assets shipped with Blueprints.

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Mar 7, 2024

How would Multiple Blueprints work?

@adamziel
Copy link
Collaborator

adamziel commented Mar 7, 2024

@bgrgicak one of then would run by default and the others would be available via CLI options.

@bgrgicak
Copy link
Collaborator Author

A few things why I think a server is useful:

  • It would create a standardized way of running a Playground server which could be used by wp-now, mobile apps, and servers.
  • This could become the standard way of hosting WordPress.
  • It would make testing of Playground Node easier by allowing us to start the server locally and make requests to it using CURL/Postman.

@adamziel
Copy link
Collaborator

adamziel commented Apr 11, 2024

Let's ditch node.js dependency and bundle this package using bun:

https://bun.sh/docs/bundler/executables

Bun's bundler implements a --compile flag for generating a standalone binary from a TypeScript or JavaScript file.
All imported files and packages are bundled into the executable, along with a copy of the Bun runtime. All built-in Bun and Node.js APIs are supported.

It "just worked" for me:

bun build ./main.js --compile --minify --outfile php-wasm-cli; ./php-wasm-cli

CleanShot 2024-04-10 at 10 10 57@2x

It kept all the dynamically loaded .wasm paths local to my machine, though, so a bit more work would be needed to bundle them. This is promising, though. No more Node.js version mismatches, dependency issues, and 3GB node_modules directories. cc @sejas @wojtekn for wp-now and Studio considerations.

@adamziel
Copy link
Collaborator

Related: #1289

@adamziel
Copy link
Collaborator

This could be a Bun alternative, if Bun doesn't pan out for any reason (so far it seems great) https://bellard.org/quickjs/

adamziel added a commit that referenced this issue Apr 29, 2024
A CLI tool for running WordPress playground locally instead of in the
browser.

## Usage when testing this PR

```shell
# Just run a clean-slate WordPress server
$ bun packages/playground/cli/src/cli.ts server --wp=6.5
WordPress is running on http://127.0.0.1:9400

# Start PHP server and mount a WordPress develop build at /wordpress
$ bun ./packages/playground/cli/src/cli.ts server --mount=../../wordpress-develop/build:/wordpress
WordPress is running on http://127.0.0.1:9400
```

The end goal is to create a portable cross-OS server binary with Bun,
see #1056 for
more context.

## Usage after merging this PR

```shell
$ npx @wp-playground/cli server --wp=6.5
```

## Flexible and unoppinionated

Playground CLI is simple, configurable, and unoppinionated. You can set
it up
to your unique WordPress setup. For example, this command would run the
documentation
workflow at https://github.com/adamziel/playground-docs-workflow:

```shell
bun --config=/Users/adam/.bunfig.toml \
    ./packages/playground/cli/src/cli.ts \
    server \
    --mount=./wp-content/plugins/wp-docs-plugin:/wordpress/wp-content/plugins/wp-docs-plugin \
    --mount=./wp-content/html-pages:/wordpress/wp-content/html-pages \
    --mount=./wp-content/uploads:/wordpress/wp-content/uploads \
    --mount=./wp-content/themes/playground-docs:/wordpress/wp-content/themes/playground-docs \
    --blueprint=./wp-content/blueprint-wp-now.json \
    --wp=6.5
```

It is long, sure, but it is also very flexible. If you need a shorter
version, you can alias
it or write a bash script. In the future, Blueprints might support
relative path mappings,
at which point that command would get much shorter.

## Usage 

Playground CLI supports three commands:

-   `server` - start a fresh WordPress playground server.
- `build-snapshot` – run a Blueprint and output a .zip file with the
resulting WordPress instance.
-   `run-blueprint` – just run the Blueprint and exit

Here's the CLI usage:

```
Positionals:
  command  Command to run                   [string] [choices: "server", "run-blueprint", "build-snapshot"]

Options:
  --help                Show help                                      [boolean]
  --version             Show version number                            [boolean]
  --outfile             When building, write to this output file.
                                             [string] [default: "wordpress.zip"]
  --port                Port to listen on when serving. [number] [default: 9400]
  --php                 PHP version to use.
  [string] [choices: "8.3", "8.2", "8.1", "8.0", "7.4", "7.3", "7.2", "7.1", "7.
                                                            0"] [default: "8.0"]
  --wp                  WordPress version to use.   [string] [default: "latest"]
  --mount               Mount a directory to the PHP runtime.            [array]
  --login               Should log the user in        [boolean] [default: false]
  --blueprint           Blueprint to execute.                           [string]
  --skipWordPressSetup  Do not download, unzip, and install WordPress. Useful for
                        mounting a pre-configured WordPress directory at /wordpress
                        [boolean] [default: false]
```

### Server

Playground is a WordPress server:

```shell
$ bun ./packages/playground/cli/src/cli.ts server
Setting up WordPress latest
Running a blueprint – 100%
WordPress is running on http://127.0.0.1:9400
```

### Builder

Playground can build a `Blueprint.json` file into a `wordpress.zip`:

```shell
$ bun ./packages/playground/cli/src/cli.ts build \
     --blueprint=./blueprint.json \
     --outfile=wp.zip
Setting up WordPress latest
Running the blueprint – 100%
Zipping WordPress to wp.zip
WordPress saved to wp.zip
```

All the mounts you specify will still apply.

## Philosophy

The data flow is as follows:

-   Start PHP
-   Mount any local directories
- Put a fresh WordPress in the resulting virtual filesystem (unless
you're mounting directly at /wordpress).
-   Start a local server, accept requests
-   Run the Blueprint

On each run, a fresh WordPress release is unzipped in the virtual
filesystem. It is sourced
from a zip file cached at `~/.wordpress-playground/`. If you mess up
your site, just restart the
server and you'll get a fresh one, again unzipped. The CLI tool never
modifies the zip file
so you can always be sure you're starting from a clean slate.

## Future work

In the guture, Playground CLI may support:

-   Loading Blueprints from URLs.
-   Saving the running WordPress site and loading it later.
- Caching all remote resources referenced in Blueprints. Currently, they
are downloaded on each run.

Conceptually, this isn't too different from Docker containers. There are
images (zip files),
containers (running instances), and commands (Blueprints). Playground
could support the same
concepts such as:

-   Listing and managing available images and containers.
-   Saving a running container and restoring it later
- Starting a container from a specific image (already supported via zip
files)
-   Running a command in a container (the `php` command)
-   Building a new image from a Blueprint (the `build` command)
- Step-by-step cache for Blueprints so that only the changed steps are
re-run.

## Interoperability

This CLI package is not just a useful tool. It drives interoperability
between the in-browser
Playground, CLI packages, and the PHP Blueprints library. Once complete,
it will reuse the
same internals as the website at https://playground.wordpress.org
whether we're talking about
running PHP code, executing Blueprints, building snapshots, serving
requests, or maintaining
multiple PHP instances

## Known issues

* The progress bar sometimes does not reach 100% and the sequencing of
the events means a newline is displayed between `Running a blueprint`
and `100%`.

## Possible improvements

* Blueprints downloads are not cached but performed each time, e.g.
gutenberg.zip will be download on each build.
* The built binary is 180MB large as it bundles all the .wasm modules.
We could only ship PHP 8.0 for starters and download the rest on demand.
* Grid build for all the OSes and CPUs.

## How do I run the binary? I'm getting an error!

@stoph Wrote this excellent guide:

Once downloaded find the file in your terminal. If you initially try to
run it, you’ll get an error

```shell
$ ./playground-cli
zsh: permission denied: ./playground-cli
```

You’ll need to grant execute permissions to allow it to run

```shell
$ chmod +x playground-cli
```

You’ll then get a pop-up form MacOS warning about untrusted code. 


![unnamed](https://github.com/WordPress/wordpress-playground/assets/205419/09e03278-d83f-44be-8417-fed9f6e0a244)

Find the file in your Finder. Right click and select “Open” This should
not give you the option to Open from the dialog.


![unnamed](https://github.com/WordPress/wordpress-playground/assets/205419/367cb3dc-9883-4de0-bc66-99e0b4804f9b)

Once that’s done, you can close the terminal it launched and should be
able to run it without issue from the command line going forward.

```shell
$ ./playground-cli server
```

cc @dmsnell
@adamziel adamziel moved this to Future work in Playground Board Jul 1, 2024
brandonpayton added a commit that referenced this issue Sep 27, 2024
… WebApp Redesign (#1731)

## Description

Implements a large part of the [website
redesign](#1561):

![CleanShot 2024-09-14 at 10 24
57@2x](https://github.com/user-attachments/assets/f245c7ac-cb8c-4e5a-b90a-b4aeff802e7b)


High-level changes shipped in this PR:

* Multiple Playgrounds. Every temporary Playground can be saved either
in the browser storage (OPFS) or in a local directory (Chrome desktop
only for now).
* New Playground settings options: Name name, language, multisite
* URL as the source of truth for the application state
* State management via Redux

This work is a convergence of 18+ months of effort and discussions. The
new UI opens relieves the users from juggling ephemeral Playgrounds and
losing their work. It opens up space for long-lived site configurations
and additional integrations. We could bring over all the [PR previewers
and demos](https://playground.wordpress.net/demos/) right into the
Playground app.

Here's just a few features unblocked by this PR:

* #1438 – no
more losing your work by accident 🎉
* #797 – with
multiple sites we can progressively build features we'll eventually
propose for WordPress core:
* A Playground export and import feature, pioneering the standard export
format for WordPress sites.
* A "Clone this Playground" feature, pioneering the [Site Transfer
Protocol](https://core.trac.wordpress.org/ticket/60375).
   * A "Sync two Playgrounds" feature, pioneering the Site Sync Protocol
* #1445 – better
git support is in top 5 most highly requested features. With multiple
Playgrounds, we can save your work and get rid of the "save your work
before connecting GitHub or you'll lose it" and cumbersome "repo setup"
forms on every interaction. Instead, we can make git operations like
Pull, Commit, etc. very easy and even enable auto-syncing with a git
repository.
* #1025 – as we
bring in more PHP plumbing into this repository, we'll replace the
TypeScript parts with PHP parts to create a WordPress core-first
Blueprints engine
* #1056 – Site
transfer protocol will unlocks seamlessly passing Playgrounds between
the browser and a local development environment
* #1558 – we'll
integrate [the Blueprints directory] and offer single-click Playground
setups, e.g. an Ecommerce store or a Slide deck editor.
#718.
* #539 – the
recorded Blueprints would be directly editable in Playground and perhaps
saved as a new Playground template
* #696 – the new
interaction model creates space for additional integrations.
* #707 – you
could create a "GitHub–synchronized" Playground
* #760 – we can
bootstrap one inside Playground using a Blueprint and benefit the users
immediately, and then gradually work towards enabling it on
WordPress.org
* #768 – the new
UI has space for a "new in Playground" section, similar to what Chrome
Devtools do
* #629  
* #32
* #104
* #497
* #562
* #580 

### Remaining work

- [ ] Write a release note for https://make.wordpress.org/playground/
- [x] Make sure GitHub integration is working. Looks like OAuth
connection leads to 404.
- [x] Fix temp site "Edit Settings" functionality to actually edit
settings (forking a temp site can come in a follow-up PR)
- [x] Fix style issue with overlapping site name label with narrow site
info views
- [x] Fix style issue with bottom "Open Site" and "WP Admin" buttons
missing for mobile viewports
- [x] Make sure there is a path for existing OPFS sites to continue to
load
- [x] Adjust E2E tests.
- [x] Reflect OPFS write error in UI when saving temp site fails
- [x] Find a path forward for
[try-wordpress](https://github.com/WordPress/try-wordpress) to continue
working after this PR
- [x] Figure out why does the browser get so choppy during OPFS save. It
looks as if there was a lot of synchronous work going on. Shouldn't all
the effort be done by a worker a non-blocking way?
- [x] Test with Safari and Firefox. Might require a local production
setup as FF won't work with the Playground dev server.
- [x] Fix Safari error: `Unhandled Promise Rejection: UnknownError:
Invalid platform file handle` when saving a temporary Playground to
OPFS.
- [x] Fix to allow deleting site that fails to boot. This is possible
when saving a temp site fails partway through.
- [x] Fix this crash:

```ts
		/**
		 * @todo: Fix OPFS site storage write timeout that happens alongside 2000
		 *        "Cannot read properties of undefined (reading 'apply')" errors here:
		 * I suspect the postMessage call we do to the safari worker causes it to
		 * respond with another message and these unexpected exchange throws off
		 * Comlink. We should make Comlink ignore those.
		 */
		// redirectTo(PlaygroundRoute.site(selectSiteBySlug(state, siteSlug)));
```
- [x] Test different scenarios manually, in particular those involving
Blueprints passed via hash
- [x] Ensure we have all the aria, `name=""` etc. accessibility
attributes we need, see AXE tools for Chrome.
- [x] Update developer documentation on the `storage` query arg (it's
removed in this PR)
- [x] Go through all the `TODOs` added in this PR and decide whether to
solve or punt them
- [x] Handle errors like "site not found in OPFS", "files missing from a
local directory"
- [x] Disable any `Local Filesystem` UI in browsers that don't support
them. Don't just hide them, though. Provide a help text to explain why
are they disabled.
- [x] Reduce the naming confusion, e.g. `updateSite` in redux-store.ts
vs `updateSite` in `site-storage.ts`. What would an unambiguous code
pattern look like?
- [x] Find a reliable and intuitive way of updating these deeply nested
redux state properties. Right now we do an ad-hoc recursive merge that's
slightly different for sites and clients. Which patterns used in other
apps would make it intuitive?
- [x] Have a single entrypoint for each logical action such as "Create a
new site", "Update site", "Select site" etc. that will take care of
updating the redux store, updating OPFS, and updating the URL. My ideal
scenario is calling something like `updateSite(slug, newConfig)` in a
React Component and being done without thinking "ughh I still need to
update OPFS" or "I also have to adjust that .json file over there"
- [x] Fix all the tiny design imperfections, e.g. cut-off labels in the
site settings form.

### Follow up work

- [ ] Mark all the related blocked issues as unblocked on the project
board, e.g.
#1703,
#1731, and more –
[see the All Tasks
view](https://github.com/orgs/WordPress/projects/180/views/2?query=sort%3Aupdated-desc+is%3Aopen&filterQuery=status%3A%22Up+next%22%2C%22In+progress%22%2C%22Needs+review%22%2C%22Reviewed%22%2C%22Done%22%2CBlocked)
- [ ] Update WordPress/Learn#1583 with info
that the redesign is now in and we're good to record a video tutorial.
- [ ] #1746
- [ ] Write a note in [What's new for developers? (October
2024)](WordPress/developer-blog-content#309)
- [ ] Document the new site saving flow in
`packages/docs/site/docs/main/about/build.md` cc @juanmaguitar
- [ ] Update all the screenshots in the documentation cc @juanmaguitar 
- [ ] When the site fails to load via `.list()`, still return that
site's info but make note of the error. Not showing that site on a list
could greatly confuse the user ("Hey, where did my site go?"). Let's be
explicit about problems.
- [ ] Introduce notifications system to provide feedback about outcomes
of various user actions.
- [ ] Add non-minified WordPress versions to the "New site" modal.
- [ ] Fix `console.js:288 TypeError: Cannot read properties of undefined
(reading 'apply') at comlink.ts:314:51 at Array.reduce (<anonymous>) at
callback (comlink.ts:314:29)` – it seems to happen at trunk, too.
- [ ] Attribute log messages to the site that triggered them.
- [ ] Take note of any interactions that we find frustrating or
confusing. We can perhaps adjust them in a follow-up PR, but let's make
sure we notice and document them here.
- [ ] Solidify the functional tooling for transforming between `URL`,
`runtimeConfiguration`, `Blueprint`, and `site settings form state` for
both OPFS sites and in-memory sites. Let's see if we can make it
reusable in Playground CLI.
- [ ] Speed up OPFS interactions, saving a site can take quite a while.
- [ ] A mobile-friendly modal architecture that doesn't stack modals,
allows dismissing, and understands some modals (e.g. fatal error report)
might have priority over other modals (e.g. connect to GitHub). Discuss
whether modals should be declared at the top level, like here, or
contextual to where the "Show modal" button is rendered.
- [ ] Discuss the need to support strong, masked passwords over a simple
password that's just `"password"`.
- [ ] Duplicate site feature implemented as "Export site + import site"
with the new core-first PHP tools from
adamziel/wxr-normalize#1 and
https://github.com/adamziel/site-transfer-protocol
- [x] Retain temporary sites between site changes. Don't just trash
their iframe and state when the user switches to another site.

Closes #1719

cc @brandonpayton

---------

Co-authored-by: Brandon Payton <brandon@happycode.net>
Co-authored-by: Bero <berislav.grgicak@gmail.com>
Co-authored-by: Bart Kalisz <bartlomiej.kalisz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Focus] Developer Tools [Type] Developer Experience [Type] Enhancement New feature or request [Type] Exploration An exploration that may or may not result in mergable code [Type] Idea
Projects
None yet
Development

No branches or pull requests

2 participants