Skip to content

[Blueprints v2] Blueprint validation - #144

Draft
JanJakes wants to merge 6 commits into
trunkfrom
blueprint-validation
Draft

[Blueprints v2] Blueprint validation#144
JanJakes wants to merge 6 commits into
trunkfrom
blueprint-validation

Conversation

@JanJakes

Copy link
Copy Markdown
Member

WIP alternative exploration to #142.

Closes#132.

@JanJakes

Copy link
Copy Markdown
MemberAuthor

Here's a bit of a demo of what this WIP does now:

$ blueprint.php info blueprint.json
ERRORS FOUND:
themes:
Invalid path "wp-content/invalid/test.php". Expected to match "wp-content/themes/*".
plugins:
Invalid path "wp-content/invalid/test.php". Expected to match "wp-content/plugins/*".
media:
Invalid path "wp-content/invalid/image.jpg". Expected to match "wp-content/uploads/*".
content:
Invalid path "wp-content/content/invalid/test.xml". Expected to match "wp-content/content/posts/*".
Invalid path "wp-content/content/invalid/test.xml". Expected to match "wp-content/content/posts/*".
BLUEPRINT:
version: 2
siteLanguage: "en_US"
wordpressVersion: "6.7"
constants: {"TEST_CONSTANT":"plugins"}
siteOptions: {"blogname":"Full Featured Test Site"}
plugins: ["./wp-content/plugins/test.php","./wp-content/invalid/test.php"]
themes: ["./wp-content/themes/test.php","./wp-content/invalid/test.php"]
media: ["./wp-content/uploads/image.jpg","./wp-content/invalid/image.jpg"]
content: [{"type":"posts","source":"./wp-content/content/posts/test.xml"},{"type":"posts","source":"./wp-content/content/invalid/test.xml"},{"type":"posts","source":["./wp-content/content/posts/test.xml","./wp-content/content/invalid/test.xml"]}]
additionalStepsAfterExecution: []
EXECUTION PLAN:
[1] defineConstants
constants: {"TEST_CONSTANT":"plugins"}
[2] setSiteOptions
options: {"blogname":"Full Featured Test Site"}
[3] installTheme
source: "./wp-content/themes/test.php"
active: false
importStarterContent: false
[4] installTheme
source: "./wp-content/invalid/test.php"
active: false
importStarterContent: false
[5] installPlugin
source: "./wp-content/plugins/test.php"
[6] installPlugin
source: "./wp-content/invalid/test.php"
[7] importMedia
media: ["./wp-content/uploads/image.jpg","./wp-content/invalid/image.jpg"]
[8] setSiteLanguage
language: "en_US"
[9] importContent
content: [{"type":"posts","source":"./wp-content/content/posts/test.xml"},{"type":"posts","source":"./wp-content/content/invalid/test.xml"},{"type":"posts","source":["./wp-content/content/posts/test.xml","./wp-content/content/invalid/test.xml"]}]

@JanJakes

Copy link
Copy Markdown
MemberAuthor

@adamziel The validation is not complete yet — some steps have more complex requirements — but I think this architecture could work.

At the moment, the BlueprintParser::parse() method returns a Blueprint instance that exposes the plan via $bluprint->getExecutionPlan(). However, that's just an intermediate array of step names and args that are later converted to the step instances.

I think I could take this further and make the parser (maybe renaming it to BlueprintCompiler) create the plan as step instances directly. This would also enable us to move the validation into the step classes by adding a validate( $args ) method to StepInterface. Not sure whether to do this move or not; it has pros and cons, but it's something we could consider.

@JanJakes
JanJakesforce-pushed the blueprint-validation branch from a7ba5a8 to 0a823e0CompareAugust 14, 2025 11:35
@JanJakes
JanJakesforce-pushed the blueprint-validation branch 2 times, most recently from 45ea455 to 8114999CompareAugust 20, 2025 14:13
@JanJakes
JanJakesforce-pushed the blueprint-validation branch 2 times, most recently from 48839cd to a9e0e95CompareAugust 21, 2025 14:12
@JanJakes
JanJakesforce-pushed the blueprint-validation branch from a9e0e95 to eb04387CompareAugust 21, 2025 14:15
@adamziel

Copy link
Copy Markdown
Collaborator

I think I could take this further and make the parser (maybe renaming it to BlueprintCompiler) create the plan as step instances directly.

This could be potentially useful in the future but it wouldn't make that much of a difference now. Let's keep this in mind and revisit it when a good use-case comes up.

}

private function is_bundle_source( string $source ): bool {
return ! str_contains( $source, '://' ) && str_contains( $source, '/' );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd need to run this against a list of data references and confirm that URLReference, GitPath etc. fail to resolve while the AbsoluteLocalPath resolves successfully, similarly to what DataReference::create() does. We have a bunch of data reference syntaxes with possibly more to come, and not even all of them are strings.

$this->assertSame( [
[
'line' => 5,
'message' => 'Invalid plugin path. The path must start with "wp-content/plugins/": ./wp-content/invalid/invalid-plugin-file.php'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message slightly confused me at first, as in I went "oh, it's about the ./ prefix. No, wait, it's about the /plugins/ part". I wonder if we could rephrase it somehow to make it clear it's about the parent path, not syntax micronuances.

@adamziel

Copy link
Copy Markdown
Collaborator

This looks good @JanJakes! I've left a few notes and there's a few failing tests. We're pretty close to merging

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Blueprints v2] Constraint the Blueprint bundle format

2 participants

@JanJakes@adamziel