-
Notifications
You must be signed in to change notification settings - Fork 466
feat: implement SemVer-compliant update checker #3251
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
Conversation
| * | ||
| * @return array<string,array<string,mixed>> The array of plugins that maybe use WPGraphQL as a dependency, keyed by plugin path. | ||
| */ | ||
| protected function get_possible_dependents(): array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function get_possible_dependents has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
| * | ||
| * @return array<string,array<string,mixed>> The array of plugins that use WPGraphQL as a dependency, keyed by plugin path. | ||
| */ | ||
| protected function get_dependents(): array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function get_dependents has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
f54cf93 to
24b8b74
Compare
24b8b74 to
6a65b0f
Compare
| return false; | ||
| } | ||
|
|
||
| return $default_value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid too many return statements within this method.
|
@justlevine very cool! Will take a look 👀 |
6a65b0f to
0e0d8db
Compare
| * @return array<string,array<string,mixed>> The array of untested plugin data. | ||
| * @throws \InvalidArgumentException If the WPGraphQL version is invalid. | ||
| */ | ||
| public function get_untested_plugins( string $release_type ): array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function get_untested_plugins has a Cognitive Complexity of 18 (exceeds 5 allowed). Consider refactoring.
| * | ||
| * @return array<string,array<string,mixed>> The array of incompatible plugins. | ||
| */ | ||
| public function get_incompatible_plugins( string $version = WPGRAPHQL_VERSION, bool $active_only = false ): array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function get_incompatible_plugins has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
| * @param string $plugin_path The plugin path used as the key in the plugins array. | ||
| * @param string $version The current version to check against. | ||
| */ | ||
| private function is_incompatible_dependent( string $plugin_path, string $version = WPGRAPHQL_VERSION ): bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function is_incompatible_dependent has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
6c99cf3 to
46cf09d
Compare
b144672 to
c4ffa98
Compare
|
PR is working and ready for feedback. Of the remaining todos in the PR description:
I'll be testing against
@jasonbahl this is your decision as to whether we do this in this PR or even at all. |
Did a basic review against
Marking ready for review. Disable autoupdates example: add_filter(
'auto_update_plugin',
static function( $should_update, $plugin ) {
// Bail early if the plugin is not the one we're looking for.
if ( ! isset( $plugin->plugin ) || ! isset( $plugin->new_version) ||'wp-graphql-headless-login/wp-graphql-headless-login.php' !== $plugin->plugin ) {
return $should_update;
}
// If autoupdates are already disabled we don't need to check further.
if ( false === $should_update ) {
return $should_update;
}
$new_version = sanitize_text_field( $plugin->new_version );
if ( '' === $new_version ) {
return $should_update;
}
// Check if it's a major release.
$release_type = \WPGraphQL\Admin\Updates\SemVer::get_release_type( WPGRAPHQL_LOGIN_VERSION, $new_version );
if ( 'major' === $release_type ) {
return false;
}
return $should_update;
},
10,
2
); |
jasonbahl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still looking through and testing things but wanted to leave a few comments.
| /** | ||
| * Disables plugins that don't meet the minimum `Requires WPGraphQL` version. | ||
| */ | ||
| public function disable_incompatible_plugins(): void { | ||
| // Initialize the Update Checker. | ||
| $update_checker = new UpdateChecker( (object) get_plugins()['wp-graphql/wp-graphql.php'] ); | ||
|
|
||
| // Get the incompatible plugins. | ||
| $incompatible_plugins = $update_checker->get_incompatible_plugins( WPGRAPHQL_VERSION, true ); | ||
|
|
||
| // Deactivate the incompatible plugins. | ||
| $notice_data = []; | ||
| foreach ( $incompatible_plugins as $file => $plugin ) { | ||
| $notice_data[] = [ | ||
| 'name' => $plugin['Name'], | ||
| 'version' => $plugin[ UpdateChecker::VERSION_HEADER ], | ||
| ]; | ||
| deactivate_plugins( $file ); | ||
| } | ||
|
|
||
| // Display a notice to the user. | ||
| if ( ! empty( $notice_data ) ) { | ||
| set_transient( 'wpgraphql_incompatible_plugins', $notice_data ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon quick scan (haven't tested or thoroughly read all the code yet), this stands out as something a bit concerning.
Mostly leaving a note for myself here, but I need to fully understand what situations will cause this. My initial reaction is that I don't want WPGraphQL to be responsible for de-activating other plugins as it could cause a lot of confusion / distrust.
That said, if this is VERY CLEARLY documented and communicated as a feature and is limited very specifically to plugins that require WPGraphQL (which I assume is already the case - need to look through and test more), then we're probably ok with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to the point about clear documentation, remember that the context here is that a plugin sets Requires WPGraphQL to a higher version than what's currently installed. I.e. it's the plugin author who is opting into this behavior.
Co-authored-by: Jason Bahl <[email protected]>
Correct me if I'm mistaken, but I just want to clarify that the recommendation for extension authors now would be to use all 3 headers. (i.e. we're not replacing "Requires Plugins: wp-graphql", but enhancing things with additional headers) i.e. a current WPGraphQL Extension plugin that had the following header: * Requires Plugins: wp-graphql // This header is recognized by WordPress core, and used on some existing extensionswould adjust like so: * Requires Plugins: wp-graphql
* Requires WPGraphQL: 1.30 // Adjust as needed
* WPGraphQL tested up to: 1.30 // Adjust version as testing is confirmed |
…WPGraphQL plugin update available. This provides a bit more clarity and more straightforward actions to take.
- make messaging in UpdateChecker.php consistent with PluginsScreenLoader
…t_compatibility_warning_message()` function so we can manage the language for the messaging in one place.
|
I ran this through various scenarios locally with WPGraphQL for ACF and overall I'm pretty happy with the experience. Very thorough and well thought out. I have some small adjustments I want to make to some of the language re: compatibility and recommended actions to take before updating, but other than that this is super solid and well tested. 🙌🏻 This will add a lot of confidence for users and maintainers as we navigate the future of releasing breaking changes. |
Close, but not exactly. All 3 are optional and can be used independently, depending on what the extension author is trying to accomplish.
|
|
@justlevine I opened a PR to your branch here with some updates to the messaging: justlevine#3 |
Ok, I get where you're going with this. WPGraphQL for ACF specifically does use some functions from WPGraphQL in the admin UI screens for configuring ACF Field Groups and Fields to show in the schema, so WPGraphQL really is required. There's likely some defensive programming to ensure the functions exist before calling them (I should probably double check 👀, but WPGraphQL really is required for it). . .but I get the spirit of the idea. Some plugins might be compatible with WPGraphQL but might not TRULY require it.
👌🏻
Great summary! This will help document this feature for release. 🙌🏻 |
chore: update messaging around compatibility and recommended actions before updating
| * @param array<string,array<string,mixed>> $untested_plugins The untested plugins. | ||
| * @return string The formatted HTML message. | ||
| */ | ||
| public function get_compatibility_warning_message( array $untested_plugins ): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method get_compatibility_warning_message has 59 lines of code (exceeds 40 allowed). Consider refactoring.
| @@ -0,0 +1,628 @@ | |||
| <?php | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File UpdateChecker.php has 314 lines of code (exceeds 250 allowed). Consider refactoring.
…ome of the wording
|
Code Climate has analyzed commit 6ae6870 and detected 12 issues on this pull request. Here's the issue category breakdown:
View more on Code Climate. |
What does this implement/fix? Explain your changes.
This PR implements Semantic Version checking when updating WPGraphQL to a newer version.
How it works:
A new
Admin\Updates\UpdateCheckerclass has been introduced to check whether an update is likely "non-breaking" (per Semantic Versioning). This class is used both to prevent auto-updates and to display update information before a manual update is applied.The
UpdateCheckerclass also checks if there are any explicitly incompatible or possibly untested WPGraphQL extensions that should be checked/updated before (auto)updating.New Plugin headers for extensions:
Requires WPGraphQL: {x.y.z}sets a minimum plugin version.WPGraphQL tested up to: {x.y.z}sets the last known compatible version.Plugins that use the
Requires Plugins: wp-graphqlor useWPGraphQLin the plugin name or description are detected with anUnknownversion compatibility.The
PluginScreenLoaderandUpdateScreenLoaderclasses inject the notices/modals into the admin screens to warn and confirm about untested extensions that are potentially breaking.packages/updatespackage contains the.scssto style our notices/modals. Additionally,webpack-remove-empty-scriptshas been added to our NPM deps to prevent the generation of an empty.jsfile.New filters:
wpgraphql_enable_major_autoupdates- allows for major versions to be auto-updateable. Defaultsfalse.wpgraphql_untested_release_type- determines which SemVer release type should be considered potentially "breaking". Defaultsmajor.graphql_get_dependentsandgraphql_get_possible_dependentsfilter the list of (possible) WPGraphQL extensions.Todo
Requires WPGraphQLversionreadme.txtDoes this close any currently open issues?
Closes #2543
Testing Instructions
Install a WPGraphQL Extension. (you can copy the mock extensions from
test/data/pluginsintowp-content/plugins)Mock an available update:
Updates Screen:
a. Visit
/wp-admin/update-core.phpand refresh the screen a few times* until the update is available.b. Select
WPGraphQLfrom the list of plugins to view the modal.c. Click
Cancelto see WPGraphQL get unchecked.Plugins Screen
a. Visit
wp-admin/plugins.phpand refresh the screen a few times* until the update is available.b. Click the inline
Update nowlink to view the modal.Warning
DO NOT try to update WPGraphQL to the fictitious version. (e.g. clicking the
Update nowbutton in the modal).It will delete the existing
wp-graphqlplugin, including the sym-linked reference to the repo.Any relevant logs, error output, GraphiQL screenshots, etc?
Plugin Screen notice:
Plugin Screen modal:
Update Screen modal:
Deactivated Plugin notice
Any other comments?
Displaying Upgrade Notes:
Possibly beyond the scope, but if as part of our Upgrade Policy (docs: update upgrading.md to highlight how breaking change releases will be handled #3218) we include Upgrade Notes in the dist version of the plugin somewhere, we can display them in our notices. Prior art: https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php#L80
SemVer-compliant Extension Updates
A personal goal is to make the API reusable enough that any WPGraphQL extension could easily tap into it to make their own updates SemVer compliant. While that's definitely beyond the scope, I will be auditing the API/method signatures so we can support this with non-breaking iteration.
Where has this been tested?
Operating System: Ubuntu 24.04 ( wsl2 + ddev + php8.2.26)
WordPress Version: 6.7.1