Problem/Motivation
Follow-up to #1827112: Convert 'install_profile' variable to Settings. Drupal 8+ really wants a valid value of install_profile in settings.php by the end of installation. Therefore, it tries to write it at end of installer. If settings.php is read-only, install will fail with an exception misleadingly explaining that settings.php must be writable. But making this file writable is not possible in many hosting environments.
Proposed resolution
Only require a value for install_profile when this information cannot be derived otherwise. When a site is running a Distribution (note the special key in the yml), we can derive the install_profile name.
Remaining tasks
None
User interface changes
None
API changes
Settings::installProfile() is now preferred over drupal_get_profile() which is marked as deprecated.
Data model changes
None
Beta phase evaluation
Issue category | Bug because Drupal is not installable in environments where it used to be. |
---|---|
Issue priority | Major because many hosts (Pantheon, Acquia, etc.) will have pain here because they default to more secure installations (non-writable settings.php |
Disruption | Not disruptive because only affects the installer, not module code. |
Comment | File | Size | Author |
---|---|---|---|
#216 | 210-216-interdiff.txt | 1015 bytes | alexpott |
#216 | 2156401-3-216.patch | 50.34 KB | alexpott |
#210 | 2156401-4-210.patch | 50.27 KB | alexpott |
#210 | 202-210-interdiff.txt | 6.16 KB | alexpott |
#202 | 2156401-3-202.patch | 50.14 KB | alexpott |
Comments
Comment #1
sunComment #2
sunAs far as I can see, the same issue appears to apply to the "drupal_hash_salt" setting → if there is a working settings.php already, then the installer will not create a new hash salt.
Both the installation profile and the hash salt are values that ought to be written into settings.php upon every installation. Regardless of whether settings.php is functional already or not.
Comment #3
larowlanWhat about config directories Conf?
Comment #4
sunThe installer rewrites settings.php already in case no valid config directories are defined yet.
However, the installer does not touch settings.php, if all of the following conditions are met:
1. settings.php exists
2. Valid $databases and database connection
3. Valid $config_directories
In that case, the entire settings processing step of the installer is automatically skipped.
See install_tasks():
That comment, and the corresponding
$install_state['settings_verified']
was meant to be a unique condition and trigger for invoking the settings form - either with an interface, or just programmatically, depending on whether the database is configured correctly already.However,
install_begin_request()
only cumulates the following conditions:That is the location in which all conditions for a potential rewrite of settings.php have to be specified.
However, given that the new
$settings['install_profile']
is almost guaranteed to be different for each installation, we might as well decide to remove the entire conditionals and always execute the settings form.That would ensure that "install_profile" and "drupal_hash_salt" are always written to settings.php for each (re-)installation of Drupal.
Thoughts?
Comment #5
larowlanAlso #2115533: Add InstallerInterface to provide a stable non-interactive installer
I don't see a problem with that although I note that the interactive installer test assumes you can skip at least the language and profile steps, not sure about the settings.
Comment #6
sunThe new
InstallerExistingSettingsTest
discovered that the "Set up database" form (install_settings_form()
) appears even if settings.php contains a valid database connection already but e.g. no config directories yet.That's a slightly different symptom, but identical root cause:
The form has to be skipped in the UI, but still needs to be executed, so that settings.php gets rewritten.
Alternatively, we could investigate whether it wouldn't make sense to split this step into two:
install_rewrite_settings()
install task that explicitly rewrites settings.php.Comment #7
sunGuess I should put this into my bucket...
Comment #8
alexpottThis is a dupe of #2451363: Ensure install_profile is exists in settings.php after installation which has patches.
Comment #9
moshe weitzman CreditAttribution: moshe weitzman commentedThis issue was not fixed by #2451363: Ensure install_profile is exists in settings.php after installation at least for the non-interactive installer (i.e. Drush). So I am reopening. To reproduce the problem, install first with minimal and then with standard (or vice versa). You end up with the old profile only in settings.php.
In Drush, we are going to just refuse to proceed with re-install in this situation and leave the fix to this issue - https://github.com/drush-ops/drush/pull/1345
Comment #10
alexpottAh it was fixed by at one point. But then we backed off one of the changes for some sensible reason.
Comment #11
alexpottActaully I've just run the test myself and the value is changed - are you sure about this?
Comment #12
alexpottAnd if I change settings.php to something unwritable I get an error if the profiles don't match.
Comment #13
greg.1.anderson CreditAttribution: greg.1.anderson commentedSeems I was having trouble with this just last week. I'll re-run the tests and confirm here.
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commentedalexpott is right and this is working for me as designed.
Comment #15
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedAttached patch skips reporting an error when the distribution can be determined purely via code. This is a big help in environments where settings.php is usually read-only.
I still would like a better error message when we fail to write to settings due to a profile mismatch. I'm not sure yet how to reliably catch that exception. That can be a follow-up, IMO
Comment #16
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedComment #17
moshe weitzman CreditAttribution: moshe weitzman at Acquia commented@alexpott suggested that we replace all calls to Settings::get('install_profile' with a new Settings::getInstallProfile() which implements the fallback to a Distribution. Its a good idea - the attached patch does just that.
Comment #18
BerdirFirst part of a docblock should be < 80 characters and a single line.
No need to have all this information here, the last sentence can be moved to the @return, and the second part also seems unecessary here (it's an implementation detail and not relevant for the caller IMHO)
Do we get multiple calls to this? Should we statically cache it, or put it inside settings when it's not set?
Should we deprecate drupal_get_profile() in favor of Settings::getProfile()? I also don't really like adding new functions...
Comment #20
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedAddressed all feedback except for getting rid of drupal_get_profile(). Instead I marked it as deprecated. I can't get rid of it without bringing along its special case for the installer. Since there are 18 callers and we are late in the cycle, I figure we can leave it as a wrapper for now.
Comment #22
alexpottI think that this is testable by creating an InstallerTestBase test and having it create the test distribution... oh we have this already - DistributionProfileTest. We should test this is that test.
Comment #23
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedAdded an assertion to DistributionProfileTest. Thanks for the pointer.
Comment #24
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedComment #25
pwolanin CreditAttribution: pwolanin as a volunteer commentedSo, am I missing something or is this going to do a file scan on every page load if you don't have the setting in place?
It also seems like it won't fall back to standard if nothing is set in settings.php?
Would be helpful to update the summary about what the current proposed resolution is and what problem it's trying to solve.
Comment #26
moshe weitzman CreditAttribution: moshe weitzman at Acquia commented@pwolanin - i clicked around and can't find any regular pages that call Settings::getInstallProfile(). I think this only happens during Drupal heart attacks like cache rebuilds. During page building, Drupal relies on the config item core.extension which already includes your profile.
I don't think fallback to Standard is appropriate. For one thing, the installer would just pick Standard in that case, and not present a chooser.
I updated the Issue Summary and added Beta Eval
Comment #27
greg.1.anderson CreditAttribution: greg.1.anderson commentedI tried applying this patch to Drupal 8.0-beta12, and installing on a system with a read-only settings.php file, and still received an error:
Comment #28
greg.1.anderson CreditAttribution: greg.1.anderson commentedI tried running Drupal 8 with this patch installed, with a writable settings.php, and the install profile line was still written to settings.php. It seems like this is expected behavior for this patch -- we are only trying to make Drupal still install if the install profile line does not exist in settings.php.
However, I have not yet been successful in making this work when settings.php is not writable, even with a couple of experimental changes to try to help things along. I'll keep trying, though.
Comment #29
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedComment #30
greg.1.anderson CreditAttribution: greg.1.anderson commentedOk, I now see that this patch is only for sites with distributions. Testing #23 on Drupal 8 beta 12 with a distribution works like a charm. This is a great improvement for hosting environments that want to set up their configuration in advance via a read-only settings.php.
Comment #32
greg.1.anderson CreditAttribution: greg.1.anderson commentedOnce this is committed, as a next step we could modify #1356276: Allow profiles to define a base/parent profile to favor the distribution that contains a 'base' attribute (inherits from some other distribution).
Comment #33
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedNote that #31 is a false negative. The bot tested an ancient patch.
Since alexpott looked at this once already, I'm assigning this to him. My apologies if that is bad form.
Comment #34
xjmThanks Moshe, and thanks Greg for the manual testing!
Since @alexpott most recently just asked for tests I don't think it specifically needs his feedback, so unassigning. However, each time I started to review this I got snagged on miscellaneous spinach that seemed a smidge too much to fix on commit, so attached cleans that up a little. I'd leave it at RTBC since these are utterly tedious coding standards fixes, but it also needs a change record since it includes a deprecation, so NW for the CR once the bot picks it up.
Also fixing a typo or two in the beta eval. It's listed not disruptive but would be good to say why; presumably because it's totally BC/API addition and only affects sites when they are first being installed.
Finally, I'm still a little concerned about #25. Extra file scans even just on cold cache sound worrisome. I think we should confirm that there isn't a performance issue being added here.
Comment #35
xjmAnd NW for the CR.
Comment #36
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedBack to RTBC. Hope thats OK. There have been no changes to the patch itself.
Comment #37
alexpottIt's not just cold cache that would need the additional disk access but going to a page like admin/modules would end up calling drupal_get_distribution() if the install profile is not written to settings.php.
So... I think we can actually make this work with container parameters - which means that the installer logic in install profile can be moved to InstallerKernel (hey this makes sense) - and the install profile ends up being written to the container.
An interdiff is attached but it might be best to just read the patch since it's a big change of approach.
Comment #38
alexpottNow with added tests that if we have an existing unwritable settings.php the installer works and the install_profile is correctly determined without being written to settings.php.
Comment #40
alexpottLook how the changes to GetFilenameUnitTest are so nice :) - no longer relying on the weird install_state global side effect for testing!
Renamed the container parameter from
install.profile
toinstall_profile
cause it matches the existing setting. And tidied up a few things.Comment #42
Fabianx CreditAttribution: Fabianx as a volunteer commentedLooks really great, I would RTBC this - but I am not sure if alexpott does not want to work more on this.
Comment #43
dawehnerI don't see the point of that, isn't the parameter enough?
That is a bit confusing, but I guess a distribution will never ship with two, I gues?
Needs the right class
I don't see the point of that at all, why is the parameter not enough? At least the factory docs should explain that, and when to use what
Comment #44
alexpottI do... adding more testing around assumptions that Drush makes about being able to override profiles even if an existing Settings.php has one set in it. Also the test added for non writable settings.php and a distribution was not quite right. Patch adds plenty of tests for the various scenarios even one where the settings.php is not writable but we have a profile mistmatch and throw and exception in the installer.
Comment #45
alexpottComment #46
xjmWe still need a change record, also.
Comment #47
catchDoes the install profile really have to live in settings.php, could it live in state instead?
Comment #48
moshe weitzman CreditAttribution: moshe weitzman at Acquia commented@catch - if nothing else, you are consistent :). See #1827112-39: Convert 'install_profile' variable to Settings where you asked same question. Then see #55 there where you declared settings.php to be the right place for this.
So, this looks RTBC to me as well.
I'm not sure what the CR would say here. install_profile was not written in D7. Further, any D8 sites in the wild are unharmed by removing the requirement to write this param.
Comment #49
dawehnerNo, this issue has two needs tags and things aren't addressed. Just because you want that in doesn't mean its automatically RTBC :)
This is totally unused
Comment #50
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedSorry, I did not see those.
Comment #51
Fabianx CreditAttribution: Fabianx as a volunteer commentedI agree that the newest approach does not need profiling, we do way worse things on container rebuild and/or module scan time.
Comment #52
dawehnerNo worries @moshe weitzman (it was late at night)
I totally agree
Comment #53
alexpottI think the fact that the install profile should be injected into services is worthy of a CR (https://www.drupal.org/node/2538996). Very few services require this but doing this will allow new ways of unit testing them. In the patch attached I've used parameter injection in the ConfigInstaller so there is an example in core.
Patch attached also removes bogus InstallProfileFactory - sorry that crept in - it was a partial idea that I dropped because it was unnecessary complexity.
Comment #54
dawehnerWhat I really like about that approach is that there is a clear state whether the install profile is determined.
Comment #55
Fabianx CreditAttribution: Fabianx as a volunteer commentedThanks for the PR, the patch looks really great now!
Comment #56
catchThis changes the behaviour in subtle ways that make me uncomfortable, it might be just a documentation issue, or it might be something we need to account for.
Consider:
1. You install a site with one distribution.
2. Later on you add a different install profile to /profiles, because you're updating your site to be a multi-site.
3. Because nothing is in settings.php, now the file scan finds the different distribution instead of the original one. Fun ensues.
With the current behaviour, once the install profile is in settings.php, it's fixed and changes to the filesystem don't mess with it.
Also wonder if since it's going into a container parameter, whether we can't use services.yml for distributions and fall back to that instead of the filescan. Not sure if that fixes the use case this is intended for though (i.e. whether the installations that don't want to write to settings.php also don't want to write to services.yml).
Comment #57
alexpottWe can throw an exception if this occurs after a site has been installed and if a site is installed with two distributions we can force the user to choose.
Comment #59
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedThe new exception looks smart to me. I noticed the path core/lib/Drupal/Core/Installer and wondered if Installer is really the right place for this. getDistribution() is in core/lib/Drupal/Core/DrupalKernelInterface.php.
Also saw one typo: distrubtion
Comment #60
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedReroll for one conflict and fixed the remaining typo from ##5.
Comment #62
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedRerolled. No logic changes. Lets see what fails.
Comment #66
anavarreComment #67
izus CreditAttribution: izus commentedHi,
Here is a rerolled #60
:)
Comment #70
opdaviesThe patch in #67 applies cleanly to HEAD.
Comment #73
phenaproximaRe-rolled against #57 at @moshe weitzman's request.
Comment #75
phenaproximaI know nothing about the install system, but let me try this on a hunch...
Comment #77
chris.smith CreditAttribution: chris.smith at Portage CyberTech commentedRe-rolled.
Patch failed to apply after commit:
Commit 41e882f on 8.0.x
Still failing testing.
Comment #78
anavarreComment #81
chris.smith CreditAttribution: chris.smith at Portage CyberTech commentedFixing whitespace issue. Oops!
Comment #84
chris.smith CreditAttribution: chris.smith at Portage CyberTech commentedMissed the new conditional in getProfileStorage(). Submitting re-roll for test again.
Comment #86
moshe weitzman CreditAttribution: moshe weitzman at Acquia commentedAnyone available to push this along? Only 4 fails.
Comment #87
dawehnerThis fixes most of the points.
Comment #90
Mile23Reroll against 8.1.x.
Because https://twitter.com/greg_1_anderson/status/721107714903011328 :-)
Comment #92
tedbowThis patch fixes an error in InstallerExistingSettingsMismatchProfileTest
It was attempting to override getInstallationUrl to pass parameters via the query string which I didn't see in the parent class or anywhere else.
Instead I changed it to override visitInstaller:
I am still seeing an failing test in InstallerExistingSettingsMismatchProfileBrokenTest
I am not sure what is happening. I see:
This is the first time I have looked at installer tests but this seem to be trying to suppress the know error.
Through putting in debug messages I can confirm that the return false is being hit but I still see the error causing a failing test.
Anyways hopefully this patch will cause 1 less failing test.
Comment #94
tedbowOk here is patch that fixes one of tests to use \Drupal::installProfile()
Should fix 1 fail. Still not sure why the known error is not being suppressed as I mentioned in #92
Comment #96
dawehnerLet's point to 8.2.x
Ideally we swap that around
We can inject the profile into this class as well.
Mh, don't those two lines disagree with each other?
Let's not add all of them here.
Should we set this up in KernelTestBase itself?
Comment #97
tedbowOk here is patch that addresses @dawehner's review and
In InstallerExistingSettingsMismatchProfileBrokenTest the last line is new here.
After chatting with @wimleers he point this out to me. It is used when a known error is written out to error.log. Errors in would then be read in simpletest_log_read and add false failing test.
Also in \Drupal\Core\Config\ExtensionInstallStorage::getAllFolders changed
Because \Drupal::installProfile() will return back a false if no profile is set yet I believe. But I am clear whether that would ever happen in this point in the install.
Comment #99
tedbowWhoops! Think I see what I did wrong here. Another patch coming shortly.
Comment #100
tedbowOk this patch fixes those test errors by adding \Drupal\system\Tests\Bootstrap\GetFilenameUnitTest::containerBuild and removing the logic KernelTestBase.
This caused a bunch of tests to fail. Not sure why.
I also fixed some dependency injection issues from my last patch.
Comment #101
dawehnerThat honestly sounds like a problem for me. If the code which kind of works on production fails ... we should better figure out now, as otherwise it will bite us in the future.
Comment #102
tedbowOk, @dawehner, I should have said I didn't have time to look into it yet.
I will.
Comment #103
tedbowOk haven't figured this out yet but the exception that is being trigger comes from drupal_get_filename in bootstrap.inc
This problem doesn't show up in GetFilenameUnitTest because it doesn't set the $modules array.
If you add
to the class it gets the same problem.
So the problem is not which containerBuild you add
to. but rather the problem shows up when you use that line AND the $modules array is NOT empty.
drupal_get_filename get called multiple types with $name == 'testing'
The first time it gets called the $files never gets filled out so this error is triggered.
On subsequent calls $files has been filled out and then this error doesn't happened.
I will take another look tomorrow.
Comment #104
tedbowOk, here is the problem.
In 8.1.x \Drupal\Core\Extension\ExtensionDiscovery::setProfileDirectoriesFromSettings gets called from \Drupal\simpletest\KernelTestBase::enableModules
$module_list = $listing->scan('module');
setProfileDirectoriesFromSettings has
$profile = drupal_get_profile();
In 8.1.x returns null so further down
Is skipped
with this patch
$profile = drupal_get_profile();
Returns 'testing.
So that if statement calls
drupal_get_path('profile', $profile);
Which ultimately causes the problem in drupal_get_filenamethat I mentioned in #103
My guess is something needs to be added to \Drupal\simpletest\KernelTestBase::containerBuild to make not through that error but maybe who is more familiar with KernelTestBase and ExtensionDiscovery would have better idea.
Comment #105
tedbowOk, after chatting with @dawehner about what I found in #103 and #104 I am going to make separate issue to see if we should add
To \Drupal\simpletest\KernelTestBase::containerBuild
So putting back to Need review for patch in #100
Regarding my comment there
We do know why now explained in #103 and #104
Comment #106
dawehner@tedbow
Do you mind opening up the follow up issue, so we don't forget about it?
I would just let people not know about \Drupal::installProfile(). Code that needs the installation profile is not really common, so let's just give them good practises
Here is one question ... is this method useful in the public outside of the context of an installer? Also given the exception it sounds like the method be better just to available in the
InstallerKernel
. Any thoughts about that?Comment #107
tedbowYeah it seems to me that this is only useful during install.
So if we moved this to InstallerKernel then we would also have to override getInstallProfile in InstallerKernel because it calls $this->getDistribution().
Comment #108
dawehnerWell, we could keep the getDistribution, but keep it protected by default and just expose it publicly in the installer.
Comment #109
greg.1.anderson CreditAttribution: greg.1.anderson commentedIt seems to me that `DrupalKernel::getDistribution()` is needed outside of the context of the installer. If there is no install profile set in settings.php, then `DrupalKernel::getInstallProfile()` will fall back on `getDistribution()` to determine the installation profile to use. The result of `getInstallProfile()` is exposed by the `install_profile` parameter in the container, which is used by the config installer, the locale module, and potentially other sources. So, moving this behavior into `InstallerKernel::getInstallProfile()` would not work. I believe this is what @dawehner implicitly meant above.
It is easy enough to remove `getDistribution()` from DrupalKernelInterface, and place the public method in InstallerKernel, as suggested. However, `getDistribution()` is called in install.core.inc via `\Drupal::service('kernel')->getDistribution()`. If we removed `getDistribution()` from the interface, then this code would still happen to work, because the 'kernel' service is always an InstallerKernel at this point in the code. I've tried this, it works; I could provide the patch if we wanted to go this way. However, without having `getDistribution()` in the interface, there is no contract that guarantees that this method is available in this service, so this code change is perhaps not desirable.
I talked with @alexpott about this, and his feeling is that `getDistribution()` is similar to `getSitePath()` in terms of usage and requirements, and should therefore be fine to leave in the DrupalKernelInterface.
Comment #110
greg.1.anderson CreditAttribution: greg.1.anderson commentedI tested #100 on Pantheon on a read-only filesystem with a distribution, and it works very well. Pending agreement on #109, I think this is good.
Comment #112
heddnRe-roll
Comment #114
heddnComment #115
heddnFailure using this patch, #2466197: Staging directory should not have to be writeable. and a hacked config_installer (https://gist.github.com/heddn/c8c1f423715fc78880773925d997d630) on platform.
Comment #116
greg.1.anderson CreditAttribution: greg.1.anderson commentedIs #115 related? This issue avoids writing to settings.php if a distribution provides an installation profile. It does nothing to allow installation to succeed when settings.php is written for some other reason, so I think that the problem above should be addressed in a follow-on issue -- either in #2466197, or some other issue, as appropriate.
Comment #117
heddnre #116, I was not sure where to post my test result, so this might be in the wrong location. My local hack is some early work on my part (not ready for public use) for #2723499: drupal_rewrite_settings called in SiteConfigurationForm. May#115 should be directed at it.
Comment #118
dawehnerI still disagree to add the method to the runtime interface, but well, I don't care that much. You know, its just sometimes helpful to keep the surface area reasonable.
The documentation doesn't make it clear whether this distribution was actually used during install.
Can we add to the documentation that this actually scans the filesystem or so?
Comment #119
greg.1.anderson CreditAttribution: greg.1.anderson commented@dawehner: I care more about getting this patch in than whether or not the method is part of the interface. Talk to @alexpott; I already have a patch that implements #108 if you guys decide that's the way you want to go. I'd just need to reroll it / add it to #114 to put it in -- not hard.
Documentation requests above are reasonable. I'll add that once there's a decision on #108, if someone else doesn't get to it first.
Comment #120
alexpottDiscussed with @dawehner. Let's go for not exposing the getDistribution() method public on the regular run-time kernel. If we find the need later then we can open another issue to discuss it. However if we make it public now then going backwards is super hard. So let's get the fix that everyone wants and have the API discussions later if necessary.
@greg.1.anderson sorry I should have suggested this approach yesterday - at least you already have the patch :)
Comment #121
greg.1.anderson CreditAttribution: greg.1.anderson commentedRemoving getDistribution() from the interface. Let's see how this fares with the testbot.
Comment #123
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedWe need to test getDistribution() when we have an InstallerKernel.
Comment #124
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedUpdate version and run the tests.
Comment #125
dawehnerThank you a lot! I really like how this is now working. Nothing is really added to the runtime surface
Comment #127
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedIt's a little harder to test this way; getDistribution() must be called on the InstallerKernel, so the test must happen after the kernel is created, but before the installation is completed. I'll get it right eventually...
Comment #128
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedActually, since the problem is just in the test, I just put the code back the way it was, but used reflection to make the method accessible so that it could be called indirectly in the test.
Comment #129
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedHere's the interdiff for 128.
Comment #130
dawehnerThis looks great for me!
Comment #131
alexpottA few coding standards issues that needed addressing.
Comment #133
dawehner.
Comment #135
alexpottUnrelated test fails
Comment #136
heddnIn a conversation with Greg, it sounded like you need to denote the install profile as a 'distribution'. Should we write some release notes to explain how to make Drupal install as a distribution and fool things so it will install on a RO filesystem? My testing has been with minimal, standard and config_installer. All of which aren't technically distributions.
Comment #137
alexpott@heddn It's not just about distributions - it is also if the install profile is already set in the settings.php and the chosen profile matches it - then, with this patch, it will no longer attempt to write it.
Comment #140
jonathanshawPatch Failed to apply
error: core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php: No such file or directory
This is different to the unrelated failing migrate test mentioned by @dawehner and @alexpott.
As far as I can see GetFileNameUntiTest has not been touched since May 8, and patch applied fine on May 23.
Does this need a reroll or is the fail still unrelated?
Comment #141
dawehnerIn order to port this to 8.1.x we would ideally
a) keep ConfigInstaller::getInstallationProfile (and call out to some other code)
b) Use underscores for new methdo names in DrupalKernel if possible
Comment #142
alexpottRerolled - needed to change the
GetFilenameTest:: containerBuild()
toGetFilenameTest::register()
to work in the new phpunit KernelTestBase environment.Comment #143
claudiu.cristeaNits.
Extra empty line.
The word "Returns" should continue on the first line. Extra space preceding "If multiple". More lines are wrapped too early.
Array short syntax?
Comment #144
balsamaUpdated patch with the nits from #143 addressed.
Comment #145
balsamaIn addition to the passing tests, I can give a +1 to this from my anecdotal in real world testing...
We've been using a backported version of the patch in #142 to install Lightning in an environment with a write protected settings file (and the config_sync/database values in an include file).
Comment #146
dawehnerFor less BC break we could
return $this->installProfile;
That seems to be an easy win.Should we use \Drupal::installProfile() in both places?
Nitpick: Let's add
{@inheritdoc}
Comment #147
phenaproximaFixed all of @dawehner's comments in #146 except for #1, which seems to refer to code that no longer exists.
Comment #148
dawehnerExactly that's my point. We are removing a function we don't actually have to remove.
This is the code we remove.
Comment #149
dawehnerI think this patch, in its current form, has a major flaw:
ExtensionDiscovery
and its call todrupal_get_profile()
starts to rely on a working container.In the case of a working Drupal this is not much of a deal, but in a world of where the cached container is gone, this could become a problem.
In order to solve that problem, here is a possible solution (as discussed with alexpott and mpotter):
core.extension
An alternative approach could be to write the installation profile into a
services.yml
file on install time and then read from that, in case its needed.Comment #150
dawehnerHere is a patch on top of addressing the review in #148
Comment #153
alexpottFixing #150 and re-rolling.
Comment #155
alexpottOopsie... a better patch (against the right branch) and an upgrade path
Comment #156
alexpottI think if we write the profile to core.extension then we shouldn't add this to the kernel since it just isn't necessary.
Comment #158
alexpottInteresting...
Comment #160
dawehnerI'm not sure what is going on with the
BrowserTestBase
failure. While these tests fail for me locally, they still return a proper response.This fixes the other 2 failing tests.
Comment #161
dawehnerShouldn't this function now also write to config, just from an API point of view? The name of the function doesn't point out that its just about settings.php to be honest.
I would try to reorganize this code to make it clear, that
Settings::get('install_profile')
is just a fallback and the config storage is the primary source of truth.IMHO we should check also the config itself
Comment #162
alexpottThanks for the review @dawehner
1. Deprecated in the current patch
2. Completely rewritten
3. Agreed
The current patch goes further and deprecates the
install_profile
setting. It also removes thegetDistribution
code because it just is not necessary anymore.Comment #163
dawehnerShould we throw an exception here, when there is no profile returned?
Don't we still want to write the second distribution to test that the first one is taken into account?
I believe confoguration should be confogoroton.
Comment #164
alexpottHere's an upgrade path test. I think we need to be cautious with \Drupal::installProfile() (because it is called by drupal_get_profile()) and ensure it returns the correct profile even if it is called before the update is run.
Comment #165
alexpottThanks for the review @dawhener!
Comment #170
alexpottFixing what happens when there is a profile mismatch - ie when a user chooses a choice different to what is written in settings.php and settings.php can not be written.
Comment #171
Crell CreditAttribution: Crell at Platform.sh commentedThis is for-reals logic, which means it should not be on the \Drupal global. That object is supposed to be just a procedural code bridge to accessing the container, not a place to put logic not accessible elsewhere in a better fashion.
What am I supposed to do other than calling this static method to get the profile, like if I'm in an class and therefore should not be calling \Drupal, ever?
Comment #172
dawehnerIMHO all contrib/custom code should use the container parameter to inject this information. Everything else are just internal storage details.
Comment #173
dawehnerThe general direction looks great!
From a pure code readability POV I would but that into a helper method like
_install_get_all_distributions()
, but this is of course a style question.Can't we check
is_writable
instead?The comment could be a little bit misleading. Its not stressing out that the configuration is the primary profile storage
IMHO this method should describe that you, as runtime level code, better want to inject the install_profile from the container parameters and that's it.
Does @alexpott creates diff against other versions?
Comment #174
Mile23+1 on #171. Turn the
install_profile
parameter into a parameter factory similar to how we didapp.root
. Then the BC layer can be a separate protected method which can be individually marked as@deprecated
.Comment #175
alexpottThis is a BC change we shouldn't make - could break distributions or things that have changed the installer.
I think all the BC should be in drupal_get_profile - since that is what we are deprecating. Let's see if we were using any of it.
Still need to address some of #173.
Comment #176
alexpottRe #173
1. I'd rather not add new methods to the installer tbh.
2. Let's see if that is even needed. If it is imo suppression is a valid option.
3. Fixed
4. in #175 it now just returns the container param.
5. Fixed in #175
Comment #177
alexpottHmm got the BC layer wrong a bit.
Comment #181
alexpottComment #182
dawehnerWell, an additional private method always improves readability, IMHO, and help to do things properly in the future.
It is a bit weird to have twice the same condition. What about using
if (empty($config['profile']) { $install_profile = Settings::get(...);} else {$install_profile = $config['profile']; }
or use the ternary from aboveShould we use
assertIdentical('',
instead?Comment #183
alexpottActually the whole choose a distribution when there is more than one change is not necessary anymore. I could have removed core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php since this functionality is no longer changed by the test but I feel since it is an installer test and this code is untested atm it is better to leave this test in and change it to test the HEAD behaviour.
Comment #184
dawehnerGreat idea.
Comment #186
dawehnerThe patch is still green ...
Comment #188
alexpottConflict in system.install because another hook_update_N function added...
Comment #191
daffie CreditAttribution: daffie commentedBack to RTBC.
Comment #192
alexpottA more honest title.
Comment #195
daffie CreditAttribution: daffie commentedComment #196
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer and at Appnovation commentedRerolled #188 - just a simple conflict on system.install
Comment #197
alexpottThe diff between #188 and #196 looks great.
Comment #198
catchIn general I think we should be moving away from install profiles being active on installed sites, however that's not the case at all in 8.x, so improving how it works now is fine.
This could have a @todo to remove, and we could probably get rid of it in 8.4.x
So on the one hand it's good to enforce this.
On the other, what happens if an install profile is marked unsupported during 8.x's release? Or if you for some other reason want to migrate off it? It's currently theoretically possible to hack that via changing settings.php, this looks like it'd make it harder.
Comment #199
dawehnerWell, one could still do a runtime level override using
global $conf
.Comment #200
dawehnerWell, couldn't this break existing sites at any point in time?
Comment #201
catchIf that's true, then the comment is wrong:
Comment #202
alexpottI agree we should have an @todo to remove this code however given this is called before updates have run I think we can't remove till 9.x because it should be possible to update from 8.1.x to 8.4.x without having to have the 8.3.x codebase. Say you forgot to update a site for whatever reason. Opened #2831065: Remove BC layer from \Drupal\Core\DrupalKernel::getInstallProfile() against 9.x.
Re #198.2 is it already impossible to change the install profile because we validate you are not uninstalling it :) because they are still modules. This check is just checking that the module list and the new configuration don't get out of sync.
Comment #203
dawehnerThank you alex for adding the follow up!
Comment #205
catchAlright I was concerned this makes it impossible to change the profile - while we don't support that, we also don't offer any way for people to migrate off unsupported (in the d.o sense) profiles so it can be necessary to do that for disaster recovery. It doesn't make it impossible, it does make it a bit harder but @alexpott's updated the change record with an example of how to do it.
So committed/pushed to 8.3.x, thanks!
Comment #206
jhodgdonThis commit broke my contrib module, by adding a new argument to the constructor for core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
Isn't this an API change? I cannot make a version of my module that is compatible with both Drupal 8.2.x and 8.3.x because of this change. I have a service that depends on this class and I have to supply arguments to the constructor... Can you please revert this?
Comment #207
jhodgdonHere's the test that broke from this commit...
https://www.drupal.org/pift-ci-job/541244
Comment #209
catchReverted.
In other patches we've made the parameter optional with a \Drupal fallback, we can do that here too.
Comment #210
alexpott@jhodgdon thanks for the quick feedback - we should definitely not break an API for this change.
The shame of course is that we can't make the code future proof because of the mix of optional and required params but at least we can trigger a silent deprecation notice and in Drupal 9 consider removing all optional params since of code that complies with the deprecation notice will be passing in all of the parameters.
Test result from your module with this patch applied.
Comment #211
jhodgdonThanks for the quick action!
Can't a new parameter be added at the end of the parameter list, with a default? Then my module wouldn't break, at least I think so... Ah, that's what you did.
I'll review the interdiff... Looks good except for maybe this:
Should this be marked (optional)? It does have a default... kind of... Maybe a note should be added that the parameter is technically optional in D8 but will become required in D9, or something like that? Or a deprecation notice that not supplying the parameter is deprecated in D8?
Comment #215
dawehnerThe remaining task seems to be a novice issue.
Comment #216
alexpottHere's the docs update.
The interdiff is a bit of lie - there is also a change to system_install() to update the hook_update_N number to 8301.
Comment #217
dawehnerThis looks good to go for me.
<3
Comment #220
catchCommitted/pushed to 8.4.x and cherry-picked to 8.3.x. Thanks!