Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
database update system
Priority:
Critical
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
26 Aug 2015 at 21:36 UTC
Updated:
14 Sep 2015 at 07:04 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
catchSee what happens.
Comment #4
catchSo the reason the tests fail, is because the database dump has absolute file paths in it, which are not the same as those as the tested site.
We should sanitize the database dump - via the dump script if necessary - to remove any hard-coded file paths (just truncating all cache table if necessary for a quick fix).
If we're storing any file paths outside of cache tables, that's a bug anyway.
Bumping this to critical since it blocks working upgrade path testing.
Note the patch also removes the module install - because you absolutely cannot install modules when you have updates pending. If modules need to be installed for the test to run, that's handled in the database dump.
Comment #5
mradcliffeShould the Drupal Extension implementation allow $root to be set? It does make sense that potentially an extension could live outside of the drupal install, but that isn't very Drupally.
Extension::serialize() could always set $root to DRUPAL_ROOT, but that doesn't solve the problem of the database dump, which will just serialize it to whatever path the user has setup since the constant will be expanded.
I guess we need to set it to test bot root - /var/www/html.
Comment #6
mradcliffe1.6MB patch. Not sure if it's worth posting a 1.4MB interdiff.
I didn't run the database dump script, but here's diffs of the uncompressed dumps.
Edit: drupalci d.o looks for diff extension too, welp. :(
Comment #8
berdirThat's not really an option, that will then cause fails on local installations and possibly on the new testbot as well?
Why is that only a problem for theme data but not for modules? Why do we even need root in there?
Possible solution: what if serialize() checks if root == DRUPAL_ROOT, and if so, sets it to NULL and then if it is NULL, sets it back to DRUPAL_ROOT when it is initialized?
Comment #10
mradcliffesystem.theme.data is the only place where Extension objects are serialized in the database dumps.
Yes, I think that @berdir's Extension::unserialize makes sense.
@catch's initial patch probably also fails on the below error most likely because the container is not set, which happens in WebTestBase::resetAll() called from WebTestBase::rebuildAll():
Comment #12
mradcliffeExtension does not do any sanity check on if the file path exists.
Should Extension::load() do a realpath and return FALSE?
Or should Extension::unserialize() automagically make assumptions if root does not exist?
Or maybe both?
And after adding the container back to the test class, we find that update.php errors out with 500 error in the test run, and none of the database updates are run. There is something in the cache clear that lets the test runner do its thing. I saw this on Monday night when I worked on this before.
For posterity, a patch that will demonstrate the above.
The cache clear is from the commit in #347959: modules_installed is broken during testing.
Comment #13
mradcliffeIt also looks like the current behavior is a regression of #1404198: Separate database cache clearing from static cache clearing and data structure rebuilding after reading that Issue Summary. Most likely changed so that the menu/router changes could go through.
Comment #14
mradcliffeTo be more verbose about the patch in #12:
which is trying to unserialize the update.php route, which unserializes fine if I paste it into unserialize somewhere with the autoloader present.
Comment #15
catchThis is why the update passes on MySQL, because it's cheating. The offset on postgres is different for whatever reason, so we see the fails.
From #2532476-67: Menu links should use a TranslationWrapper to encapsulate safe translatable strings from YAML files .
So we should be able to remove that code here too (and it should never have been added IMO).
Comment #16
catchupdate.php moved back to a front controller in #2540416: Move update.php back to a front controller - so why are we unserializing the update.php route?
Comment #17
dawehnerWell, its part of the previous dump, right?
This is certainly the right step. You have to ship with everything in the dump, if you want to test the update both.
Do you mind explaining why without refreshing ca che is the right thing to do?
Comment #18
catchJust trying this to see what happens if we never serialize app.root in Extension. drush cr works, didn't try anything else.
Comment #19
dawehnerShould we cast it to a string here and in __construct ?
The only way is to execute raw DB queries, right?
Comment #20
catch#1 would it ever not be a string?
#2 yes I can only think of direct database queries. Or we go the other way, require a predictable user/email/pass in the database dumps, then override $this->rootUser with the same values.
Comment #22
catchThe unserialize gets called too early to use the container, trying DRUPAL_ROOT.
Comment #24
mradcliffeIt's difficult to read about serialization, but there's always looking at C source in PHP: https://github.com/php/php-src/blob/master/ext/standard/var_unserializer...
Is there an extra byte that is serialized in the route object?
Or is the error in the serialized route with the colon?
s:37:"#^/update\.php(?:/(?P<op>[^/]++))?$#sComment #25
catchTrying generating those URLs with base://
Comment #26
catch#26 might be overkill, I have a feeling it's just the maintenance mode link that would actually cause a problem.
Comment #28
catchManually tested this one locally and got a clean update run.
I can definitely reproduce errors running update.php manually with HEAD, so I think our tests are properly lying at the moment.
However the test fails are different to what I'm getting with the patch here so not sure if the bot will still show different failures.
Comment #30
dawehnerFixed a couple of test failures ...
Comment #31
catchCross-post - I hacked routing calls out of everywhere that update.php triggers the route generator and got to green test run for me update test. This is not sustainable but shows the problem at least.
Comment #34
dawehnerLet's see what happens if we use a custom url generator on opt of my earlier patch.
Comment #36
effulgentsia commentedTagging beta target per #2341575-45: [meta] Provide a beta to beta/rc upgrade path.
Comment #37
catchDiscussed this on the critical triage call with xjm, alexpott, effulgentsia and webchick.
We all agreed this issue is critical - at least that UpgradePathTestBase should not call rebuildAll() and install modules as the title said.
How we fix the resulting notices from the menu upgrade I'm personally not sure about at this point.
I would seriously consider starting from a later database dump (so we lose test coverage for that particular update and the earlier patches on here start to pass), then focus on adding early update support for the next time something like this comes up.
However if we can reduce the router-dependency of update.php itself further without introducing an entire parallel API for updates themselves that's worth doing.
#34 has interesting fails.
Comment #38
webchickI personally would be fine starting with a later database dump. While we started requiring update hooks in beta-12, we did not broadly announce this to site builders in order to see how beta-13 would go. beta-13 resulted in problems, which means that the earliest beta-to-beta upgrade path that core would support would be beta-14 to beta-15, so starting the dump from beta-14 seems fine.
Comment #39
effulgentsia commentedFor me, what's most critical about this issue is if it's surfacing bugs with running update.php at all (due to UpdatePathTestBase doing things that are not done (and cannot be done) when actually running update.php). So, I tried installing beta-12 (from the web UI), then added an article node, then updated to HEAD, and tried running update.php. I'm getting failures like in this screenshot (no CSS to hide the "Skip to main content" link, JS errors preventing the batch from starting). #28 says it was manually tested, but it doesn't get me past these problems. Not sure how related that is to this issue, but it is an indication that update.php (unlike UpdatePathTestBase) isn't clearing caches, so is serving some stale assets and maybe has other problems related to stale caches.
Comment #40
mradcliffeExtra period.
I think this is not giving a 200 response for UpdatePathWithBrokenRoutingTest and UpdatePathWithBrokenRoutingFilledTest.
UpdatePathTestBaseTest, UpdatePathTestBaseFilledTest, BlockContextMappingUpdateTest, BlockContextMappingUpdateFilledTest, and UpdateScriptTest need to call this function.
I think in UpdatePathTestBaseTest::setUp() right after parent::setUp()
Comment #41
dawehnerTo be clear, the issues aren't on
/update.phpThese two obviously break, because we are going to /, ... we know that this is broken
Can you check whether you use aggregated files there? #2538274: DbUpdateController has broken mainteneance mode logic, and update.php doesn't run due to aggregated JS assets had the same kind of problems ...
Well, then all of those need a new partial dump which have those modules installed ...
With those, we know the reason for all those 7 failing tests afaik ...
Comment #42
jhedstromI'll generate the partials for the modules noted in #41.
Comment #43
jhedstromThis gets
UpdatePathTestBaseTestpassing. This is based off of #34(Partial table generated courtesy of #2544972: Add options to limit tables, exclude data, or only export data to DbDumpCommand :)
Comment #44
jhedstromOh, I just realized that
UpdateScriptTestuses a different set of modules. I'll add those partials too.Comment #45
jhedstromer, nevermind
UpdateScriptTestis usingWebTestBaseand loads no db dump scripts.Comment #47
dawehnerI'll have a look at the other failures.
Comment #48
dawehnerSome work.
Comment #50
dawehnerLet's try again with --binary
Comment #52
jhedstromI'll see if I can fix more failing tests.
Comment #53
jhedstromThe block context update tests were failing because the language context was not available. This gets enabled during install by the default config in the language module. Even though not strictly necessary for these tests, I also installed the default config from the block_test module.
Since the language dump is binary, this is the change I added there to install the configuration.
Comment #54
jhedstromComment #56
jhedstromActually, this approach of directly reading in the config probably isn't the best. If those change in the future, things could break, so we probably need these to just be the raw serialized arrays of the current yml files.
Comment #57
catchWe discussed this issue on the EuroCriticals call and Berdir had the following idea, which I'd also mulled over a bit but not for this issue specifically:
- for the menu update, we could add an equivalent of _update_prepare_d7_bootstrap() - run it in update.php before doing any rendering or anything else, to sort out the router - check the system schema version so it only runs once.
That lets us fix UpdateTestBase, and keep a beta12 database dump starting point, without having to tackle the broader problem of routing updates and update.php - at least until the next time we have such an update.
It's very hacky, but we could also remove that hack for the first RC - on the basis that you have to go last-beta before you can go to first release candidate.
The route generator changes we could still end up doing, but that at least lets us split those out to a separate issue.
Comment #58
dawehnerWill exclude the route generation changes into its own issue now.
Just wanted to post that this fixes UpdateScriptTest
Comment #59
dawehner#2559637: Don't rely on a working router on /update.php for URL generation Is the dedicated issue for that.
Comment #60
dawehnerQuick reroll
Comment #63
dawehnerAs we no longer access / on update.php + we have a dedicated route provider for /update.php results in no read access to {router} OR {menu_tree}
so I kinda think that #57 at least for now, is not needed. Feel free to disagree :)
Posting the binary patch now.
Comment #65
catchI'm slightly concerned about not having the route generator available during actual updates - this goes back to trying to avoid a parallel updates API vs. doing the three stage update issues.
For this at least I can't think of a single use case for accessing the generator during an update, but could we restore the normal one for running the actual updates? Then we can always reverse that decision later, but it keeps updates running within a 100% full environment for now.
Comment #66
dawehnerThe other failures ...
Comment #67
dawehnerMh
--binaryComment #70
dawehnerMeh.
Comment #71
berdirI don't really understand why this isn't hardcoded in the first place?
What if we keep the default route provider and fall back to that if it is not a pre-defined route? Then we know we can get through the initial steps but if an update for some reason wants to load a custom route (e.g., one common thing is to display a message with a link to some settings page or so. Just like we're doing with the maintenance mode.
nitpick: parent::rebuildAll().
Comment #72
berdirWanted to add test runs for postgresql and sqlite, but apparently DrupalCI doesn't like your patch?
WTF?
Comment #73
dawehnerLet's postpone on #2559637: Don't rely on a working router on /update.php for URL generation first
Comment #74
berdirSo the problem is that DrupalCI uses patch to apply patches, which does not support --binary. Which we have to fix.
The problem is that file isn't actually binary but git treats it as one because of the long lines in there.
Trying to force it to text in the meantime, so we can get the tests to run.
Did this with the following change to .gitattributes, why it doesn't do that with the existing line for *.php I have no idea:
Will postpone again after posting.
Comment #75
dawehnerAlright
Comment #76
MixologicIsntall/Jthorson fixed drupalci - try again. It now uses
git apply -v -p1Let us know if it needs to do more.
Comment #77
dawehnerThank you @Mixologic
Let's reroll as this patch is no longer postponed.
Comment #78
catchRemoving the notice eating. I think this is RTBC once that's gone.
Comment #79
catchGot the comment number wrong and uploaded the interdiff as the patch, almost as if predicting the need for a second comment.
Try this instead.
Comment #82
jibranWith correct patch now. Same interdiff as #78.
Comment #84
dawehnerLet me try as well :)
There was once this issue where 3 core developers tried to figure out how to create a patch. It was a hard and long journey.
Comment #85
dawehnerHaha, good try, we need the binary flag + the thing in #74 I think (not sure whether DrupalCI was fixed yet)
Comment #86
dawehnerComment #90
catch#78 was missing the change to parent::rebuildAll().
This is with --binary but not berdir's trick from #74, interdiff is against #85. I failed to mention patch in #78 and #79 had a difference too :(
Comment #91
catchAnd with berdir's trick in case that's still necessary.
Comment #92
dawehnerNice! As said on IRC I would have expected
$this->container = $this->kernel->getContainer()but if this works fine as well, let's go with itComment #93
stefan.r commentedsuperfluous full stop
but /this/ is not safe to do here
Comment #94
catchPostgres is down to 64 fails vs. 80. Some of those are still menu unserialize() errors though, but also the installer. Might need an issue each for those.
Comment #95
dawehnerJust fixed those points.
@catch
Yeah posted some quick comment on the main pgsql issue
Comment #97
dawehnerComment #98
alexpottCommitted ec41d08 and pushed to 8.0.x. Thanks!
Minor fixes done on commit.