FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Fix latest plugin version not being downloaded consistently by ShyamGadde · Pull Request #1693 · WordPress/performance · GitHub

Fix latest plugin version not being downloaded consistently - #1693

Merged
westonruter merged 6 commits into
WordPress:trunkfrom
ShyamGadde:fix/download-link-plugin-version
Nov 26, 2024
Merged

Fix latest plugin version not being downloaded consistently#1693
westonruter merged 6 commits into
WordPress:trunkfrom
ShyamGadde:fix/download-link-plugin-version

Conversation

Copy link
Copy Markdown
Contributor

Summary

Fixes #1690

This is done so that it automatically downloads the latest version
ShyamGadde marked this pull request as ready for review November 22, 2024 14:07

github-actions Bot commented Nov 22, 2024
edited
Loading

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ShyamGadde <shyamgadde@git.wordpress.org>
Co-authored-by: westonruter <westonruter@git.wordpress.org>
Co-authored-by: felixarntz <flixos90@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->install( $plugin_data['download_link'] );
// Remove the version number from the link to download the latest plugin version.
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+\.zip#', '$1.zip', $plugin_data['download_link'] );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

It might be safer to do:

Suggested change
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+\.zip#', '$1.zip', $plugin_data['download_link'] );
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d.*.zip#', '$1.zip', $plugin_data['download_link'] );

The reason being that it's possible for plugin versions to have -rc or -beta tagged on.

For example:
https://wordpress.org/plugins/rest-api/
=>
https://downloads.wordpress.org/plugin/rest-api.2.0-beta15.zip

Granted, it's highly unlikely that we'll ever release one of our plugins with such a Stable Tag, and it's not super common across the repo: https://wpdirectory.net/search/01JDAFQMKVDE6ME17SH47V33D9

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

So I don't feel strongly about this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Worst case in such a scenario is that the original URL ends up getting used without the version removed, which will likely still work (even if it has the even slighter possibility of downloading a stale version).

ShyamGadde Nov 22, 2024
edited
Loading

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Thank you for pointing this out! I hadn’t considered the possibility of version tags like -rc or -beta. That’s an oversight on my part.

However, I believe the regex '#(\/plugin\/[^\/]+)\.\d.*.zip#' might not work as intended because it could capture the plugin name greedily. For instance, in the example provided, the download link might end up being https://downloads.wordpress.org/plugin/rest-api.2.zip instead of https://downloads.wordpress.org/plugin/rest-api.zip.

To address this, one solution could be to simply modify the regex to capture the plugin name non-greedily:

'#(\/plugin\/[^\/]+?)\.\d.*.zip#'

Alternatively, another approach would be to use the following regex:

'#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+(?:-\w+)?\.zip#'

This pattern accounts for optional tags like -rc or -beta and aligns with the regex used in the versions command, so it seems like a good choice to me.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Note in the example https://downloads.wordpress.org/plugin/rest-api.2.0-beta15.zip there is no patch version either, just a major and minor. So that would need to be optional as well.

This should address the greediness issue, by using \.\d.*?.zip instead of \.\d.*.zip:

$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d.*?.zip#', '$1.zip', $plugin_data['download_link'] );

westonruter added this to the performance-lab n.e.x.t milestone Nov 22, 2024
westonruter added [Type] Bug An existing feature is broken [Plugin] Performance Lab Issue relates to work in the Performance Lab Plugin only labels Nov 22, 2024
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->install( $plugin_data['download_link'] );
// Remove the version number from the link to download the latest plugin version.
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+(?:-\w+)?\.zip#', '$1.zip', $plugin_data['download_link'] );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality
Suggested change
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+(?:-\w+)?\.zip#', '$1.zip', $plugin_data['download_link'] );
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d.*?.zip#', '$1.zip', $plugin_data['download_link'] );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Or rather, per #1693 (comment)

Suggested change
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+(?:-\w+)?\.zip#', '$1.zip', $plugin_data['download_link'] );
$download_link = (string) preg_replace( '#(\/plugin\/[^\/.]+)\..+?\.zip#', '$1.zip', $plugin_data['download_link'] );

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Stripping off everything up to the first . makes sense. However, I also noticed that some plugins have their download link as https://downloads.wordpress.org/plugin/<plugin-slug>.zip, particularly those with tags like trunk, such as https://downloads.wordpress.org/plugin/better-search-replace.zip.

Given this, I think we might need a regex like this:

$download_link = (string) preg_replace( '#(\/plugin\/[^\.]+).*\.zip#', '$1.zip', $plugin_data['download_link'] );

This should account for both cases where the version exists (like rest-api.2.0-beta15.zip) and where it doesn't (like better-search-replace.zip).

ShyamGadde Nov 25, 2024
edited
Loading

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

On second thought, can’t we just construct the download link directly from the slug in the $plugin_data as:

https://downloads.wordpress.org/plugin/<plugin-slug>.zip

This would simplify and remove the need for regex.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Hah. Good point.

Copy link
Copy Markdown
Member

Lastly, note that many plugins also use Stable tag: trunk: https://wpdirectory.net/search/01JDB0D3QBVXR8KWR1X9BRYYPB

I haven't seen trunk show up in the download URL, but in theory it might?

Here's another search for plugins using non-standard versions: https://wpdirectory.net/search/01JDB0R6MBNNEMH0A1X8AHKQYC

The WP Umbrella plugin version doesn't begin with a digit:

https://downloads.wordpress.org/plugin/wp-health.v2.16.4.zip

That being said, perhaps we should just strip off everything up to the first . since I don't believe any plugin is allowed to have that as a character in the slug.

Copy link
Copy Markdown
Member

Again, this is all likely splitting hairs since none of the plugins we include here should ever use a non-standard version!

$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->install( $plugin_data['download_link'] );
// Remove the version number from the link to download the latest plugin version.
$download_link = (string) preg_replace( '#(\/plugin\/[^\/]+)\.\d+\.\d+\.\d+(?:-\w+)?\.zip#', '$1.zip', $plugin_data['download_link'] );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm not a fan of regexing this from the download_link. Is there no externally controlled place (API responses or elsewhere) that exposes the format we want here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Seeing comments like #1693 (comment) confirms my above concern: Using a regex for this is error-prone. Is there no way to get the actual URL from somewhere?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

You’re right; relying on regex for this isn’t ideal. The plugins_api() function, when called with the plugin_information action, provides a versions field in the response that seems to include the URLs in the required format. Here's an example of the response:

{
    ...
    "versions": {
        "0.1.0": "https://downloads.wordpress.org/plugin/optimization-detective.0.1.0.zip",
        "0.1.1": "https://downloads.wordpress.org/plugin/optimization-detective.0.1.1.zip",
        ...
        "trunk": "https://downloads.wordpress.org/plugin/optimization-detective.zip"
    },
    ...
}

We could use the trunk key to get the required URL in most cases. However, there are scenarios where the trunk key doesn’t exist in the versions field. In those cases, the download_link itself is typically already in the desired format without a version or tag.

That said, implementing this approach would require making multiple API calls—one for each plugin—which again might not be ideal.

felixarntz Nov 25, 2024
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Don't we only need the plugin download URL if we actually want to download the plugin? I think making an extra request for that purpose makes sense. We shouldn't make all these requests for all the plugins when we cache the information. But for the moment when someone clicks "Activate" and we have to install that plugin, I think it's reasonable to make the request. I think that's even what WordPress Core does to install a plugin.

And even if the plugin also requires dependencies, making individual requests for these should not be an issue since realistically that shouldn't be more than 2-3 plugins.

This solution would be more reliable than us assuming things about the download URL and using a regex.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

That makes sense to me.

Replaced transient-cached plugin data with a real-time `plugins_api()`
call during installation to avoid installing outdated versions.

westonruter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Since we're not using the download_link anymore in the response to perflab_query_plugin_info(), I removed it from being explicitly returned. I also explicitly requested download_link and requires_plugins when installing, although it seems these are all returned by default anyway.

felixarntz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Thanks @ShyamGadde @westonruter, LGTM!

westonruter merged commit d2d5eae into WordPress:trunk Nov 26, 2024
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Performance Lab Issue relates to work in the Performance Lab Plugin only [Type] Bug An existing feature is broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Old Plugin Version Downloaded Due to Cached API Response in Transient

3 participants


Back | FazBrowse Home | New Git URL