Problem/Motivation
Because of #2807145: [policy, no patch] Allow contrib projects to specify multiple major core branches, Drupal 9 may need to retrieve modules that start with 8.x-. The update module is not currently aware that modules starting with 8.x can be compatible with Drupal 9. Also once as part of #3009338: [META] Support semantic versioning for extensions (modules, themes, etc) in Drupal core, and allow modules to be compatible with Drupal 8 and 9 at the same time Drupal also need to retrieve modules that have semantic versioning releases and don't start with 8.x
Drupal.org now offers a new update xml feed /current
that returns both 8.x- modules but also all the new semantic version modules that will be available.
We can't simply switch the /current
feed because it does not have the same metadata for projects and releases.
Proposed resolution
- Update requests should no longer request information from URLs that have
\Drupal::CORE_COMPATIBILITY
(8.x) as the final path segment. This should be replaced with 'current'. For example, a request that previously requested https://updates.drupal.org/release-history/paragraphs/8.x will now request https://updates.drupal.org/release-history/paragraphs/current - The contents of
/current
has a somewhat different structure than what was returned by requests to/8.x
, The update module and its tests will need refactoring to reflect those changes.- The following tags are no longer provided, the information should be parsed from the version tag instead:
version_major
,version_minor
,version_patch
,version_extra
recommended_major
(which differed depending on the API requested) has been removed. This was only used to determine which major version should be used for available updates if the currently installed version is not supported. Instead the next major version that is supported, as determined bysupported_branches
. Since currently contrib modules don't have branches that have minor version the supported branches should be the same.For core which does have minor branches this will not distinguish between minor core branches. This the same functionality that the update module currently provides for core since the current XML only sends
recommended_major
not branches.supported_majors
replaced withsupported_branches
, which includes core compatibility for non-semver version numbers.In addition to determining the major version should be used as the target major for updates, all updates that are in unsupported branches will not be shown.
- Other tags are removed from the new XML feed and weren't used in core at all
api_version
(also no longer relevant),mdhash
,filesize
- The following tags are no longer provided, the information should be parsed from the version tag instead:
Remaining tasks
Follow-ups
#3100115: The update module should recommend updates based on supported_branches rather than major versions majors
#3100386: Create contrib update module test cases that use semantic versioning
User interface changes
API changes
Data model changes
Release notes snippet
In order for Drupal core's Update Manager module to list all updates for modules when drupal.org allows new semantic version releases of modules, the Update Manager module now requests an alternative XML feed from updates.drupal.org. The path for the new feed ends in /current
rather than /8.x
. The new feed will include not only module releases with version numbers starting with 8.x-
, such as 8.x-3.1
, but also all releases that use the new semantic versioning number system. Site owners will not need to make any changes for this change. For those interested in the differences between the new and old XML feeds the differences are detailed in this documentation page.
Comment | File | Size | Author |
---|---|---|---|
#108 | 3074993-8.8-reroll.patch | 200.07 KB | tedbow |
#101 | 3074993-101.patch | 197.06 KB | tedbow |
#101 | interdiff-99-101.txt | 4.87 KB | tedbow |
#99 | 3074993-99-interdiff.txt | 4.34 KB | kim.pepper |
#99 | 3074993-99.patch | 196 KB | kim.pepper |
Comments
Comment #2
tedbowHere is a patch that just uses "/all"
Comment #3
drummI haven’t done a full look through of the code lately. I suspect there may be some logic that ignores the API compatibility prefix, assuming it is the same all the time. Be sure that testing for
8.x-1.0
>7.x-2.0
exists.Comment #4
Wim LeersThe changes look fine.
But … only somebody who knows the existing translation infrastructure can truly sign off on this. I think that's @drumm and @Gábor Hojtsy, who else?
Comment #5
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedComment #6
Gábor HojtsyThis has nothing to do with the translation infrastructure, that would be #3016471: Make localization file download major version agnostic. This is about fetching available update data for modules. We should check some scenarios:
1. Changing to
/all/
will return 7.x, etc. releases of the modules. This will increase processing need on the client on the data. Not sure if we have projects which had LOTs of releases to the extent this could be a penalty but would be good to check. @drumm can maybe help query the Drupal.org DB for projects ordered by number of releases.2. Changing to
/all/
will return 9.x releases in 8.x and vice versa. Do we have code elsewhere to filter those out? Will d.o allow 9.x release prefixes? If so, will those be explicitly only 9.x+ compatible or could those be also 8.x compatible? If so how does Drupal core tell which release to suggest as viable new update to install. (While update module currently does not resolve the requirements/dependencies of projects (nor info.yml nor composer.json), at least it only suggests projects compatible with the same major core version. Changing this to/all/
changes that behaviour once people release 9.x branched projects (if we allow that).Comment #7
Wim LeersOops, right. Sorry. Mixing up issues 🙃
Comment #8
drummmysql> SELECT n.title project, n.type, count(1) releases, concat('https://www.drupal.org/i/', n.nid) link FROM node n INNER JOIN field_data_field_release_project fdf_rp ON fdf_rp.field_release_project_target_id = n.nid WHERE n.status = 1 GROUP BY n.nid ORDER BY releases DESC LIMIT 50;
Comment #9
drummSee also #3009338: [META] Support semantic versioning for extensions (modules, themes, etc) in Drupal core, and allow modules to be compatible with Drupal 8 and 9 at the same time which effectively removes the core compatibility version number component, making 8 in 9 / 9 in 8 irrelevant.
Comment #10
tedbowin #3078111: Project browsing/search compatibility filter should work off dependency data part of the proposed solution is
So I think this would entail pulling core compatibility from info.yml files into release nodes.
Could this also be used determine what releases should be returned for available update purposes?
It seems like for search any if we have more fine grained search by minors we will still need to be able to search for 8.x or 9.x compatible modules. For instances someone may simply know they are building a Drupal 8(or Drupal 9) site and are looking to see if a module with a general functionality is available.
So if we have search for 8.x or 9.x this means we need to pull this from info.yml files onto release nodes. If we had it on release nodes we could still request '8.x' or '9.x' compatible releases(even though it might not actually be compatible but that is problem now)
Comment #11
tedbowin #3078111: Project browsing/search compatibility filter should work off dependency data part of the proposed solution is
So I think this would entail pulling core compatibility from info.yml files into release nodes.
Could this also be used determine what releases should be returned for available update purposes?
It seems like for search any if we have more fine grained search by minors we will still need to be able to search for 8.x or 9.x compatible modules. For instances someone may simply know they are building a Drupal 8(or Drupal 9) site and are looking to see if a module with a general functionality is available.
So if we have search for 8.x or 9.x this means we need to pull this from info.yml files onto release nodes. If we had it on release nodes we could still request '8.x' or '9.x' compatible releases(even though it might not actually be compatible but that is problem now)
Comment #12
xjmComment #13
tedbowPostponing on #3076183: [Meta] Determine how available updates for modules should be handled if they are not compatible with the current version of Drupal core because we need to figure what the functionality should be now that we have modules that are compatible with multiple branches and branch/version name will not correspond directly to core compatibility
Comment #15
drummWe will want change
all
tocurrent
when #2688479: Update update status XML for Drupal 9 and contrib semantic versioning is done. Figuring out how to get this committed is still very important, especially in the 9.0.x branch, so update status can keep working in general.Comment #16
dwwI'm pretty concerned about the bandwidth and RAM required for slurping down those 'all' XML feeds. :/ Some of them are completely huge. If we suspect that most sites use 10-50 contrib modules, huge * 20 is Really Huge(tm). ;) Although there is (was?) code to batch fetch the feeds, we still have to load *all* of it into RAM to process the available updates report. We don't (yet?) do the logic one module at a time, independently. Maybe we could. It's been a long time since I looked at any of it.
Therefore, I think a new 'current' feed would be much better for everyone, once it exists. TBD.
However, all this code is going to get much more complicated, since there's no way for update.module on your site to know everything about the requirements/compatibilities/etc of all the future releases coming down those feeds. This whole system was designed ~14 years ago when contrib was totally locked to specific versions of core. Now that we're breaking that assumption, update.module is going to have a really hard time keeping up.
e.g. I'm running token 3.2.5 on 8.9.3 core. Token 4.0.0 is released, which is only compatible with 9.1.x and up. How will update.module know that? What's it going to tell me? That a new release of token is available, but I better click on the release notes and read the fine print? Or are we somehow going to teach update.module all about the dependency web of everything? Or do we hope that all contrib maintainers everywhere actually implement SemVer properly, and update.module never recommends (blindly) that you jump major versions? Or what?
We're getting into the territory of Wrong Tool For the Job(tm).
Either we're going to find ourselves re-implementing all the dependency reconciliation logic of composer, or we're going to have a system that gives people bad advice.
Or we're going to realize that update.module has served us well for a long time, but maybe should now be put out to pasture.
Perhaps we should focus on the composer initiative, and have a UI that talks to that, and can give you a report of what would happen if you did a "composer update"...
Love you, update.module. You were probably my biggest contribution to core. But maybe you need to die. ;)
-Derek
Comment #17
dwwp.s. If we want to keep update.module for the usage stats on projects, we've got the telemetry initiative for that, right? We could still have folks opt-in to a system that lets core "phone home" to send info about what's in use, PHP versions, etc, but stop linking that to the available updates functionality. That can (should?) be a different system from an in-core web UI around
composer update --dry-run
(or equivalent).p.p.s. Is there a more appropriate meta to be having this discussion in?
Comment #18
drummI think I have the code for this all ready to deploy. It needs a bit more testing, and documentation. I expect I’ll be doing that on Monday when I’m back at home.
I am removing the
<version_*>
tags, so progress on #3085717: [PP-1] Do not rely on version_* tags would be appreciated.The other big change will be from
<supported_majors>
to<supported_branches>
. “branch” in this case is not a Git/etc branch (releases are not actually aware of Git history, or require logical use of tags and branches); it is the version number with everything after the last.
removed. So core using semver may have<supported_branches>7.,8.8.,8.9.,9.0.</supported_branches>
, and a contrib module using both semver and legacy versions may have<supported_branches>7.x-1.,8.x-1.,1.1.</supported_branches>
. The code for generating these in project_release on Drupal.org is https://git.drupalcode.org/project/project/blob/d4fba0cab5cc6c3b8cd920bc...<recommended_major>
is also going away. If we need a<recommended_branches>
, I have that ready to go: https://git.drupalcode.org/project/drupalorg/blob/81b4df451532067dd19d19...Comment #19
tedbowComment #20
drumm#3074998: Add explicit information about core compatibility to update data is also coming into availability. It will take a few days for the data to get fully re-parsed, and xml regenerated. The tag added there is only in the
current
XML.Comment #21
tedbow#20
@drumm thanks for the drupal.org changes
I working on the changes to display the core compatibility for each module update in line with what has been agreed upon in #3076183: [Meta] Determine how available updates for modules should be handled if they are not compatible with the current version of Drupal core
Comment #22
dwwGeneral concern before we get too much further in here. Apologies if this is discussed elsewhere that I missed.
What's the long-term plan for the "current" feeds? They're briefly introduced/described at #2688479-7: Update update status XML for Drupal 9 and contrib semantic versioning thusly:
So what's going to happen 8 years from now when a site is still on 8.8.N, queries for updates.d.o/project/drupal/current/current.xml (or whatever it is) and only D9-D11 releases are in that feed?
Is "Current" just going to grow from here on out, eventually becoming so huge and hard to work with that we're not much better off than using "All"?
Do we want something in "current" to indicate a "version" of the API between update.module and updates.d.o? NOT a Drupal Core API compatibility term (which is indeed on the way to the dustbin of history), but a update.module app vs. server API version #?
current-v1
, then someday we can move tocurrent-v2
, etc.We have to think about this crap now, for whatever we put in 8.8.0, or it's going to come back to haunt future-us in N years. ;)
Thanks,
-Derek
Comment #23
tedbowHere is patch that is bit of work in progress. Putting here now because I think we need to work on some other issue first.
for this patch
\Drupal\update\UpdateProjectCoreCompatibility
which sets the core compatibility range based ofcore_compatiblity
which in now in the /current updates feed.For an example see https://updates.drupal.org/release-history/commerce_bambora_europe/current
Not sure if all projects have this feed yet.
This class calculates the ranges and the message. This may need to be split out into separate classes
I think are some issues that need to be resolved before we can finish this issue.
version
The functional test coverage for contrib updates is not comprehensive so for any cases like #3085717 where we are changing where we are getting metadata but the functionality remains the same it would be great if make sure we have test coverage for the current functionality.
Anything we can do before this issue would be great.
Comment #24
tedbowComment #25
tedbowComment #26
drummThat is the current plan, yes.
current
includes any release with an8.x-
API compatibility prefix to the version number, or any without an API compatibility prefix.Bandwidth isn’t too much of a concern here. What can be hard to work with is the general finickiness of formatting - I saw some evidence that release ordering in the XML being significant tripped people up at least a couple times.
I’ve never encountered schema documentation, I went ahead and made some: https://www.drupal.org/drupalorg/docs/apis/update-status-xml
current
is indeed essentially a new API version. I only added<core_compatiblity>
to current and a few things are taken away. I also removed the<release>
-level<mdhash>
and<filesize>
elements, https://git.drupalcode.org/project/drupalorg/commit/25d1c79c84fc75d306d5...Now is a good time to remove other inessential elements, like
<release>
’s<status>
looks like it is alwayspublished
. And<download_link>
is duplicitous, but core does currently use it.I don’t want to add much more changed that affect core’s implementation since this does need to get into core for update status to work properly for Drupal 9. There is no https://updates.drupal.org/release-history/drupal/9.x and https://updates.drupal.org/release-history/drupal/8.x does not contain 9.x releases.
The next version of this API might be something completely different, like using Drupal.org’s composer endpoint directly.
Comment #27
tedbowI think this is not a great time to be changing more things the update xml because current functionality on the core side is not covered with comprehensive testing. So anything we change on the core side we should really be making sure we add test for the current functionality before update core. Otherwise we have a big risk of breaking the current functionality. see #3094304: Create tests that cover contrib non-full releases and contrib patch versions
Could we make the switch to /current and then remove what we need to remove? Right now since /current is new do we have to consider it an API for consumers except drupal core itself.
@group
to the test.Comment #28
tedbowSo thinking more about switching to the /current feed.
If we could changes the /current or the current feed I think this is what would work best with core changes in considering 1) We want to get the "This module is compatible with 8.7.11 to 9.1" changes in during 8.8.0-rc and 2) currently the update module does not great test coverage for modules(non-core) update availability
I think the least disruptive change for core would be
core_compatibility
to current feed that uses 8.x.This would allow to make only the change to show "This module is compatible with 8.7.11 to 9.1"
Then make sure our test coverage for module update availability is solid.
core_compatilibity
Comment #30
catchThis is probably OK I think? - In eight years, 8.8.N will be more than five years out of support.
Comment #31
tedbowSo many tests failed in #27 because our tests actually call out to
updates.drupal.org
. So switching to/current
actually pulls in the new new/current
feed from Drupal.org on our test runs not a mocked XML that can be found undercore/modules/update/tests/modules/update_test
Most of the tests under
core/modules/update/tests/src/Functional
use the mock XML by calling\Drupal\Tests\update\Functional\UpdateTestBase::refreshUpdateStatus
which callswhich will fetch the mock XML.
A couple of tests under
core/modules/update/tests/src/Functional
though I think by mistake don't call\Drupal\Tests\update\Functional\UpdateTestBase::refreshUpdateStatus
so they are actually fetching real updates.drupal.org xml in the tests. For instance\Drupal\Tests\update\Functional\UpdateContribTest::testUpdateBrokenFetchURL
Also I think all tests that extend
UpdatePathTestBase
we triggerupdate_calculate_project_data()
with XML from drupal.org. If the request is successful then if XML has any changes in the format then it will likely cause test errors like in #27The reason #2 didn't fail any tests is because switching to
/all
return real updates.drupal.org that was in the same format.So in effect our tests are testing live updates.drupal.org XML. Is this intentional? It doesn't seem like a good thing.
In the case that our test requests to updates.drupal.org are not successful then this will not cause a test failure unless we were explicitly asserting that "Failed to get available update data" didn't appear which we aren't.
It seems that all tests that extend
UpdatePathTestBase
or otherwise would trigger request updates.drupal.org should actually be calling something like\Drupal\Tests\update\Functional\UpdateTestBase::refreshUpdateStatus
to change the update URL so we aren't making real requests to updates.drupal.orgThis would mean we won't be testing live XML from updates.drupal.org. My guess this would also cause our update tests to run a little faster.
Comment #32
tedbow#31 is an existing only somewhat related issue .
I created #3095755: Tests should not do requests to updates.drupal.org. If anyone has info/opinions or more info on that problem please comment on that issue
Comment #33
drummRe #30
https://updates.drupal.org/release-history/drupal/current will indefinitely contain all 8.* & later releases. The simplicity of generating static files is still a bigger win than trying to keep the number of releases in a file down.
Comment #34
drummRe #28
Done, #3074998-29: Add explicit information about core compatibility to update data. All release history XML should be regenerated within the next 20h.
Comment #35
drummThis has caused tests to randomly fail in the past. Testing shouldn’t also be an uptime and connectivity check with Drupal.org. Notably, one of the core tests was downloading translations, and failing often enough to be temporarily be removed until a replacement using bundled artifacts was made.
I do have one more change I’d like to consider. I was unable to find a code path which outputs anything other than “published” for the release status,
<releases><release><status>published</status>
.Comment #36
dww@drumm re: #26:
@catch re: #30: I just invented 8 years. ;) Regardless, I'm worried by "that's okay, X will no longer be supported" -- we want update.module to tell people they're not supported and what to upgrade to so they return to the happy pasture of supported Drupalness. So I think whatever we do, we have to plan to support it working far into the future, even past official "supported" status.
@tedbow re: #31: great find! I commented at #3095755: Tests should not do requests to updates.drupal.org.
@drumm re: #33: Fair enough. I think that might come back to haunt us some day, but that's probably the best we can hope for.
Does it make sense to only put 8.8.x and higher core releases in the https://updates.drupal.org/release-history/drupal/current feed, since only core 8.8.x and higher will be consuming it?
Thanks all,
-Derek
Comment #37
tedbowI split out #3096078: Display core compatibility ranges for available module updates this because #34 thanks @drumm!
Hopefully it will will make this issue smaller. neither really blocks the other but I think/hope #3096078 will be quicker
Comment #38
tedbowOk so here is patch without "This module is compatible with ...." message logic. It will fail in all the same ways that #27 did for reasons explained in #31. So I am not going to run tests on it.
But I am also uploading another patch that adds #3085717-11: [PP-1] Do not rely on version_* tags. More should pass. not sure about all but want to see.
Comment #40
tedbowWhoops last patch didn't have new files from #3085717-11: [PP-1] Do not rely on version_* tags
Comment #41
Gábor Hojtsy@dww: by switching to this "current" "API-version" of the update info, we don't attach to always use it in the future in Drupal 10, 11, etc. For Drupal 10 we can choose to stop growing "current" with items that are not Drupal 9 compatible and switch to composer endpoint data, or whatnot as @drumm indicated above. As you pointed out elsewhere update module is magically holding up but is less and less desirable as a feature set given the much more complicated nature of dependencies both in the back-backend (shorter PHP release cycles) and in Drupal. So I would be surprised if update module as-is survives too long.
Comment #42
Gábor HojtsyReparenting to the alpha1 issue as this is currently listed as an alpha blocker.
Comment #43
Gábor HojtsyComment #44
tedbowHere is patch that updates the rest of the test XML:
supported_majors
and replaces it withsupported_branches
recommeded_major
and replaces it withrecommeded_branch
default_major
yet but I think it should be able to be removedThis is still a work in progress but I think the tests will pass.
There are no changes under
core/modules/update/tests/src/Functional
so it keeps the update list the same.I am going clean this up so I am assigning to myself.
Comment #45
tedbowThis should really be
ModuleVersionParser
and the only thing it needs is a version number.Fixed this and some other cleanups
Comment #46
tedbowThis patch removes
defualt_major
from the test XML and the update logic. This is not in the new/current
feed.Comment #47
tedbowA better name would be
getVersionStringWithoutCoreCompatibility()
Comment #48
tedbowDecided to make
\Drupal\update\ModuleVersionParser::createFromSupportBranch()
instead to return a new module version parser.Unassigning from myself. I am not sure #3085717: [PP-1] Do not rely on version_* tags needs to be its own issue now though it would make this patch a bit smaller if we want to do it first. The patch is mostly big because of the XML changes.
Probably still make sense to do #3094304: Create tests that cover contrib non-full releases and contrib patch versions first. I have a patch started on that.
Comment #49
drummAgreed, I actually started that as an experiment to help check how doable it might be. Whatever strategy makes the whole switch to /current most committable is best.
Comment #50
drummThis is actually multiple
recommeded_branches
if we want to flip this on.recommeded_major
was the recommended major version for each API compatibility, but we do not have specific API compatibility anymore. Switching this to “branch” helps, we’re not doing something like recommending 3.x.x for everyone, when 3 might only work with a certain range of core and other dependencies.Currently, there are no rules for what can be recommended, other than it had to be supported. I couldn’t think of a good reason to have a restriction, since I wasn’t sure if the whole “recommended” concept still made sense, I don’t know of an analogue* in other projects, and implementing it that way in our form was just easier. (The legacy
…/8.x
,…/7.x
, etc XML generation picks the highest major version that’s recommended in the API compatibility.)I know it is a larger change, but I’m still not sure that we need “recommended” at all. If we do need it, I don’t know if there’s any way around having multiple recommended branches.
* marking branches as LTS is sort of an analogue, it is a meaningful label for a branch. That’s a whole other issue.
Comment #51
bnjmnmA reroll was needed.
Comment #52
bnjmnmUpdated IS to summarize the XML changes.
Went through the patch and only found nits, but this could probably use a bit of clarification as to whether #50 necessitates any additional steps. (There are also some additional possible use cases that @tedbow brought up in a discussion, but it's not yet clear if those are in-scope for this issue)
Split "Dataprovider" into two words.
Since a constant is no longer used, this and other instances can now be built inside double quotes instead of dot concatenation.
Comment #53
tedbowSo this would be bigger change.
Right now the current patch doesn't actually touch anything under
core/modules/update/tests/src/Functional
so functionally it still recommends the same updates.but at least with this change we would need
I realize now that this will be a problem. The code after this assumes that every release in the
$target_major
is supported which might not be the case.For contrib this actually is a safe assumption currently because with branches like
8.x-1.
we can't specify a "minor" branch. But as soon as we have semantic versioning in contrib with branches like1.2.
we would run into a problem.Since core already has semantic versioning we would already have this problem. But in core we are very unlikely to have newer full releases in branches that aren't supported.
I am uploading a patch that demonstrates this problem though.
Comment #55
drummClarifying
recommended_branches
in the issue summary.Comment #56
tedbowCurrently this is how
recommended_major
is used.So I am not sure what our logic should be in we don't have something like this.
Considering in this issue we are pretty much sticking to the current functionality and not listing update split into branches it seems we still need to have target major if the current major is not supported. On thing we could do is find the next branch that is supported.
This will have a different effect than our current logic for contrib in this example:
in the current case if you have 8.x-1.x installed you update.module would recommend 8.x-3.x. If don't have
recommended_branches
we would have to chose in core to recommend 2.x or 3.x(we won't have any concept that 1 major was recommended by the author. but maybe that makes sense, should you skip a major version is this way?The current functionality of the update module and the current XML would be to recommend update to 3.x.
I am including a patch that if the current branch is not supported it will just go to the next major branch that is supported.
\Drupal\Tests\update\Functional\UpdateCoreTest::testNoUpdatesAvailable()
failed because it used the same test XML but\Drupal\Tests\update\Functional\UpdateCoreTest::testNormalUpdateAvailable()
did notComment #57
tedbowThis doesn't have a test
changing this so
\Drupal\update\ModuleVersionParser::getPatchVersion()
will return NULL.These shouldn't be name
$releaseInfo
but should be updated to match the renamed class.all the test xml still has
recommended_branch
. removingIt seems there will be very few contrib modules that will be affected by this. You would have to 3 or major versions of Drupal module just for Drupal 8. Otherwise if you just had 2 then effect would be the same.
I suppose we could figure out if any modules actually have that somehow.
Comment #58
tedbowCreated a follow issue #3100115: The update module should recommend updates based on supported_branches rather than major versions majors
And also #3100110: Convert update_calculate_project_update_status() into a class but that doesn't have to done in a particular order
Comment #59
tedbowComment #60
bnjmnmThe nits in #52 still need to be addressed
And one other thing:
There's a line break and missing 'the' here, but that may be irrelevant as this function no longer takes into account the project maintainers recommended branch.
Comment #61
tedbowFixed the nits from #52
Update the comment mentioned in #60 for the new functionality
Comment #62
bnjmnmWith that last bit of stuff addressed in #61 this can get RTBC'd.
Comment #63
alexpottI wonder if we should do this on construct as when we parsing the XML files we do ->getMajorVersion() followed by ->getMinorVersion() and as this is a value object there's no harm of a $this->versionParts property getting out-of-sync with $this->version.
I know there are plans to remove \Drupal::CORE_COMPATIBILITY which make total sense but this code is analogous to \Drupal\Component\Version\Constraint::parseConstraint() and that's getting its core compatibility from the constant. I think whilst we still have the constant we should be using it.
Nice.
Comment #64
tedbowCouple thoughts/questions:
\Drupal\update\ModuleVersion
be @internal? I could see it being useful for custom code but also anytime we can avoid making an API we should.\Drupal\update\ModuleVersion::getVersionStringWithoutCoreCompatibility()
is now only called in the constructor should would we just move the logic there and remove the method. I like having the constructor easier to read but could be convinced the other way.This will make the patch a bit bigger but those are clear changes
api_version
in our XML. This is removed in/current
. I will remove that in the next patch and check to make sure everything else is removed that should be gone.Comment #65
alexpott@tedbow changes look good. Re questions:
1. Starting out @internal is a good idea. That said I can't imagine making an incompatible API change.
2. Not sure it matters too much given the method is private - but there's also no harm in inlining - up to you.
Comment #66
tedbow\Drupal\update\ModuleVersion::getVersionStringWithoutCoreCompatibility()
I like it for clarity./current
feed: api_version(whole point of /current means we aren't using this anymore, mdhash, filesizesorry this again make the patch bigger but again just XML changes
Comment #67
bnjmnmReviewed the interdiffs and confirmed the feedback since the last RTBC was addressed, and that the test XML matches the structure of the actual content in /current feeds for Drupal and contrib.
Comment #68
tedbowjust a reroll after #3096078: Display core compatibility ranges for available module updates was commited 🎉. Thanks @Gábor Hojtsy!
Comment #69
bnjmnmReroll has straightforward changes, so this can go back to RTBC.
Comment #70
tim.plunkettOne question, one missing test case, and some nits. The patch as a whole looks great!
It strikes me that there are a lot of count() calls and ternary operators and numeric array access.
Instead of keeping versionParts as a property, why not initialize 3 properties?
Not trying to derail an RTBC issue, but figured I'd ask.
This is missing a case like
1.2.x
. Otherwise there's full unit test coverage.Nit: no space between static and (
Nit: no local variable needed
Nit: here and throughout "expected" is spelled "excepted"
Comment #71
tedbow@tim.plunkett thanks for the review
Comment #72
tedbowchatted with @tim.plunkett
he suggested
I changed this to
createFromVersionString()
because we already havecreateFromSupportBranch()
which also creates from a string. Also I foundpublic static function createFrom
47 times in core andpublic static function from
only 16 times so sticking with that naming conventionComment #73
tim.plunkettThe changes above are great and address my concern. But I especially like the resulting change to this method!
Setting back to RTBC
Comment #75
tedbowThis test should have been
!== NULL
otherwise "0" won't pass.Updated and updated test cases in unit tests to "0" in all version parts. We had function tests that broke but not the unit test for the class. Fixed
Comment #76
kim.pepperI think we need a test-only patch for #75 to show it failing.
Comment #77
alexpott@kim.pepper the need for #75 is shown by the test failures in #72.
Comment #78
tedbowChatted with @mixologic. I thought if a contrib module used semantic versioning the would support branches like core 1.2.x. But they will be able to do 1.x also.
So you given a version number you can't determine the support branch.. Change to
isInSupportBranch()
Comment #79
tedbowThere is some in 8.9.x that actually doesn't make much sense I think by removing it it might make this patch much simpler. Assigning to myself to research this.
Comment #80
tedbowupdate_calculate_project_update_status()
I was referring to in #79$patch
is only ever referenced in 1 other spot in where it is set to an empty string$release['version_patch']
if it isn't we set it as so.$patch == $release['version_patch']
. Of course because we will also set it to this value if it is not equal already and since the$patch
is not used elsewhere the setting and the checking are meaningless$release_patch_changed
. it is only referenced once outside of this block to set to an empty string. So there no purpose in setting we could simply use$release
in second if block.This is relevant now because this code is the only place in the update module where
version_patch
is used coming from the XML.version_minor
is not used at all.Since we don't need these then we also don't need the new
getVersionPatch()
andgetVersionMinor()
. It might seem that since we have value object class for ModuleVersion we should leave these in but since this in@internal
class I don't think we should put in any methods that we don't need to use.Another reason not to put in these methods is that it is unclear in version string such as
8.x-1.7
if the 7 is a minor or patch number. See #3104912: Swap storage of version minor & patch and the fact that our composer shim would turn this into1.7.0
both meaning that it is a minor. But we also have documentation that labels this as "PatchLevel" https://www.drupal.org/docs/8/understanding-drupal-8/understanding-drupa....As part of #3009338: [META] Support semantic versioning for extensions (modules, themes, etc) in Drupal core, and allow modules to be compatible with Drupal 8 and 9 at the same time we will clean up our documentation but if core itself doesn't need to assess minor or patch for anything then we shouldn't add to the confusion. Once we need to assess these values we can add them.
This actually is overly complicated.
Really the support branch is simply the version with the last part removed. The part might be the minor-extra or the minor.patch.extra
So basically it is the start of the version.
So 8.x-1.1 and 8.x-1.0 are both in the support branch 8.x-1.
And 1.2.3 and 1.2.0 are both in the support branch 1.2. and they are also in 1. Contrib now will be able to decide if they want to base support on minors or on majors. Hopefully drupal.org will prevent 1 single project from creating both support branches 1.2. and 1..
Another 2 cases which this current function will not catch is
8.x-1.2 is not in the support branch 1.2.
1.2 is not in the support branch 8.x-1.
for now I am not sure we actually need
isInSupport()
. We currently already haveThis can simply be changed to
We could move
strpos($version, $supported_branch) === 0
back into the class but I don't think we need to.Comment #82
tedbowThis should not be the ModuleVersion object but rather the version string. This caused a bunch for test failures.
I will upload a patch with just this fix and not the next to show that will pass tests(and that next problem needs test coverage).
It is true that the
$patch == $release['version_patch']
check in the 2nd if statement is useless(though another set of eyes would not be bad).I think by point #80.1.4 is wrong.
The docblock for the function documents how the recommended release should be selected
Basically if there is release with "extra" after the no "extra" release it should be recommended. This is not actually test anywhere.
So in the code mentioned in the previous comment
$release_patch_changed
might be from the previous time around the loop.I will open a new issue to create test for this. I also think will actually break for semantic versioning but core doesn't do this pattern so it has mattered yet.
chatted with @tim.plunkett about this and going to move this logic back into the constructor.
Comment #83
tedbowCreated #3074993: Use "current" in update URLs instead of CORE_COMPATIBILITY to retrieve all future updates
Also earlier today created #3105353: Remove the ability for module to define "major" in their info.yml files which I found while working on this
Comment #84
xjmI think the first issue in #83 was supposed to have been something else, since currently it's referring to this issue?
Comment #85
xjm(Bear with me; I'm just starting to review this issue and parts of the IS are hard to understand.)
I like this class, but there's a number of eyebrow-raisers in it (comments follow).
Immediately confused here... isn't one of our goals to deprecate
CORE_COMPATIBILITY
? Is there a followup related to this, and how willModuleVersion
work after? Shouldn't we be handling the case where that constant no longer exists?An example would be good, e.g.:
If the module version is '2.0.3-alpha1', then the version extra string is 'alpha1'.
(Or whatever a correct example is here.)
This seems to recognize that the module version may not start with
CORE_COMPATIBILITY
, but (again) not that core itself will deprecate the constant later.Also, what about cases where the module is
7.x-1.2
? Should we be throwing an exception or otherwise handling prefixes that are not based on the core compatibility constant?Finally, I think we should also at least have a code path and
@todo
for modules with9.x-
prefixes. Right now we're depending on d.o disallowing that branch, but core should also hardcode that expectation so we don't get undefined behavior. The reason I think a followup might be needed is those ≈10 projects that managed to create a9.x-
branch before we disallowed it. We have to decide how we're going to deal with those first. There might already be an infra issue about those projects.Wait but... what about semver? It's not supported yet, but we're trying to support it. Also, shouldn't this also support core modules, which do have a minor version?
Maybe we don't need it yet, but shouldn't we set things up such that a BC break isn't necessary once we do?
Does "support branch" in this context mean "supported branch of core"?
This is the only mention of minor versions in the class.
Also, will the patch version actually always be
NULL
?Nit: This is a run-on. I'd change it to:
The version extra string if available, or otherwise NULL.
Comment #86
xjm"currently supported development branches" seems like an oxymoron to me. In core and in the CI branch labels, we use "development branch" to mean the branch that hasn't had a stable release nor pre-release milestone yet, and is therefore totally unsupported.
Would "currently supported core branches" be accurate? (Or "currently supported branches of the project" if it's about the project's branches and not core?)
We don't call
isset()
first anymore, so we should update this comment to reflect that we're checking that it's notNULL
instead.Also, I wonder if any such projects from CVS days are even remotely supported anymore? Maybe we can file a followup to clean that up?
I don't think we mean to change this line to put
SEE
in all caps? :) Rolling that back should also un-weirdify the diff.Comment #87
xjmNext step of reviewing this is of course going to be to read
update.compare.inc
again, which I last did several years ago and which has haunted me ever since. 👻Comment #88
xjmI read through all the test fixture changes just to help verify that the only changes were removing the defunct keys (and I guess that @tedbow wasn't inserting any trolling about llama skeletons or something). I didn't double-check the exact supported branches for each fixture as yet.
A few general questions about the new feed structure (that, by definition, are probably all actually out of scope for this issue):
The IS doesn't mention these things being removed from the feed, but I'm guessing they must be since this issue removes them. Is the new feed and what was changed and why documented somewhere, maybe in a closed infra issue?
Whoa, funky, the data from d.o actually ends in a dot?
Like, does d.o actually strip off the
x
that actually exists on the ends of the branch names I create in git? 😲And like. What if someone creates a
8.x-1.y
branch? Or literally calls it8.x-1.
or any other such thing? I guess that probably fails some regex and therefore never ends up in the feed nor other d.o functionality. (Hopefully.)Is the concept of a default branch also going away?
Now I feel like I need to go back and check the indentation of this in all the fixtures. :P
(I've now set myself up for @tedbow to insert an Easter egg into one of the fixtures and see if I notice it before commit.)
Comment #89
drummhttps://www.drupal.org/drupalorg/docs/apis/update-status-xml
Yes. Specifically, everything after the last dot is stripped to determine a release’s “branch”. This is not the same as a Git branch, it is grouping versions into a series.
Nothing is actually preventing people from making non-sensical releases, like tagging
8.x-1.0
on a7.x-3.x
branch. You can make a8.x-1.y
branch, or any other branch/tag you want, but you can only make releases when those match the version number formatting, which is indeed mostly regexps.Yes. The D7 code comments show this was some legacy layer:
Drupal.org can generate all update status XML files within 12 hours, so any we are producing would have been updated. The legacy update status XML still includes
default_major
since there’s probably a few outdated sites which can’t understand the replacement.And all of these API elements related to “major” versions just don’t make sense as we move toward semver.
“Default branch” as a property of a Git repository remains, that is part of Git. It never has affected what goes in update status XML. That’s just the branch you get from
git clone
without a--branch
parameter.Comment #90
tedbowre #84, yes indeed did not mean to relate this issue to itself. Was suppose to be #3105463: Create tests for recommended bugfix releases. I blame whoever invented browser tabs 😜
re #85
I updated
update_calculate_project_update_status()
Patch and Minor are tricky because have documentation that in version strings 8.x-1.2 , 2 is "PatchLevel" but in our composer shim it is converted to 1.2.0 which makes in the minor. If core doesn't have an opinion on this it would easier.
::getVersionExtra()
will always return NULL for branches.re #86
/current
feed that we are using will only return 8.x and new versions including the semantic version contrib then we should not get any of these releases.It would only be problem we weren't making this switch. So removing the comment and the check for NULL. Updated
\Drupal\update\ModuleVersion::createFromVersionString()
to throw an exception if the major is not numeric. This will mean we will skip these releases because the logic that was put in above in this comment for skipping releases that through exceptions.re #87 I am also haunted #87. Someday 🙏 #3100110: Convert update_calculate_project_update_status() into a class
re #88
Comment #91
xjmLet's
@see
https://www.drupal.org/drupalorg/docs/apis/update-status-xml.Comment #92
xjmNormally I'd worry about still not having a policy for how we use
private
(technically the docs still say we don't use it and the issue's still open) but given that this is a totally new, totally internal, immutable value-object-thing with factory methods (and not injecting services nor of any conceivable use to contrib with the constructor), I think it's actually totally justifiable in this case under a current read of core policy.The only remaining thought I'd have with the class then is that the name itself sounds much more generic and globally useful than it is, but I'm also not sure I agree with myself about making the name something more specific either.
Maybe this could say "...for both Drupal 8 and 9"? (Or whatever of that fits in 80 characters.)
Should we be testing that 8.x branches aren't invalid as well?
Should we add unit test coverage about non-dot-ended branch names?
With the rewriting I now realize it says "The project defines... for the project..." We could say "The projecrt defines its currently supported branches in its Drupal.org configuration" or something along those lines.
+1 for this; I had originally second-guessed my suggestion throwing an exception because of potential disruptions, but this mitigates it.
"us the current major" indeed. We totally are!
A comma's also needed, so:
If there are no valid supported branches, use the current major.
Comment #93
xjmComment #94
tedbowre #92
core: 8.x
. Technically if you had module that did something very simple or I guess even complex that interacts with bit of we never change it could be compatible with 8, 9, and 10.8.x-
denotes compatiblity with 8 but know we will ignore at least in 9 and maybe after that.So added extra checks for valid branches and valid version strings. Added extra test coverage for all this too.
So other code changes
This would actually would fail for to specific version numbers.
dev snapshot
8.x-8.x-dev
because it has 28.x-
that would be replaced.dev snapshot
8.x-dev
in this case8.x-
is actually not a core prefix but a snapshot release for support branch8.
branchFixed and added test cases
This would fail for dev snapshots for support branches such as
1.x-dev
and10.x-dev
fixed and added test cases
I realized that adding an "x" on the to end of the branch means that we can't added validation in
\Drupal\update\ModuleVersion::createFromVersionString()
and throw an exception for versions like 8.x-1.x which is not a valid version number. So changing this to add a "0" instead which will create a valid version number. Since we no longer havegetVersionMinor()
andgetVersionPatch()
we don't have to worry about what they would return.I also add validation here to make sure the branch ends in "."
I realized these are test datasets with no keys. This makes debugging harder.
I also add 2 other data providers that also have just 1 string argument tests cases. I create new helper method
createKeyedTestCases()
to create key test cases for all these providers.Comment #95
xjm#91 does not appear to be addressed yet.
Comment #96
xjmNice catch on that!
Comment #97
xjmNitpick here, but we have an allowed value at the end of the string, related to a different value that can end in a literal
.
. Can we end this and any such exception messages with something like:The only core prefix expected... is: 8.x-
That way we don't need to put a period at the end grammatically and we don't confuse sentence-ending periods with the literal
.
that we have to deal with also from the update XML.Same suggestion here, "...in: $var" rather than "...in $var."
(Here and elsewhere.) If we add parameter documentation for the test method (i.e., explaining each key passed from the provider), that goes a long ways to making the strings of numbers more clear in terms of what's being tested. Inline comments in the provider for each case can help too.
Comment #98
xjmNW for #91 and #97.
Comment #99
kim.pepperFixes nits in #91 and #97.
Comment #100
tim.plunkettI last RTBC'd this in #73.
Reviewed every comment and response since then, only two bits of remaining work to be done:
#85.3
Missing examples on docs of
\Drupal\update\ModuleVersion::$versionExtra
Extra blank line here, and only 2 of the 7 methods had the docs added.
Additionally, none of the data providers document themselves. See
\Drupal\Tests\layout_builder\Unit\OverridesSectionStorageTest::providerTestExtractEntityFromRoute()
for an example.With those two docs changes made, I am comfortable RTBCing this.
Comment #101
tedbow@kim.pepper thanks addressing #91 and #97
@tim.plunkett thanks for the review
Fixed #100
Comment #102
tim.plunkettThanks Ted!
This is ready to go
Comment #105
xjmCommitted and pushed to 9.0.x and 8.9.x, yay!
I think we might want to backport this even further, so setting to PTBP while I discuss with @catch.
Comment #106
xjm@catch and I agreed to backport this (and it'd be great to do before 8.8.2); however, we need to backport #3096078: Display core compatibility ranges for available module updates first, which in turn needs to have its usability issues resolved before being backported to a production release: #3102724: Improve usability of core compatibility ranges on available updates report. So postponing for now.
Comment #107
tedbow#3102724: Improve usability of core compatibility ranges on available updates report has been committed working on this backport
Comment #108
tedbowreroll for 8.8.x
Comment #109
tedbowtests passed 🎉
Comment #110
Gábor HojtsyRe #107, #3102724: Improve usability of core compatibility ranges on available updates report has not actually been committed to Drupal 8.8 yet. Which one depends on which one?
Comment #111
tedbowre #110
the xml fixtures in #3102724: Improve usability of core compatibility ranges on available updates report don't have
<version_major>
,<version_minor>
etc.So they won't pass until this issue is committed.
We could add those to the XML fixtures and see if it passes but it might have other problems.
I think the current issue should get committed first
Comment #113
Gábor HojtsyOk that makes sense given that #3102724: Improve usability of core compatibility ranges on available updates report is a reroll away. Reroll-party! Thanks!
Comment #114
xjmSince this is an important change and could have disruptive impacts compared to a typical patch release, it should be mentioned in the release notes.
Comment #115
tedbow