Open adamziel opened 1 year ago
@adamziel For semver combinations, (ie "php": ">=7.4 <8.0"
) would it be appropriate to use logical-and space
notation here? https://devhints.io/semver (see: Combining ranges
)
It looks to be supported by the major semver libs in both JS & PHP:
https://www.npmjs.com/package/semver#advanced-range-syntax
https://getcomposer.org/doc/articles/versions.md#version-range https://packagist.org/packages/composer/semver
@seanmorris that could be an interesting direction! Probably nothing to worry about for now, though – the constraints
field isn't supported at the moment. I was envisioning it while writing up this issue, but noone ever asked to actually implement it so maybe the demand isn't there.
This Blueprint.json for the interactive-code-block plugin could come handy when exploring this issue: https://github.com/WordPress/playground-tools/blob/trunk/packages/interactive-code-block/public/blueprint.json @seanmorris
Consider each step and each property of the Blueprint as its own datatype. If we do that and take inspiration from the Monoid
type class, we can think of each type having an append
method (as well as an empty value empty
that provides a no-op when appended to another).
For a PHP version the empty value is going to be >= 1
or perhaps for our sake >= 5.6.4
. The append needs to find the intersection of intervals.
For steps we probably need to separate out those which demand sequence and those which don't. For plugins and theme installations then, the empty value is just an empty list, and the append merges two lists with uniqueness.
For inherently irreconcilable properties like landingPage
we can form a deterministic semantic: first-in-wins or last-in-wins. The empty value is the default /
and the append is replacement.
And so on.
Oooh Monoid
-ization is an interesting idea @dmsnell, thank you for that – I love it. In other words, the mental model is that each Blueprint is already a function composition like below:
blueprint_a = (phpVersion 7.0) . (installPlugin "gutenberg") . ( landingPage "/" )
blueprint_b = (installTheme "pendant" ) . (phpVersion 8.2) . (installPlugin "classic-editor")
But if so, merging them both would be just composing all the functions together:
blueprint_c = blueprint_a . blueprint_b
Or perhaps even:
blueprint_a = (phpVersion 7.0) >>= (installPlugin "gutenberg") >>= ( landingPage "/" )
blueprint_b = (installTheme "pendant" ) >>= (phpVersion 8.2) >>= (installPlugin "classic-editor")
blueprint_c = blueprint_a >>= blueprint_b
the mental model is that each Blueprint is already a function composition like below:
more specifically, each kind of property in the Blueprint is, and any properties/steps that aren't explicitly defined are implicitly there with their empty value.
this is based on the idea that the properties are probably independent and most things are append-only. e.g. there's no removePlugin
step.
const finalBlueprints = allBlueprints.reduce( mergeBlueprints, emptyBlueprints );
@adamziel not sure why this wasn't on the board, pulling it in.
Surfacing this relevant comment from Running Multiple Blueprints:
@swissspidy so if I understand correctly, you would like to:
...like in multi-stage Docker builds?
If so, you should be able to do it with:
npx @wp-playground/cli@latest run-blueprint --blueprint=my-blueprint.json --mount-before-install="./my-wp-dir:/wordpress"
npx @wp-playground/cli@latest run-blueprint --blueprint=remote-blueprint.json --mount-before-install="./my-wp-dir:/wordpress"
This will use your local directory as the base site without forcefully installing WordPress in VFS and using that.
I would love to support that natively in the Playground webapp. It should be fairly easy with the upcoming first-class support for stored sites. We could accept multiple Blueprints via the Query API or, alternatively, consider a run-blueprint
step.
It related to Merging Blueprints, except merging would run two Blueprints at once and with sequential runs we could run the first Blueprint, wait a month, and run a second one. This seems similar to Docker base images.
Perhaps the "multistage build" strategy could become the first official way of "merging Blueprints". It's not quite merging, sure, but perhaps merging was the wrong idea all along. Multistage seems clean, doesn't require any special resolution rules, and conveniently it gives us multistage builds for free. And if it's ever not enough, then we can discuss where it falls short and how to address that. Ha! Thank you @swissspidy! This is why I really like letting some of these architectural problems simmer for a long time.
I want to be able to merge these two Blueprints:
And get a single Blueprint which sets up a site that's both a blog and a store
Known plugins with a Blueprint.json file
Let's use these Blueprints to explore the merging process
Related