#3266057: Allow profiles to define a base/parent profile [continue of #1356276] is the continuation of this issue.

Updated: Comment [#516]
Jump to page 2

Problem/Motivation

Install profiles are not inheritable, so if you want to, say, take Drupal Commons, and base your site off of it, but add one or two extra modules in your own customized install profile, you have to clone the entire install profile and change it to your needs. Allowing install profiles to declare base profiles (just like themes can declare base themes) would drastically simplify customizations to existing distributions by:

  • Inheriting configuration from a parent install profile (base-profile)
  • Overriding specific configuration from the base-profile
  • Inheriting customizations in the installer from the base-profile
  • Having additional installer tasks and form items to customize their own "start-state"

Additional motivations are detailed on Dries's blog post.

Proposed resolution

  • Modify the module load system to take into account base install profiles.
  • Modify the install profile system to run parent installer(s) in the correct order.
  • One proposed solution was to simply use modules instead of profile inheritance. This was discussed at length and the prevailing attitude was that the functionality for profile inheritance has valuable use cases that cannot be solved by modules alone.
  • An early resolution was to include a tag to exclude dependencies and themes. In an effort to clearly define focus for this patch, this functionality was removed from this patch. The use case for excluded_dependencies and excluded_themes is still very much valid, so this feature request has been given its own issue.

Complications

Implementing this would expose or compound existing problems with the way distributions handle config. Specifically how distributions provide low level config bug fixes and new features to existing sites. #3004662: [META] Standardize the way distributions handle config updates was opened to see if we can get consensus around a solution.

Remaining tasks

  • Convince someone on the Core Team that this is a good idea.
  • Create plan
  • Write useful issue summary
  • Fix issue from #405
  • Fix issue from #412
  • Fix issue from #476
  • Update Change Record.
  • Make tests pass.
  • Extensively test this patch against a real-world base-profile
  • Add to existing documentation page (To be published only after patch is applied.)
  • Review Documentation to make sure they are up-to-date.

User interface changes

None.

API changes

Install profiles can define base profiles using the syntax base profile: BASE_PROFILE inside their .info.yml files.

Please post all followups at #3266057: Allow profiles to define a base/parent profile [continue of #1356276].

CommentFileSizeAuthor
#688 interdiff--1356276-667--1356276-688.txt26.54 KBRajab Natshah
#688 1356276-688.patch58.46 KBRajab Natshah
#686 diff_reroll_1356276_680-686.txt17.63 KBankithashetty
#686 1356276-686.patch65.5 KBankithashetty
#680 1356276-679-680-interdiff.txt4.55 KBRoSk0
#680 1356276-680.patch65.19 KBRoSk0
#679 interdiff_678-679.txt1.17 KBranjith_kumar_k_u
#679 1356276-679.patch64.98 KBranjith_kumar_k_u
#678 interdiff-675-678.txt19.16 KBRoSk0
#678 1356276-678.patch64.99 KBRoSk0
#677 interdiff--1356276-675---1356276-667-subprofile-support-9.3.x.txt51.81 KBRajab Natshah
#677 interdiff--3143958-15-subprofile-support-9.1.x----1356276-667-subprofile-support-9.3.x.txt32.37 KBRajab Natshah
#677 1356276-667-subprofile-support-9.3.x.patch58.27 KBRajab Natshah
#675 reroll_diff_673-675.txt3.86 KBsaltednut
#675 1356276-675.patch64.25 KBsaltednut
#673 1356276-673.patch64.29 KBjoseph.olstad
#673 interdiff-1356276_672_to_673.txt1.18 KBjoseph.olstad
#672 interdiff-1356276_671_to_672.txt1.3 KBjoseph.olstad
#672 1356276-672.patch64.49 KBjoseph.olstad
#671 interdiff-1356276_670-671.txt792 bytesnevergone
#671 1356276-671.patch64.36 KBnevergone
#670 interdiff-1356276_669-670.txt754 bytesnevergone
#670 1356276-670.patch64.34 KBnevergone
#669 interdiff-1356276_668-669.txt2.81 KBnevergone
#669 1356276-669.patch64.32 KBnevergone
#668 interdiff-1356276_665-668.txt5.94 KBnevergone
#668 1356276-668.patch63.89 KBnevergone
#665 interdiff-1356276_661-665.txt5.92 KBnevergone
#665 1356276-665.patch63.87 KBnevergone
#661 interdiff-1356276_659-661.txt2.22 KBshweta__sharma
#661 1356276-661.patch63.85 KBshweta__sharma
#659 D93x-1356276-659.patch63.85 KBjoseph.olstad
#658 InstallStorage.patch561 bytesSubhransu sekhar
#657 D91x-1356276-656.patch63.52 KBjoseph.olstad
#656 D91x_AND_D93x-1356276-656.patch63.55 KBjoseph.olstad
#656 1356276-interdiff_652_to_656.txt638 bytesjoseph.olstad
#652 interdiff.txt6.68 KBKapilV
#652 1356276-652.patch63.54 KBKapilV
#651 reroll_diff_633-651.txt2.42 KBjay.dansand
#651 1356276-651-by-mpotter-balsama-phenaproxima-9.1.0-9.2.x.patch63.53 KBjay.dansand
#639 interdiff-627-638.txt526 bytesErik Frèrejean
#639 1356276-91x-638.patch41.72 KBErik Frèrejean
#638 interdiff-633-638.txt8.34 KBjrglasgow
#638 1356276-638-allow-profiles-to-define-a-base-parent-profile.patch66.68 KBjrglasgow
#633 interdiff-631-633.patch1.39 KBvierlex
#633 1356276-633-by-mpotter-balsama-phenaproxima-9.1.0-9.2.x.patch63.63 KBvierlex
#632 interdiff-1356276-603-631.txt11.53 KBsylus
#632 1356276-631-by-mpotter-balsama-phenaproxima.patch67.75 KBsylus
#630 1356276-adding-patch-in-622-plus-a-few-changes.patch50.59 KBsylus
#627 1356276-91x-626.patch44.8 KBjrglasgow
#627 interdiff-622-626.txt1.35 KBjrglasgow
#625 1356276-91x-625.patch30.91 KBjrglasgow
#622 1356276-90x-622.patch58.47 KBErik Frèrejean
#622 1356276-91x-622.patch41.49 KBErik Frèrejean
#622 interdiff_621-622.txt3.35 KBErik Frèrejean
#621 1356276-621.patch38.32 KBErik Frèrejean
#616 1356276-90x-616.patch38.32 KBvierlex
#603 interdiff_602-603.txt853 bytesVVVi
#603 1356276-88x-603.patch61.09 KBVVVi
#602 interdiff_601-602.txt5.05 KBVVVi
#602 1356276-88x-602.patch60.62 KBVVVi
#601 drupal-n1356276-601-88x.patch57.56 KBDamienMcKenna
#598 core-1356276-598-89x.patch57.56 KBrobpowell
#594 reroll_diff_587-594.txt11.08 KBshaal
#594 1356276-88x-594.patch58.72 KBshaal
#592 reroll_diff_588-592.txt16.43 KBshaal
#592 core-base-parent-profile-1356276-592.patch58.54 KBshaal
#588 drupal-n1356276-588-87x.patch57.65 KBDamienMcKenna
#587 interdiff_586-587.txt2.81 KBdwkitchen
#587 1356276-587.patch58.09 KBdwkitchen
#586 interdiff_1356276_572-586.txt5.09 KBnevergone
#586 1356276-586.patch58.58 KBnevergone
#572 interdiff-549-572.txt954 bytesbalsama
#572 1356276-572.patch58.6 KBbalsama
#546 1356276-531-reroll.patch56.42 KBdpagini
#546 1356276-546.patch57.28 KBdpagini
#546 interdiff_531-546.txt2.87 KBdpagini
#546 1356276-546-wtests.patch58.69 KBdpagini
#546 interdiff-546-wtests.txt1.02 KBdpagini
#546 1356276-546-8.6.x.patch57.19 KBdpagini
#546 1356276-546-8.6.2.patch56.5 KBdpagini
#531 1356276-531.patch56.42 KBphenaproxima
#515 interdiff-1356276-511-515.txt2.56 KBbendeguz.csirmaz
#515 1356276-515.patch56.01 KBbendeguz.csirmaz
#511 interdiff-1356276-507-511.txt945 bytesbendeguz.csirmaz
#511 1356276-511.patch54.59 KBbendeguz.csirmaz
#510 interdiff-1356276-507-510.txt1.01 KBdpagini
#510 1356276-510-testonly.patch55.33 KBdpagini
#507 interdiff-1356276-505-507.txt3.42 KBphenaproxima
#507 1356276-507.patch54.04 KBphenaproxima
#505 interdiff-1356276-501-505.txt466 bytesphenaproxima
#505 1356276-505.patch51.15 KBphenaproxima
#501 interdiff-1356276-498-501.txt4.41 KBphenaproxima
#501 1356276-501.patch51.15 KBphenaproxima
#498 interdiff-1356276-473-498.txt3.82 KBphenaproxima
#498 1356276-498.patch50.68 KBphenaproxima
#490 interdiff_473-490.txt1.42 KBdpagini
#490 1356276-490.patch50.49 KBdpagini
#488 interdiff_473-488.txt865 bytesdpagini
#488 1356276-488.patch50.09 KBdpagini
#487 interdiff_473-487.txt532 bytesdpagini
#487 1356276-487.patch49.66 KBdpagini
#486 interdiff_473_486.txt12.33 KBdpagini
#486 1356276-486.patch35.07 KBdpagini
#473 interdiff-1356276-471-473.txt1.13 KBphenaproxima
#473 1356276-473.patch48.97 KBphenaproxima
#471 1356276-471.patch49.72 KBphenaproxima
#470 interdiff-1356276-468-470.txt837 bytesphenaproxima
#470 1356276-470.patch50.22 KBphenaproxima
#468 interdiff-1356276-466-468.txt589 bytesphenaproxima
#468 1356276-468.patch49.48 KBphenaproxima
#466 interdiff-1356276-464-466.txt623 bytesphenaproxima
#466 1356276-466.patch49.48 KBphenaproxima
#464 interdiff-1356276-462-464.txt3.17 KBphenaproxima
#464 1356276-464.patch49.48 KBphenaproxima
#462 interdiff-1356276-461-462.txt4.32 KBphenaproxima
#462 1356276-462.patch49.19 KBphenaproxima
#461 interdiff-1356276-459-461.txt4.77 KBphenaproxima
#461 1356276-461.patch49.25 KBphenaproxima
#459 1356276-459.patch50.19 KBphenaproxima
#450 drupal-n1356276-450-85x.patch28.14 KBDamienMcKenna
#446 interdiff-1356276-444-446.txt2.43 KBphenaproxima
#446 1356276-446.patch51.97 KBphenaproxima
#444 interdiff-1356276-443-444.txt3.21 KBphenaproxima
#444 1356276-444.patch52.96 KBphenaproxima
#443 interdiff-1356276-441-443.txt3.89 KBphenaproxima
#443 1356276-443.patch52.82 KBphenaproxima
#441 interdiff-1356276-433-441.txt51.24 KBphenaproxima
#441 1356276-441.patch52.15 KBphenaproxima
#433 1356276-433.patch62.03 KBbalsama
#428 1356276-428.patch54.67 KBbalsama
#426 1356276-426-D8.patch28.14 KBmohit1604
#424 1356276-424-D8.patch27.96 KBmohit1604
#422 drupal-n1356276-417-d8.5.x.patch61.26 KBdpagini
#419 1356276-419--8.4.4.patch66.62 KBpingers
#417 drupal-n1356276-417-d8.5.*.patch61.26 KBscor
#415 drupal-n1356276-414-d8.4.3.patch61.25 KBDamienMcKenna
#413 drupal-n1356276-413-d8.4.patch61.25 KBDamienMcKenna
#408 1356276-408--8.4.x.patch61.31 KBphenaproxima
#402 Screen Shot 2017-10-30 at 12.34.30 PM.png62.04 KBkreynen
#397 drupal-n1356276-397-8.5.x.patch58.95 KBDamienMcKenna
#389 interdiff-385-389.txt1.64 KBbalsama
#389 interdiff-360-389.txt10.2 KBbalsama
#389 1356276-389.patch58.96 KBbalsama
#386 interdiff-360-385.txt9.67 KBbalsama
#386 1356276-385.patch59 KBbalsama
#384 1356276-384.patch58.63 KBbalsama
#369 cds.info.yml291 bytessylus
#366 composer.json_.txt1.33 KBtimcosgrove
#362 interdiff-360-362.patch3.38 KBoriol_e9g
#362 1356276-362.patch65.35 KBoriol_e9g
#360 interdiff-356-360.txt2.02 KBmpotter
#360 1356276-360.patch61.27 KBmpotter
#356 interdiff-348-356.txt18.61 KBoriol_e9g
#356 1356276-356.patch60.46 KBoriol_e9g
#352 1356276-358.patch59.5 KBoriol_e9g
#352 interdiff.patch13.69 KBoriol_e9g
#348 1356276-interdiff-327-348.txt9.26 KBbalsama
#348 1356276-348.patch57.26 KBbalsama
#346 1356276-interdiff-344-346.txt720 bytesbalsama
#346 1356276-346.patch57.23 KBbalsama
#344 1356276-interdiff-341-344.txt2.89 KBbalsama
#344 1356276-344.patch57.22 KBbalsama
#341 1356276-interdiff-327-341.txt8.92 KBbalsama
#341 1356276-341.patch56.97 KBbalsama
#339 1356276-interdiff-327-339.txt6.66 KBbalsama
#339 1356276-339.patch55.85 KBbalsama
#327 interdiff-1356276-319-327.txt789 bytesShawn DeArmond
#327 1356276-327-8.4.x.patch51.8 KBShawn DeArmond
#319 interdiff-1356276-303-319.txt963 bytesbalsama
#319 1356276-319.patch51.85 KBbalsama
#308 1356276-306-8.3.0.patch1.14 MBGravypower
#307 interdiff-1356276-303-306.txt789 bytesGravypower
#307 1356276-306.patch51.78 KBGravypower
#304 interdiff-281-303.txt10.46 KBbalsama
#304 interdiff-302-303.txt1.53 KBbalsama
#304 1356276-303.patch51.84 KBbalsama
#302 interdiff-291-302.txt1.37 KBbalsama
#302 1356276-302.patch51.47 KBbalsama
#292 interdiff-290-291.txt2.06 KBbalsama
#292 1356276-291.patch51.39 KBbalsama
#290 interdiff-289-290.txt4.94 KBbalsama
#290 1356276-290.patch50.46 KBbalsama
#289 interdiff-282-289.txt2.32 KBbalsama
#289 1356276-289.patch45.76 KBbalsama
#283 interdiff-1356276-8.2.x-276-283.txt1.3 KBbalsama
#283 1356276-283-8.2.x.diff44.55 KBbalsama
#282 interdiff-1356276-281-282.txt1.3 KBbalsama
#282 1356276-282.diff44.68 KBbalsama
#281 1356276-281.patch44.57 KBbalsama
#276 1356276-276-8.2.x.patch44.44 KBbalsama
#276 interdiff-273-276.txt5.81 KBbalsama
#276 1356276-276.patch44.78 KBbalsama
#274 1356276-274-8.2.x.patch44.28 KBphenaproxima
#273 interdiff-1356276-271-273.txt3.16 KBphenaproxima
#273 1356276-273.patch44.62 KBphenaproxima
#271 interdiff-1356276-269-271.txt1.23 KBphenaproxima
#271 1356276-271.patch44.06 KBphenaproxima
#269 interdiff-1356276-267-269.txt6.35 KBphenaproxima
#269 1356276-269.patch44.28 KBphenaproxima
#267 1356276-267.patch42.4 KBphenaproxima
#264 interdiff-1356276-264.patch969 bytesoriol_e9g
#263 interdiff-1356276-262-263.txt703 bytesbalsama
#263 1356276-263.patch42.33 KBbalsama
#262 interdiff-1356276-249-262.txt1.21 KBbalsama
#262 1356276-262.patch41.95 KBbalsama
#249 interdiff-239-249.txt1.69 KBmpotter
#249 1356276-249.patch40.6 KBmpotter
#239 interdiff-231-239.txt1.47 KBmpotter
#239 1356276-239.patch40.42 KBmpotter
#231 interdiff.txt5.43 KBdawehner
#231 1356276-231.patch40.29 KBdawehner
#230 interdiff.txt10.21 KBdawehner
#230 1356276-230.patch38.74 KBdawehner
#227 interdiff-1356276-222-227.txt8.55 KBmpotter
#227 1356276-227.patch36 KBmpotter
#226 interdiff-1356276-222-226.txt9.47 KBmpotter
#226 1356276-226.patch34.88 KBmpotter
#222 interdiff.txt1.08 KBdawehner
#222 1356276-222.patch38.77 KBdawehner
#220 interdiff.txt17.4 KBdawehner
#220 1356276-220.patch38.75 KBdawehner
#217 interdiff-1356276-214-217.txt8.67 KBmpotter
#217 make_inherited_install-1356276-217.patch36.31 KBmpotter
#216 interdiff-1356276-214-216.txt5.18 KBmpotter
#216 make_inherited_install-1356276-216.patch33.99 KBmpotter
#214 interdiff-1356276-208-214.txt9 KBmpotter
#214 make_inherited_install-1356276-214.patch31.34 KBmpotter
#209 interdiff-1356276-200-208.txt22.59 KBmpotter
#209 make_inherited_install-1356276-208.patch27.48 KBmpotter
#207 interdiff-1356276-200-207.txt24.08 KBmpotter
#207 make_inherited_install-1356276-207.patch29.05 KBmpotter
#200 interdiff-1356276-198-200.txt5.21 KBmpotter
#200 make_inherited_install-1356276-200.patch20.61 KBmpotter
#199 interdiff-1356276-196-198.txt2.98 KBmpotter
#199 make_inherited_install-1356276-198.patch21.33 KBmpotter
#196 make_inherited_install-1356276-196.patch21 KBmpotter
#193 interdiff-1356276-183-193.txt4.96 KBmpotter
#193 make_inherited_install-1356276-193.patch20.97 KBmpotter
#183 interdiff-1356276-181-183.txt13.1 KBmpotter
#183 make_inherited_install-1356276-183.patch21.25 KBmpotter
#181 interdiff-1356276-176-181.txt8.56 KBmpotter
#181 make_inherited_install-1356276-181.patch18.69 KBmpotter
#176 interdiff-1356276-170-172.txt6.82 KBmpotter
#176 make_inherited_install-1356276-176.patch19.49 KBmpotter
#172 make_inherited_install-1356276-172.patch13.13 KBmpotter
#170 make_inherited_install-1356276-170.patch11.04 KBmpotter
#158 make_inherited_install-1356276-158.patch10.78 KBdas-peter
#157 make_inherited_install-1356276-157.patch3.15 KBmqanneh
#143 1356276-143-test-only.patch2.62 KBmpotter
#133 make_inherited_install-1356276-133.patch2.64 KBmpotter
#131 make_inherited_install-1356276-131.patch2.59 KBmpotter
#129 make_inherited_install-1356276-129.patch1.97 KBmpotter
#120 frodobaggins1.png234.86 KBphenaproxima
#112 inheritable-1356276-112.patch16.43 KBtimodwhit
FAILED: [[SimpleTest]]: [MySQL] 59,593 pass(es), 1 fail(s), and 1,387 exception(s). View
#110 inheritable-1356276-109.patch16.39 KBtimodwhit
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch inheritable-1356276-109.patch. Unable to apply patch. See the log in the details link for more information. View
#107 inheritable-1356276-107.patch16.4 KBtimodwhit
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch inheritable-1356276-107.patch. Unable to apply patch. See the log in the details link for more information. View
#92 1356276-base-profile-91.patch21.54 KBgeerlingguy
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-base-profile-91_0.patch. Unable to apply patch. See the log in the details link for more information. View
#91 1356276-base-profile-91.patch0 bytesgeerlingguy
FAILED: [[SimpleTest]]: [MySQL] Setup environment: Test cancelled by admin prior to completion. View
#87 1356276-base-profile-87.patch18.45 KBgeerlingguy
PASSED: [[SimpleTest]]: [MySQL] 57,828 pass(es). View
#86 1356276-base-profile-86.patch0 bytesgeerlingguy
PASSED: [[SimpleTest]]: [MySQL] 58,224 pass(es). View
#84 1356276-base-profile-84.patch18.65 KBgeerlingguy
FAILED: [[SimpleTest]]: [MySQL] 57,339 pass(es), 1 fail(s), and 32,128 exception(s). View
#74 1356276-D7-inheritable-profiles.patch12 KBamcgowanca
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-D7-inheritable-profiles.patch. Unable to apply patch. See the log in the details link for more information. View
#72 1356276-inheritable-profiles.patch1.98 KBamcgowanca
PASSED: [[SimpleTest]]: [MySQL] 40,270 pass(es). View
#71 1356276-inheritable-profiles.patch0 bytesamcgowanca
PASSED: [[SimpleTest]]: [MySQL] 40,431 pass(es). View
#59 1356276-base-profile-59.patch18.47 KBgeerlingguy
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-base-profile-59.patch. Unable to apply patch. See the log in the details link for more information. View
#57 1356276-base-profile-57.patch18.67 KBgeerlingguy
FAILED: [[SimpleTest]]: [MySQL] 57,990 pass(es), 0 fail(s), and 47,508 exception(s). View
#46 1356276-cleanup-patch42-45.patch21.92 KBdagomar
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-cleanup-patch42-45.patch. Unable to apply patch. See the log in the details link for more information. View
#42 1356276-base_profiles_variable-42.patch21.92 KBtom friedhof
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-base_profiles_variable-42.patch. Unable to apply patch. See the log in the details link for more information. View
#40 interdiff.txt983 byteslucascaro
#39 1356276-base-profile-d7-39-do-not-test.patch22.09 KBlapith
#38 1356276-base-profile-d7-38-do-not-test.patch21.03 KBhelior
#37 1356276-base-profile-37.patch19.02 KBhelior
PASSED: [[SimpleTest]]: [MySQL] 46,240 pass(es). View
#36 1356276-make-D7-21-redux.patch1.98 KBgeoffreyr
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-21-redux.patch. Unable to apply patch. See the log in the details link for more information. View
#35 1356276-make-D7-17-redux.patch2.03 KBgeoffreyr
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-17-redux.patch. Unable to apply patch. See the log in the details link for more information. View
#32 1356276-32-base-profile-do-not-test.patch21.17 KBezeedub
#29 1356276-base-profile-do-not-test.patch21.76 KBhelior
#25 1356276-profile-inheritance.patch2 KBcweagans
PASSED: [[SimpleTest]]: [MySQL] 36,884 pass(es). View
#21 1356276-make-D7-21.patch1.98 KBmpotter
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-21.patch. Unable to apply patch. See the log in the details link for more information. View
#20 1356276-make-D7-20.patch1.98 KBmpotter
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-20.patch. Unable to apply patch. See the log in the details link for more information. View
#17 1356276-make-D7-17.patch2.04 KBtirdadc
PASSED: [[SimpleTest]]: [MySQL] 39,170 pass(es). View
#11 1356276-2-recurse-parents-pressflow-7.12-git.patch2.14 KBpatcon
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-2-recurse-parents-pressflow-7.12-git.patch. Unable to apply patch. See the log in the details link for more information. View
#2 1356276.patch2.05 KBe2thex
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276_0.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots. View
#2 1356276-make-D7.patch2.04 KBe2thex
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7.patch. Unable to apply patch. See the log in the details link for more information. View
#1 1356276.patch1.98 KBe2thex
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots. View
#1 1356276-make.patch1.98 KBe2thex
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots. View
#547 1356276-547-wtests.patch58.66 KBdpagini
#547 interdiff_531-547.txt2.87 KBdpagini
#549 1356276-549-8.6.2.patch56.47 KBdpagini
#549 1356276-549-8.6.x.patch58.7 KBdpagini
#549 interdiff_531-549.txt4.65 KBdpagini
#549 1356276-549-wtests.patch58.7 KBdpagini

Issue fork drupal-1356276

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

e2thex’s picture

FileSize
1.98 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots. View
1.98 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots. View

This patch adds a recursive function that goes the profile and any of it parents and adds paths for each of them.

e2thex’s picture

FileSize
2.04 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7.patch. Unable to apply patch. See the log in the details link for more information. View
2.05 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276_0.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots. View

Change the patch so that it use base instead of parents so that it is inline with

base = BASE PROFILE

or

base[] = BASE PROFILE
e2thex’s picture

Status: Active » Needs review
febbraro’s picture

Title: Modules and themes From One profile being avaiable in a sub Profile. » Make install profiles inheritable

Changing to a more accurate title

DuaelFr’s picture

Looks great ! I will give it a try soon.

patcon’s picture

DuaelFr’s picture

@patcon
Profiler's base profile allow to inherit some base profile's things like installation functions but it do not add all the base profile directories to the stack when looking for modules' or themes' locations.

patcon’s picture

I can't say with 100% accuracy until I test, but I was under the impression that Profiler was designed for that same reason. Inherited *.install files were secondary, I believe. Are you certain on that?
http://drupalcode.org/project/profiler.git/blob/refs/heads/7.x-2.x:/READ...

patcon’s picture

Hm. Ok, I think this clarified for me (although I guess I can still spin up a site myself):
http://drupal.org/node/1275160

You're right. Sorry for the confusion and derailing :)

patcon’s picture

FileSize
2.14 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-2-recurse-parents-pressflow-7.12-git.patch. Unable to apply patch. See the log in the details link for more information. View

Same patch as #2, but rerolled against pressflow 7.12 using git (hopefully drush_make supports this now, or i'll be back :) )

Crell’s picture

cweagans’s picture

patcon’s picture

@cweagan I'm ashamed to admit how many clicks it took me to realize I was in an infinite loop of duplicate issue links...

EDIT: Guessing this was the one :)
#555212: Install profile inheritance

cweagans’s picture

Heh, whoops. Link fixed.

patcon’s picture

GOOOO TEAM! *anchorman leap*

tirdadc’s picture

FileSize
2.04 KB
PASSED: [[SimpleTest]]: [MySQL] 39,170 pass(es). View

I rerolled http://drupal.org/files/1356276-make-D7.patch against 7.14, had to make some minor adjustments. Will test and update this comment.

mpotter’s picture

Status: Needs work » Reviewed & tested by the community

Been using this on several large production sites and works great!

David_Rothstein’s picture

Version: 7.x-dev » 8.x-dev
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs backport to D7

This needs to go into Drupal 8 first, but it looks like the kind of change that might be acceptable for Drupal 7 backport, if it's the direction we decide to go in.

Some issues on a quick readthrough:

+ * recusive function to find listing paths from profiles and their parents

This has typos ("recusive" => "recursive") and grammar mistakes (sentence should start with a capital letter and end with a period). Also similar issues elsewhere in the documentation.

+  $info  = drupal_parse_info_file("profiles/$profile/$profile.info");

It seems pretty bad that we're going to manually parse the .info file every time this function runs, rather than taking advantage of information cached elsewhere. But it's a low-level function, so I'm not sure how best to solve that.

+    $searchdir = drupal_system_listing_profile($profile, $directory, $searchdir);
   }
-
+  

Extra whitespace.

mpotter’s picture

Status: Needs work » Needs review
FileSize
1.98 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-20.patch. Unable to apply patch. See the log in the details link for more information. View

Here is a re-roll of the patch with the spelling, grammar, and whitespace issues fixed. The drupal_parse_info_file() isnt' really a problem because that function already has it's own cache. But I'd welcome other suggestions or patch improvements.

mpotter’s picture

FileSize
1.98 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-21.patch. Unable to apply patch. See the log in the details link for more information. View

Bah, missed one more space at the end of a line. Here is the cleaner patch.

mpotter’s picture

Grr. Marking this as a D8 issue is causing the D7 patch to fail testing. Is there a way to mark a patch as "for D7" for the tester so this doesn't happen? Is there any special patch naming trick for that?

If you are using D7, ignore the failed test result of #21. It applies just fine to 7.14.

DuaelFr’s picture

I had seen a naming convention before but the documentation does no longer mention it.

You can just add a "-do-not-test" suffix to say to the bot to skip your patch.

cweagans’s picture

Status: Needs work » Needs review
FileSize
2 KB
PASSED: [[SimpleTest]]: [MySQL] 36,884 pass(es). View

Rerolled patch for D8.

sun’s picture

Status: Needs review » Needs work

This looks incorrect to me.

We do not want to re-evaluate the base profile at run-time.

Instead, the only change to the foreach in drupal_system_listing() would be the replacement of $profile with something along the lines of this:

$profile = drupal_get_profile();
$profiles = array();
do ($profile) {
  $profiles[] = $profile;
  $profile_info = system_get_info('profile', $profile);
  $profile = isset($profile_info['base'] ? $profile_info['base'] : FALSE);
} while ($profile);
// Search from top/parent profile first.
$profiles = array_reverse($profiles);

Ideally, of course, we'd store the already prepared base profile information with each profile's info already, so we can avoid the repetitive system_get_info() calls for every profile in the inheritance.

I'm also missing some other essential changes to the Drupal installer and actual profile installation in this patch. Merely taking the base profile information into account for path lookups does not fulfill the promise of making install profiles inheritable.

cweagans’s picture

@sun, it enables this kind of setup: http://www.agileapproach.com/blog-entry/inheriting-your-drupal-profile-e...

IMO, what is here so far could go into Drupal 7. The installer changes and profile installation seem more like D8 things.

sun’s picture

Yes, that post is how I learned about this issue. New features go into HEAD first though. I will admit that the existing patch provides some degree of profile inheritance, but it totally was not what I expected. It sorta tries to tack the new feature onto a system that's otherwise unaware of the feature, which obviously won't fly.

If we want this to land, then we need to make the system properly aware of possible install profile inheritance. I support this change, since it was mentioned in a couple of other issues and personal discussions already. I do not see a technical reason for why it couldn't be supported.

That said, while this feature addition in core seems feasible and doable, there will still have to be support for it coded into drupal.org's distro/profile packaging scripts, which inherently/actually means to support it in Drush. But that's a separate follow-up issue.

helior’s picture

The previous patch wasn't exactly what I was expecting, either. Also, pushing fake inheritance in the parts of Drupal's non-OOP code is a foreign pattern that exists nowhere else in Drupal – and feels a bit hacky imo. Certainly if install profiles were re-written as classes then that would totally make sense, as well as be trivial to implement.

Instead, this patch contains a different approach that follows the pattern of Drupal's theme system, in which there is a concept of defining a single "base". So everywhere in the system where an install profile is requested to participate – instead of invoking the single current profile, it invokes the ancestral chain of profiles starting from the top-parent down to the last sub-profile.

This allows developers to truly extend Drupal distributions with the same ease as creating a sub-theme.

This patch is for D7 – Sorry, I know new features need to go in D8 first, but I just wanted to put this out there. I'll try getting in contact with the right developers to see what direction install profiles are going in D8 (#1530756: [meta] Use a proper kernel for the installer suggests it will be a complete rewrite, so I'm not sure how the back port to D7 will look like.)

sun’s picture

Thanks! That looks a lot more like it :)

Btw, some of the changes clash/conflict with #562042: Search for install profiles in sites/[all|site]/profiles folders, and move core profiles into /core/profiles, which I'd like to see getting in first. But since that is RTBC already and we don't have a patch for D8 here yet, that doesn't seem to be an issue in the first place. ;)

dixon_’s picture

Status: Needs work » Needs review

The bot should take a ride with the latest patch.

ezeedub’s picture

Slight addition to #29 to check for drupal_get_profiles(), which is defined in install.inc, and so not normally included.

sun’s picture

Status: Needs review » Needs work

Sorry, we really need a patch for D8 here. The patches for D7 are very confusing, so I'd appreciate if we could stop posting them.

#25 is obsolete by now, drupal_system_listing() does not have to be touched at all, since D8 scans for profiles everywhere already.

This also needs to be taken into account when forward-porting #32 to D8.

ezeedub’s picture

My bad. To be honest, I kind of knew that, but since local patches don't work in drush make yet, I posted here. That's an abuse of this issue queue though, so I will go stand in the corner for 20 minutes...

geoffreyr’s picture

FileSize
2.03 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-17-redux.patch. Unable to apply patch. See the log in the details link for more information. View

Just a small tweak to #17: it looks like the $bases array generated in drupal_system_listing_profile was never being used. Trying to use it as is caused the base module to not be used at all, and displayed the following error:
Warning: Invalid argument supplied for foreach() in drupal_system_listing_profile() (line 5220 of includes/common.inc).

geoffreyr’s picture

FileSize
1.98 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-make-D7-21-redux.patch. Unable to apply patch. See the log in the details link for more information. View

Same again for #21.

helior’s picture

Status: Needs work » Needs review
FileSize
19.02 KB
PASSED: [[SimpleTest]]: [MySQL] 46,240 pass(es). View

Finally, a Drupal 8 patch :)

I moved drupal_get_profiles() to common.inc since it makes more sense to keep it there (as @ezeedub pointed out in #32 that install.inc isn't always included). Also incorporated all the D8 changes (that I know of) including the update mentioned in #30 and #33.

helior’s picture

Also, for those using the D7 patch, here is an equivalent update.

lapith’s picture

Here is a reroll of #38 to include a fix for base profile dependencies.

lucascaro’s picture

FileSize
983 bytes

FYI an interdiff for the previous 2 patches:

pcho’s picture

#36: 1356276-make-D7-21-redux.patch queued for re-testing.

tom friedhof’s picture

FileSize
21.92 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-base_profiles_variable-42.patch. Unable to apply patch. See the log in the details link for more information. View

I took the patch from #39 and pulled all the logic out of runtime. It was a pretty big performance hit finding sub-profiles on every request. This patch is for D7. Is there another issue open for 7.x core to post patches to, so we don't pollute this space with 7.x issues?

olofbokedal’s picture

Without looking through the code, is there a reason why there is a variable called 'install_profiles' that everything depends on? The old 'install_profile' variable does still exist.

The main reason I'm asking, is because we couldn't update an existing site with this patch, since that variable is created during the installation. We solved it by simply adding the variable manually, but it would be nice if it could be solved automatically.

Aside from this, the patch at #42 has worked on several sites we've been testing.

dagomar’s picture

I haven't tried the patch yet, but I have a question, will the child profile inherit update hooks in the parent profile? Thanks!

dagomar’s picture

FileSize
21.92 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-cleanup-patch42-45.patch. Unable to apply patch. See the log in the details link for more information. View

I have tested and can confirm this works beautifully. I had 2 issues with existing sites, the variable "install_profiles' was missing, as previously mentioned. I just installed a blanc site to get the correct variable and imported that entry manually. The other issue I had was that the parent wasn't enabled in the system table, after I enabled it I was good to go.

I have recreated the patch because of whitespace issues. Note, it's for D7.

helior’s picture

@dagomar Yes, parent profile's update hooks are picked up as well.

geerlingguy’s picture

+++ b/includes/common.incundefined
@@ -232,6 +232,22 @@ function drupal_get_profile() {
+ * Returns a list of related install profiles in decending order of their

s/decending/descending

Could we maybe file a helper issue for D7 so those patches don't distract from getting this into D8 (if it isn't already?)? I'm a bit late to the game here, and haven't read through the entire issue+comments.

frob’s picture

I don't see why this would be added to Drupal 7 at all. Lets keep this in D8.

geerlingguy’s picture

@frob - the issue has the 'needs backport to D7' tag... which is used for issues that are possibly going to be backported/included in D7.

frob’s picture

Issue tags: -Needs backport to D7

I am removing that tag. I might be out of line and I wont be offended if it gets added right back in. But to me this isn't fixing a bug or glaring UX, DX problem that needs a backport. It is a nice to have in Drupal 7, so to me it doesn't need a backport.

mparker17’s picture

Issue tags: +Needs backport to D7

I would like inheritable installation profiles in Drupal 7.

Here is my attempt to explain why...

Background

Install profiles are the core of Drupal Distributions — a really quick way to set up a complex sites.

Creating a Drupal Distribution is simple: you create an installation profile; add a set of Drush makefiles to download specific versions of core and contributed modules, themes and libraries; and add your own features, custom modules and themes. If you have any patches to core or contrib, stuff to add to .htaccess or settings.php, or you write any behavioural or functional tests of the system as a whole, you can put them in sub-folders. Any changes to the database that don't belong to a particular module or theme can go in the install profile's .install file. You can build the whole site's filesystem with a single Drush make command. And, because this is an installation profile, you can easily build a fresh database for use behavioural and functional tests or to deploy on a new machine.

The result is a folder which only contains the code you've customized or written from scratch, but not cluttered with environment-specific stuff or content. This folder is ideal for checking in to version-control. And, any older version of the site can be upgraded to a new version by running update.php and reverting all features.

When do I use Distributions?

Currently, we build a Drupal distribution for any client site we work on. It lets any number of developers work on it, developers seldom need to touch staging or live directly (Jenkins does almost everything), and we don't have to constantly share copies of the database.

Why inheritable install profiles would make this better.

Inheritable install profiles would allow us to build a base install profile common to all sites we work on, containing modules, themes, etc. that we use on every project. Also, it would make it easier for us to build sites on other popular distributions. And, if a client wanted a new site similar to their old one, we could inherit from the old one.

Why I want this patch backported to D7.

We're using distributions as the base for our sites right now on D7. Since D7 will be maintained until D9 comes out, at the very least, we will be using or maintaining this methodology for a while yet.

mparker17, you seem pretty passionate about this; why aren't you helping with this issue more?

Sorry :S Somebody already wrote a patch for D7 before I knew this issue existed!

I did actually try on my own time to see if I could write a patch for D8, but I found that I didn't understand enough about D8 at the time to be able to make any progress. I know a lot more about D8 now: if I had the time, maybe I could take another crack at it. But, I don't think I'll have the time before the feature freeze.

Remove the tag or not?

@frob makes a pretty good point — this is a "nice to have" not a "need".

Is there a "would be nice to have a backport to D7" tag instead of a "needs backport to D7" tag?

cweagans’s picture

Let's not argue about the tag. Open Atrium needs it, it is backportable (since it does not change any existing behavior of install profiles unless you mark your install profile as inheriting from another), and people seem to want it. Regardless, it needs to get into D8 before anything else happens with it, so let's focus on that.

juan_g’s picture

mparker17 wrote:
> Also, it would make it easier for us to build sites on other popular distributions.

And for example well-known distributions such as Drupal Commons or Open Atrium have been only recently ported from D6 to D7 (OA for D7 still in alpha). D8 is far away for them. A backport to D7 would be indeed good for Drupal distributions in general. Of course after it's first into D8.

frob’s picture

It's not that I don't want it backported; it is that the conversation about backporting never took place. The purpose of backporting is to make sure bugs that get fixed for D8 that that are also in D7 get fixed in both code bases. Personally I want this in D7 too.

So then is the backport patch done? Someone review it please.

cweagans’s picture

We need a patch for 8.x first, and that has to be done in the next couple of days if it's going to be committed before feature freeze.

geerlingguy’s picture

Status: Needs work » Needs review
FileSize
18.67 KB
FAILED: [[SimpleTest]]: [MySQL] 57,990 pass(es), 0 fail(s), and 47,508 exception(s). View

Rerolled patch from #37 for D8 (some files have moved, also fixed a couple of the typos mentioned earlier in the thread). Let's see how the testbot likes it.

geerlingguy’s picture

Status: Needs work » Needs review
FileSize
18.47 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-base-profile-59.patch. Unable to apply patch. See the log in the details link for more information. View

Whoops! Put part of the patch in the wrong section of system.install. Attached patch should fix those errors.

Pancho’s picture

Priority: Normal » Critical
Issue tags: +Needs tests

Raising to major per #53.
Not sure though this would be subject to the API freeze, as it is an API addition that shouldn't affect handling of standalone profiles.

In any case this needs extensive test coverage, especially because it is not used by core.
Inheriting requirements basically seems to work but I don't believe we're already taking care of everything.
How about precedence of required modules if multiple instances are included, possibly the one patched by a distro or in a different version? There might be tricky cases to take care of.
How about inheriting config or hook_install or whatever else could possibly be included in a profile? We might omit that but need to make an informed decision.
I believe we can't do this right without a sophisticated inherited profile test case. Another option would be making standard profile inherit from minimal profile, even though that would be a very basic implementation.
Either case this would be an opportunity to vastly expand and improve our profile test cases.

Some definitive input on whether this issue is subject to the July 1st API freeze or not, would be very valuable! Depending on this we need to put much more efforts into this one - or can take our time in order to do it 100% right.

Pancho’s picture

Priority: Critical » Major
cweagans’s picture

Priority: Major » Normal

No. This is not major. It has a pressing deadline, but that doesn't make it any more important than the other features that should go into D8 either. This needs to be done before 7/1 if it's going to happen, though there's a possibility that it could go in after (since we're already considering it backportable to 7.x). Safest bet is to plan on having it done by 7/1, and if it turns out that it can be improved after that date, then great.

Pancho’s picture

It has a pressing deadline, but that doesn't make it any more important than the other features that should go into D8 either.

A pressing deadline certainly wasn't my argumentation, especially as I don't expect the deadline to be pressing for this issue.
Rather I refered to your own comment #53, also recognizing that "Major priority is also used for tasks or features which consensus has agreed are important" (Priority levels of issues)

Safest bet is to plan on having it done by 7/1, and if it turns out that it can be improved after that date, then great.

IMHO it's too late for playing safe. This issue still needs a considerable amount of manpower, which not many are able/ready to invest right now that other important tasks really are endangered by July 1st API freeze.

This needs to be done before 7/1 if it's going to happen, though there's a possibility that it could go in after (since we're already considering it backportable to 7.x).

That's a contradictio in adiecto, but with the second half-sentence I do agree. Some authoritative input by a core maintainer would be helpful.

dagomar’s picture

Hi guys,

how can I help? I'm planning to test the patch with a simple custom install profile that extends minimal. Then I could do some tests with upgrades and stuff.

Note, I have been using the patch for D7 and the only thing that does not work is inheriting libraries, which is an issue with the contrib libraries module (my workaround is to use a libraries folder in the root drupal folder).

That being said, I'll devote some hours today to test the D8 patch. If someone could tell me what I can do to do n accurate test, that would be helpful! Let's get this in (and backported ;))

frob’s picture

dagomar, I think that the best thing to work on is to make sure unit tests are in place. It will be easier on everyone if they get in now.

dagomar’s picture

Thanks for the reply frob. I have 0 experience with unit testing, just barely know what it is tbh. I'll read up on it and see if I can do anything. In the meantime I'll test the patch manually to see if anything obvious comes up...

helior’s picture

I'm glad to see this issue is gaining interest again!
@dagomar This is a corresponding patch I've been using with Libraries API so it can support libraries found in your base profiles. #1811486: Libraries API cannot find libraries in "base" profiles.

Dustin@PI’s picture

I'm guessing that groups.Drupal.org will want this so that it can inherit commons as part of the D7 upgrade. This patch is a pretty big deal from a functionality perspective so I would love to see it go in.

What's the best way to help with testing?

geerlingguy’s picture

The best way to help, it seems, would be to write tests for this functionality... it may be a bit complicated, since testing the installer/profiles is already more complex than testing systems that only run in a fully-bootstrapped Drupal environment :-/

frob’s picture

I would consider making standard a sub-theme of minimal. Then verifying that tests for both themes are being executed.

amcgowanca’s picture

Version: 8.x-dev » 7.x-dev
FileSize
0 bytes
PASSED: [[SimpleTest]]: [MySQL] 40,431 pass(es). View

Re-rolled with minor updates the D7 patches.

amcgowanca’s picture

FileSize
1.98 KB
PASSED: [[SimpleTest]]: [MySQL] 40,270 pass(es). View
geerlingguy’s picture

Version: 7.x-dev » 8.x-dev

Please leave the status at D8, since the patch has to go in there first.

amcgowanca’s picture

FileSize
12 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-D7-inheritable-profiles.patch. Unable to apply patch. See the log in the details link for more information. View

Hey,

What patch is everyone using above for D7? Reason I ask is I have had countless issues with many if not all of them. I have included another patch completely fresh.

Aaron

David_Rothstein’s picture

Status: Needs work » Needs review
geerlingguy’s picture

#59: 1356276-base-profile-59.patch queued for re-testing.

cweagans’s picture

Right now, we need to focus on getting this into D8. Once that's done, it can go into D7. If you want to move this forward, focus on D8 first.

geerlingguy’s picture

#59: 1356276-base-profile-59.patch queued for re-testing.

geerlingguy’s picture

#59: 1356276-base-profile-59.patch queued for re-testing.

geerlingguy’s picture

Assigned: Unassigned » geerlingguy

I'm going to try to update the issue summary and possibly get some tests written for the patch in #59 for Drupal 8.

To those wanting this for Drupal 7: Please, please, please consider opening a separate issue to track the D7 patch(es) alongside this issue, instead of continuing to add them to this issue directly for now—it's already a slim-to-none chance of this getting into D8 (though I think it would be awesome!), but the signal-to-noise in this issue is getting pretty bad.

frob’s picture

I created a D7 issue here: https://drupal.org/node/2067229

geerlingguy’s picture

@frob - thanks! I've updated that issue's summary, and just a note—when linking to other issues, you can use syntax like [#NUMBER], where NUMBER is the issue number, or [#NUMBER-COMMENT] to point to a specific comment in the issue. For example:

geerlingguy’s picture

Issue summary: View changes

Updated issue summary. added link to D7 issue.

geerlingguy’s picture

Issue summary: View changes

Updated the issue summary with the issue summary template.

geerlingguy’s picture

FileSize
18.65 KB
FAILED: [[SimpleTest]]: [MySQL] 57,339 pass(es), 1 fail(s), and 32,128 exception(s). View

Re-rolled the patch from #59. No tests added yet, but some things have moved as a result of #mwds's WSCCI sprint.

geerlingguy’s picture

Status: Needs work » Needs review
FileSize
0 bytes
PASSED: [[SimpleTest]]: [MySQL] 58,224 pass(es). View

Missed a couple lines in system.install again. Testbot, go!

geerlingguy’s picture

FileSize
18.45 KB
PASSED: [[SimpleTest]]: [MySQL] 57,828 pass(es). View

Zero-byte file in last comment. This one may work.

mparker17’s picture

Wait what? It shows up as having passed now. Perhaps Testbot was feeling a bit under-the-weather?

geerlingguy’s picture

Status: Needs work » Needs review

That testbot had a hiccup, and so the test was manually re-run. It passed, so back to needs review!

geerlingguy’s picture

Issue summary: View changes

Changed 'parent' to 'base' to reflect latest patches.

geerlingguy’s picture

Issue summary: View changes

Updated remaining tasks.

geerlingguy’s picture

FileSize
0 bytes
FAILED: [[SimpleTest]]: [MySQL] Setup environment: Test cancelled by admin prior to completion. View

Attached patch:

  • Parses .info.yml files instead of .info files (which no longer exist in D8).
  • Makes the standard profile depend on the minimal profile, and remove bits of minimal that don't belong in standard.

When installing standard profile manually (via UI) with latest HEAD, I'm getting the following error (which can be ignored, and the rest of the install still completes): The plugin (search_form_block) did not specify an instance class.. I'm guessing this is a regression in core—see #2067881: Search is missing from block admin UI after installation.

I might be able to introduce a test or two to make sure that standard inherits from minimal properly—or maybe I'll use the test profile to do a little extra inheritance testing. I'm guessing this patch will fail due to the above issue.

geerlingguy’s picture

FileSize
21.54 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1356276-base-profile-91_0.patch. Unable to apply patch. See the log in the details link for more information. View

Attaching an actual patch this time...

frob’s picture

We also need to make sure that the tests from all profiles get fired

geerlingguy’s picture

So... something is funky with the search form block—if I simply remove core/profiles/standard/config/block.block.bartik.search.yml and try the install again, the install completes successfully, with everything enabled and configured correctly. With that file, I get the error The plugin (search_form_block) did not specify an instance class..

I'm looking into why this might be happening (maybe a different bug?).

[Update: I can't figure out what's causing the search_form_block to make the installation fail. Other than that, this patch is working well...]

geerlingguy’s picture

Issue summary: View changes

Updated old .info file syntax to YAML.

geerlingguy’s picture

I updated the issue summary's remaining tasks; primarily, someone needs to figure out why enabling the search form block breaks the standard install profile.

Grayside’s picture

Worth noting that in the original patches and the Agile Approach blog, it was considered a feature that a sub-profile did not actually depend on the parent. In that way you could pick and choose which aspects of the parent you actually need to use.

I am agnostic about this--but if anyone is playing with patches since #36, dependency is presumed.

amcgowanca’s picture

@Grayside: Can you share the link to original patches and Agile Approach blog? Would love to have a good read about that approach.

Grayside’s picture

geerlingguy’s picture

Assigned: geerlingguy » Unassigned
Issue tags: -Needs tests

...since I don't have time to keep pushing this right now.

geerlingguy’s picture

Issue tags: +Needs tests

Grr... Cross post?

amcgowanca’s picture

@Grayside: Ah yes, I have read that as well. You previously mentioned that you don't believe the dependency between the base and derived should be enforced, what are the benefits of this in your opinion?

@geerlingguy: I would be happy to take over and assist in pushing this if you would like?

geerlingguy’s picture

@amcgowanca - go for it!

Grayside’s picture

@amcgowanca, I haven't actually formed a definite opinion on that. My point was really just to identify for issue visitors that there was a significant functional change in what's being done.

Happy to go into it further for the sake of clarity.

The original version of this patch limited the concept of profile inheritance to module & theme discovery. In this way you could build a codebase in which one profile could specify "get all the stuff for my parent profile and stick it in that corner, I'll add my own stuff as needed then decide what to do with it all."

The evolved version says "also, enable all that parent stuff as a default assumption, I'll turn on my additions."

The latter approach makes sense if a parent profile is treated as a black box to which you want to add more stuff. I'd say that takes more planning. The Standard profile ships with Overlay, OA ships with a Blog feature... if those are enforced on, you can't easily replace them with different solutions in your child profile without retroactively disabling those modules.

One example of how this might work is the need to separate Drupal products into minimal and standard profiles like Core. Developers can build child profiles that sit on top of the access control, plugin mechanisms, theme assumptions, and so forth of the minimal profile. Site builders can grab the complete product, make tweaks, and deploy their solution.

In a current project that forced me to go back to #36, I have a child profile that complete swaps out the media handling of the base profile. By not enabling those modules in my child profile, I am free to swap in my own media handling modules. Since those were Features modules tossing content types and fields around, it would not be pleasant to dig in and undo all that work by hand instead of skipping the module enable.

mcrittenden’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests, -Needs backport to D7

#92: 1356276-base-profile-91.patch queued for re-testing.

Anonymous’s picture

Issue summary: View changes

Updated remaining tasks.

timodwhit’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
16.4 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch inheritable-1356276-107.patch. Unable to apply patch. See the log in the details link for more information. View

Re-rolling the patch to match changes over the last 3 months.

Still needs to be tested, though.

timodwhit’s picture

Status: Needs work » Needs review
FileSize
16.39 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch inheritable-1356276-109.patch. Unable to apply patch. See the log in the details link for more information. View
timodwhit’s picture

Status: Needs work » Needs review
FileSize
16.43 KB
FAILED: [[SimpleTest]]: [MySQL] 59,593 pass(es), 1 fail(s), and 1,387 exception(s). View

Re-re-re-re-...-re rolled the patch.

timodwhit’s picture

If I could get a hand with the failure of the patch that would be awesome. I basically tried to reroll the original patch, and it looks like i could have missed something somewhere a long the line.

@geerlingguy or @amcgowanca have you had any issues with the patch failing tests.

Thanks for the help and thanks for the original patch!

geerlingguy’s picture

Yes, I had trouble with the search form block (see #95). Couldn't figure it out after a few hours of debugging at the Midwest dev summit.

geerlingguy’s picture

Just an update, for those using D7 and interested in this issue; @bryanhirsch has a module (in development) that may offer an alternative solution for now. See his comment in #2067229-60: Allow install profiles to declare base profiles for Drupal 7.

DuaelFr’s picture

Version: 8.0.x-dev » 8.1.x-dev
Status: Needs work » Postponed

The patch in #112 no longer applies and would need more than a simple reroll. Plus, even if I'd love to see this shipped in 8.0.x, the feature freeze won't allow it so I'm postponing to 8.1.x.

frob’s picture

Status: Postponed » Needs work

postponed isn't the correct status for this issue, it still needs work even if it is being pushed to 8.1

andypost’s picture

Related issues: +#2234315: Dependency graph resolved plugins for installer tasks

only one month left for 8.1

phenaproxima’s picture

Assigned: Unassigned » phenaproxima
FileSize
234.86 KB

Frodo
I'll take this on.

alvar0hurtad0’s picture

@phenaproxima can I help you?
This is a really good improvement for people who uses profiles based workflows.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mpotter’s picture

Can somebody summarize what is needed on this? The description talks about patch #92 and a search block issue but it seems like patch #92 is really old. #117 seems to imply a large amount of work.

Can we maybe split this into two parts? (1) get the basic module searching working, (2) doing more real "inheritance" with info files, config, etc.

I've always had an issue with the inheriting of the base profile info file. I don't actually want to enable all the modules that the base distro has listed. It's a lot easier to manage those dependencies in my own child profile info.yml. In fact it's a lot easier to enable the stuff I want then to figure out how I'd possible *disable* something that is automatically inheriting from the base.

The (1) requirement is the blocker for those of us developing client profiles where we want to use something like Lightning as a base profile. I just want to tell Drupal to also look for modules in profiles/lightning.

I'm tempted to go back to just this (1) in a simple patch for D8 and then let people build on it. Otherwise I feel like it's going to be Drupal 9 before this gets addressed.

jhedstrom’s picture

+1 for splitting this work into 2 parts as suggested in #123. Perhaps we can open a child issue here to do the bare minimum for module/theme discovery in a profile designated as a 'base' profile of another and get that into 8.2?

phenaproxima’s picture

+1 to splitting it out.

DuaelFr’s picture

Agreed too.
Just a thing: given we want to allow profiles to be inheritable, we could have chains of profiles inheritance (like themes) so we need to recursively look for modules/themes in all the profile's ancestors.
My 2 cts

frob’s picture

Issue summary: View changes

Done #2692403: Make info and configuration inheritable in profiles

I have also modified this issue to refocus.

frob’s picture

Title: Make install profiles inheritable » Make inherited install profiles load base profile modules/themes in correct order
mpotter’s picture

Status: Needs work » Needs review
FileSize
1.97 KB

OK, here is an attempt at something super simple.

The replacement for drupal_system_listing() in D8 is the ExtensionDiscovery class. As mentioned in #2503927: Convert ExtensionDiscovery to a service, this class cannot simply be converted to a service that we could override. It needs to be usable without a container and be kept very lean. Thus, we can't really load the profile info.yml file to look for a "base profile".

ExtensionDiscovery already supports something called "profileDirectories" which add additional search directories to the extension discovery process. Interestingly, the constructor even accepts a profileDirectories argument that is never used by core. Core directly instantiates new ExtensionDiscovery classes in very hardcoded ways, so it's not a simple thing to override.

There is already a function called setProfileDirectoriesFromSettings() that loads the profileDirectories with the path to the current profile. It already has some additional code to add a "parent profile" when using simpletest.

My approach is to literally implement "setProfileDirectoriesFromSettings" by taking values from $settings['profile_directories'] and adding them to the profileDirectories array. This provides a super-simple mechanism to add additional search paths via the settings.php file. The same mechanism that is used for the simpletest parent profile.

In addition to ExtensionDiscovery, DrupalKernal.php also has moduleData() which performs very similar tasks. The same simpletest changes were added here, so I also added the $settings['profile_directories'] functional to that.

Seems to work in my testing here, but feel free to point me to the proper place to add a test for this so that we get the search order correct (look in current profile first before looking in $settings['profile_directories'])

Edited Note: Profiles can use this mechanism to add support for a "base profile" the same way it currently adds the $settings['install_profile'] to the settings.php.

jhedstrom’s picture

Issue tags: +Needs tests

Could we still support the concept of base_profile in the info files, but only use it during install and actually write out the profile_directories setting in the settings.php file (via a modification of install_write_profile() perhaps)?

This will need a few tests too I think.

A few nits:

  1. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -721,6 +721,13 @@ protected function moduleData($module) {
    +      $settings_profile_directories = Settings::get('profile_directories');
    +      if (!empty($settings_profile_directories)) {
    +        $profile_directories = array_merge($settings_profile_directories, $profile_directories);
    +      }
    

    I think this could be simplified to one or two lines using the default value parameter of Settings::get('profile_directories', []) (removes the need for the if statement).

  2. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -256,6 +263,14 @@ public function setProfileDirectoriesFromSettings() {
    +    $settings_profile_directories = Settings::get('profile_directories');
    +    if (!empty($settings_profile_directories)) {
    +      $this->profileDirectories = array_merge($settings_profile_directories, $this->profileDirectories);
    +    }
    

    Ditto here.

mpotter’s picture

Here is an updated patch to address the suggestions from #130:

  • 1 & 2 fixed.
  • Added code to install_write_profile() to update the settings.php profile_directories based on a base_profile key in the profiles.info.yml file.

For tests, I'll need some help here. Looking at the existing core/modules/system/src/Tests/Common/SystemListingTest.php, doing a real test of the added profile_directories functionality would require creating an additional test profile so we could test to see if a module similar to drupal_system_listing_compatible_test module could be found in the correct base profile directory if it didn't exist in the current profile. I'm not sure we want to create a whole new test profile just for this or if there are easier ways to test it.

frob’s picture

I have not looked at these patches at all.

Just thinking about the tests, could have have the test profile set the minimal profile as a base profile.

Excluding tests, should the standard profile have the minimal profile set as its base profile?

mpotter’s picture

We'd need to be able to add a test module to the base profile, similar to how the drupal_system_listing_compatible_test module is added to the test_profile.

Edited: Oh, and we don't need to set "minimal" as the base for "standard" because this patch ONLY deals with searching for modules and neither of those profiles contain any modules. For true inheritance of stuff like config, see the bigger issue at #2692403: Make info and configuration inheritable in profiles that you created in #123.

jhedstrom’s picture

Issue tags: +Needs manual testing

Regarding tests, I was thinking we could potentially use vfsStream to mock out a profile directory structure, but the DrupalKernel fairly well hardcodes it's root path in the constructor:

    $this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));

I also spent a bit of time trying to do a unit test, but ran into other issues there (even if it was possible to get all the way at the DrupalKernel::boot() method, that wouldn't address the hard coded root). The alternative would be to use a unit test only on the protected DrupalKernel::moduleData method and use php reflection to make it callable (and also then the protected root variable could be set to use a vfsStream of our chosing).

If all that sounds a bit much, tests may need to wait on #2605654: Modify Drupal\Core\Extension\ExtensionDiscovery to allow for scanning multiple file systems, enabling vfsStream testing.

Tagging for manual testing for now.

mpotter’s picture

Yeah, the more I thought about the testing last night, the more I felt it just isn't that needed in this case.

The patch in #133 is just using the existing profileDirectories functionality of ExtensionDiscovery. This functionality is already well tested in core (SystemListingTest). All we are doing in this patch is loading the profileDirectories from the $settings.

About all there is to test here is when multiple directories are specified in the $settings array to check to see that they get processed in the correct order. But that's a pretty simple manual test. I worry that we could really go overboard and make this patch super complicated with a test that isn't really needed.

Interested in what others think, but #133 just seems super straight-forward and just provides an easy way to use a pre-existing mechanism for expanding the module search path.

dawehner’s picture

Yeah, the more I thought about the testing last night, the more I felt it just isn't that needed in this case.

How about, no :) If we add a feature we should add tests, otherwise it will break at some point. Its kinda simple.

mpotter’s picture

I understand the need for tests, believe me. But all we are doing is setting profileDirectories from the settings.php. The use of profileDirectories to control the module search order is already tested (by SystemListingTest). So what are we testing here? I'm all for tests if somebody could go into more detail on what kind of test is needed and how it might be done.

dawehner’s picture

@mpotter
When I try to write tests I don't try to look at the actual tested code, but rather try to think of possible inputs and outputs. By that, later changes causes less potential required changes in the tests. For this particular case there is an additional input.

I'm happy to help out writing a test, even if its seems to be pointless. For me tests are also a way of documentation, when they are written properly

mpotter’s picture

Is the test method shown in the issue linked in #141 the right approach to take here? Seems like it would be easy.

But also seems like both issues are trying to accomplish something similar: support for a base profile. I wonder if we could somehow combine these efforts into this more general patch for adding new profileDirectories?

mpotter’s picture

mpotter’s picture

So yes, tests are good!! This test uncovered something interesting:

I tried running the test from #143 without the patch from #133 and it still passed! Learned that ExtensionDiscovery::scan() is doing this:

// Search the core directory.
$searchdirs[static::ORIGIN_CORE] = 'core';

This means that core/profiles/testing/modules is ALWAYS being searched! Regardless of the profileDirectories command. So, in fact, even the SystemListingTest is a bit wrong. It uses $listing->setProfileDirectories(array('core/profiles/testing')); but that isn't necessary since scan is always looking at all subdirectories of core.

In order to do these discovery tests properly, we would need to put a test module somewhere outside of core. Any ideas?

DuaelFr’s picture

Would it be possible that the test create a fake module in the temporary directory during its setup?

dawehner’s picture

Yeah I think when we write a unit test, we could totally setup the filesystem using vfs://

mpotter’s picture

I'll work on a test using the virtual file system to not only test this issue but also to perform a better test to ExtensionDiscover itself (improving the SystemListingTest).

jhedstrom’s picture

Issue tags: -Needs manual testing

Removing the manual testing tag since automated tests are underway.

Some feedback on the patch in #143:

  1. +++ b/core/modules/system/src/Tests/Common/ExtensionDiscoveryProfilesTest.php
    @@ -0,0 +1,65 @@
    +/**
    + * @file
    + * Contains \Drupal\system\Tests\Common\ExtensionDiscoveryProfilesTest.
    + */
    

    This can be removed since #2304909: Relax requirement for @file when using OO Class or Interface per file went in.

  2. +++ b/core/modules/system/src/Tests/Common/ExtensionDiscoveryProfilesTest.php
    @@ -0,0 +1,65 @@
    +        $this->assertTrue(file_exists(\Drupal::root() . '/' . $filename), format_string('@filename exists.', array('@filename' => $filename)));
    

    format_string is deprecated, and for both exceptions and test messages I think the standard has switched back to simple concatenation.

  3. +++ b/core/modules/system/src/Tests/Common/ExtensionDiscoveryProfilesTest.php
    @@ -0,0 +1,65 @@
    +    $settings['profile_directories'] = array (
    

    Coding standard nit array (.

zach.bimson’s picture

I've just applied the patch at #133 on both my base profile and my child profile installations, my child info file is the same as my base profile info just all the modules are stored within my base profile. I've added the directories for both in my settings file and added the base profile in my child profile info.

The base profile installs fine as expected on its own, but when the profile is places within my child profiles install /profiles directory and i try to enable the same set of modules i get un met dependencies issues...

Stepping though the install on both profiles (base on its own and child inheriting from base in its own install) i get the modules installed in a totally different order, with the base on its own getting way more modules enabled before any of my custom modules are enabled.

I was under the impression that the order in the info file was what was read but that doesnt seem like the case.

Not really sure where to start fixing this so thought id stick it up here, maybe im approaching this wrong..

saltednut’s picture

Status: Needs review » Needs work

Not sure if the reroll goes to #2692403: Make info and configuration inheritable in profiles but the patch from #133 no longer applies to 8.2.x

Edit: Got caught up on the issue, confusion alleviated.

dawehner’s picture

Personally I believe that its fine for people to use this patch as a workaround for specific things.
On the other hand I actually believe we should tackle our base system/extension system issues like #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList first and then look into making install profiles actually inheritable. This then would allow us to not expand the brittleness, but rather give people a proper base to build upon.

DuaelFr’s picture

I totally agree. We need a more robust inheritance system if we want our distributions to rise.
Themes are a a great example of what can be done. We have a fully chained inheritance with overrides and everything we can dream of. I'd love to see something similar in profiles.

dawehner’s picture

Assigned: phenaproxima » dawehner

I'll have a look what this would actually require us to do

frob’s picture

Title: Make inherited install profiles load base profile modules/themes in correct order » Make sub install profiles load base profile modules/themes in correct order
Issue summary: View changes

These are the goals of this issue. Ideally, I would want this to work like the theme system's base theme -> sub theme relationship.

The issue has gotten off and then on the rails several times. I wonder if the word "inheritance" is loaded and throwing people off on what this is supposed to do. I have change the title to mirror the concept of the base and sub profile mirroring the base and sub theme relationship.

There is more to this than just allowing a sub profile declare a base profile, which is why this issue got split into two parts.

dawehner’s picture

Title: Make sub install profiles load base profile modules/themes in correct order » Allow profiles to provide a base/parent profile and load them in the correct order

These are the goals of this issue. Ideally, I would want this to work like the theme system's base theme -> sub theme relationship.

Can't agree more. Sadly the issue got derailed. Well, things happen, but let's discuss that in its own issue: #2743197: Load additional profile directories via settings

In order to resolve this issue I think we need a couple of those steps:

  • Allow installation profiles to define a parent/base profile
  • Ensure that installation tasks (and all the other various hooks) are fired in the installer for the base profiles as well
  • Adapt \Drupal\Core\DrupalKernel::moduleData to add the parent installation profiles as well during runtime into the list of available "modules"
  • Adapt \Drupal\Core\Extension\ExtensionDiscovery::setProfileDirectoriesFromSettings to take into account profile parents
  • In general ensure that modules from subprofiles can override moduels from their base profiles
  • Write a test case which provides a base profile and ensures that each of the previous points work properly
dawehner’s picture

Assigned: dawehner » Unassigned
das-peter’s picture

I just gave this a try.
I've created a profile which depends on the 8.x version of panopoly.
However, I hit the issue described here #2743197-8: Load additional profile directories via settings by mpotter.
It seems a bit odd that the current approach would require me to adjust the settings.php even before I can install.
So I fiddled a bit around and came up with something similar to ThemeHandler - but no ProfileHandler yet.
I kept the stuff that relies on / writes the paths in settings.php untouched.
I'm tempted to have something like ProfileHandler because core/lib/Drupal/Core/Config/ConfigInstaller.php currently needs an include to ensure the function install_profile_info() is available, which is not very nice.
The patch introduces following syntax for profile info files:

base_profile:
  name: panopoly
  excluded_dependencies:
    - panopoly_demo

The new key excluded_dependencies allows exactly what it implies - excluding certain dependencies from the parent profile.
In my tests the install hooks of the base profile are invoked and the configuration is imported (I had to suppress the error messages of duplicated configurations for all install profiles in the chain - not just the selected one.)
Patch is against 8.1.x

Saphyel’s picture

Status: Needs work » Needs review

@das-peter maybe is better do it in 8.2.x and then pick up to 8.1.x ?

mpotter’s picture

mqanneh: please keep work on the simple patch that just provides the $settings profile_directory extension in issue #2743197: Load additional profile directories via settings.

This issue was split in #155 and the focus here should be on patches that solve the bigger problem of providing true profile inheritance or something similar to how themes and sub-themes are handled.

I think the patch in #158 tries to address the larger issue from the OP. However, the reason we want to split this is because the simple changes to allow profile_directories to come from $settings has a much better chance of getting tested and added to 8.2.x.

I will re-roll the patch in 2743197 so it only contains the $settings code. It will still need tests to get committed.

In this issue, let's focus on getting #158 to pass testing and to add new tests for it. It should definitely be done against 8.2.x first and then backported to 8.1.x as needed.

mpotter’s picture

OK, just cleaned up the patch in 2743197. Let's get some people testing and marking that as RTBC so we can get it into 8.2.x. Then we can remove that dup code from the patch in #158 and focus on this larger issue of supporting a base_profile.

mpotter’s picture

Tested #158 with Octane inheriting from Lightning distro and it seems to work well so far.

I'm starting to wonder if putting base_profile in the info.yml file and the whole $settings['profile_directories'] stuff is the "right way" since I think we are trying to move to a more read-only settings.php.

Perhaps the base_profile information belongs in it's own simple config yml file? When I worked on Features D8 I know I was advised not to mess with the info.yml files in modules and to instead create a modulename.features.yml file.

Or, rather than loading and parsing a yml file, perhaps we just need a new hook for hook_base_profile_info() to return this data. That would prevent the messing Include in the ConfigInstaller. But I know that's also a bit of "D7-like-thinking" and maybe it should be something different in D8?

Looking for opinions. I think this patch is on the right track but we just need to tweak how it's getting and passing around it's data for profile directories.

mpotter’s picture

Something is still not quite right with the inherited module dependency and config system.

If I create a profile (like Octane) that has a base_profile of Lightning, and then try to list "lightning_core" and "lightning_layout" in my octane.info.yml file, then when I do the site-install I get errors about Unmetdependencies:

exception 'Drupal\Core\Config\UnmetDependenciesException' with message 'Configuration objects [error]
(core.entity_form_display.node.landing_page.default, core.entity_view_display.node.landing_page.default,
core.entity_view_display.node.landing_page.full, field.field.node.landing_page.field_meta_tags, field.field.node.page.panelizer,
node.type.landing_page) provided by lightning_layout have unmet dependencies' in
/var/www/build/html/core/lib/Drupal/Core/Config/UnmetDependenciesException.php:84

Looking into the specific dependencies that are not met, it is stuff like "metatags", which is a module dependency for lightning_layout/config/install/core.entity_view_display.node.landing_page.full.yml

So when it builds the config dependency graph, I'm not sure it is taking into account the config within the base profile. I think it is trying to enable the lightning_layout module before the metatags module (alpha order) because it doesn't know there is config in lightning_layout that requires metatags. Metatags is not listed as a direct dependency in the lightning_layout.info.yml.

Will dig into this a bit more.

mpotter’s picture

Looks like the problem in #166 is with the lightning_layout module not declaring it's config dependencies in it's module info.yml file. I'll report that in the Lightning queue. After fixing that, the child Octane profile is installing properly with Lightning as a base.

Since the patch from #158 seems to be working in a real site, I'll switch to looking at why the tests are failing.

dawehner’s picture

Just some super quick feedback.

  1. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -248,8 +256,15 @@ public function setProfileDirectoriesFromSettings() {
    +
    +    // Allow additional profile directories to be added from settings.php.
    +    // This provides support for "base profiles".
    +    $this->profileDirectories = array_merge(Settings::get('profile_directories', []), $this->profileDirectories);
    +
    

    I still think this is simply a hack we should not introduce

  2. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -265,6 +280,40 @@ public function getProfileDirectories() {
       /**
    +   * Returns a list of related installation profiles.
    +   *
    +   * @param $profile
    +   *   Name of profile.
    +   *
    +   * @return array
    +   *   List of dependent installation profiles in descending order of their
    +   *   dependencies.
    +   */
    +  public function getProfileDependencies($profile) {
    

    Could we try to put that into its own service? Profile dependencies IMHO are something which doesn't belong in a discovery of extension ... the rule of thumb is basically: Extension discovery should not parse info files.

    Its tricky

  3. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -265,6 +280,40 @@ public function getProfileDirectories() {
    +    $cache = &drupal_static(__FUNCTION__, array());
    

    IMHO we should never introduce new drupal_static() examples, especially in OO code

mpotter’s picture

#2: Funny timing...I'm working on a new class for the getProfileDependencies() method as we speak! Not even sure it needs to be a real service since it has to do it's own parsing. But even if we move this out of ExtensionDiscovery directly, it will still ultimately need to parse info files since that's where the dependent profiles are listed.

But profile dependencies ARE something that needs to be considered when discovering extensions since extensions need to be discoverable in those dependent profile paths, right?

Did you have an idea of a better place to put this base_profile info if not in the info.yml file?

#3: Yes, once we put getProfileDependencies() into it's own class we won't need the drupal_static.

Any preference on the name of the new class? I was thinking of Drupal\Core\Extension\ProfileHandler

mpotter’s picture

Status: Needs work » Needs review
FileSize
11.04 KB

OK, here is a revamp of #158. Notes:

1) Removed all of the $settings['profile_directories'] stuff. No longer related to #2743197: Load additional profile directories via settings.

2) Created a ProfileHandler service. Moved all the functions related to profile inheritance into that service: getProfileDependencies, getProfileDirectories, isProfile

3) Removed the code in DrupalKernel for moduleData() function. That function is already loading all profiles as long as they are in the current module list. With this new approach, all base profiles are installed normally so they are already in the module list. Since we got rid of profile_directories in #1 we no longer need any change here.

4) Removed the base_profiles stuff in install.inc. All it needs is the base_profile info. It doesn't need to additionally store the list of profiles since it can get that from the ProfileHandler. This makes the code much cleaner and the only downside is that the profile info.yml file gets parsed twice (once in install_profile_info() and once in ProfileHandler, which is cached). Since this only happens during install I'd rather have the cleaner code.

5) Removed the complexity in ConfigInstaller needing to load the install.inc file. It just uses the new ProfileHandler

6) ExtensionDiscovery also just uses the new ProfileHandler. The logic for detecting a profile name is moved to the isProfile function in the ProfileHandler.

7) The reason the tests were failing was because during tests there isn't any install profile and the previous drupalGetBaseProfiles() wasn't handling that. This function is no longer needed and local testing looks good so we'll see what the testbot says.

8) Yes, we still need to write some tests for this. We'll need to use the vfsStream stuff again like in the related issue along with some unit tests for ProfileHandler itself.

9) Comments are welcome! There are probably still things to clean up (and maybe some new things that I didn't do correctly yet)

jhedstrom’s picture

I like this approach.

A few nitpicks, and questions:

  1. +++ b/core/includes/install.inc
    @@ -1073,6 +1080,25 @@ function install_profile_info($profile, $langcode = 'en') {
    +    if (!empty($info['base_profile']['name'])) {
    +      $base_profile = install_profile_info($info['base_profile']['name'], $langcode);
    

    Should a shortcut like

    base_profile: my_profile

    be supported? If not, for developer experience, should we throw an exception if base_theme is set but name isn't?

    Also, stylistically, should we follow base theme and remove the underscores here?

  2. +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
    @@ -80,6 +87,7 @@ public function __construct(ConfigFactoryInterface $config_factory, StorageInter
    +    $this->profileHandler = \Drupal::service('profile_handler');
    

    This should be injected I think.

  3. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,81 @@
    +class ProfileHandler {
    

    This should implement ProfileHandlerInterface probably?

  4. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,44 @@
    +   * @param $profile
    +   *   Name of profile.
    ...
    +   * @param $profile
    +   *   Name of profile.
    ...
    +   * @param $profile
    +   *   Name of profile.
    

    Missing parameter type here.

  5. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,44 @@
    +   * @return bool
    

    Missing return description.

mpotter’s picture

Good feedback!

And WOOT!! Tests passed on #170. Let's hope this passes too.

1) Yes, I agree is should follow the same as "base theme". Have changed it to "base profile". Also supporting the shortcut of just "base profile: name" when there aren't any excluded dependencies.

2) I knew this would be a comment! Already changed in my dev.

3) Oops, good catch! Left over from before I had an interface. Fixed.

4) Yep!

5) and Yep.

Here is a new patch.

dawehner’s picture

+++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
@@ -248,8 +249,10 @@ public function setProfileDirectoriesFromSettings() {
     if ($profile) {
-      $this->profileDirectories[] = drupal_get_path('profile', $profile);
+      $profile_handler = \Drupal::service('profile_handler');
+      $this->profileDirectories = array_merge($profile_handler->getProfileDirectories($profile), $this->profileDirectories);
     }

Could we somehow force people to set the profile directories from outside, or at least allow to set it from outside? The extension discovery ideally should be able to run without an actual working container, just for itself. This is no longer the case with this change

mpotter’s picture

dawehner: well, that is why I originally proposed using $settings['profile_directories']. The $settings were outside the container. Do you have a suggestion for how to set it from outside? Seems like it would still be a kludge involving some hooks and then passing data somehow running early in the bootstrap process.

Since extension discovery without a container doesn't make sense for profiles, can we maybe just add a conditional around this so it only runs if a container is available?

mpotter’s picture

Status: Needs review » Needs work

There are some obscure problems still with this patch. Let me summarize an IRC discussion with dawehner and some other notes:

1) extensionDiscovery needs to work in cases where there isn't any container. Meaning that services are not available. Thus, it cannot always call the new ProfileHandler service. Specifically extensionDiscovery is used by moduleData() in DrupalKernel. When called after a cache-clear it runs without a container. In this case, the base-profile is not found.

2) We need to avoid changes to extensionDiscovery. It's already complicated enough and in the process of being greatly reworked. Meta issue is #2186491: [meta] D8 Extension System: Discovery/Listing/Info. Lots of work currently being done in #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList that might effect us.

3) The only time extensionDiscovery needs to know anything about profiles is at the end when it calls filterByProfileDirectories(). Without a container, all it knows is the $settings["install_profile"]. It will filter extensions in parent profiles.

4) Issue #2156401: Write install_profile value to configuration and only to settings.php if it is writeable is almost ready to hit 8.2.x and will change how $settings is handled. The idea is to inject the profile info into the container. This patch also assumes a single profile, so we'll be patching inherited profiles over that when it gets committed. dawehner is going to try and push 2156401 forward so we can make progress. I'll be reviewing it to see what might need to change here.

5) The issue in #4 doesn't change the fact of 1,2,3 regarding extensionDiscovery not having a container, so it still won't have access to the profile(s).

6) dawehner suggests putting the profile and base-profile info into Config since there are other examples in DrupalKernel that need access to Config without having services available that might be models for extensionDiscovery. Doesn't help us directly today, but gives a direction to go as to where to store the profile stuff.

7) The patch in #172 passes normal testbot testing. However if you try to run tests via simpletest and the run-tests.sh script, they will fail with errors about not finding the parent profile. This illustrates the complexity of the issue regarding when services are available and when they aren't. It also shows that the current Core test coverage of all this is not robust enough.

THE PLAN

A) Will try to reroll #172 to fix the issue of the parent profile not being found when running run-tests.sh. This might involve putting code back into DrupalKernel to handle the situation where the service container is not available. This will give us an interim solution I can use for my current clients. I'll likely post a backport for 8.1.x as well.

B) We get 2156401 committed.

C) We reroll our patch and add the changes needed because of (B).

D) Then we wait for 2208429 and update our patch based on those changes.

E) Then we hopefully get our patch committed with clean profile inheritance! Then Profit.

Hopefully all of this in time for 8.2.0 (hey, I can dream!)

mpotter’s picture

Here is a new patch and interdiff. It fixes the issue with run-tests.sh not working. Here are some notes:

1) The problem with run-tests.sh has nothing to do with containers and moduleData. The issue is that the _system_rebuild_module_data() function specifically only adds the main profile to the list of modules. Thus causing errors when the parent profile is queried. It actually finds the *modules* within the parent profile just fine. The fix was for the InstallStorage as mentioned below in #3 and #4.

2) In the case of moduleData() calling extensionDiscovery without any container, it already calls setProfileDirectories(array()) which causes the scan() to return ALL profiles, not just the current profile. It then filters in moduleData() based on the enabled modules in the module list. In this case, the code in setProfileDirectoriesFromSettings that calls the ProfileHandler is never called (because profile_directories is already set). So no changes were needed to moduleData.

3) There are several places in Drupal that call scan('profiles') to get the profile list and then call
drupal_get_filename('profile', $profile, $profile_list[$profile]->getPathname());
to set the filename cache directly. I think this kind of behavior is going away in some of the issues mentioned above (Good! because it's horrible!). This kind of code assumes a single profile path. So several places (InstallStorage, ExtensionInstallStorage) had to be updated to call the ProfileHandler to get a list of profiles to loop through and set.

4) In add cases of using drupal_get_filename(..,..,value) to set the cache, I have just let it set the path for *all* profiles instead of just the current profile. It doesn't hurt to have all the profile path info cached. You cannot call the ProfileHandler->getProfileDependencies(profile_name) unless this filename cache is already set.

jhedstrom’s picture

+++ b/core/modules/system/system.module
@@ -963,22 +963,31 @@ function _system_rebuild_module_data() {
+  // Include the installation profile in modules that are loaded.
+  $weight = 1000;
+  foreach ($profile_names as $profile_name) {
+    $modules[$profile_name] = $profiles[$profile_name];
     // Installation profile hooks are always executed last.

Should this array be reversed in order so that the actual profile has the heaviest weight, so it can always override hooks provided by base profiles?

As I understand it now, if there were, for instance, 3 profiles (foo, foo_base_1, and foo_base_2), foo_base_2 would be the heaviest, rather than foo...

+++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
@@ -248,8 +249,15 @@ public function setProfileDirectoriesFromSettings() {
     // In case both profile directories contain the same extension, the actual
     // profile always has precedence.
     if ($profile) {
-      $this->profileDirectories[] = drupal_get_path('profile', $profile);
+      if (\Drupal::hasService('profile_handler')) {
+        $profile_handler = \Drupal::service('profile_handler');
+        $this->profileDirectories = array_merge($profile_handler->getProfileDirectories($profile), $this->profileDirectories);
+      }
+      else {
+        $this->profileDirectories[] = drupal_get_path('profile', $profile);
+      }

There should probably be a code comment here explaining why the profile_handler service may be unavailable.

dawehner’s picture

+++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
@@ -0,0 +1,45 @@
+  /**
+   * Returns a list of related installation profiles.
+   *
+   * @param string $profile
+   *   Name of profile.
+   *
+   * @return array
+   *   List of dependent installation profiles in descending order of their
+   *   dependencies.
+   */
+  public function getProfileDependencies($profile);
+
+  /**
+   * Returns an array of install profile directories
+   *
+   * @param string $profile
+   *   Name of profile.
+   *
+   * @return array
+   *   List of profile paths
+   */
+  public function getProfileDirectories($profile);

IMHO this is a bad interface design, but rather a copy of the potential public methods one could have onto an interface. IMHO we should just have a getProfileDependencyExtensions which returns a list of extension objects. This allows you to both use them as names and for directories.

mpotter’s picture

dawehner: I could merge getProfileDependencies() and getProfileDirectories() into the single getProfileDirectories() (and use array_keys when you just want the profile names). But returning a full extension object is probably a bad idea since this function is called at a low level when the extension objects themselves are not available yet. For example, when getProfileDependencies() is called from InstallStorage::getAllFolders() it has already fetched the list of profiles via the ExtensionDiscovery scan() and that is not available within the ProfileHandler class. We'd need to add calls to ExtensionDiscovery::scan within the ProfileHandler itself which then prevents the caller from using the same listing object to scan for modules. I think it would make the code a lot more complex just for the sake of a "better interface".

Can we handle stuff like that in later revisions/re-rolls? This patch is obviously going to change a lot as the 2156401 and 2208429 issues get committed. So I'd rather focus on getting something that works for now and then worry about making it nicer after those other two issues drop.

jhedstrom: Regarding the weights, the current order is correct. The getProfileDependencies() returns the profiles in dependent order with the parent profiles first and the main profile last. So I believe this already assigns the highest weight to the profile you want to run hooks for last (the main profile. parent hooks run first). I'll improve the comment for getProfileDependencies() to make this order more obvious.

mpotter’s picture

Here is a reroll that incorporates the changes requested above (simplified the interface as much as I could without fully loading extensions). Also fixes the failed test from #176 where _system_rebuild_module_data() was returning all profiles when no profile was being used.

mpotter’s picture

Re #179: I just looked at what the Extension class actually entails. It's not as much as I thought, so returning Extension objects for the profiles might be easier than I thought. Looking into it.

mpotter’s picture

OK, dawehner you are brilliant! Your suggestion to return Extension objects worked really well. In fact, it allowed me to greatly simplify the system module _system_rebuild_module_data() function. I was able to move all of the profile-related stuff into the ProfileHandler, such as the weights starting at 1000, having profiles be hidden and required, etc. It also no longer parses the info file twice.

This patch is starting to accomplish what I originally hoped in encapsulating the gory details of Profiles into implementation of a clean service!

Cross fingers for tests.

das-peter’s picture

Status: Needs work » Needs review

@mpotter Awesome! This really is starting to look pretty nice. Hope I can give it a test run soon :)

das-peter’s picture

Status: Needs review » Needs work

Oops, test-bot just came back with "Needs work". Fixing status.

mpotter’s picture

Yep, I think we are really close. I wasn't surprised that the last reroll had some test failures given the extensive changes made in _system_rebuild_module_data() but hopefully I'll be able to fix those.

mpotter’s picture

Hmm, so one reason tests are failing is that ProfileHandler is setting the profiles as required *before* _system_rebuild_module_data_ensure_required is executed. In the past the _system_rebuild_module_data_ensure_required call is done before the profiles were set to required.

This is dirty since _system_rebuild_module_data would still need to know something about the profile instead of ProfileHandler handling it all. But it's causing dependent modules of the profile to be added to the array.

Hmm, looking at the _system_rebuild_module_data_ensure_required() code it doesn't seem to check first if the extension is actually in the array. Extensions get added as Extension objects, but if you have a dependency that isn't yet in the list a stdClass object is created indirectly in _system_rebuild_module_data_ensure_required. I think I can fix that directly in the _system_rebuild_module_data_ensure_required function, so let me play with that.

mpotter’s picture

I'll have to look at this more tomorrow. If somebody wants to help in the meantime, the quick test to run locally via run-tests.sh is "Drupal\Tests\system\Kernel\Extension\ModuleHandlerTest". It completes in about 30 secs on my dev system, making it a quick turnaround.

In _system_rebuild_module_data() if I remove the "if (empty($module->info))..." conditional around the info_parser then the test passes. If I put this conditional back in, the test fails (also restored the other bits in _system_rebuild_module_data() originally computing Hidden and Required).

I don't understand why using the cached info_parser result is different from calling the info_parser again fresh. When I var_dump() the non-empty array and the newly parsed array there are not any significant differences in the dependencies that should be causing these errors. So there is some other bizzare side-effect going on here.

Rajab Natshah’s picture

Hi Drupal Profiles Developers,
I have tested all list of patches.
We do need to have a full Start to End solution. This is not working right now.

- Profiles must install and start working without showing the "Base Profile".
- Profiles must start work without the need to any changes in the settings.php.

It should be something like "Profile Manager" .. and have a menu link called "Profiles"
Users must be able manage profiles as they manage Themes. Like the "Theme manager" and the appearance link.

mpotter’s picture

RajabNatshah: The patch in #183 doesn't require any changes to settings.php and is a full solution. However if you read the issues you'll see that this patch is still in "Needs work" state and is not passing tests. This issue isn't about anything like "Profile Manager". Profiles cannot be managed like Themes because you can change Themes on a running site, but you cannot change Profiles. Profiles are only for Install time. If you have requests for other ways of doing this, please create a new issue.

Back to the patch...

I think I might have found a core issue, or else I don't know exactly what is going on with the caching of the Extension system. I downloaded a fresh copy of Drupal 8.2.x and then in the System::_system_rebuild_module_data() function I changed line 996 from
$module->info = \Drupal::service('info_parser')->parse($module->getPathname());
to this

    if (empty($module->info)) {
      $module->info = \Drupal::service('info_parser')->parse($module->getPathname());
    }

Basically, I'm just trying to prevent un-needed info file parsing. If the $module->info array already exists, then it shouldn't need to re-read it again, right?

Well, after making this one change, tests break. Specifically the Drupal\Tests\system\Kernel\Extension\ModuleHandlerTest breaks:

Drupal\Tests\system\Kernel\Extension\ModuleHandlerTest 5 passes 3 fails
FATAL Drupal\Tests\system\Kernel\Extension\ModuleHandlerTest: test runner returned a non-zero error code (2).
Drupal\Tests\system\Kernel\Extension\ModuleHandlerTest 0 passes 1 fails

Looks like an issue with dependent modules, but I'm not sure. Anyone know what Drupal is doing with the $module->info data that is requiring it to be regenerated all the time?

Now that I know what was causing the tests to fail, I'll go back to the patch and see if I can come up with a way to set the profiles info array within ProfileHandler and yet still allow _system_rebuild_module_data to regenerate it. It will likely be messy though. Maybe one of the other issues for reworking _system_rebuild_module_data() will help with this eventually.

mpotter’s picture

OK, let's fire up the testbot. I found that you cannot set the "required" property for the profile before calling _system_rebuild_module_data_ensure_required(). So I removed that from ProfileHandler and moved it back into System::_system_rebuild_module_data(). Let's see if that fixes the issues.

mpotter’s picture

Status: Needs work » Needs review
mpotter’s picture

Nasty little test! That one failing test is because it's looking for $module->origin even though "origin" is not an official property of the Extension object. Dirty OOP here. It's a special value added by the scan() function not documented for Extension objects. Just set extension->origin = '' for now to see if that's good enough. If we really need this origin setting then we'll need to do a scan('profiles') within ProfileHandler and then also document in Extension that Origin is a required property. But in this case I think it's more of an issue with the specific test.

jhedstrom’s picture

This is looking really close!

Just a few tiny nitpicks here:

  1. +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
    @@ -54,6 +55,13 @@ class ConfigInstaller implements ConfigInstallerInterface {
    +   * ProfileHandler
    

    Tiny nit, should be "Profile handler.".

  2. +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
    @@ -462,7 +473,8 @@ public function checkConfigurationToInstall($type, $name) {
           // modules because those may depend on the current module being installed.
    
    +++ b/core/lib/Drupal/Core/Config/InstallStorage.php
    @@ -155,16 +155,18 @@ protected function getAllFolders() {
    +      // Now that we can fetch the path, get dependent profiles and add the extensions
    

    This line exceeds 80 characters, so needs to wrap. It also needs a '.' at the end.

  3. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,102 @@
    +        // See @1356276-192.  Issue in System::_system_rebuild_module_data,
    

    This should probably be a proper link? Alternatively, a clear explanation directly in the code comment might be preferable, unless there's an associated @todo task in the linked issue.

  4. +++ b/core/modules/system/system.module
    @@ -994,6 +991,12 @@ function _system_rebuild_module_data() {
    +    else {
    +    }
    

    The empty else can be removed here since it does nothing.

phenaproxima’s picture

This is looking real good. I'm super glad we're finally going to have a ProfileHandler service (long has this been needed!) and that the system will start treating profiles like first-class extensions. I don't see much that is functionally wrong this patch; the overwhelming majority of my comments are basically nitpicks.

  1. +++ b/core/includes/install.core.inc
    @@ -21,6 +21,7 @@
    +use Drupal\Core\Extension\ProfileHandler;
    

    It doesn't look like this class is actually used in this file...?

  2. +++ b/core/includes/install.core.inc
    @@ -439,6 +440,13 @@ function install_begin_request($class_loader, &$install_state) {
    +    $profile_handler = \Drupal::service('profile_handler');
    +    $profiles = $profile_handler->getProfiles($profile);
    

    Nit: For brevity's sake, can this be $profiles = \Drupal::service('profile_handler')->getProfiles($profile)?

  3. +++ b/core/includes/install.core.inc
    @@ -1550,7 +1558,11 @@ function install_profile_themes(&$install_state) {
    +  $profile_handler = \Drupal::service('profile_handler');
    +  $profiles = $profile_handler->getProfiles();
    

    Same here.

  4. +++ b/core/includes/install.inc
    @@ -1073,6 +1082,27 @@ function install_profile_info($profile, $langcode = 'en') {
    +    $base_profile_name = !empty($info['base profile']['name']) ? $info['base profile']['name'] :
    +      (!empty($info['base profile']) ? $info['base profile'] : '');
    

    I find this a bit on the convoluted side. Seeing as how it's repeated elsewhere in the patch, can it maybe be made into a method of ProfileHandler?

  5. +++ b/core/includes/install.inc
    @@ -1073,6 +1082,27 @@ function install_profile_info($profile, $langcode = 'en') {
    +      $info['dependencies'] = array_merge($info['dependencies'], $base_profile['dependencies']);
    +      // If there are dependency excludes from the base apply them now.
    +      if (!empty($info['base profile']['excluded_dependencies'])) {
    +        $info['dependencies'] = array_diff($info['dependencies'], $info['base profile']['excluded_dependencies']);
    +      }
    

    What if the base profile is, itself, depending on another base profile? Shouldn't the dependencies be resolved recursively?

  6. +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
    @@ -54,6 +55,13 @@ class ConfigInstaller implements ConfigInstallerInterface {
    +   * @var \Drupal\Core\Extension\ProfileHandler
    

    Should be ProfileHandlerInterface.

  7. +++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
    @@ -118,11 +118,9 @@ protected function getAllFolders() {
    +          $profiles = \Drupal::service('profile_handler')->getProfiles($profile);
    

    Why isn't this using $this->profileHandler?

  8. +++ b/core/lib/Drupal/Core/Config/InstallStorage.php
    @@ -155,16 +155,18 @@ protected function getAllFolders() {
    +      $profiles = \Drupal::service('profile_handler')->getProfiles();
    

    Is there any way to inject the profile handler?

  9. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -7,6 +7,7 @@
    +use Drupal\Core\Extension\ProfileHandler;
    

    It doesn't look like this is being used.

  10. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -248,8 +249,21 @@ public function setProfileDirectoriesFromSettings() {
    +        $profile_handler = \Drupal::service('profile_handler');
    +        $profiles = $profile_handler->getProfiles($profile);
    

    Nitpick, but can this be collapsed into a single line?

  11. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,102 @@
    +  /**
    +   * Static state cache.
    +   *
    +   * @var array
    +   */
    +  protected static $cache = array();
    

    Not a big deal, but why is this static? The ProfileHandler is stateful service maintained by the service container, so this can be a normal class member.

  12. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,102 @@
    +   * The info parser to parse the profile.info.yml files.
    

    Should be a space between "profile" and ".info.yml", otherwise it makes it sound as though we're looking for files actually named profile.info.yml :)

  13. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,102 @@
    +      if (!empty($profile)) {
    

    This if check doesn't make sense. If $profile is empty, it is set to the value of drupal_get_profile() at the very beginning of the method. So it should never, ever be empty.

  14. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,102 @@
    +        $base_profile_name = !empty($profile_info['base profile']['name']) ? $profile_info['base profile']['name'] :
    +          (!empty($profile_info['base profile']) ? $profile_info['base profile'] : '');
    

    As mentioned before, can this maybe be a method of ProfileHandler? Perhaps getBaseProfile($child_profile) or something like that?

  15. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,102 @@
    +        $filename = file_exists($profile_path . "/$profile.$type") ? "$profile.$type" : NULL;
    

    Can the $type = $profile['type'] line be moved to just before this line, for clarity's sake? Also, it's not clear what the type key does, so I think this needs a comment to explain.

  16. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,23 @@
    +/**
    + * Interface for classes that manage profiles.
    + */
    

    This doc comment is kinda obvious. :) How about "Defines an interface for listing and managing installation profiles."?

mpotter’s picture

Fixes from #197. Except the comment in ConfigInstaller was an existing comment and already exactly 80 chars with a period. Added @todos and tried to be more verbose with some of the comments, but probably won't iterate those any further because I expect this to all change once the other #2156401: Write install_profile value to configuration and only to settings.php if it is writeable and #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList issues are committed. Hoping that those issues clean up the code to make this cleaner.

mpotter’s picture

Lol, phenaproxima we posted at about the same time! But thanks for the detailed comments. Here is an updated patch and interdiff for your comments. And for now we get a nice round #200 comment number for it :)

1. done
2. done.
3. done.
4. well, this is allowing the profile info.yml to use a shortcut of just "base profile" as suggested in #171. This info data is not directly available within ProfileHandler and I'd rather not make the interface more complex for it at this time. I'll revisit this in the future. I don't want to do getBaseProfile($child_profile) which would then need to load and parse the info array again for this.
5. I think the dependencies already get handled recursively. All we are doing here is removing any dependencies explicitly excluded in the info.yml file. Perhaps when I actually write tests for all this I'll try doing a triple profile dependency to ensure it works properly.
6. done.
7. I didn't inject the ProfileHandler service into ExtensionInstallStorage because the constructor has the $include_profile = TRUE argument at the end. Thus, adding another dependency would change the signature and potentially break somewhere else. Once the related issues are committed if this is still required then I'll add it.
8. Similar to #7, there are places in Core that call "new InstallStorage()" so wasn't sure exactly how to inject it since it's not just coming from the services.yml.
9. done.
10. done.
11. done.
12. done.
13. The empty($profile) still makes sense because drupal_get_profile() will return an empty string if there isn't any current profile.
14. see #4.
15. moved line done. This code came from elsewhere copy/paste and handles the general case of extensions having their $type defined in the info.yml file. I didn't want to change this to hardcode it as "profile" although we certainly could if people wanted.
16. done.

OK, let's see if it still passes tests!

dawehner’s picture

I really like the simplicity of the approach! It is a bit sad, that this patch has no sign of test coverage for the new features.

  1. +++ b/core/includes/install.inc
    @@ -1029,6 +1030,14 @@ function drupal_check_module($module) {
    + * - base profile: Existence of this key denotes that the installation profile
    

    I would have expected no space in here ... any opinions about it?

  2. +++ b/core/includes/install.inc
    @@ -1029,6 +1030,14 @@ function drupal_check_module($module) {
    + *   - name: The shortname of the base installation profile.
    + *   - excluded_dependencies: An array of shortnames of other modules that have
    + *     to be excluded from the base profile requirements. This allows e.g. to
    + *     disable a demo module that would be installed by the base profile.
    

    I'm a bit confused why we add this feature as part of this patch. This seems quite some scope creep, at least for me.

  3. +++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
    @@ -86,13 +86,13 @@ protected function getAllFolders() {
    +        $profiles = $listing->scan('profile');
    +        foreach ($profiles as $profile_name => $profile_object) {
    

    What about name it $profile_extension here?

  4. +++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
    @@ -118,11 +118,9 @@ protected function getAllFolders() {
    +          $profiles = \Drupal::service('profile_handler')->getProfiles($profile);
    +          foreach ($profiles as $extension) {
    +            $profile_folders = $this->getComponentNames(array($extension));
    

    we should document why we cannot use the profile from $profiles above, as it seems to contain similar information

  5. +++ b/core/lib/Drupal/Core/Config/InstallStorage.php
    @@ -155,16 +155,19 @@ protected function getAllFolders() {
    +      $profiles = $listing->scan('profile');
    +      foreach ($profiles as $profile_name => $extension) {
    +        // Prime the drupal_get_filename() static cache with the profile info
    +        // file location so we can use drupal_get_path() on the active profile
    +        // during the module scan.
    +        // @todo Remove as part of https://www.drupal.org/node/2186491
    +        drupal_get_filename('profile', $profile_name, $extension->getPathname());
    +      }
    +      // Now that we can fetch the path, get dependent profiles and add
    +      // the extensions.
    +      $profiles = \Drupal::service('profile_handler')->getProfiles();
    +      foreach ($profiles as $extension) {
    +        $this->folders += $this->getComponentNames(array($extension));
    

    Also here we should document why we need to use both services ...

  6. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -248,8 +248,20 @@ public function setProfileDirectoriesFromSettings() {
    +      // ExtensionDiscovery can be called without a service container.
    +      // (@drupalKernel::moduleData) so check if profile_handler is available.
    +      if (\Drupal::hasService('profile_handler')) {
    +        $profiles = \Drupal::service('profile_handler')->getProfiles($profile);
    

    Just a random idea. What about allow to pass along the profile handler as constructor argument, and just otherwise fallback to \Drupal::service()?

  7. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,104 @@
    +
    +/**
    + * Class that manages profiles in a Drupal installation.
    + */
    +class ProfileHandler implements ProfileHandlerInterface {
    +
    
    +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,23 @@
    +/**
    + * Defines an interface for listing and managing installation profiles.
    + */
    +interface ProfileHandlerInterface {
    +
    

    Can we document for example when this should be used over the extension list ? (I guess most of the time, as it provides caching and some additional abstractions?)

  8. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,104 @@
    +    static $weight;
    

    Do we really need a static variable here? I cannot really think of a reason.

  9. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,104 @@
    +
    +        $extension->info = $profile_info + $info_defaults;
    +        $extension->weight = $weight;
    +        $extension->origin = '';
    

    I'm wondering whether instead of shuffling it onto the existing extension object and knowing that PHP just likes you I'm wondering whether we could have a ProfileExtension extends Extension or something similar here.

  10. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,23 @@
    +  /**
    +   * Returns a list of related installation profiles.
    +   *
    

    Let's define that "related" means.

  11. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,23 @@
    +   * @return array
    +   *   List of installation profile extensions keyed by profile name
    +   *   in descending order of their dependencies.
    +   *   (parent profiles first, main profile last)
    

    I love that the order is documented

mpotter’s picture

Yep, tests are coming. Hopefully today.

1. "base profile" is modeled from "base theme", so I think the space is appropriate.

2. Not being able to exclude dependencies was a reason much much earlier in this thread for *not* implementing true inheritance. In many client profiles you don't want to inherit the full list of enabled modules from the base profile. This feature removes this limitation in a clean way making inherited profiles much more useable in the real world. So I applauded das-peter for adding this. I'll probably move some of the logic for this into ProfileHandler to also make it easier to test.

3. Yep. Actually changing it to $extension to mirror the loop naming later in that same function.

4. Will improve the comment. scan('profile') returns a list of all profiles found on the file system in no particular order. ProfileHandler::getProfiles returns the ordered list of just the current profile and its parent(s).

4a. The whole bit done here (and elsewhere) to "prime the static cache" for drupal_get_filename() I find messy and I'm thinking of ways to move that into another method of ProfileHandler.

5. Same as 4.

6. I think that is a good idea as it would allow moduleData to pass the profile info in similar to what it's doing with the config in the pseudo container. Similar to figuring out how to inject ProfileHandler as mentioned in #198 so it's not a hard-coded service. I'll take a stab at this.

7. Related to 4 and 5. Yes, I'd rather put the documentation into ProfileHandler itself rather than needing to comment on it every time it is used.

8. So getProfiles() is a recursive function. This static was a way to persist the weight as it gets incremented as the profile tree is traversed. Couldn't see a cleaner way to do it without breaking the function into more pieces, but I'm welcome to suggestions.

9. This is a bigger question. It's not just "ProfileExtension". Even Module extensions need the origin and weight. I think this is more of an issue with Extension itself being abused and these properties need to be added to the parent class if they are being used like they are. But see the code in system_rebuild_module_data() for example. Drupal Core is doing this kind of "ad hoc property" stuff with Extensions all over the place.

10. Will do.

11. Yep, since that's the whole main point of this ;)

Thanks for the feedback. Will be posting new patches today with some changes and start of testing.

dawehner’s picture

Drupal Core is doing this kind of "ad hoc property" stuff with Extensions all over the place.

Sure not question, but this is not a reason to not add more sadness :)

mpotter’s picture

8. Hmm, the $weight stuff was broken...I was stupid. Reworking.

9. It's not really adding "more sadness", it's just moving some sadness from _system_rebuild_module_data into profile_handler. I'm working on a new iteration that encapsulates this $info processing stuff into another protected function that should make it easier to clean up in the future as needed. Also moving the handling of dependencies and excluded_dependencies out of the install.inc and into profile_handler.

Edited: Also, the actual messy bit was the need for "info_defaults" since the way _system_rebuild_module_data() is currently written we cannot set the "required" property when the info.yml is first parsed. It can only be set *after* the _system_rebuild_module_data_ensure_required() is called. As I mentioned in #192, this is all messy until the bigger problems with _system_rebuild_module_data() can be solved. For now just doing what needs to be done to get it working without involving all those related issues.

dawehner’s picture

9. It's not really adding "more sadness", it's just moving some sadness from _system_rebuild_module_data into profile_handler. I'm working on a new iteration that encapsulates this $info processing stuff into another protected function that should make it easier to clean up in the future as needed. Also moving the handling of dependencies and excluded_dependencies out of the install.inc and into profile_handler.

That's fair :)

Rajab Natshah’s picture

Mike: You do have a better solution for this.
I have tested all patches. I will still wait to get to the best fix solution for this.

About the Profile Management.

1. Install Drupal, Install Parent profile, and then Install the Child profile.
- The [Profile manager] will only work in the installation process. around the selection of profiles.
- We could have the [Profile Manager Generator] only to generate new profiles.
- Profile configuration and conflicts with drupal or parent profile.
2. Update Drupal, Update Parent profile, and then Update the Child Profile.

Rewarded work :)

mpotter’s picture

RajabNatshah: I think you should create a new issue for discussion of a Profile Management. You don't "Install Drupal, Install Parent profile, then Install Child profile". You just install the Child profile directly. There isn't any such thing as "Install Drupal". You are *always* using some sort of profile, such as "Standard" or "Minimal". Please keep the discussion in this issue directly related to this patch. This issue has already gone off track too many times in it's 5 year history. This is not the place for other discussions.

Back to the patch. Before embarking on tests, I wanted to upload a new version of the patch to run the testbot on some refactorings mentioned in #202. I moved a lot more profile code into ProfileHandler to simplify other functions. Also dealt with the messy drupal_get_filename() caching issue for profiles. This work should make it easier to refactor as other related issues get committed.

Added an interdiff to make it easier to comment, but would love another review by people on these changes while I go work on tests. Thanks!

dawehner’s picture

  1. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -2,21 +2,33 @@
     /**
      * Class that manages profiles in a Drupal installation.
      */
     class ProfileHandler implements ProfileHandlerInterface {
     
       /**
    

    I would like to have all that stuff to be marked as internal to allow for further improvements in the future. This is needed maybe to get into a better shape with #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList again.

  2. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -46,59 +65,195 @@
    +    $modules_cache = &drupal_static('system_rebuild_module_data');
    

    Urgs. Is there no way to get around that?

  3. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -46,59 +65,195 @@
    +  static function getProfileBaseName($info) {
    

    Is this method meant to be public?

mpotter’s picture

Bleh, sorry about that. Try again. Removed the debug stuff and the info_defaults that I forgot to remove.

(Also, the patch itself might be easier to review than the interdiff at this point ;)

mpotter’s picture

dawehner:

1. Not sure what you mean by "all that stuff to be marked as internal". At this point we should consider everything in ProfileHandler to be subject to change based on the related issues we have already linked previously. I think there are already several @todo comments about reworking stuff based on those issues.

2. Sadly not that I could find. I sort of "raged" when I discovered that the drupal_get_filename() function calls trigger_error() when there is a cache-miss rather than firing any sort of exception that can be caught. So this was the best I could come up with. This whole cache priming thing is a complete mess, but at least this moves it out of several other places for work later.

3. Nope, I meant it to be static for now. It allows modules to use ProfileHandler::getProfileBaseName without instantiating the service to just determine the base profile name. This was more important before I ended up consolidating the calls and moving them all into ProfileHandler itself. But for a while other modules were calling this, so I left it. We might eventually just make it protected if we decide nobody else needs this information.

btw, that was a fast review! But you didn't notice the debug_backtrace() call ;)

dawehner’s picture

1. Not sure what you mean by "all that stuff to be marked as internal". At this point we should consider everything in ProfileHandler to be subject to change based on the related issues we have already linked previously. I think there are already several @todo comments about reworking stuff based on those issues.

Right, but in order to be able to do that, we need those classes/interfaces as @internal ...

3. Nope, I meant it to be static for now.

Well yeah, either make it public or protected, but don't leave it hanging in the middle of it and let PHP fallback to public :)

btw, that was a fast review! But you didn't notice the debug_backtrace() call ;)

I just expected you to fix it anyway :P

mpotter’s picture

1. OK, let me know where to put the "@internal"...I've never done that. Although I'm not sure I agree it's @internal since I think it handles what it is doing in a really clean way and we'll always need a service to return a list of profiles in proper order.

3. Doh, yep.

OK, here is a new patch that has the first pass at tests. The ProfileHandler testing is covered. All we need to do next is actually test a real install. I'll poke around the existing tests to see how that is done. But I've added the testing_inherited profile (inherits from minimal) so testing that it installs and that the proper modules get enabled (or not) should be an easy job for tomorrow. I'm done for today.

Edited: Uh-oh, tests failed above, so this won't pass either. More work for tomorrow.

Rajab Natshah’s picture

mpotter: I totally understand what you are talking about.

Agree with you I will create a new issue or new project about the "Profile manager" : Profile installation handler, Profile update management, and malty nested profiles.

If you read my first comment #191

full Start to End solution.

- Profiles must install and start working without showing the "Base Profile".
- Profiles must start work without the need to any changes in the settings.php.

I will keep following and testing patches, until we do have a stable and tested one.

Rewarded work you have :)

mpotter’s picture

Status: Needs work » Needs review
FileSize
33.99 KB
5.18 KB

I think I found the source of at least one of the failing tests. And it's related to the request by RajabNatshah in #215. The last refactor was setting the default distribution name to "Drupal" in the ProfileHandler. But we don't want this because then *every* profile has a distribution name and the installer will always pick the first one it finds. This resulted in the Minimal profile always getting installed.

Just picking the first matching distribution seemed a bit arbitrary, so in this patch I have add a new function to ProfileHandler to select a distribution from a list of profiles. Any base-profiles are removed from the list. Then if there are more than one it will select the first one.

So now if the child profile adds the distribution name to it's info.yml file, it should get selected as the profile to install even if it's parent profile also has the distribution name selected. If the child profile doesn't add a distribution name, then rather than just installing the parent profile, the user gets a choice of which profile to install. This puts control over the installer back into the hands of the main child profile rather than letting the parent profile control it.

I also added a new test that actually tests installing an inherited profile and ensures the proper modules are enabled or excluded.

mpotter’s picture

Issue tags: -Needs tests

Woot, tests pass! I'm done with my refactoring now, so any last feedback would be welcome.

dawehner’s picture

This patch in general is great, here are some points I would have pointed out in a review.

I still bet with you that every committer will say: excluded extensions is a scope creep, but well, if you think you actually save time by not creating simply a small follow up issue.
Given that we are in beta phase for 8.2.x now, this is a 8.3.x feature.

dawehner’s picture

Status: Needs work » Needs review
FileSize
38.77 KB
1.08 KB

This should be it, ideally.

mpotter’s picture

Thanks for updating the patch with your changes. I'm not up on the latest coding standard stuff and didn't realize we were using [] over array() now, so that was good to see. Also, thanks for updating the new test to be a Browser test instead of the older WebTest. I looked at both the Minimal and Standard profile tests as examples, but they each do it differently and wasn't sure which to follow (I followed Minimal which I guess is outdated).

My only concern is the duplicate code for the tests for selectDistribution and selectDistributionExtension. I can understand that my attempt to write a more general purpose function that accepted either strings or objects might not follow strict guidelines. But having both functions seems to make the class/interface messier especially given that this is only needed by the installer.

In fact, it looks like in install.core.inc the $install_state['profiles'] array is already keyed by the profile name, so I suggest we just keep selectDistribution and pass it array_keys($install_state['profiles']) since _install_select_profile() returns a profile string name anyway. Let me know what you think.

dawehner’s picture

My only concern is the duplicate code for the tests for selectDistribution and selectDistributionExtension. I can understand that my attempt to write a more general purpose function that accepted either strings or objects might not follow strict guidelines. But having both functions seems to make the class/interface messier especially given that this is only needed by the installer.

Well, as you just realized in your comment is that we actually just need one of the two methods. Having one method which has two behaviours is always a code smell and a sign that actually it should work in a different way.

mpotter’s picture

Oh also looks like we also need a test for the shortcut "base profile: name". The new code added to getProfileInfo()

        $info['base profile'] += ['excluded_dependencies' => []];

won't work in that case. So I'll add code to normalize the $info to handle both syntaxes.

phenaproxima’s picture

This looks pretty good to me, honestly. I have nitpicks, but nothing major leaps out at me. I don't think I'm experienced enough with the low-level extension handling systems to to RTBC this patch.

  1. +++ b/core/includes/install.core.inc
    @@ -1213,11 +1221,8 @@ function _install_select_profile(&$install_state) {
    +  if ($distribution = \Drupal::service('profile_handler')->selectDistribution(array_keys($install_state['profiles']))) {
    +    return $distribution;
    

    Ye gods. Can we do the call to selectDistribution() on its own line, purely for readability?

  2. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -99,6 +99,15 @@ class ExtensionDiscovery {
    +   * It is used to determine the directories we want to scan modules for.
    

    Should be "in which we want to scan for modules"?

  3. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -248,8 +267,18 @@ public function setProfileDirectoriesFromSettings() {
    +        $profile_directories = array_map(function($extension) {
    +          return $extension->getPath();
    +        }, $profiles);
    

    I've seen this repeated elsewhere in the patch. Maybe it could be added as a convenience method -- ProfileHandlerInterface::getProfileDirectories()?

  4. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,302 @@
    +   * @var \Drupal\Core\Extension\Extension[][]
    

    Why [][]?

  5. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,302 @@
    +    if (!$this->scanCache && !isset($modules_cache)) {
    

    $this->scanCache is not defined on the object. Can it be?

  6. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,302 @@
    +    if (!isset($this->infoCache[$profile])) {
    +
    +      // Set defaults for profile info.
    

    There's an extra blank line here.

  7. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,302 @@
    +      if ($base_profile_name = $info['base profile']['name']) {
    

    Shouldn't we do isset($info['base profile']) first?

  8. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,75 @@
    +  public function setProfileInfo($profile, $info);
    

    $info should be type hinted as an array.

  9. +++ b/core/tests/Drupal/KernelTests/Core/Extension/ProfileHandlerTest.php
    @@ -0,0 +1,107 @@
    +  /**
    +   * @covers ::selectDistribution
    +   * @covers ::setProfileInfo
    +   */
    +  public function testSelectDistribution() {
    

    No description in the doc comment.

dawehner’s picture

This addresses feedback from @phenaproxima and myself.

I've seen this repeated elsewhere in the patch. Maybe it could be added as a convenience method -- ProfileHandlerInterface::getProfileDirectories()?

To be honest I really like the general idea to NOT have arbitrary helper methods, but actually always deal with the objects.

Why [][]?

I renamed the variable to $profilesWithParentsCache to make its purpose a bit clearer.

$this->scanCache is not defined on the object. Can it be?

Its for me :)

Shouldn't we do isset($info['base profile']) first?

IMHO no, because we += ed above already.

dawehner’s picture

A couple of more small improvements.

DuaelFr’s picture

I did some manual testing.
It works quite well, congratulations!

I have some issues though:

  1. the base profiles themes are not inherited, you have to define your own theme section in your info.yml file
  2. all the base profile config/install files seems to be loaded so, if you exclude a dependency that's needed for one of these files (or if you forget to define the same themes as the base profile), you'll get an error upon install

Let's try with this very simple profile:

name: testinherit
type: profile
core: 8.x
base profile:
  name: standard
  excluded_dependencies:
    - block_content

The result is :

Starting Drupal installation. This takes a while. Consider using the --notify global option.
exception 'Drupal\Core\Config\UnmetDependenciesException' with message 'Configuration objects
(block.block.bartik_account_menu, block.block.bartik_branding, block.block.bartik_breadcrumbs,
block.block.bartik_content, block.block.bartik_footer, block.block.bartik_help,
block.block.bartik_local_actions, block.block.bartik_local_tasks, block.block.bartik_main_menu,
block.block.bartik_messages, block.block.bartik_page_title, block.block.bartik_powered,
block.block.bartik_search, block.block.bartik_tools, block.block.seven_breadcrumbs,
block.block.seven_content, block.block.seven_help, block.block.seven_local_actions,
block.block.seven_login, block.block.seven_messages, block.block.seven_page_title,
block.block.seven_primary_local_tasks, block.block.seven_secondary_local_tasks, block_content.type.basic,
field.field.block_content.basic.body) provided by standard have unmet dependencies'

Themes not being inherited, none of the blocks can be installed, plus, block_content being excluded, its configuration cannot be installed either.

mpotter’s picture

Since the theme is one of the first things usually changed on a site I don't think not inheriting the theme is necessarily a problem. Profile themes are often tied to its functionality and like the case of the config you mentioned it's very possible a theme could be broken if you turned off some of the modules.

My guess is that the theme issue will be solved or made easier by those other core issues that are meant to better treat modules, themes, and profiles uniformly so I'd wait till they get finished before trying to mess with this patch anymore.

On the config issue, I don't see any way to really fix that. This is why I discourage profiles from putting config directly within the profile rather than within some modules. But I think your example of excluding "block_content" is a bit contrived and in reality you wouldn't be doing that. All this means is that certain profiles are better suited to being a "base profile" than others.

DuaelFr’s picture

Status: Needs review » Reviewed & tested by the community

I was just thinking that it would work more like themes where everything that's not explicitely excluded or overriden is inherited from the base theme.

If my concerns in #232 are not relevant, then this patch is RTBC for me.
I'm going to use it in production for my next project. Let's live dangerously ;)

catch’s picture

Component: install system » extension system
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs issue summary update, +Needs change record

This issue really needs an issue summary update and draft change notice.

Also moving it to extension system since that's where most of the changes are.

dawehner’s picture

Issue summary: View changes

I'm honestly believe that we should think about #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList as well, given its really related and ensure that this issue will fit into the long term bigger picture.

timcosgrove’s picture

Noting that this change in Features, committed to 8.x-3.0-rc1:
https://www.drupal.org/node/2625310

Breaks the work done in patch 227
https://www.drupal.org/files/issues/1356276-227.patch

because that core patch for profiles modifies ConfigInstaller, and the Features changes include FeaturesConfigInstaller now extending ConfigInstaller rather than just implementing the ConfigInstallerInterface.

You can avoid the issue by pinning Features at 8.x-3.0-beta9 for the time being.

Not sure where to put this comment, but posting here.

mpotter’s picture

Status: Needs work » Needs review
FileSize
40.42 KB
1.47 KB

Here is an updated patch to fix the issue from #238. We forgot to make the new profile_handler argument optional in the ConfigInstaller. But also from #238, you should not pin Features to beta9 since it has important bug fixes since then.

Also, reminder that this patch probably shouldn't be RTBC'd until the related issues mentioned above in the Extension system are committed first. This patch will need to be updated depending on those changes. We don't want to commit this patch first and then have to work around it in other core issues.

kreynen’s picture

Glad to see #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList is no longer postponed. Since we are hoping to use a base profile and sub profiles for each University of Colorado campus, we'd really like to help move this forward in any way that would be useful. Is it worth building proof of concept base/sub profiles using #239 and the dev branch of Features? The latest Extension system patches are failing to apply. @mpotter are you saying that getting this into 8.3 will depend on that? Should we only be testing if we can get that to apply?

mpotter’s picture

kreynen: The above patch #239 should work fine with Drupal core 8.2.x and the latest Features rc1. We use it on several projects already that have profiles using lightning as the base profile. (I think it also works with Drupal core 8.1.x but haven't tried in a while)

What I am saying is that for 8.3.x we want to work on the other core Extension issues first, get those committed, and then rework this patch as needed to get it working with the new extension system. So stay tuned to this issue thread for updated 8.3.x patches as they are needed. But the intent is to keep the functionality of this patch and just adjust it as needed for api changes. The idea of using "base profile" in your info.yml etc shouldn't change.

I don't think you need the other extension issues for this, unless you are doing something else that requires those other patches. Certainly #239 is not going to work with those other patches yet. I want to wait until they are more rtbc'd before spending time reworking the patch here since I have limited time on this.

So you don't even need to build a proof of concept. The concept has already been proven on several projects. Just go ahead and use #239.

DuaelFr’s picture

@mpotter For the record, we use this patch with Features rc1 and it works well except that Features contained in the parent profile are not shown in the Features UI and they are never used to calculate dependencies. Should I open an issue in the Features queue?

mpotter’s picture

DuaelFr: I cannot reproduce that. I build the Octane project which has Lightning as it's base profile and I can see the Lightning features in the Features UI just fine. Now, there are maybe some other issues with Features in 8.2 that could be related to this inherited profile patch that I am investigating, but let's keep the discussion over in the Features queue since this patch thread is plenty long enough without side-tracking. If it turns out you find an issue with this patch, upload a new patch here.

josebc’s picture

Patch in #239 fixes features issue but breaks drush for me
Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container. in [error]
/core/lib/Drupal.php:129

Anybody else facing the same issue?

mpotter’s picture

josebc: what version of drush and what drush command are you trying to call? I've used both drush 7 and 8 without a problem, but maybe it is a specific version issue? Probably also need to mention if the error is happening during your drush site-install what your profile setup looks like. I've only been testing when using Lightning as a base profile.

Edited: Also, is this just a problem with #239? Did #231 have the same problem? The more details on reproducing this you can give the better the chance of getting it fixed.

josebc’s picture

mpotter thank you for the reply, I tried the patch on a clean lightning and its working good, I'm using head drush so that is not the issue.
I'm guessing it happens when used with another patch or module, ill keep digging and post back here in case anyone else is facing the same problem

josebc’s picture

I tracked down the problem to libraries module in LibrariesServiceProvider alter method, still need to figure out if the issue is with the service or the alter method
error happens after calling $config_factory = $container->get('config.factory');

saltednut’s picture

Can we get an issue summary update? Its unclear to me what is happening now as I have been out of the loop and we've been using the patch from #157 like bad kids over in the Demo Framework project to "inherit" Lightning for too long...

Perhaps @mpotter (or anyone else) can confirm the fllowing:

1. Declare base_profile, in my info file -- ie: octane.info.yml declares base_profile: lightning
2. Do a site-install using my profile as the argument (drush si octane)
- First,the base profile (lightning) is installed, any config/install hook_install or otherwise are run.
- Second, the sub profile (octane) is installed, any config/install or hook_install should not duplicate, but possibly override base profile

Is this a correct description of the expected functionality to test?

mpotter’s picture

@brantwynn:
1) The key is "base profile" (with a space, not a _. Same as the convention for base theme)
Otherwise yes, you got it. You site-install your profile.

While doing some unit testing, I found a problem with this patch since the InstallStorage tries to grab the profile_handler service when there might not be a container. Here is an updated patch and interdiff.

josebc’s picture

Last patch seems to fix issue with libraries

kreynen’s picture

The updated syntax of base[SPACE]profile vs. base_profile confused me at first because the Octane example on GitHub was still using base_profile. I submitted a PR to fix that https://github.com/phase2/octane/pull/4/files

I'm also seeing notices if excluded_dependencies isn't included in the base profile definition or it is included with no items with #249. It only works as expected when at least one project from the base profile is excluded. I didn't add excluded_dependenciesto the octane PR, so these notices should be easy to reproduce.

I also have some concerns about steps in a base profile's install and update hooks that will assume a dependency defined in the base profile is enable, but I guess the solution for that is anyone who wants a profile to be used as a base needs to write install and update hooks that check what's enabled in case a sub profile is excluding dependencies.

DuaelFr’s picture

I found two little minor issues related to this patch.

  1. If the base profile has a dependency that you excluded in your own profile. Then, for any reason if you enabled that dependency manually after the installation. You cannot uninstall it anymore as the parent profile is enabled a depends on it.
  2. The parent profile is available in the admin/modules/uninstall UI and nothing prevents this to happen.
dwkitchen’s picture

I had the same problem with excluded_dependencies, I simply added the key with a single blank dependency as a tempory solution.

base profile:
  excluded_dependencies:
    -

I also found that theme dependencies are not correctly loaded. My base profile uses Stark and there is install config for blocks. The child profile uses Seven so there where unmet dependency error until I added Stark as a dependency of the child profile.

EDIT: I also found that when I added tasks from the base_profile install they didn't run as the functions were not found. The base_profile.profile is not being loaded during install. I added this to the child_profile.profile file:

module_load_include('profile', 'base_profile');
phenaproxima’s picture

Status: Needs review » Needs work

We discovered a problem with this patch over in #2831438: dblog and UI modules should not be profile dependencies. In short, if you have a profile with dependencies, and you install a sub-profile of that profile, you can no longer uninstall dependencies of the base profile.

I traced this a little bit and discovered that the trouble comes down to line 146 of system module's ModulesUninstallForm:

if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) {

$profile is the result of drupal_get_profile().

When this line is reached, the module being checked will have both profiles -- the installed profile, and its base profile -- listed as dependendents. But it's only checking that the installed profile is a dependent. Therefore, the form will think that the module is depended upon by the base profile, and refuse to uninstall it.

To me, the real fix here is to enforce that modules are never, ever dependent upon install profiles. An install profile is essentially meant to be a one-and-done thing. It runs during install time, sets things up, then should fade into the ether. Having modules depend on profiles is not only deeply unkosher, but it leads to these kinds of problems. I'm not sure exactly how to fix this, but it seems like system_rebuild_module_data() may need some love. This problem has always existed, apparently, but it's being exacerbated and manifested by this patch (and the whole concept of sub-profiles). So I suggest we handle this here, now.

kreynen’s picture

To me, the real fix here is to enforce that modules are never, ever dependent upon install profiles. An install profile is essentially meant to be a one-and-done thing. It runs during install time, sets things up, then should fade into the ether.

"Enforcing" this would really limit how install profiles could be used. In D7, we wrote Profile Module Manager in part to keep make sure that the dependencies declared in the install profile used by ~1,000 sites we run as a service for the University of Colorado remained. Currently, if a module that was added as a dependency to the profile's .info failed to get enabled (for whatever reason), the profile itself would get disabled on the next module enable and any alters or future update hooks in the profile would never run.

The idea that an install profile should be nothing but the distribution of code that *could* be used together is not new, but I don't see what's stopping anyone from developing a profile that is just a code distribution while still supporting other use cases like a single application with an install profile. Most large/mature profiles have already adopted the concept of a "core module" that is enabled by the install profile and manages the dependencies. With Express, we install slightly different cores for internal hosting, hosting on Pantheon, and testing on Travis CI. Projects required by the profile itself are common to all cores, but as we move towards D8 we are planning on doing even less in the profile and moving most of what was done in the cores to subprofiles.

I don't think the problem is with the patch, but with the profile you are using as the base trying to do too much and getting in the way of what you want to do at the subprofile level.

Aren't these really the same issues you'd have using a theme as a base that wasn't designed to be a base and overreaches in what it is trying to do?

balsama’s picture

The problem I see is that this patch effectively changes the way core treats dependencies of profiles. Without the patch, dependencies of profiles can be uninstalled. I don't think this issue aimed to change that behavior - which it does.

If/when this finally lands, I can see users using Standard as a base profile and then extending Standard with a subprofile. Currently, that setup would disallow users from uninstalling views_ui, for example, because Views UI is a dependency of Standard.

geerlingguy’s picture

FYI, we should probably update the Issue Summary at this point—it was last updated as of comment #96, and is now ~150 comments and ~3 years out of date...

saltednut’s picture

Late to dinner here as usual but let me clarify something? Are we saying in:

The problem I see is that this patch effectively changes the way core treats dependencies of profiles. Without the patch, dependencies of profiles can be uninstalled. I don't think this issue aimed to change that behavior - which it does.

So like, if this patch goes into core as-is, then someone installs the Standard profile, they would not be able to uninstall views_ui or any other module declared in standard.info.yml - correct?

To me, this actually makes a lot of sense, and perhaps Drupal should have worked this way all along. However, it has not worked this way for years and people expect to be able to override the basic setup. This would discourage any users who expect to be able to click their way to solutions knowing little, if not nothing at all about how the install profile system works.

Could Drupal provide a 'spartan' install profile that is recommended for actual builds? It would basically need to be empty. Perhaps it could be so bold as to delcare node as a dependency but I'm not going to go crazy.

At the same time, what @balsama says in #256 makes sense. We could rebuild the Standard profile to work as-is, but as a sub-profile. A Sub-Standard profile, if you will?

We would need to provide some type of community consensus for doing this. One idea that comes to mind is combining this with the existing demo profile (snowman?) efforts.

Proposal:

  • In addition to the work from patch #249
  • Add 'spartan' profile and extend it (call it whatever you want, the bikeshed is over here?: {future issue placeholder})
  • Refactor standard profile and stark profiles to extend 'spartan'
  • Possible Followup: convert standard profile over to a more fleshed out "demo" that contains example content
saltednut’s picture

I got some further clarification from chatting online with @balsama that I had missed, which may affect some decisions.

For the record, only dependencies of parent profiles are affected. so if you were _just_ using standard, not extending it, you could still turn [views_ui] off

Given that likely a high percentage of users that install the Standard profile are intending to click around and maybe turn things on or off, it could also be left as-is with this new system merged in. These users would never be affected by the sub-profile problem unless a vendor delivered them a sub-profile driven site without letting them in on this nuance. E.g. someone downloads and installs Lightning, then cannot disable some things and is confused or dissatisfied with that experience.

In an ideal world, only people that are willingly opting in to being locked down by their parent profile dependencies would sign up for using sub-profiles.

Existing base profiles can also change to accommodate this feature - likely by using an install hook to enable a *_core module that finishes the actual install process we've come to know and love from distributions. E.g. Lightning has no dependencies in it's *.info.yml but still kicks off the module installer in lightning.install for lightning_core or whatever else it reads from lightning.extend.yml

mpotter’s picture

From #254, couldn't we also change the ModulesUninstallForm so that instead of just using drupal_get_profile() to get the current installed profile that instead it calls the ProfileHandler service to get a list of all profiles? If the module is part of any of the profiles then we let it be uninstalled.

That would seem to maintain the existing core behavior. This patch has been sidetracked *so* many times that I think the decision on whether to change the way core handles module dependencies of profiles mentioned in the other comments should be handled in a separate issue.

Trying to get this back on track...seems like the remaining work on patch from #249 is:

  1. Handle missing excluded_dependencies (from #251 and #253)
  2. Handle theme dependencies (from #253)
  3. Allow modules from parent profile to be uninstalled (from #254)
  4. Remove parent profiles from module listing (from #252)

Items listed in #258 to go to a new issue.

sylus’s picture

I just wanted to give a huge thank you to @mpotter for getting this moving and functionality mostly complete. I am successfully now extended off of lightning by just the following:

distribution:
  name: WxT

# Base profile
base profile: lightning

It properly inherits all of the enabled modules and I only need to extend with our additions. Definitely a great DX workflow :) Again greatly appreciated.

Next I will be trying one more + final level of inheritance. @mikepotter do you foresee any issues with:

install profile (opendata) -> install profile (wxt) -> install profile (lightning)

Edit: multiple inheritance (see above) does work as well!

balsama’s picture

Small update to allow module dependencies of parent profile to be uninstalled:

  1. Handle missing excluded_dependencies (from #251 and #253)
  2. Handle theme dependencies (from #253)
  3. Allow modules from parent profile to be uninstalled (from #254)
  4. Remove parent profiles from module listing (from #252)
balsama’s picture

Status: Needs work » Needs review
FileSize
42.33 KB
703 bytes

And another tiny update to remove the parent profile from the list.

  1. Handle missing excluded_dependencies (from #251 and #253)
  2. Handle theme dependencies (from #253)
  3. Allow modules from parent profile to be uninstalled (from #254)
  4. Remove parent profiles from module listing (from #252)

Setting to NR to trigger tests.

oriol_e9g’s picture

FileSize
969 bytes

We are planning to use this feature, we can help testing. I have go away the excluded_dependencies notices with a simple isset.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

phenaproxima’s picture

  1. +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
    @@ -73,13 +81,21 @@ class ConfigInstaller implements ConfigInstallerInterface {
    +    if (!isset($profile_handler) && \Drupal::hasService('profile_handler')) {
    +      $this->profileHandler = \Drupal::service('profile_handler');
    +    }
    +    else {
    +      $this->profileHandler = $profile_handler;
    +    }
    

    This can be $this->profileHandler = $profile_handler ?: \Drupal::service('profile_handler') for brevity.

  2. +++ b/core/lib/Drupal/Core/Config/InstallStorage.php
    @@ -56,9 +64,17 @@ class InstallStorage extends FileStorage {
    +    if (!isset($profile_handler) && \Drupal::hasService('profile_handler')) {
    +      $this->profileHandler = \Drupal::service('profile_handler');
    +    }
    +    else {
    +      $this->profileHandler = $profile_handler;
    +    }
    

    Ditto.

  3. +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
    @@ -102,12 +111,23 @@ class ExtensionDiscovery {
    +    if (!isset($profile_handler) && \Drupal::hasService('profile_handler')) {
    +      $profile_handler = \Drupal::service('profile_handler');
    +    }
    +    elseif (!isset($profile_handler)) {
    +      $profile_handler = new FallbackProfileHandler($root);
    +    }
    

    I think it would be less confusing to change this to a try-catch around ServiceNotFoundException:

    try {
      $profile_handler = $profile_handler ?: \Drupal::service('profile_handler');
    }
    catch (ServiceNotFoundException $e) {
      $profile_handler = new FallbackProfileHandler($root);
    }
    
  4. +++ b/core/lib/Drupal/Core/Extension/FallbackProfileHandler.php
    @@ -0,0 +1,73 @@
    +  public function getProfileInfo($profile) {
    +    if (isset($this->profileInfo[$profile])) {
    +      return $this->profileInfo[$profile];
    +    }
    +  }
    

    The interface doc comment says this should return an array, but it will be implicitly returning NULL if $profile does not exist.

  5. +++ b/core/lib/Drupal/Core/Extension/FallbackProfileHandler.php
    @@ -0,0 +1,73 @@
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function selectDistribution($profile_list) {
    +  }
    

    This should return an explicit NULL for interface conformance.

  6. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +
    +  /**
    +   * Returns an extension discovery object.
    +   *
    +   * @return \Drupal\Core\Extension\ExtensionDiscovery
    +   *   The extension discovery object.
    +   */
    +  protected function getExtensionDiscovery() {
    +    if (!isset($this->extensionDiscovery)) {
    +      $this->extensionDiscovery = new ExtensionDiscovery($this->root);
    +    }
    +    return $this->extensionDiscovery;
    +  }
    

    Why is this method needed? Couldn't we just do this in the constructor:

    $this->extensionDiscovery = $extension_discovery ?: new ExtensionDiscovery($root)

  7. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +      // module scan as the module scan requires knowing what the active profile is.
    

    Nit: Exceeds 80 characters.

  8. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +        // Prime the drupal_get_filename() static cache with the profile info file
    

    Ditto.

  9. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +      $info = $this->infoParser->parse($profile_file);
    +      $info += $defaults;
    

    I think this could be combined into one line:

    $info = $this->infoParser->parse($info_file) + $defaults

  10. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +      // Installation profiles are hidden by default, unless explicitly specified
    

    Nit: Exceeds 80 characters.

  11. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +      if (!empty($profile)) {
    

    This check makes no sense to me. The first thing this method does is set $profile if it was empty -- so why would it be empty after that? The rest of the function cheerfully assumes that $profile has a value.

  12. +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php
    @@ -0,0 +1,301 @@
    +  public function selectDistribution($profile_list) {
    

    $profile_list should be type hinted.

  13. +++ b/core/modules/system/src/Form/ModulesUninstallForm.php
    @@ -143,7 +146,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    +        if (!in_array($dependent, array_keys($profiles)) && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) {
    

    Micro-optimzation -- we're calling array_keys($profiles) repeatedly in this loop. Can we instead call it once before the loop begins?

phenaproxima’s picture

Rerolled against 8.4.x and addressed my own feedback except for #266.11.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
44.28 KB
6.35 KB

Fixed a few things I missed that will break the tests, and I addressed #263.2, at least to some extent. Parent profile themes will now be installed along with themes from the child profile, and the child profile can exclude parent themes the same way it can exclude parent dependencies. (I added an excluded_themes key for this purpose.) And I adjusted the tests to cover these changes. Bam!

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
44.06 KB
1.23 KB

Sorry about that. Arrogant idiocy on my part.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
44.62 KB
3.16 KB

Fixing that failing test and confirmed that this patch applies cleanly against 8.3.x.

phenaproxima’s picture

Here's a backwards reroll of the patch against 8.2.x, for distributions like Lightning that want to leverage this functionality now.

mpotter’s picture

Sorry for the delay. Answers to #266:

1 & 2) It seems like there were cases where the service wasn't available in some situations like when ModuleData is called without any service container. But maybe that only applies to the ExtensionDiscovery class and these others were just from copy/paste.

3) I don't think that is the correct Exception. I think when ExtensionDiscovery is called without a container you get the ContainerNotInitializedException exception. But the current code checks ::hasService() because that is faster than going through exception handling and handles any possible case of the service not being found (no container, no service, etc).

4) Yep, should return [] if not found, although this raises a bunch of other issues where callers to getProfileInfo() are not handling that error case and are referencing keys in the returned array that won't exist whether it is null or [].

5) yes.

6) I think the idea here was to not instantiate the ExtensionDiscovery object until/unless it is needed. But that really shouldn't be a big performance issue or anything, so this can probably be done in the constructor.

7 & 8) sure.

9) Yep

10) sure

11) Yep, that check was probably left over from a refactor. Not needed.

12) Yes

13) Even better...it's checking to see if $dependent is in the array_keys($profiles)...why doesn't it just check for isset($profiles[$dependent]) which would be even faster (getting rid of the slow in_array also).

balsama’s picture

I think @phenaproxima addressed his own feedback in the previous patch. This patch just adds an isset before trying to diff the excluded_dependencies and excluded_themes arrays so the install screen doesn't get plastered with warnings.

balsama’s picture

Status: Needs work » Needs review

Not sure why testbot set this to NW. Trying again.

frob’s picture

Status: Needs review » Needs work

@balsama because the patch failed testing.

balsama’s picture

Status: Needs work » Needs review
FileSize
44.57 KB

Reroll for the 8.4.x branch.

balsama’s picture

Looks like the logic to allow dependencies of parent/base profiles to be uninstalled (added in #262) was accidentally removed in #269. This patch brings it back.

frob’s picture

@balsama, unless this is being used in prod with drupal 8.2, there is no need to do extra effort to backport. This won't be included as an new feature of D8 until at least 8.4 possibly 8.5 or beyond. No need to duplicate effort maintaining two patches.

balsama’s picture

Dane Powell’s picture

Status: Needs review » Needs work

I found that very strange things happen if you uninstall a base profile that contains dependencies on uninstalled modules. I think that we need to force base profiles to be considered a dependency of subprofiles and not allow them to be uninstalled to avoid a lot of potential confusion.

I'm using Lightning and a custom subprofile. All Lightning modules are enabled except Lightning Page, Lightning Layout, and (critically) the Lightning profile itself. I accidentally uninstalled the profile while trying to uninstall Lightning Layout (which is a dependency of Lightning). Nothing seemed off at first, but the fun started when I tried to run database updates and install new modules.

First, I'm unable to run update hooks. Lightning 2.0.6 includes several update hooks in lightning_core and lightning_media. Even though these modules are already enabled on my site, when I try to run drush updb to apply these updates, I get errors like "Update function lightning_core_update_8005 not found". If I instead try to use update.php, the error is:

Fatal error: Class 'Drupal\lightning_core\ConfigHelper' not found in lightning/modules/lightning_features/lightning_media/lightning_media.install on line 768

Second, when I'm on the `admin/modules` page, if I just load that page and then click save without making any changes at all, I get this message:

11 modules have been enabled: Basic Page, Contact Form, Lightning Core, Lightning Media, Lightning Search, Lightning Workflow, Media Document, Media Image, Media Instagram, Media Twitter, Media Video

I can repeat that over and over, without ever making any changes. Just keep saving the page, and the message keeps popping up.

Taken together, these two bugs make me think that something related to the profile inheritance feature is causing Drupal to have inconsistent internal module states. It's like they are enabled in some places (the UI), but not others (when autoloading classes and update hooks). And it's all resolved by simply re-installing the Lightning extension. An easy fix once you understand what went wrong, but it's not really a situation that should be allowed in the first place.

balsama’s picture

I think that we need to force base profiles to be considered a dependency of subprofiles and not allow them to be uninstalled to avoid a lot of potential confusion

Agree. Looking into this now.

balsama’s picture

I accidentally uninstalled the profile while trying to uninstall Lightning Layout

How did you uninstall the base profile? Via drush? I don't think this patch allows you to uninstall the base profile through Drupal.

I don't think Drupal really offers any protection against uninstalling stuff other than at the form level (i.e. not presenting options that shouldn't be uninstalled (profiles) or disabling options (modules that other modules depend on)). So we'll have to fix this in drush I think - unless you found another way to uninstall a base profile outside of drush.

balsama’s picture

Status: Needs work » Needs review
FileSize
45.76 KB
2.32 KB

> I don't think Drupal really offers any protection against uninstalling stuff other than at the form level

I take that back. _system_rebuild_module_data() makes special exceptions for the install profile. This patch updates that function so it makes that exception for all profiles returned by the profile_handler instead of just drupal_get_profile.

It also fixes an issue where base profile themes were getting unset if the inherited profile didn't provide an excluded_themes key.

balsama’s picture

As identified over here: https://github.com/acquia/lightning/issues/317

There are a few other places where drupal needs to be updated to account for the possibility of more than one profile being installed. Specifically in the ConfigImportSubscriber. This also fixes a situation in ModuleInstaller where you couldn't uninstall a dependency of a base profile in certain situations.

Mixologic’s picture

@ RajabNatshah : Please do not add lots of tests to old patches. In this issue, you went through many, many old patches, and queued them up for every possible environment: https://www.drupal.org/node/1356276

You should only ever need to run tests on the *most recent patch*, and you should only ever need to run it on other databases and other versions of php if you think there is a specific issue with those, or as one final sanity check before marking something RTBC.

Rajab Natshah’s picture

Hi Ryan,

Noted; and taken.

Sorry, If that engaged Jenkins-CI, I was testing the issue.
I panicked a bit. as we need to have that in our product. But it's not applying the patch.

ResponseText: Additional uncaught exception thrown while handling exception.OriginalSymfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "profile_handler".

I will only test the recent ones. from this point.

Thank you for all your work on Drupal.org :)

Mixologic’s picture

If you are trying to test the issue, that means you download the patch locally to your system, apply it, and verify that it works there, it's usually not helpful to just add additional testing environments to existing tests, unless you are trying to determine if there is a descrepancy between environments.

balsama’s picture

Missed another isset and, as a result, dependencies would get completely unset if a child profile didn't define an excluded_dependencies array.

Rajab Natshah’s picture

Totally my fault Ryan.

I had 22 patches downloaded and tested manually in my local
before I started the automated tests. for D.8.4.x and D.8.3.x

Committed changes to a profile project in Drupal.org, the build will come out with no profile_handler service on install step.

I think the issue when the base profile covers the option to select which profile will be installed.
the automated test will pass as testing_inherited and testing is really a sample profile.

name: Testing
type: profile
description: 'Minimal profile for running tests. Includes absolutely required modules only.'
# version: VERSION
# core: 8.x
hidden: true
dependencies:
  # Enable page_cache and dynamic_page_cache in testing, to ensure that as many
  # tests as possible run with them enabled.
  - page_cache
  - dynamic_page_cache
# @todo: Remove this in https://www.drupal.org/node/2352949
themes:
  - classy
name: Testing Inherited
type: profile
description: 'Profile for testing base profile inheritance.'
version: VERSION
core: 8.x
hidden: true

base profile:
  name: testing
  excluded_dependencies:
    - page_cache
  excluded_themes:
    - classy

dependencies:
  - block
  - config

themes:
  - stable

Some profiles like Lightning, Thunder, Varbase .. covers the option to select which profile

name: Lightning
core: 8.x
type: profile
description: 'A fast and feature-rich Drupal distribution.'
version: '8.x-2.x-dev'
distribution:
  name: Lightning
name: Thunder
type: profile
description: 'The Drupal8 based CMS for professional publishing.'
core: 8.x
distribution:
  name: Thunder
  install:
    theme: thunder

Some profiles do have more config items.

distribution:
  name: [Distribution name]
features: true

Following up with Mike Potter and Balsama.
Not sure which patch is better for 8.3.0 as it will be released

balsama’s picture

And this patch accounts for the possibility that core.extension doesn't have a profile set at all because a config import is being done as part of a site install.

I'm really sorry for all these piecemeal patches. It's been tough considering all the possible scenarios. I've included an interdiff from the reroll in #281 as well.

Gravypower’s picture

I am experiencing an issue when using drush or the drupal console. It seems that if there is that the drupal IOC container is initialised.

Drupal console error:
[ERROR] \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container.

Drush error:
Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real [error]
container. in /home/ajob/Projects/Pantheon/greaterbendigo/core/lib/Drupal.php:129
Stack trace:

This also surfaces in the browser if the cache is not built:
The website encountered an unexpected error. Please try again later.
Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container. in Drupal::getContainer() (line 129 of /home/ajob/Projects/Pantheon/greaterbendigo/core/lib/Drupal.php).

I have managed to work around this issue by checking to see if drupal has profile_handler before asking for it.

Patch to come.

Aaron

Gravypower’s picture

Please find attached patch and interdiff. This is my first attempt in also generating an interdiff so my apologies if something is not right.

Gravypower’s picture

Please disregard, I did not generate correctly.

frob’s picture

@Gravypower, you need to set the project to needs review if you want someone to review your patch or for the automated tests to review it.

amme’s picture

Status: Needs work » Needs review
geerlingguy’s picture

Also... how did this patch go from ~50 KB to 1 MB? I'm thinking something went wrong with the patch generation. Also, an interdiff would be really useful here.

frob’s picture

My guess is this patch was made against the wrong HEAD. I noticed it is adding compressed files in core/modules/system/update/fixtures for 8.2

Gravypower’s picture

#308 is incorrect as per its comment, I was not able to delete it. I did add an interdiff on #307

Gravypower’s picture

frob’s picture

Are you going to generate a good patch?

Gravypower’s picture

Is the patch in #307 not good?

pingwin4eg’s picture

@Gravypower patch in #307 failed tests. Obviously, it's not that good.

balsama’s picture

Status: Needs work » Needs review
FileSize
51.85 KB
963 bytes

I didn't follow what the last two patches were attempting. This fixes the test errors introduced in 303.

jonathanshaw’s picture

#307 is a very simple change, it only produced failures failed because of pre-existing failures in #303. Added to #319 it should be green.

What #307 claims to address is that sometimes we need to access the InstallStorage class before the container is initialised, and because this patch tries to load the profile handler service from the container in the construct method of InstallStorage, it blows up in these situations.

Shawn DeArmond’s picture

Status: Needs review » Reviewed & tested by the community

I applied this patch and it works great.

I took an existing install profile (sitefarm_seed) that we have in production and created a new child profile (sitefarm) that inherits from it with this in the sitefarm.info.yml file:

base profile: sitefarm_seed

The child-profile has its own modules, default content, and additional module and theme dependencies.

I also confirmed #253 comment that the base profile's .profile file was not being loaded. The solution @dwkitchen mentioned worked for me.

I then ran 189 Behat scenarios (2161 steps) and they all passed.

So impressed by the awesome work by everyone involved. This is going to be huge for us! Thank you!

jonathanshaw’s picture

Status: Reviewed & tested by the community » Needs review

This can't be RTBC until a response to the issue raised by @Gravypower in #306 is agreed.

dawehner’s picture

I try to give a proper review on this issue today/tomorrow after the flight.

dawehner’s picture

I tried to read the issue summary to understand why this specific solution was chosen. It seemed to be that people wanted inheritance first, and not thought about possible alternatives, which is fine, but you know, when you pick your end goal in a specific way, you end up with a specific design.

I'll try to be as open as possible about this patch. I have some general architectural problems with the idea: Instead of making the system simpler, it really increases the complexity by introducing profiles as a more complex thing, with different behaviours than modules.

So what are the usecases we try to solve for this particular issue?

  • Sharing configuration between install profiles
  • Allow to override specific configuration in the sub install profiles
  • Sharing customizations in the installer
  • Probably some more?

These kind of goals should have been described in the issue summary.

I'm really wondering why this sharing of code and configuration cannot be achieved with modules + composer requirements.
Don't get me wrong, there are parts of the patch which are absolutely nice, like centralizing logic around profiles instead of having it widespread everywhere, but I'm wondering whether this additional dimension of complexity is the only way to achieve your goals

jonathanshaw’s picture

This is not technical enough to address the important questions @dawehner raises, but in case it's helpful here is Dries' top-level perspective:

One particularly exciting development is the concept of "inheriting" distributions, which allows Drupal distributions to build upon each other. For example, Acquia Lightning could "inherit" the standard core profile – adding layout, media and workflow capabilities to Drupal core, and Open Social could inherit Lightning - adding social capabilities on top of Lightning. In this model, Open Social delegates the work of maintaining Layout, Media, and Workflow to the maintainers of Lightning. It's not too hard to see how this could radically simplify the maintenance of distributions.

The less effort it takes to build and maintain a distribution, the more distributions will emerge. The more distributions that emerge, the better Drupal can compete with a wide range of turnkey solutions in addition to new markets.

Shawn DeArmond’s picture

Issue summary: View changes

The use case for us in Higher Education is similar:

The University of California system could have a base distribution with shared configuration and data architecture across all ten campuses. While the core functionality is maintained by a central systemwide development team, each campus would create a sub-profile with campus branding and campus data system integrations specific to that campus. Then, if desired, a department within the campus could even have their own sub-sub-profile with further customizations for that department.

The big purpose of this, and the difference between simply creating more modules, is that a Distribution is meant to be a full website-in-a-box upon install, and the .info, .install, and .profile files in the Profile is where all the magic happens upon install.

As Dries says, "this could radically simplify the maintenance of distributions."

The issue description could use some work, though, so I'll take a stab at that. I'll leave this as "Needs Review", because it would be good to have the input of others who have been working on this patch.

Shawn DeArmond’s picture

Here's an updated patch with @Gravypower's change on top of #319. Rolled against 8.4.x. Let's see if tests pass now.

Shawn DeArmond’s picture

Status: Needs review » Needs work

I've run into a bug, and I'll try to describe it in as much detail as I can, because it's a little obscure. I was able to replicate it both with Content Types and Block Types, but I'll use a content type for my example below.

To replicate:

  1. Create a custom content type and add some custom fields to it.
  2. Save the content type config (including custom fields and field storage) to a module in /profiles/baseprofile/modules/contenttype1
  3. List contenttype1 module as a dependency of baseprofile in baseprofile.info.yml
  4. Create subprofile in /profiles/subprofile and include "base profile: baseprofile" in subprofile.info.yml
  5. Create another custom content type, and "Re-use an existing field" from one or more of your custom fields from contenttype1.
  6. Save the content type config (including fields, but not existing field storage, of course) to a module in profiles/subprofile/modules/contenttype2
  7. List contenttype1 module as a dependency of contenttype2 in contenttype2.info.yml
  8. List contenttype2 module as a dependency of subprofile in subprofile.info.yml
  9. Perform a fresh site install for the subprofile.

Install throws errors such as these:
Drupal\Core\Config\PreExistingConfigException: Configuration objects (field.storage.block_content.body, sharemessage.addthis, sharemessage.settings, sitemap.settings) provided by contenttype1 already exist in active configuration in /path/to/web/core/lib/Drupal/Core/Config/PreExistingConfigException.php:65

It kinda looks like it's trying to install contenttype1 twice. In fact, these errors are thrown even if step #8 above isn't performed and contenttype2 isn't even supposed to be installed by default. That's very odd.

Next:

  1. Remove contenttype1 from the dependency list of contenttype2 in contenttype2.info.yml
  2. Perform a fresh site install for subprofile

Now the install throws errors such as this:
Drupal\Core\Config\UnmetDependenciesException: Configuration objects provided by <em class="placeholder">baseprofile</em> have unmet dependencies: <em class="placeholder">block.block.seven_breadcrumbs (block, seven), block.block.seven_help (help, block, seven), block.block.seven_local_actions (seven, block), contact.form.feedback (contact)</em> in /path/to/web/core/lib/Drupal/Core/Config/UnmetDependenciesException.php:98

Just to see the difference, when I created a new content type that does NOT re-use fields from an existing content type, the install works as expected. Also, if both contenttype1 and contenttype2 are in the same profile, the site installs fine.

balsama’s picture

Hi Shawn. First off, thanks for helping move this issue forward! It's very much appreciated.

I'm trying to reproduce this and I'm getting hung up on what seem to me to be superfluous dependencies in your steps to reproduce. Let me explain what I did first:

  1. Used Lightning as a base profile - which includes a module which includes a field definition for meta tags (modules/lightning_features/lightning_core/config/install/field.storage.node.field_meta_tags.yml).
  2. Created a content type (subprofile_content_type) that reuses the Meta Tags field defined in Lightning Core.
  3. Exported that content type as a module via features
  4. Created a subprofile (subprofile) that defines Lightning as it's subprofile and gave the subprofile a dependency on subprofile_content_type
  5. Installed "subprofile"

I don't see a need to list lightning_core as a dependency of subprofile_content_type because subprofile_content_type contains field.field.node.subprofile_content_type.field_meta_tags.yml which has a dependency on field.storage.node.field_meta_tags which is provided by lightning_core.

In your example, I don't think you should be including Step 7 because contenttype2 should contain field.field.node.contenttype2.field_FIELDNAME.yml which should have a dependency on field.storage.node.field_FIELDNAME.

Does that make sense and does removing that dependency fix your problem?

FWIW, I don't have a dependency on Features, Features is not enabled, and I removed the subprofile_content_type.features.yml file from the exported config just so there's no question. The full structure of my subprofile_content_type module is this:

subprofile_content_type
  - config
    - install
      core.entity_form_display.node.subprofile_content_type.default.yml
      core.entity_view_display.node.subprofile_content_type.default.yml
      core.entity_view_display.node.subprofile_content_type.teaser.yml
      field.field.node.subprofile_content_type.body.yml
      field.field.node.subprofile_content_type.field_meta_tags.yml
      node.type.subprofile_content_type.yml
      user.role.subprofile_content_type_creator.yml
      user.role.subprofile_content_type_reviewer.yml
    subprofile_content_type.info.yml 

And subprofile_content_type_info.yml looks like this:

name: 'Subprofile content type'
description: 'Defines a content type that shares a field with a content type defined in the base profile.'
type: module
core: 8.x
dependencies:
  - field
  - menu_ui
  - metatag
  - node
  - path
  - text
  - user
balsama’s picture

Status: Needs work » Needs review

It occurred to me that, since I was testing against Lightning, I was using an outdated patch. I just retested again against #327 with the same results. Setting this back to Needs Review.

chr.fritsch’s picture

Status: Needs review » Needs work

I've tested the latest patch with the Thunder distribution and a very simple sub-profile. That worked very well so far. There is just one thing i noticed during the installation:

The current drupal behavior for distributions is the installer skips the "Select profile" step and just installs the profile with the distribution key.

With this patch i am able to select which profile i want to install, again. Normal ones like "Standard" and "Minimal", the distribution profile "Thunder" and the sub profiles.
So if one of my profiles is a distribution, i would expect, that i am just able to select between the distribution profile and sub-profiles, that are based on the distribution. "Standard" and "Minimal" should not be there.

Also the installer theme, should be the distribution one from the beginning.

Shawn DeArmond’s picture

Okay, I think we've finally reproduced the issue reliably.

Strangely, it's the alphabetical order of the modules that makes the difference.

@balsama, in your case, "lightning_core" is alphabetically before "subprofile_content_type", so it works fine for you.

Try renaming your module (including the .info.yml, and other module files) to "asubprofile_content_type". I'll bet it fails.

(You don't need to change the name of your content type itself nor any of the config files.)

Also, to answer your question, yes, contenttype2 DOES need to list contenttype1 as a module dependency, because otherwise we get an unmet dependency error:

Drupal\Core\Config\UnmetDependenciesException: Configuration objects provided by <em class="placeholder">contenttype2</em> have unmet dependencies: <em class="placeholder">field.field.node.contenttype2.field_fieldname (field.storage.node.field_fieldname)</em> in
/path/to/web/core/lib/Drupal/Core/Config/UnmetDependenciesException.php:98
balsama’s picture

Ok, thanks for the clarification. I still don't think you should need the dependency from contenttype2, but hopefully fixing the underlying problem will fix that (or I'll gain some clarity into why it _is_ needed).

I'm traveling this week and have a company event next week. But I'll try to dig into both issues identified above ASAP if no one else gets to them first.

segovia94’s picture

I have spent the past couple days poking at Shawn's issue and trying to reproduce it consistently. I believe it's ultimately not an issue with this patch and is instead related to the Features module. I think the inheritance of a sub profile just brought it to light when dependencies on base profile modules were needed. I filed an issue in the Features module. #2878970: Site Installation fails if a feature module overwrites config from core or another module and its module name is too high in the alphabet

Shawn DeArmond’s picture

Status: Needs work » Needs review

Moving this back to Needs Review after @segovia94's revelation.

balsama’s picture

Re #331, that's not the behavior I'm seeing. When I have a profile in my codebase that has the distribution property, that profile is automatically chosen. I tested with Thunder as well and I see the same behavior - that is:

  • I built my codebase with thunder-project
  • applied this core patch
  • visited /core/install.php

I was not able to select which profile to install and I was presented with the Thunder install screen. This is in keeping with the documentation which states:

A profile will be selected in the following order of conditions:

  • Only one profile is available.
  • A specific profile name is requested in installation parameters:
    • For interactive installations via request query parameters.
    • For non-interactive installations via install_drupal() settings.
  • A discovered profile that is a distribution. If multiple profiles are distributions, then the first discovered profile will be selected. If an inherited profile is detected that is a distribution, it will be chosen over its base profile.
  • Only one visible profile is available.
kreynen’s picture

@chr.fritsch or @balsama, can you share the sub-profile project you are using to test this? We are getting a lot of doesn't work when I do X comments in this issue without the code to reproduce the configurations.

frob’s picture

Updated tests with the failing configuration would be ideal.

balsama’s picture

This patch cleans up ConfigImportSubscriber a little bit to make it more clear and adds a test that asserts that a parent profile cannot be uninstalled and that parent profile dependencies can be uninstalled during config sync.

balsama’s picture

Ok, this should fix the test failures and breaks the new test into two clearer methods (one for parent profiles and one for sub-profiles) that tests

  • That install profiles cannot be uninstalled by config
  • That dependencies of profiles can be uninstalled by config
balsama’s picture

Status: Needs work » Needs review
balsama’s picture

Status: Needs work » Needs review
FileSize
57.22 KB
2.89 KB

Forgot to account for the possibility that a profile might not be set during config import.

balsama’s picture

Status: Needs work » Needs review
FileSize
57.23 KB
720 bytes

Grrr. Bad patch file. actually, it wasn't. Legitimate bug.

balsama’s picture

Status: Needs work » Needs review
FileSize
57.26 KB
9.26 KB

Ok, so those failures were just due to a sloppy isset. Included a diff back to the last passing test, 327. This patch cleans up ConfigImportSubscriber a bit and adds a test that asserts:

  • install profiles cannot be uninstalled by config
  • dependencies of profiles can be uninstalled by config

The test covers both child profiles and parent profiles. The existing ConfigImportInstallProfileTest covers a single (non-inherited) profile.

phenaproxima’s picture

I had a few thoughts about the ProfileHandlerInterface API. Also, do both implementations have dedicated unit test coverage with a test for every public method? If not, they should.

  1. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +   * Parse and process the profile info.yml file.
    +   * Processing steps:
    

    This should be active voice and present tense, like "Parses and processes the info for a profile thusly..."

  2. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +  public function getProfileInfo($profile);
    

    I think this should throw \InvalidArgumentException or similar if the requested profile does not exist.

  3. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +  /**
    +   * Stores info data for a profile.
    +   *
    +   * This can be used in situations where the info cache needs to be changed
    +   * This is used for testing.
    +   *
    +   * @param string $profile
    +   *  The name of profile.
    +   * @param array $info
    +   *   The info array to be set.
    +   *
    +   * @see install_profile_info()
    +   */
    +  public function setProfileInfo($profile, array $info);
    

    If this is a testing-only method, it should definitely not be part of the interface. It could be part of ProfileHandler (or better yet, a test-only subclass of ProfileHandler), but not the interface.

  4. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +  /**
    +   * Clears the profile cache.
    +   */
    +  public function clearProfileCache();
    

    I'd rename this to clearCache() or resetCache(). Seeing as how this is part of the profile handler, I think it's pretty obvious that it's clearing a cache of profile info. :)

  5. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +   *   (parent profiles first, main profile last)
    

    This is a leaky abstraction that exposes implementation details. ProfileHandlerInterface should include a getActiveProfile() or getMainProfile() method which is responsible for returning the main profile only.

  6. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +  public function getProfiles($profile = NULL);
    

    I think this should be renamed. getProfiles() sounds like it's going to return info on *all* profiles, which it will not. I'm not sure what a better name would be, but getProfiles() is too ambiguous, IMHO.

  7. +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
    @@ -0,0 +1,79 @@
    +   * @param string[] $profile_list
    +   *   List of profile names to search.
    

    Couldn't this parameter be optional, and if not passed, it calls $this->getProfiles() -- or whatever getProfiles() will be renamed to -- to get the profile list? It might make for cleaner DX.

dpagini’s picture

I have been using the patch in this issue (327) for a while now on my site and have been very happy with how it's working. I intend to update to 348 and give that a shot as well, but this seems like it's pretty close and just needs to get over the hump. I feel like the suggestions in the previous comment make sense to me, but are these what's stopping this one from moving forward now? If so, I could attempt to build on 348 with the above feedback if that would not be stepping on anyone's toes?

balsama’s picture

@dpagini if you have the time to work on #349, please do!

oriol_e9g’s picture

I'm planning to use this functionality creating a sub-sub-profile, so I have added some tests for testing a two level deep dependency.

Plus, I have worked in some of the comments in #349

1. done
2. done
3. TODO
4. renamed to clearCache()
5. TODO
6. Maybe getInheritProfiles() ? Ideas? I'm not an english speaker, so it's difficult for me improve documentation and find good names.
7. TODO

jonathanshaw’s picture

+++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
@@ -0,0 +1,82 @@
	+  /**
+   * Returns a list of dependent installation profiles.
+   *
+   * @param string $profile
+   *   The name of profile. If none is specified, use the current profile.
+   *
+   * @return \Drupal\Core\Extension\Extension[]
+   *   An associative array of Extension objects, keyed by profile name in
+   *   descending order of their dependencies.
+   *   (parent profiles first, main profile last)
+   */
+  public function getInheritProfiles($profile = NULL);

Re #352.6:

If I understand this right, the passed $profile is in the returned list, as well as its ancestors.

If this is true, I suggest "getApplicableProfiles" or "getProfileLineage" or "getProfileInheritance".
The function comment also needs elaborating: "Gets a list comprised of the profile, its parent profile if it has one, and any further ancestors.

If this is not true I suggest "getAncestorProfiles" or "getInheritedProfiles".
The function comment also needs elaborating: "Gets a list of the parent profile and any further ancestors."

oriol_e9g’s picture

Status: Needs work » Needs review
FileSize
60.46 KB
18.61 KB

I have fixed my tests and added a sub-sub-profile tests to ensure that this is possible and all works with three inheritance levels.

#349.1 - Done

#349.2 - Done

#349.3 - TODO

#349.4 - Renamed to clearCache()

#349.5 - The main/active profile can be reconverd with a simple drupal_get_profile(); Is it really needed a drupal_get_profile() wrapper in the ProfileHandlerInterface?

public function getMainProfile() {
  return drupal_get_profile();
}

#349.6 / #355 - Renamed to getProfileInheritance()

#349.7 - If we accept an empty $profile_list = [] in selectDistribution() and then call getProfileInheritance() to recover a $profile_list inside this always returns an empty value because drupal_get_profile() (current/main/active profile) is set during install, and selection is before installing. Maybe we really need a getAllProfiles() function?

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

drupalninja99’s picture

Is it an expectation that if the subprofile has the same config file in config/install as the parent that it overrides/replaces the parent config file of the same name? That was my expectation but it doesn't seem to be working as expected. I have a subprofile that creates 2 responsive image styles and uses those responsive image styles in field display config. If I have the overridden files in the sub and the parent files of the same name in the parent, I get dependency errors. I have to delete the files of the same name in the parent to prevent the error which to me would defeat the purpose. Is anyone else running into this particular problem?

mpotter’s picture

Status: Needs review » Needs work

I think there is a remaining problem in the configImportSubscriber::validateModules.

When testing the patch in #2788777: Allow a site-specific profile to be installed from existing config to install a profile using config, installing a sub-profile of Lightning where the lightning_roles module has been excluded in the child profile results in the error:

Unable to install the Lightning module since it requires the Lightning Roles module.

Looking at the code with patch (#356) I see that the above error happens before the patched code to handle uninstalling modules in the profile. I think some additional logic is needed when it actually tries to install the profile itself and checks if all the profile dependencies are met.

Will work on a fix.

mpotter’s picture

Status: Needs work » Needs review
FileSize
61.27 KB
2.02 KB

OK, here is the patch that fixes the validateModules. This patch works with #2788777-83 and can successfully install a sub-profile of Lightning from config-sync.

vijaycs85’s picture

Tested patch in #360 and here is my findings:

Setup

I have created two profiles:

1. Site builder(site_builder): To create structure of the sites. Menus, content types, etc.
2. My site(mysite): One of the site which is going to be used by content editor to editorial/content workflow purpose
They inherit inStandard -> Site builder -> My site order. I always try to install with 'Mysite'.

- No config/sync folder present
- Have few modules excluded from standard in Site builder(color, dblog and history) and Mysite(field_ui, views_ui and menu_ui) level using excluded_dependencies
- Have few modules added in Site builder(paragraphs and entity_reference_revisions) and Mysite(default_content) level using dependencies
- Have few new configuration files under site_builder/config/install(paragraph types) and mysite/config/install (nodes exported using Default Content module).
- Have few config files overridden under site_builder/config/install and mysite/config/install

One added bonus is, when I install from 'Site builder' profile, I get a full site without any content. This would be a nice place to start for new sites instead of copy/paste everything from the start.

One down side is, can't exclude modules with default configuration in parent profile. For example, when I tried to exclude search module got error that block.block.search in standard needs it and installation failed.

oriol_e9g’s picture

I have added a new test to prove the bug found in #361

balsama’s picture

I would argue that we should allow base profiles to enforce required config. I don't think that was the intention of Standard in this case, but it's a valid opinion for a base profile.

By providing config in it's /config/install directory, the base profile is effectively saying "I cannot be installed without this config and its dependencies". Config that is indeed optional should be moved into /config/optional or into a the dependent module itself.

Ultimately, if Standard were to be a good candidate for being used as a base profile, I think stuff like block.block.bartik_search.yml should be moved into config/optional.

oriol_e9g’s picture

@balsama the problem is that config/optional is not met during profile install. If you want to add config during the installation but not enforce their use in inherited profiles there is not a clean way. We can say "work as designed", but ideally we should document or found a clean way for this use case (met during install but not enforced in inherited profiles), this can be solved in a followup.

I think that we can try to push a minimal patch and refine in followups. We have functional code, used in some projects, tests and testers.

Anyone can summarize what is missing in #360 and what can be refined in followups? I think that the actual patch is very close.

timcosgrove’s picture

FileSize
1.33 KB

Please be advised that #360 will cause errant code to be created when applied via cweagans/composer-patches to drupal/core 8.3.x 8.4.x and 8.5.x, when git 2.14.x is installed. Specifically, it will create the following additional directories:

docroot/core/b/core/ (with lib, modules, profiles, and tests subdirectories)
docroot/core/core (with lib, modules, profiles, and tests subdirectories)

I've confirmed that the patch when applied to a direct git checkout of drupal/core does NOT create these directories. It only happens when applied via composer-patches.

I'm testing other scenarios. Composer.json which replicates the issue attached, renamed for attachment validation.

Note that this does not appear to be a problem directly with the patch. This issue on composer-patches is possibly relevant: https://github.com/cweagans/composer-patches/issues/148

timcosgrove’s picture

Just to confirm that this appears to be a combination of the current version of cwegans/composer-patches and git 2.14 . If you are running git earlier than 2.14 you won't see the behavior.

So, not a problem with the patch per se. Just a word of warning.

marcelovani’s picture

This is the recording of relevant discussion on DrupalCon Vienna
https://www.youtube.com/watch?v=6yiK9DIJQvo

sylus’s picture

FileSize
291 bytes

Hi there!

First just wanted to say really appreciate the work that went into this patch and for the most part it is working brilliantly. I do think I have found an edge case issue though so wanted to see if anyone would have any idea what is going on.

Scenario 1

Lightning (github.com/acquia/lightning) => WxT (github.com/drupalwxt/wxt) => OD (github.com/open-data/od)

Scenario 2

Lightning (github.com/acquia/lightning) => WxT (github.com/drupalwxt/wxt) => STC (private repo for department)

So given the above scenarios everything is working great and all of my dependencies + profiles are installed in the correct order. Lightning leverages patch 360 in this queue.

Scenario 3

Lightning (github.com/acquia/lightning) => WxT (github.com/drupalwxt/wxt) => CDS

This will fail during the install due to issues with dependencies, yet if I rename the CDS profile to say MDS everything works. It seems that my install profile has to have a name after the namespace Lightning to work.

I have attached what is in my cds.info.yml and in theory anyone sub-profiling off of Lightning should be able to reproduce by calling this profile and just change the base profile to their sub-profile name which is depending on Lightning.

balsama’s picture

I been listening to the discussion at the DC Vienna session and others - and I want to attempt to explain why I still think this patch is critical. I think one thing we can agree on is that there is tremendous value in distributions. They are something that makes sense to decision makers and developers alike. “If I use distro A, I get features X, Y, and Z”.

But since the distro also occupies the “special” territory in Drupal called the install profile, there is no way extend or override those features in your own profile, which is critical - especially when Drupal is used in a large organization.

It doesn’t make sense to use modules to solve this problem. It’s exactly what distributions were created for (Imagine a module that just had four dependencies and one piece of config - and required a specific version of core plus two core patches).

An example: Something like Workflow is critical for a modern application. But it’s been two years and that functionality still isn’t quite ready out of the box with Drupal 8. You can say “install WBM + Scheduled Updates, grab these seven patches and add this config”, but you really need a distribution to do that for you if you want it to be maintainable and marketable. And when it comes to updating the underlying modules, you definitely do.

The only realistic option for packaging something like that is a distro. But without this patch, that’s not a viable option for users who need to further customize using a profile.

A custom profile per-project has become the de facto standard for most Drupal projects. Without this patch, each custom profile needs to recreate and maintain all of the functionality that might already be available in a distributions profile.

I understand that there are technical challenges to profile inheritance, but I think the functionality is critical.

jonathanshaw’s picture

@sylus #369 issues with things being alphabetically sensitive were also noted in #332 - 334, albeit in what looks like a slightly different context. I wonder if there's a link.

@balsama #370 thanks for laying out the top level case. Do you think that's adequate to respond to @dawehner's fundamental concerns in #324? If yes, perhaps it'd be good to update the IS with your arguments addressing those concerns.

sylus’s picture

Ah thanks I took a read at that particular comment and looks close to what I am experiencing, although according to #334 it was noted their problem was due to features which mine is not.

The good news is this bug should be fairly reproducible (Scenario 3 @ #369) so if anyone has any ideas it would be greatly appreciated :)

Shawn DeArmond’s picture

I just want to echo @balsama's comment #370. The University of California is relying heavily on this functionality in order to provide inheritable install profiles for campuses, while still standardizing on a consistent set of functionality and initial installation state.

This patch does just what we need, and it's already being put to the test.

We spent weeks evaluating other methods, including separate modules, and only the profile-inheritance model works for our use case.

sylus’s picture

Just thought I would mention that am in complete agreement with @balsama et al that the profile inheritance is the way to go to manage complex dependencies.

For the Government of Canada we leverage Lightning extended by the WxT distribution which provides our common look and feel etc that all goc sites need. Then on a departmental level we extend the WxT distro say with our customized STC (Statistics Canada) distro and so on for each department.

We currently have about quite a few sites almost ready to go out including Open Data. So needless to say this functionality is really important to us.

sun’s picture

Hi everyone! ❤️

I listened to the recording of the Core Conversation from DrupalCon Vienna. Some valid points in there. But I do not agree with some of the conclusions drawn there.

Before we dive into further details: The current patch and proposed solution contains support for "excluding" extensions, which were originally marked as required in a parent profile. Not sure why that was introduced as a hidden gem here, but it should be reverted (and moved into a separate issue, if need be, but chances for that to happen are very low). That part of the proposal violates the ideas of (1) security, (2) stability, (3) clear responsibilities, and (4) separation of concerns. So let's remove this part from the patch and the discussion, please.

The fundamental idea of inheritance is aggregation of requirements. That is what this issue and the proposed solution was originally about. It is very comparable to theme inheritance, which follows the same principles of inheriting requirements from a parent theme into a child theme. It is pretty hard to undo something a parent theme has set up – and it should be – because the whole point is that you want to use the parent theme's composition, configuration, and overall setup as a base for your own theme, including updates, upgrades, and upstream changes. If that isn't in line with your thinking, then you'd copy/fork the parent theme instead; simple as that.

If this model follows themes, do we happen to have the necessary inheritance mechanisms for dependencies and configuration already? Yes, we do.

It is indeed about composition. But the composition is not optional.

Modules are optional by design, so they are not a sufficient replacement. The mechanism at play here is a bigger one. Install profiles define the functionality and the final configuration of a Drupal site. Drupal's extension system needs to be aware of the necessary order / layering.

Here's a very concrete and typical use-case scenario that is required to drive the open-source development of distributions:

  1. I'm using Drupal for my projects, because it is a solid content management framework well suited for the goals of my clients.

    🔻

  2. I'm using the Thunder distribution for my projects, because it is well aligned with the goals of my clients.

    🔻

  3. I need to build custom features on top of Thunder, so I need to create my own, common install profile My Distro for all of my clients.

    Everything I develop in here has a good chance to be contributed back into the base distro Thunder at some point, but until that happens, I need to keep the code for my common base distro managed and maintained, including upstream changes from Thunder.

    🔻

  4. For each of my customers, I need a Customer Distro, in order to be able to override configuration (at minimum API keys, but typically more) and add modules implemented specifically for the customer, not shared with others in my common base distro.

    The customer's in-house developers will add new features here, and they might be contributed one level up at some point, but until that happens, they need to keep the custom and final code for their site managed and maintained – in the same way my common base distro can be installed and maintained independently, and in the same way Thunder can be installed and maintained independently.

    🎉

The business requirement is that the customer's site can be installed with the last layer. And installing that is all I need to do to achieve the defined state, including all modules, dependencies, and dependencies of dependencies, and their final, aggregated configuration.

This common scenario results in a dependency chain:

Customer Distro > My Agency Distro > Thunder > Drupal Core

Add to the mix that Thunder uses a custom composer.json for composition already. Composer does not really seem to have a concept for wrapping a type:project (Thunder) into a type:project (My Distro) at this point in time and likely will not in the foreseeable future.

I can use config_split for some of this. But config_split is about configuration only, not code. Everything I litter into the epic junks of config bins equals a trash bin most of the time – not thought through, individual solutions, not prepared at all for being contributed upstream (regardless of whether my private common base distro or a public one like Thunder). So this might work on a per-project basis, but it blocks and damages the ecosystem of distros that we're after.

Fun fact:

Internally, the Extension system treats the install profile like a module already. In fact, the install profile is registered as a module. "Inheritance" for install profiles just simply acts like "dependencies" for modules: In essence, it just ensures that profile A exists and is installed before profile B.

And that's literally all we should be shooting for here: Extending profile A with profile B. Just (1) extending its dependencies and (2) extending or overriding its configuration.

Anything else on top of that (blacklisting, reversing, muting, undoing, …) is not core material. — It's in the spirit of the Drupal Community to collaborate on different use-cases and conflicts instead. It's perfectly possible that some distros should be reduced to a smaller baseline, which is extended with a more focused profile, so that others are able to choose to use the uncontroversial baseline only. That kind of collaboration is the actual (massive) work of distro maintainers – for any single topic there are lots of ready solutions to choose from anyway today already.

Therefore, this issue (still) resolves a very common and highly relevant problem that blocks the entire Drupal ecosystem from evolving into its next phase of existence. Resolving issues like this truly unblocks Drupal's future. As a community, we need to resolve them as soon as possible in order to stay relevant in our markets.

segovia94’s picture

My concern with removing excluded_dependencies and excluded_themes is that those are extremely valuable in real-life scenarios. For example, in D7 we used Panopoly as a base profile. We needed our own specific implementation of the Ckeditor wysiwyg so did not want to include the module dependency to panopoly_wysiwyg. Also, we didn't need the overhead of panopoly_search. By allowing subprofiles to exclude module/theme dependencies it gives greater flexibility to subprofiles to not have to find strange workarounds to remove modules that have no application in their specific use case.

Another example is if a parent profile has a specific module that loads in default content. This is important for doing demos, but in my client's project I want that excluded since it has no application to what I'm building. A distro may want "required" modules like that on install for that distro alone, but it's not actually required in my distro even though I'm using it the other as a base profile.

DamienMcKenna’s picture

So we have two key pieces here:

  1. Logic to handle inherit installation profiles, so one builds upon another. Like Sun says in #375, this makes the installation profiles work the same as many other subsystems so is a logic fit.
  2. Functionality to allow some configuration to be excluded.

Sun's comment brings up a very good point that this issue should focus on its basic goals - profile inheritance. Why don't we work on getting this part to RTBC and committed, and split off the secondary functionality into its own issue? We have the benefit of code already having working code. :)

jonathanshaw’s picture

Priority: Normal » Major

@DamienMcKenna #377 Agreed. Most use cases discussed emphasise they want to rely on a distro; excluding from it seems like a less common use case.

I tentatively created #2914389: Allow profiles to exclude dependencies of their parent to discuss that aspect separately.

In which case the outstanding tasks here seem to include:

  1. Rework patch from #360 to remove excluding
  2. Overriding config from a parent distro seems still in scope for this issue; but according to #358 that doesn't work yet with the current patch
  3. This may or may not be the same problem as that listed in #328-9 and #332-334. To help move that forward we need and a confirmation whether it still happens even if the features module is not in use, and then revised replication steps for #332, preferably with a zip of the necessary files.
  4. Installation fails if the install profile has a name that is alphabetically prior to the name of the base distro #369
  5. Code cleanups outstanding from #356
  6. Extraneous profiles/distro are selectable during installation #331
  7. The installer theme should be the distribution one from the beginning #331

Upgraded to major following Dries' references to this issue and @sun #375:

this issue resolves a very common and highly relevant problem that blocks the entire Drupal ecosystem from evolving into its next phase of existence.

balsama’s picture

Excellent. Huge thanks to @sun for explaining the need so eloquently. I think excluding dependencies is important, but if removing that from this issue helps get it back on track, I'm all for it.

One thing to clarify is that dependencies of profiles are currently treated as exceptions in that you can actually uninstall them - unlike dependencies of modules. I think we should maintain that functionality for parent profiles. So that if I extend Standard with a sub-profile, for example, I can still uninstall Database Logging. Just want to make sure that's not lost when we drop support for excluded dependencies.

dsnopek’s picture

For example, in D7 we used Panopoly as a base profile. We needed our own specific implementation of the Ckeditor wysiwyg so did not want to include the module dependency to panopoly_wysiwyg. Also, we didn't need the overhead of panopoly_search. By allowing subprofiles to exclude module/theme dependencies it gives greater flexibility to subprofiles to not have to find strange workarounds to remove modules that have no application in their specific use case.

This is pretty tangential, but Panoploy in D7 has a solution to this problem! We've worked very hard to make Panopoly be a sum of its modules, with the profile just putting some standalone defaults that would be useful if you were a site builder looking to use Panopoly as you would Drupal core. To build a child distribution, you build a .make file which includes all the Panopoly modules (optionally excluding those you don't need), essentially creating a whole new profile with no idea of inheritance.

While this inheritance patch is super cool, and I'd love to have it as a way (not the way) to extend Panopoly, we're still going to try to make the profile be the sum of it's modules and decouple them as much as possible, so the "old way" is still an option for those looking to exclude stuff (except now you'd probably use composer.json and not a .make file). This is important because excluding in the old way will keep the unnecessary code out of the child distro, and that includes not just, say, panopoly_wysiwyg, but also its dependencies (ie. TinyMCE, etc). If you just exclude via the exclude_modules feature, you're still stuck with TInyMCE being in your codebase, even if you never use. That could be a security risk (stray JS/HTML files), a support risk (say a user turns it on!) and just plain makes the tarball bigger for no reason. :-)

So, we're going to continue to support the old way whether the exclude functionality in this patch gets merged or not, because even if it does, it's still valuable in some cases to do it the old way.

Ok, end of tangent :-)

mlncn’s picture

As segovia94 says, in most any real-world situations flexibility to override is crucial, and indeed this patch is working and is being used in real-world situations where there is extremely close collaboration between distribution maintainers but the capabilities in this patch are still needed.

Forcing collaboration through artificial technical constraints is not a principle of Drupal.

Please let's let this proven-through-use patch get into core without another refactoring.

frob’s picture

@mlncn I don't think this will get into core without refactoring out the above mentioned controversial features. Let's get this core functionality into core and then tackle refining additional features in future issues.

@balsama how does that uninstallation affect upstream updates? My thought would be that if a base-profile provides too much functionallity then the base-profile should be refined to a use generic base-profile. Currently standard was built without this idea in mind at all, maybe a part of this patch should be the creation of a sub-standard base-profile that acts as the generic that our profile's can depend on and also modify standard to use sub-standard as base as well.

I understand sub-standard is not a great name, but I am just using it as an example.

mpotter’s picture

The problem here is that the dependencies in the profile.info.yml aren't really just "dependencies". It is also a list of default functionality to be enabled at install time. With a proper configuration management workflow (installing a profile via config), this list of "enabled modules" can be properly moved into core.extensions.yml config and taken out of the profiles info.yml.

As long as the dependencies in the profile info.yml are used for "optional" but "default" functionality, we need the ability to exclude them.

In the core Standard profile, "dblog" is a great example of this. It's not really a true "dependency", it just gets enabled as default functionality. And most sites later disable this on production anyway. That is why there is special-case code throughout core to allow dependencies of profiles to be uninstalled without uninstalling the root profile.

In the DrupalCon video linked in #368 it mentioned "white listing" instead of "black listing" and I would be all for that. But that will require Lightning to re-architect itself to put functionality such as lightning_media, lightning_layout, etc into real modules on drupal.org that we could then list in our composer.json, (dependent on some lightning_core module). Let composer handle the dependency issues. But composer still just addresses the build manifest. It downloads the code for modules but isn't responsible for which modules to enable.

A real installed site is really the combination of the downloaded modules (composer) AND the configuration of the site. This "list of enabled modules" is part of the config. So when we talk about "excluding dependencies" what we are REALLY talking about is "overriding config". It might not just be the list of enabled modules, but perhaps some other config provided by the base profile or some module. The child profile needs to be able to override any of that config, including core.extensions.yml.

If we had the ability to install profiles via config (see #2788777) and then if Lightning was just a module (or set of composer requires) and not a profile, then we wouldn't need inherited profiles. But each client site we build is based on a profile for that client (composer.json + config) so if we wanted to include functionality from Lightning without inherited profiles, then Lightning couldn't be a profile itself. If the Lightning wanted to be able to update certain config, it could put that into another module (like lightning_config) that had the update hooks or config-actions to do that. Sites that didn't want automatically updated config just wouldn't use that lightning_config module.

Sorry if this got a bit off-track. But maybe it becomes more important to get something like 2788777 into core first and then see if we still need inherited profiles. Until then, I have to continue using this patch (#360) for all my client sites with Lightning because that's the only way we can currently deliver the Drupal solutions our clients need.

balsama’s picture

I talked this over with @phenaproxima and he had a good idea about solving this problem by essentially generating a list of modules to be installed based on the "base profile" key, but not actually installing any parent profiles.

A quick discussion led me to believe that that might be a more sustainable approach that still accomplishes what we're looking for in this issue.

That said, I think that approach probably deserves its own issue. And in the interest of moving this issue forward, here is a patch which removes the the ability to exclude parent profile dependencies.

balsama’s picture

Here's a patch created from the correct repo (drupal/drupal, not drupal/core) plus an interdiff from 360.

balsama’s picture

Status: Needs work » Needs review

Here's a patch created from the correct repo (drupal/drupal, not drupal/core) plus an interdiff from 360.

balsama’s picture

Status: Needs work » Needs review
FileSize
58.96 KB
10.2 KB
1.64 KB

This should fix the remaining test.

Shawn DeArmond’s picture

but not actually installing any parent profiles

What exactly do you mean by this? Functionally, what's the difference?

kreynen’s picture

a patch which removes the the ability to exclude parent profile dependencies

I am really glad to see this going back in this direction. I've always considered the use case for an install profile that is designed to be used as a base AND work well on its own to be questionable. To me, this would be like using the Zen or Omega base themes without a sub-theme. Technically you can do this, but it isn't going to look very good since that's not what a base theme is supposed to be doing.

@Shawn DeArmond I think it means that the .profile of the base (or .profiles if you are using a child of a base as your base) won't actually be enabled so the child would need to copy any hooks in the base including installs, but I've just started to test this. hook_install and hook_update_n at every level of the base/child relationship is being picked up, which is good, but I think that if you did something like build a child profile for a school that uses OpenEdu, none of the hooks in http://cgit.drupalcode.org/openedu/tree/openedu.profile or http://cgit.drupalcode.org/lightning/tree/lightning.profile would be available... but since these are designed as base profiles there are no hooks at that level.

So https://github.com/ucdavis/sitefarm_seed/blob/8.x-1.x/sitefarm_seed.profile would still work if sitefarm_seed was the child, but it wouldn't if someone else wanted to use lightning->sitefarm_seed->custom_child

This makes sense to me since sitefarm_seed isn't being designed or maintained as a base profile. Again, someone could still technically get this to work by copying the hooks from an unintended base profile.

segovia94’s picture

@kreynen just to clarify, sitefarm_seed is a base profile and is never intended to be installed on its own. This is why anything in the .profile folder has already been abstracted into a service so that what happens in hooks can be reused in a child profile. I believe @Shawn DeArmond's concern is that items in the base profile like that service (which is not in a module) are still registered along with config that is in the base profile and not in a module.

Shawn DeArmond’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

We have been running extensive Behat tests against this patch for 6 months on our SiteFarm Seed base profile.

In July, we conducted a 2-week R&D sprint evaluating all aspects of this patch, and its viability for our SiteFarm project. We answered many questions as to the usability and extensibility of the profile inheritance system and are confident that it is flexible and robust.

After adjusting our tests to account for Drupal 8.4's interface changes, I'm pleased to say that we have all behat tests passing for patch #389. Tests consist of 146 scenarios and 1,765 steps. (View Pull Request)

oriol_e9g’s picture

I'm with @Shawn DeArmond to commit this because we cannot continue managing this feature in a issue with 400 comments.

We have a minimum patch in #389 that works, do the basic trick, is tested and all controversial features are out and can be managed and discussed in follow ups.

DamienMcKenna’s picture

Seems like the patch maybe needs a reroll?

DamienMcKenna’s picture

Status: Needs work » Needs review
FileSize
58.95 KB

Rerolled against 8.5.x.

DamienMcKenna’s picture

FYI the only difference between 389 and 397 is that core/modules/config/src/Tests/ConfigImportInstallProfileTest.php was converted to browser tests and moved to core/modules/config/tests/src/Functional/ConfigImportInstallProfileTest.php.

oriol_e9g’s picture

Status: Needs review » Reviewed & tested by the community

#397 it's only a reroll of #389 I think that we are still RTBC

jonathanshaw’s picture

Status: Reviewed & tested by the community » Needs work

Can it really be RTBC if no one has confirmed that the bugs listed in #378 have been addressed (or never existed)?

Shawn DeArmond’s picture

Commenting on points raised in #378:

  1. Rework patch from #360 to remove excluding
    Done
  2. Overriding config from a parent distro seems still in scope for this issue; but according to #358 that doesn't work yet with the current patch
    Thoroughly tested
  3. This may or may not be the same problem as that listed in #328-9 and #332-334. To help move that forward we need and a confirmation whether it still happens even if the features module is not in use, and then revised replication steps for #332, preferably with a zip of the necessary files.
    Config overrides don't work at all if a module is not a Feature. With or without this patch. Features issue has been filed with a link to a testing repo
  4. Installation fails if the install profile has a name that is alphabetically prior to the name of the base distro #369
    I have confirmed that this is not an issue. I created a subprofile with a name alphabetically prior to the base profile, and included a number of config .yml files to override, and it worked fine.
  5. Code cleanups outstanding from #356
    I think the only piece of this left to address is #349.3 and #349.7. (Re: #349.5, I would argue that the wrapper is unnecessary.)
  6. Extraneous profiles/distro are selectable during installation #331
    Now that there are sub-profiles, there could be multiple profile options, so I would argue that all should be displayed. In any case, any additional functionality in this realm can be its own issue.
  7. The installer theme should be the distribution one from the beginning #331
    It's probably desirable that a subprofile will show the base profile theme from the beginning, but in the interest of getting this path committed, I'd say it's fine now. If you want that functionality, open a new issue.

Anyone want to look at #349.3 and #349.7?

kreynen’s picture

Now that there are sub-profiles, there could be multiple profile options, so I would argue that all should be displayed. In any case, any additional functionality in this realm can be its own issue.

Are you saying we should see the sub and base or multiple subs?

We're testing with https://www.drupal.org/project/express/releases/8.x-1.x-dev with a sub-profile packaged in the parent project on Drupal.org if anyone is interested in following along. This works as expected with only Demo Express showing up in the install UI. The Express base is not displayed, but if I add ucb_express as an additional sub profile of Express it does show up.

We're experimenting with maintaining a single express base profile and ucb_express as a sub-profile for the University of Colorado Boulder. Other CU campuses maintain their own sub-profiles. but rather than maintain 4 or 5 upstreams on a hosting provider like Pantheon, we'd rather maintain 1 and combine all public sub-profiles of Express in a build process for the drop repo.

We did test asking for a theme that didn't exist in http://cgit.drupalcode.org/express/commit/demo_express/demo_express.info.... That errors with...

InvalidArgumentException: Unknown themes: demo_express. in Drupal\Core\Extension\ThemeInstaller->install() (line 114 of core/lib/Drupal/Core/Extension/ThemeInstaller.php).

So not as user-friendly as...

Configuration objects provided by <em class="placeholder">ucb_express</em> have unmet dependencies: <em

... but still gets the job done.

Shawn DeArmond’s picture

Thanks, @kreynen, for the extra testing!

Are you saying we should see the sub and base or multiple subs?

At this point, I think we're saying "all". So, multiple subs, base(s), single(s), etc. Which is the current behavior in this patch.

That being said, I can imagine a situation where, like sitefarm_seed, the base profile is not intended to be installed on its own, so perhaps including a flag in the .info.yml file to hide it from the interface could be helpful.

But I really don't want to go there now. That can be another feature request after this patch is committed.

frob’s picture

What changes need to be made to the documentation once thing things gets committed. I have been following this for a while but I stopped reviewing a while ago, unfortunately I cannot write the changes to the docs.

I think we should open a new issue for the documentation after this is committed. We can have the docs update when the tag for the release this is in gets published.

DamienMcKenna’s picture

Now that there are sub-profiles, there could be multiple profile options, so I would argue that all should be displayed. In any case, any additional functionality in this realm can be its own issue.

If we're following the UX of the theme system, which displays all available themes, regardless of whether other themes inherit from it, then yes, all profiles should be available unless something else overrides this.

The remaining items are:
#394.3

+++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
@@ -0,0 +1,79 @@
+  /**
+   * Stores info data for a profile.
+   *
+   * This can be used in situations where the info cache needs to be changed
+   * This is used for testing.
+   *
+   * @param string $profile
+   *  The name of profile.
+   * @param array $info
+   *   The info array to be set.
+   *
+   * @see install_profile_info()
+   */
+  public function setProfileInfo($profile, array $info);

If this is a testing-only method, it should definitely not be part of the interface. It could be part of ProfileHandler (or better yet, a test-only subclass of ProfileHandler), but not the interface.

#394.7

+++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php
@@ -0,0 +1,79 @@
+   * @param string[] $profile_list
+   *   List of profile names to search.

Couldn't this parameter be optional, and if not passed, it calls $this->getProfiles() -- or whatever getProfiles() will be renamed to -- to get the profile list? It might make for cleaner DX.

jonathanshaw’s picture

@catch said in #235 that this needs a change record. A CR was started at [#2907148] but it is only a stub.

kreynen’s picture

I think the state I was seeing in #402 was because the base was missing a dependency at that point. In that scenario, the sub-profiles are still listed as options in the UI. If a user selects a sub-profile, the install will fail.

I'm not sure what the correct behavior is, but this doesn't seem like it.

While @DamienMcKenna suggested we follow the UX of base/sub themes, without #474684: Allow themes to declare dependencies on modules themes don't have to deal with unmet dependencies beyond the dependency of the sub on the base. I would like to hide the base from users in the UX, but we can just make it clear users should never use Express alone in the profile's description and deal with an option to hide base profiles from the user in another issue.

I do think this should be updated so that if the dependencies of a base aren't met, users aren't able to select a sub-profile that uses that base.

phenaproxima’s picture

This is a reroll of #360 against 8.4.x. So, you know, don't use it unless you're on 8.4.x and you want the functionality in #360. :)

eric.chenchao’s picture

It seems the patch on #408 has already been applied to Drupal 8.4.3.

balsama’s picture

@eric.chenchao - I don't think it's been applied - but it will no longer apply because of other changes. You can use the patch here for 8.4.3 if you need it: https://www.drupal.org/files/issues/1356276-408--8.4.3.patch

thomscode’s picture

Reattaching the 8.4.3 patch so it shows up in the file listing

sun’s picture

  1. +++ b/core/includes/install.inc
    @@ -1043,6 +1043,14 @@ function drupal_check_module($module) {
    + * - base profile: Existence of this key denotes that the installation profile
    + *   depends on a parent installation profile.
    + *   - name: The shortname of the base installation profile.
    + *   - excluded_dependencies: An array of shortnames of other modules that have
    + *     to be excluded from the base profile requirements. This allows e.g. to
    + *     disable a demo module that would be installed by the base profile.
    + *   If there are no excluded_dependencies, a shortcut of "base profile: name"
    + *   can be used.
    

    excluded_dependencies are still mentioned in the code documentation and should be removed as well now, no?

    If there will be an exclusion feature in the future, then I don't think it will be specific to a particular parent, because you want to exclude something from the sum of all profiles. And given that there can only be one parent profile with this revised declaration format, there's no point in having the exclusions as a subkey in the first place. Therefore we should turn base profile into a single string key without subkeys, do you agree?

    That said, this new declaration format does not support "mixins" anymore; i.e., collecting macro-features from multiple parent (peer) profiles. Are we okay with losing that option?

  2. +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
    @@ -81,14 +89,17 @@ class ConfigInstaller implements ConfigInstallerInterface {
    +    $this->profileHandler = $profile_handler ?: \Drupal::service('profile_handler');
    
    +++ b/core/lib/Drupal/Core/Config/InstallStorage.php
    @@ -56,9 +64,14 @@ class InstallStorage extends FileStorage {
    +    if (\Drupal::hasService('profile_handler')) {
    +      $this->profileHandler = $profile_handler ?: \Drupal::service('profile_handler');
    +    }
    

    Looks like the dependency is not always injected from all callers - the calling code should be fixed instead, right?

  3. +++ b/core/lib/Drupal/Core/Extension/FallbackProfileHandler.php
    @@ -0,0 +1,77 @@
    +/**
    + * Implementation of the profile handler usable before any working system.
    + */
    +class FallbackProfileHandler implements ProfileHandlerInterface {
    

    The class level docs should explain how the class operates in the case of not having "any working system".

    What's the difference to regular runtime operations? Under which circumstances should it be used?

    Or is the implementation for a single purpose and doesn't make sense in other situations? In case it is, it can probably be named accordingly; e.g., "ContainerlessProfileHandler" or similar (I'm sure we have names for this elsewhere already)

  4. +++ b/core/profiles/testing_inherited/testing_inherited.info.yml
    @@ -0,0 +1,21 @@
    +  excluded_dependencies:
    +    - page_cache
    +  excluded_themes:
    +    - classy
    

    Some more code relating to the former "excluded" feature here.

DamienMcKenna’s picture

DamienMcKenna’s picture

Rerolled specifically for 8.4.3.

bircher’s picture

I like the direction this is going in. Thanks @sun.
I added #820054: Add support for recommends[] and fix install profile dependency special casing as a related issue. Since basically profiles now abuse the "dependency" which is not really a dependency. We then also need to also get away from expecting the install hook to have access to all the modules being installed which are not real dependencies. Both of these things would significantly help also with the re-installing a site from existing configuration.

scor’s picture

Status: Needs work » Needs review
FileSize
61.26 KB

rerolling against 8.5.x branch.

pingers’s picture

Re-rolled for 8.4.4.

owenpm3’s picture

Are these install profiles supposed to be showing up in the list of modules? They seem to be doing just that on all my test sites.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dpagini’s picture

Just trying to re-upload #417 with a new name to get the tests to run and not see the "Patch validation error" message. I applied this to my project moving to 8.5 today, and this patch worked for me.

jonathanshaw’s picture

Issue tags: +Needs reroll

needs reroll for 8.6?

mohit1604’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
27.96 KB

Rerolled, please review:)

mohit1604’s picture

Status: Needs work » Needs review
FileSize
28.14 KB

Fixing CS errors.

balsama’s picture

It looks like all the patches after #397 are rerolls. So here is a reroll of #397 against 8.6.x. Once we get this passing again, we can start addressing the feedback in #405 and #412 and work an Issue Summary that accurately reflects the 400+ comments :)

balsama’s picture

Status: Needs work » Needs review
balsama’s picture

Status: Needs work » Needs review
FileSize
62.03 KB

This converts the ConfigImportBaseInstallProfileTest previously included in this patch to PHPUnit and makes the patch compatible with the new ExtensionList service in 8.6.x.

phenaproxima’s picture

I re-read @balsama's comment in #370 and @sun's in #375, plus some of the surrounding discussion, and I'd like to make a suggestion: let's postpone this on #2952888: Allow install profiles to require modules.

Don't throw tomatoes at me just yet: I suggest this because #2952888: Allow install profiles to require modules allows profiles to explicitly define two groups of extensions: the actual hard dependencies of the profile, and the "optional" dependencies that comprise the profile's out-of-the-box functionality.

This simple change solves several problems related to this issue, specifically the dependency exclusion stuff. It means that the hard dependencies of the parent profiles can be maintained, and the soft dependencies (i.e., stuff to install that is not needed in order for the profile to function properly) can be massaged and excluded by sub-profiles. Everyone goes home happy.

Thoughts?

phenaproxima’s picture

Re-posted #434 at #2914389-4: Allow profiles to exclude dependencies of their parent, because I realized in discussion with @balsama that it's out of scope of this issue.

My understanding, then, is that all we're trying to accomplish in this patch is allowing a profile to load extensions from other profile directories, not just the installed profile. Is that correct? If so, I think we need to improve the IS to make this clearer, and re-title the issue.

balsama’s picture

all we're trying to accomplish in this patch is allowing a profile to load extensions from other profile directories

That's not entirely true. That's more of a required side effect than the goal.

Let's work on better summarizing in the IS, but basically:

  1. Allow profile's to define a parent (which may have ancestors)
  2. Install profile dependencies from all ancestors and the active profile

Since profile dependencies may live inside the profile directory, #2 requires that we be able to load extensions from other profile directories. But it's not the goal.

phenaproxima’s picture

Issue tags: +Needs title update

Okay, that makes sense. I'm also tagging the issue for re-titling, for clarity.

phenaproxima’s picture

I began reviewing the patch again but I stopped when I had a fairly major question.

  1. +++ b/core/core.services.yml
    @@ -507,10 +507,10 @@ services:
    -    arguments: ['@app.root', 'module', '@cache.default', '@info_parser', '@module_handler', '@state', '@config.factory', '@extension.list.profile', '%install_profile%', '%container.modules%']
    +    arguments: ['@app.root', 'module', '@cache.default', '@info_parser', '@module_handler', '@state', '@config.factory', '@profile_handler' ,'@extension.list.profile', '%install_profile%', '%container.modules%']
    

    Nit: This looks like the argument order was scrambled a bit, which makes these lines hard to compare. Can we keep this as close as possible to the previous order (i.e., put the profile handler at the end of the list)?

  2. +++ b/core/includes/install.core.inc
    @@ -453,6 +453,12 @@ function install_begin_request($class_loader, &$install_state) {
    +    $profile_directories = array_map(function($extension) {
    +      return $extension->getPath();
    +    }, $profiles);
    

    For sanity checking's state, can the $extension argument be type hinted?

  3. +++ b/core/includes/install.core.inc
    @@ -1581,7 +1586,10 @@ function install_profile_themes(&$install_state) {
    +  // Install all the profiles.
    +  $profiles = \Drupal::service('profile_handler')->getProfileInheritance();
    +  \Drupal::service('module_installer')->install(array_keys($profiles), FALSE);
    

    This might be a naive question, but why do we need the 'base profile' key, or any inheritance-specific API stuff? Couldn't we simply list the base profile as a normal dependency of the child profile, and take advantage of the existing dependency system? This would reduce API surface and make this patch easier to review, test, and grok.

    I do realize that we need to be able to determine the profile directories from which to load extensions, but we could still do that by comparing the list of profile dependencies with the list of profiles returned by the extension.list.profile service.

gr8tkicks’s picture

@phenaproxima Regarding your concept of just requiring the base profile as a dependency of the children, is there anything we lose by doing that? It sounds like functionally they would be the same. I mean if someone doesn't include then dependency then, it is its own profile more or less. Anyone else have comments here?

phenaproxima’s picture

I discussed this on Slack with @dawehner and we came to a couple of conclusions.

First, I don't think using the normal dependency system is going to work, because that would imply the possibility of a profile having multiple "parents". This could lead to a lot of insanity, e.g. config conflicts. If a profile inherits from two parents, and both provide the same piece of config, which parent's config will "win"? There's no real way to resolve that. So we need to enforce single inheritance, which is what the "base profile" key already does.

Secondly, @dawehner pointed out that a lot of what the profile handler does, could be done by the new extension.list.profile service that was added to 8.6.x. So if we can reduce the size of the profile handler, or remove it entirely in favor of extension.list.profile, that would be favorable.

phenaproxima’s picture

Let's see if this flies.

I refactored the patch on top of extension.list.profile. I was able to completely remove the profile handler and greatly reduce the API surface of the patch, which I hope will be very pleasing to both the committers and the extension system maintainers. (It should also please reviewers, since the patch is now 10 KB lighter!) The tests passed locally for me, but I expect a fair number of failures on Drupal CI.

phenaproxima’s picture

In a move that I suspect will be controversial...I believe I can fix most of the failures in #443 if KernelTestBase has a $profile property (much like BrowserTestBase does), which is used to set the install_profile container parameter.

The smart money says this will fail Drupal CI too, but not as hard as #441.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
52.96 KB
3.21 KB

Let's see how this does.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
51.97 KB
2.43 KB

Okay, let's see here.

I had to undo the change to KernelTestBase that I made in #443; it looks there are several tests which depend on no profile being known in KernelTestBase. I also backed off the change to ExtensionList, since that broke at least one test which did not expect to read information for uninstalled extensions.

This may fail pretty hard, but fingers crossed...

hasmimeraj’s picture

Hi,

i am using lightening with drupal 8.2.8. i have one custom profile which extend lightening 8.x-1.5. recently i updated drupal core to 8.3.9 and after that when i try to install my profile, it does not load base profile lightening.

scenario:

My custom profile has some module dependency. And these modules are part of lightening(profile/contrib/lightening/modules). So when i install my custom profile it does not find dependent module which is part of lightening. so i am unable to install my profile.

kreynen’s picture

@hasmimeraj, @phenaproxima has already replied in #2961418: Module not loading from lightening. Please keep issues specific to Lightning's support for subprofiles in that project's queue.

DamienMcKenna’s picture

A reroll of #426 against the current 8.5.x codebase, for anyone who needs it.

DamienMcKenna’s picture

Status: Needs work » Needs review
gr8tkicks’s picture

Doesn't seem like there is a working patch for 8.5.2 or 8.5.3, still getting

You have requested a non-existent service "profile_handler"

error message during install. I wish we could get this into core soon, so we can stop dealing with these patches.

UPDATE 1
Another person within the UC is also trying to use subprofiles... seems like he used a different patch https://www.drupal.org/files/issues/2018-04-17/drupal-n1356276-450-85x.p...

His failure was slightly different:

ReflectionException: Class Drupal\Core\Extension\ProfileHandler does not exist in ReflectionClass->__construct() (line 1157 of /vendor/symfony/dependency-injection/ContainerBuilder.php).

UPDATE 2
Looks like after removing several of the patches for this issue "Allow profiles to provide a base/parent profile" and then only relying on the patch provided in the modules/contrib/lightning_core/composer.json file (if you are using Lightning), then the patch does seem to apply okay, and without error.

"drupal/core": {
   "1356276 - Allow profiles to provide a base/parent profile and load them in the correct order":
   "https://www.drupal.org/files/issues/1356278-408--8.5.x-real.patch"

However, I don't have a good test suite to ensure the sub-profiles are behaving correctly. Does anyone have a way to test that peace?

jonathanshaw’s picture

Title: Allow profiles to provide a base/parent profile and load them in the correct order » Allow profiles to define a base/parent profile and load them in the correct order
Status: Needs review » Needs work

AFAIK we are NW for #405, #412, 1 test failure in #446, change record and issue summary update.

frob’s picture

Issue summary: View changes

Updated IS

nevergone’s picture

And now? :S

frob’s picture

@nevergone, I don't understand the question.

ricovandevin’s picture

The patches from #426 and #450 contain code that tries to create an instance of the non-existing class FallbackProfileHandler that was present in earlier versions of the patch.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
50.19 KB

Rerolled #446 for 8.6.x. Let's see how many tests break.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
49.25 KB
4.77 KB

Adjusted the patch to account for the changes in #2952888: Allow install profiles to require modules, which cleanly separated the concept of "dependencies" from "stuff to install". Hopefully this guy passes tests.

phenaproxima’s picture

I changed some of the logic in ProfileExtensionList::doList() to which should fix a couple of flaws I discovered in the exclusion patch, and streamlined the code flow.

EDIT: I don't know how the hell that test got changed. If it fails, I'll reroll it without that.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
49.48 KB
3.17 KB

Let's try that again.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
49.48 KB
623 bytes

One damn character.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
49.48 KB
589 bytes

That's embarrassing.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
50.22 KB
837 bytes

Not proud of this hack (it makes all profile ancestors into hard dependencies, which kind sucks), but let's see if this helps...

phenaproxima’s picture

Re-rolled against 8.6.x.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
48.97 KB
1.13 KB

This should fix that.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dwkitchen’s picture

Status: Needs review » Needs work

Lots of great work going on here, happy to see #2914389 out of scope for this issue.

I am running through upgrades to 8.6 core and the latest patch here.

I am back to the same issue I had in https://www.drupal.org/node/1356276#comment-11808273 for themes.

 [ERROR] Configuration objects provided by <em class="placeholder">jnjos</em> have unmet dependencies: <em              
         class="placeholder">block.block.stark_admin (stark)</em>     

I have stark theme in info file for both parent and child profiles, but I guess it is to do with the order that config is being installed and enabling themes.

metalbote’s picture

I encounter a similar error:

Drupal\Core\Config\UnmetDependenciesException: Configuration objects provided by varbase have unmet dependencies: block_content.type.basic (block_content), core.entity_form_display.block_content.basic.default (text), core.entity_view_mode.block.token (block), features.bundle.varbase (features), field.field.block_content.basic.body (field.storage.block_content.body, text), field.storage.block_content.field_image (block_content, media), field.storage.node.field_categories (node, taxonomy), [...snip...] in Drupal\Core\Config\UnmetDependenciesException::create() (line 98 of /app/web/core/lib/Drupal/Core/Config/UnmetDependenciesException.php).

I installed 8.6.0-rc1 with the patch 1356276-473.

As dwkitchen I suspect an error in the order the configuration is imported, but this does not seem to be limited to themes alone. My subprofile is alphabetical before my base profile.

EDIT: Changing the alphabetica order by renaming my subprofile does NOT solve the problem.

EDIT2: I have to revise my statement (xdebug now runs correctly :-) ), it is also a theme that causes the error. This is a theme that is requested in base_profile.info.yml, especially the block configuration has unmet dependencies.

EDIT3: After further investigations I have noticed that the base profile (in my case varbase) is already installed in position 13 in the "install profile modules" task. This is long before modules like block, taxonomy etc. Therefore block configurations cannot be import and the installation dies with the unmetdependencies error. I have tried to understand myself through the installation process and how this batch comes about, but I'm stuck with the little free time I have. Where is the order of the modules defined? I've read that it depends on dependencies, and otherwise random, but can't find the right place in the code.

Rajab Natshah’s picture

I confirm the issue with sub profiles on Drupal 8.6.x
1356276-473.patch

Testing other re-rolled patches from
1356276-461.patch

I have checked what the Lightning team did in Lightning core

"1356276 - Allow profiles to define a base/parent profile and load them in the correct order":
"https://www.drupal.org/files/issues/2018-07-12/1356276-473.patch",
"2914389 - Allow profiles to exclude dependencies of their parent":
"https://www.drupal.org/files/issues/2018-07-09/2914389-8-do-not-test.patch"

Testing if we do have to have the exclude dependencies, not to exclude anything. as it was removed from the latest patch for Drupal 8.6.x
As in the Demo Framework
https://cgit.drupalcode.org/df/tree/df.info.yml?id=ba23158

owenpm3’s picture

So we tried updating our Pantheon upstream with the 1356276-473 patch and ran into errors as well. We're using standard as the base profile and the error comes back as a problem with the configuration files in standard.

We have grandchildren profiles, standard >> profile >> subprofile, and unless we remove those profiles we also get an error immediately on the first page of the install:

Warning: Illegal offset type in Drupal\Core\Extension\ProfileExtensionList->computeAncestry() (line 177 of core/lib/Drupal/Core/Extension/ProfileExtensionList.php). Drupal\Core\Extension\ProfileExtensionList->computeAncestry(Array, Array) (Line: 125)
Drupal\Core\Extension\ProfileExtensionList->doList() (Line: 274)
Drupal\Core\Extension\ExtensionList->getList() (Line: 406)
Drupal\Core\Extension\ExtensionList->recalculateInfo() (Line: 366)
Drupal\Core\Extension\ExtensionList->getAllAvailableInfo() (Line: 30)
Drupal\Core\Extension\ProfileExtensionList->getExtensionInfo('demo_umami') (Line: 1106)
install_profile_info('demo_umami') (Line: 1322)
{closure}(Object)
array_filter(Array, Object) (Line: 1324)
_install_select_profile(Array) (Line: 477)
install_begin_request(Object, Array) (Line: 122)
install_drupal(Object) (Line: 44)

Warning: array_unique() expects parameter 1 to be array, null given in Drupal\Core\Extension\ProfileExtensionList->doList() (line 155 of core/lib/Drupal/Core/Extension/ProfileExtensionList.php).
Drupal\Core\Extension\ProfileExtensionList->doList() (Line: 274)
Drupal\Core\Extension\ExtensionList->getList() (Line: 406)
Drupal\Core\Extension\ExtensionList->recalculateInfo() (Line: 366)
Drupal\Core\Extension\ExtensionList->getAllAvailableInfo() (Line: 30)
Drupal\Core\Extension\ProfileExtensionList->getExtensionInfo('demo_umami') (Line: 1106)
install_profile_info('demo_umami') (Line: 1322)
{closure}(Object)
array_filter(Array, Object) (Line: 1324)
_install_select_profile(Array) (Line: 477)
install_begin_request(Object, Array) (Line: 122)
install_drupal(Object) (Line: 44)

It's not just the Umami demo, but it shows up for all of our install profiles.

drupalninja99’s picture

@metalbote I am having essentially the same issue with my base profile.

drupalninja99’s picture

@RajabNatshah I tried to use 8.6x-dev with same patches as lightning_core and I still get the same kind of config dependency errors as I was getting before.

Rajab Natshah’s picture

Me too - Same issue

metalbote’s picture

As far as I can see, and I'm just at the beginning of learning the drupal core code basis, the problem lies in the generation of the dependency graph. Themes are apparently outside the view, so modules are installed that have dependencies to themes and vice versa at a time when the dependency is not fulfilled. Correctly, the validator then throws the error. Creating the dependency graph is a critical process, but what I don't understand is why themes are treated differently from modules, since both can be dependent on their configuration files.r

frob’s picture

@metalbote, might be worth opening a new issue and postponing this one till the dependency issue is worked out.

dpagini’s picture

Just wondering, does anyone have this patch working on 8.6.0? I'm having trouble upgrading with the latest passing patch, due to the same reasons mentioned above (#476).

frob’s picture

Issue summary: View changes

@dpagini, it sounds like we need another test if the others are passing and this is failing to install.

dpagini’s picture

Ok, I think this patch will demonstrate the error I'm seeing on top of this patch. I had to add a block to the base profile that we're testing in.

So I'm expecting this test to fail. This same test was basically passing for me prior to the 8.6 release (b/c in practice I'm using this patch with a subprofile that does have blocks).

dpagini’s picture

Hmm.. That patch was embarrassing. Trying again. Same comments.

dpagini’s picture

One more try. My test did fail, but so did every test. =)

dpagini’s picture

Argh, I can try again, but here is the failure I was going for... I think I really need to create a whole new base profile for this test so as not to affect any other tests...

dpagini’s picture

dpagini’s picture

Alright, I think this is the outcome I was looking for. A few extra tests failed b/c they were using the same profile, but overall this is the error I'm getting, and mentioned in a few of the comments above.
Apologies for my 5 comments to get the test to a place I wanted. I hope this helps convey the error I'm seeing!

fago’s picture

I had the same issue while making the contentpool distribution working as inherited profile of thunder with 8.6.x.

After debugging it I realized the issue is that the following is not supported any more with the latest patch:

Or, override dependencies from the base profile using the syntax:

base profile:
name: BASE_PROFILE

and that makes sense, since we now have install/dependencies as separate keys, the exclude_* feature is deprecated.

Thus, what is necessary to make it work again is to update the info.yml to simply

base profile: parent

and use dependency / install keys to decide what gets installed.

Besides that, I noted that dependencies in the form of "project:module" do not work any more. So I revert to the "module" syntax for now.

However I'm still stuck due to the same issue as metalbote in #482 - config of the parent profile depends on the theme, which is not active yet:

The following modules are required but were not found. Move them into the appropriate modules subdirectory, such as
In UnmetDependenciesException.php line 98:

Configuration objects provided by thunder have unmet dependencies: der">block.block.thunder_base_account_menu (thunder_base)

fago’s picture

Issue summary: View changes

I've removed the deprecated alternative info.yml format from the issue summary.

DamienMcKenna’s picture

Is there an issue for the project:module dependency syntax being broken?

phenaproxima’s picture

Assigned: Unassigned » phenaproxima

Assigning to myself to fix the project:module syntax, and the fact that extensions contained in the profile tree are undiscoverable.

luenemann’s picture

There is an open issue for the project:module syntax to be broken in installation profiles: #2855026: Installation profiles do not support project:module format for dependencies

b_sharpe’s picture

I have drilled down this issue (using Lightning as an example), hopefully this isn't too hard to follow:

In docroot/core/lib/Drupal/Core/DrupalKernel.php in function moduleData() the profile is getting set here while looking for module directories:

$profiles = array_intersect_key($all_profiles, $this->moduleList);

This normally comes up as empty as the sub-profile isn't in the module list (core.extensions) until it's been "installed" which is one of the final tasks of install, in which case I believe it is just doing setProfileDirectoriesFromSettings() in docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php, which grabs both parent/child profile directories as it should.

However, when you get to the part that installs the parent profile (Lightning), this changes, as now IT is in the module list, but your subprofile is not. This means that at any point past installing the parent, it can no longer look in the sub-profile directory for modules/config to be installed.

I can confirm that installation proceeds per normal just by doing $profiles = [] in it's place. Obviously this is not a fix and likely breaks other parts of that function, but I haven't had a chance to see how/why this changed from previously working versions, so hopefully may help someone who is also debugging this issue.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
50.68 KB
3.82 KB

Added a bit of test coverage to ensure that modules contained within child and grandchild profiles can be installed.

dpagini’s picture

@phenaproxima this patch still does not address the errors in #490 though, right? It seems there are a handful of users in the above comments experiencing that same error. I tried isolating the error to a single test (in 490), but that could use some work still. I could take another pass at writing the test a bit more isolated, but I'm not sure where to turn to FIX the failing test...
B/c of that, unless I'm missing some obvious work-around that I'm not implementing, I think this needs to stay in "Needs work" if the only thing being done is adding more test coverage?

phenaproxima’s picture

Status: Needs review » Needs work

this patch still does not address the errors in #490 though, right? It seems there are a handful of users in the above comments experiencing that same error.

I plan to address that problem, and add test coverage based on your work. I had to set the issue to "needs review" to automatically trigger the testbot, though.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
51.15 KB
4.41 KB

Changed the functional tests to use InstallerTestBase, which install Drupal using the UI. Turns out the problems were caused by the fact that my test modules had their info files ending in .yml, rather than .info.yml. I renamed those, and both tests passed. Let's see how this does.

phenaproxima’s picture

Status: Needs review » Needs work

Back to NW for the bug in #490.

dpagini’s picture

Ah, my apologies! Thanks for all your work on this one! Please let me know if there's anything I can do!

bendeguz.csirmaz’s picture

-hidden: true
+# hidden: true

I think the profile testing_subsubprofile.info.yml should stay hidden.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
51.15 KB
466 bytes

This will fix one of the broken tests, but not InstallUninstallTest.

phenaproxima’s picture

Assigned: phenaproxima » Unassigned
Status: Needs work » Needs review
Issue tags: +Needs manual testing
FileSize
54.04 KB
3.42 KB

Okay! This fixes InstallUninstallTest (turns out to have been a minor problem with the test modules' info files), and as a bonus, it fixes a problem that has been reported: modules located in child or grandchild profiles are not discoverable during installation, so installation fails. For some reason, InstallerTestBase does not catch this, so it needs to be tested manually. Which I did, and it worked fine (after initially being able to reproduce the failure). I'm marking this as needing manual testing for this reason, and unassigning myself since i've fixed everything I set out to fix in this iteration.

balsama’s picture

Status: Needs review » Needs work

Unfortunately, manual test of this just failed for me.

I used HEAD of Headless Lightning to test:

  1. Install using Drush, success (expected)
  2. Install using UI, failed (expected)
  3. Used patches ignore to ignore 473 patch and apply 507 patch
  4. Install using UI, failed

Steps 1 and 2 resulted in the same exception:

InvalidArgumentException: The module json_content does not exist. in Drupal\Core\Installer\InstallerModuleExtensionList->getPathname() (line 55 of /Users/adam.balsam/Sites/headless-lightning/docroot/core/lib/Drupal/Core/Installer/InstallerModuleExtensionList.php)

dpagini’s picture

So I tried this patch, and am still experiencing the failures I got in #490 and others have mentioned. It's definitely a different error than just mentioned by @balsama, but consistent with some of the other users on here.

dpagini’s picture

Here is another attempt at writing a test only. This may not be the most efficient test, but it required me to change the least amount of code to demonstrate. Hopefully this one works on the first try...

bendeguz.csirmaz’s picture

Status: Needs work » Needs review
FileSize
54.59 KB
945 bytes

Solved the problem from #508, tested it manually with Headless Lightning.

bendeguz.csirmaz’s picture

diff --git a/core/lib/Drupal/Core/Extension/ModuleExtensionList.php b/core/lib/Drupal/Core/Extension/ModuleExtensionList.php
index 62b5d92..f37f97e 100644
--- a/core/lib/Drupal/Core/Extension/ModuleExtensionList.php
+++ b/core/lib/Drupal/Core/Extension/ModuleExtensionList.php
@@ -100,8 +100,7 @@ protected function getExtensionDiscovery() {
   protected function getProfileDirectories(ExtensionDiscovery $discovery) {
     $discovery->setProfileDirectories([]);
     $all_profiles = $discovery->scan('profile');
-    $active_profile = $all_profiles[$this->installProfile];
-    $profiles = array_intersect_key($all_profiles, $this->configFactory->get('core.extension')->get('module') ?: [$active_profile->getName() => 0]);
+    $profiles = $this->profileList->getAncestors($this->installProfile);
 
     // If a module is within a profile directory but specifies another
     // profile for testing, it needs to be found in the parent profile.

I just realized, patch #511 is actually changing the behaviour of the function - it only finds the directories of the current profile and its ancestors, not the directories of all the enabled profiles.

bendeguz.csirmaz’s picture

Status: Needs review » Needs work

I'm not sure this is correct, so I'm making this "Needs work".

b_sharpe’s picture

This is the same issue I had found as well, it appears to be littered throughout the different ExtensionList classes.

$profiles = array_intersect_key($all_profiles, $this->configFactory->get('core.extension')->get('module') ?: [$active_profile->getName() => 0]);

It's grabbing the profile in the core.extension config, which will the child profile UNTIL the parent profile is installed, then the parent is where is starts looking for modules. IMO this should just always be the active profile and it's ancestors.

bendeguz.csirmaz’s picture

Extended InheritedProfileTest to test the "{profile}/modules/custom/{module}" and "{profile}/modules/contrib/{module}" modules are being discovered.

balsama’s picture

Updated IS to include concerns about compounding problems in the existing config system as it related to distributions.

ergonlogic’s picture

I'm seeing what I expect is the same issue as @fago in #492:

In UnmetDependenciesException.php line 98:

  [Drupal\Core\Config\UnmetDependenciesException]
  Configuration objects provided by <em class="placeholder">social</em> have unmet dependencies: <em class="placeholder">features.bundle.social (features)</em>

It appears that sub-profile config is being imported prior to sub-profile dependencies being enabled.

Shawn DeArmond’s picture

I've been testing this with SiteFarm Seed, and I'm getting the same error as @fago in #492:

Drupal\Core\Config\UnmetDependenciesException: Configuration objects provided by <em class="placeholder">sitefarm_seed</em> have unmet dependencies: <em class="placeholder">block.block.seven_breadcrumbs (block, seven), block.block.seven_local_actions (seven, block), contact.form.feedback (contact), features.bundle.sitefarm (features), shortcut.set.development (shortcut), views.view.frontpage (core.entity_view_mode.node.rss, core.entity_view_mode.node.teaser, node, views), views.view.taxonomy_term (core.entity_view_mode.node.teaser, node, taxonomy, views)</em> in /var/www/web/core/lib/Drupal/Core/Config/UnmetDependenciesException.php:98

Shawn DeArmond’s picture

I stepped through the install process, and followed the stack trace for a while and basically modules aren't being installed in the right order.

I ran out of time before I could figure out how Drupal determines the order that the modules will be installed, because all through the install process, it installs modules with the $enable_dependencies = FALSE. So there must be some place where it decides all the dependencies, and decides which order to install them.

What's strange is that it does install a number of the dependencies of the base profile, and not in any particular order that I could see, and then it installs the base profile earlier than it should, causing the config install to fail since other dependency modules haven't been installed yet.

I don't know if this is helpful, but I banged my head against this for a few hours today and I wanted to write it down.

b_sharpe’s picture

A manual test of patch 515 works for me using lightning as a base and ignoring patch 473, I tested the following scenarios and all are working, note #5/#6 some dependencies were needed to be modified due to changes in lightning/dependent modules, but this did not prevent install after rectified:

  1. UI install of just Lightning - Passed
  2. Drush install of just Lightning - Passed
  3. UI install of subprofile with a module inside the profile - Passed
  4. Drush install of subprofile with a module inside the profile - Passed
  5. UI Install of subprofile with multiple modules and config - Errors about unmet dependencies (as reported above) Had to change some dependencies in subprofile and its modules based on lightning changes with entity browser and panelizer - Passed
  6. Drush Install of subprofile with multiple modules and config - Errors about unmet dependencies (as reported above) Had to change some dependencies in subprofile and its modules based on lightning changes with entity browser and panelizer - Passed
Shawn DeArmond’s picture

@b_sharpe, would you elaborate on:

Had to change some dependencies in subprofile and its modules based on lightning changes with entity browser and panelizer

metalbote’s picture

@b_sharpe Did you add any theme related configuration such as block config etc. to your subprofile? Did you use any non core themes? If so, please post how you got it working...

b_sharpe’s picture

Here's the diff: https://bitbucket.org/ixm/openedu/pull-requests/192/oel-000-lighting-320...

In summary:

  • Ignore patch 473, and replace with 515
  • Remove/Update any non-applying patches
  • Attempt install
  • For config errors, found where dependencies were now missing and added them to either profile info.yml or submodule's info.yml depending on where the config error was

Note that this update is Drupal 8.6.1, BUT lightning 3.2.0 (as we are still using panelizer currently)

dpagini’s picture

I would sort of assume this is working for lightning b/c the only config I see in `config/install` is a user role. All of the blocks are in `config/optional` (and my guess is they aren't installing). I think it makes sense that the config behavior that many of us are reporting seeing is not applicable to lighting as a base profile because of its setup.

bendeguz.csirmaz’s picture

I ran out of time before I could figure out how Drupal determines the order that the modules will be installed, because all through the install process, it installs modules with the $enable_dependencies = FALSE. So there must be some place where it decides all the dependencies, and decides which order to install them.

There is an install task called install_profile_modules() in the file install.core.inc that sets the batch processes. This function decides what modules to install in what order.

arsort($required);
arsort($non_required);

$operations = [];
foreach ($required + $non_required as $module => $weight) {

Currently the installation order of modules is decided by their weights. This causes the base profile (such as Standard) to get installed prematurely, causing the infamous UnmetDependenciesException.

drupalninja99’s picture

@bendeguz.csirmaz seems to be on the right track. I am curious why this is breaking now against 8.6 when it hadn't been before. Did install.core.inc change the logic in install.core.inc?

Shawn DeArmond’s picture

Yup, @bendeguz.csirmaz is right. That function does a terrible job determining the install order of modules.

bendeguz.csirmaz’s picture

I don't think this function is faulty, the problem is with the calculation of the base profile's weight. My best guess is the install key from the profile's info.yml is not being considered.

Shawn DeArmond’s picture

It looks like the real issue here is that the base profile is being installed well before its dependencies are. I stepped through the code more, and found ModuleHandler->buildModuleDependencies() and when the base profile shows up here, it doesn't have any dependencies listed, so the method doesn't think it actually needs to install any modules before it installs the base profile.

#820054: Add support for recommends[] and fix install profile dependency special casing might help, because it's supposed to allow Profiles to distinguish between Dependencies and Recommendations. And force Dependencies to be HARD Dependencies. I applied the patch (and it actually applied, which shocked me because it's like 5 years old) but it didn't immediately fix the problem either.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
56.42 KB

Re-roll of #515.

Status: Needs review » Needs work

The last submitted patch, 531: 1356276-531.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

drupalninja99’s picture

Re: #528 - can we get some examples of the full dump of module weights from that file to analyze? Is the install profile being weighted too high which means its being installed before all the dependencies are met? It seems to me that the install profile should be weighted really low relative to other modules being installed (maybe last?).

Another thing I am curious of is if explicitly setting dependencies on the sub-profile is a workaround for the issue?

drupalninja99’s picture

In my tests, even if I copied over all the dependencies to the sub profile info.yml I still get the same error.

drupalninja99’s picture

One thing I tried is adjusting the base profile's weight in either direction (-999 or 999). I found when I adjusted it to -999 it *almost* installed except that it still choked on the theme dependencies when it try to install the block config.

drupalninja99’s picture

After additional testing I found a work around for the block config was moving it to the "optional" folder in my base install profile. It still installed as expected. So that allowed me to do a full install with patch #515 *if* I forced the weight of the base install profile to be -999 (just as a demonstration). With that knowledge I think I would like to play around with the profiling weighing inside of "protected function doList() {" to see if there is a change there that would make this patch work.

drupalninja99’s picture

One thing to note is that doList has this line "Give the profile a heavy weight to ensure that its hooks run last." but the weigh that ends up inside of install.core.inc seems to be reset to zero?

drupalninja99’s picture

The core issue I am seeing that might be the crux of the problem is that core/lib/Drupal/Core/Extension/ModuleExtensionList.php appears to be run after web/core/lib/Drupal/Core/Extension/ProfileExtensionList.php and ends up resetting the weights of the profile ancestors. The base install profile weight should be over 1000 after ProfileExtensionList.php but by the time you get to install.core.inc the weight is set to zero which I believe is happening inside of ModuleExtensionList.php.

Shawn DeArmond’s picture

That's exactly my experience as well. It looks to me that, because the base profile doesn't have any "dependencies" in its array, Drupal doesn't give it an appropriate weight.

Also, be careful manually adjusting weight. That will be a problem in the future:
#1808132: Move module_set_weight() into ModuleHandler::setWeight(), add ModuleHandler::getWeight() to replace missing functionality
#2968232: Deprecate module_set_weight()

phenaproxima’s picture

If the bug is not introduced by this patch, we should fix it in another issue.

Shawn DeArmond’s picture

The bug is introduced by this patch. Before this patch, there was never a situation where a Profile would be a dependency of another Profile.

Read my comment #530. That's as far as I got digging into it.

drupalninja99’s picture

Also I for testing purposes I created a local patch (hack) that manually sets the base install profile weight to -999 in install.core.inc just to see if that would work and it did for me (after moving block config to /optional). We are going to test on some other projects that use the sync directory.

What I found is that the profile weighting is getting lost or reset somewhere in between ProfileExtensionList.php and install.core.inc's dependency sorting.

frob’s picture

The bug is introduced by this patch. Before this patch, there was never a situation where a Profile would be a dependency of another Profile.

@Shawn DeArmond, just because profiles where never a dependency of another profile doesn't mean this patch induced the error. From what you have said it sounds like this patch just exposed the error. Is this patch the reason that core/lib/Drupal/Core/Extension/ModuleExtensionList.php runs after web/core/lib/Drupal/Core/Extension/ProfileExtensionList.php and ends up resetting the weights of the profile ancestors back to zero?

dpagini’s picture

This is tough. I've been using this patch for ~2 years now (foolishly) thinking it was close to being accepted. Changes in 8.6.x core branch have now caused this patch to stop working for me, but it's being chalked up to not an issue with this new functionality? I have tried to post patches demonstrating the failures too... You literally can't use the standard install profile as a base profile, but the simple test profiles provided here do work.

Shawn DeArmond’s picture

@frob, I see your point, and given what @dpagini said, and our own experience of the same, means that in Drupal 8.6, they did change something that makes this new Profile Inheritance functionality we're trying to implement "no longer work".

At this point, I'm a bit at a loss of how to fix it. My knowledge of the extension weight system is limited to the poking around I've done over the past couple weeks.

dpagini’s picture

FileSize
56.42 KB
57.28 KB
2.87 KB
58.69 KB
1.02 KB
57.19 KB
56.5 KB

Let me start by saying if any of this works, I will fall off my chair. I'm sure I did something wrong here...

I have several files here...

  • 1356276-531-reroll.patch - reroll of 531 which was not applying cleanly for me on 8.7.x HEAD. I am expecting this to fail with the same 2 errors found in the test run of 531.
  • 1356276-546.patch - the code I've found to hopefully fix both the errors in 531, and the errors we're seeing in 475, 476, 486, 492, 517, 518, etc. This is at least solving my problem locally.
  • 1356276-546-wtests.patch - Adding in the tests I attempted to write in #510, which I would now expect to pass.
  • 1356276-546-8.6.x.patch - the main fix for 8.6.x that I used to test this against my project.

So I want to explain my logic in case what I'm doing here is crazy. I realized that ProfileExtensionList was returning the profile information of a subprofile with a dependency on its base profile. B/c it's a dependency, it was getting installed as a normal module dependency in the core installation process before themes, and causing the errors. I was going to just remove it as a dependency, but I think the reason it's added as a dependency is because you shouldn't be able to uninstall the base profile while the subprofile is installed, so we want to keep it there. So I mostly left that generation alone, except that I added the base profile dependencies to the subprofile dependencies list.
Next, I realized I had to REMOVE the base profile from the installation profiles dependencies array, so the profile would be installed as a profile, and not as a module. This is done in the install.inc::install_profile_info() method.

dpagini’s picture

Status: Needs work » Needs review
FileSize
58.66 KB
2.87 KB

Hmm... one mistake for sure. Let me try this again.

Status: Needs review » Needs work

The last submitted patch, 547: 1356276-547-wtests.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

dpagini’s picture

Ah, I think this is failing due to 2855026. That changed the module from page_cache to drupal:page_cache so this new test needs to look for that.

This, along with the fixes I just made, have me about 90% confident this group of patches is the right bunch.

Rajab Natshah’s picture

Thank you David,
The #549 patch is working.

Sorry, In a quick action to seeing the patch I ran the automated test on the 1356276-549-8.6.2.patch - for sure it will fail to apply.
as it on the 8.x-6.x branch. the 1356276-549-8.6.x.patch as you had provided us.

More testing with sub-profiles.

metalbote’s picture

Although it looks like we have a solution, let's be honest, shouldn't the whole installation process even be considered? The whole dependency stuff isn't really understandable, at least the documentation should be better. Of course, the bug that appeared wasn't introduced by this feature, but is based on the different handling of profiles, modules and themes during installation, although configuration management can lead to dependencies on each other. I'm not a bad programmer, but the code has really left me behind... This goes in the direction that phenaproxima suggested, considering a separate meta issue to clearify the install process and its dependency check.

kreynen’s picture

Next month this issue will be 7 years-old. We've given up on ever seeing this in core and "de-sub-profiled" our D8 configuration. This regression combined with our experience trying to convince the Umami project leads to build that as a sub-profile of standard has been really discouraging.

I don't even know what would have to change for this patch to get into core. Until it is in core, building on it is a HUGE risk.

Express recently surpassed Open Atrium and Open Social and is now 5th most popular install profile according to https://www.drupal.org/project/project_distribution. Our dream with D8 was to collaborate with the other University of Colorado campuses on a common D8 base profile and try harder to keep this free of CU-isms so that it might be useful to any other .edu that want to run Drupal as a service.

We've given up on that dream.

Shawn DeArmond’s picture

Status: Needs review » Reviewed & tested by the community

#549 is working great For Drupal 8.7.x. And I ran 145 behat scenarios against it.

Can we get this into core now? Marking as RTBC.

metalbote’s picture

Tested with a real world example, a subprofile of varbase.

I can confirm it is working and issue from #476 seems to be solved.

Shawn DeArmond’s picture

Issues from #405, #412, and #476 are either fixed, or no longer relevant.

Updated Change Record.

Tests are passing, and it has been extensively tested against a real-world base-profile. Two of them, actually.

Documentation will "be published only after patch is applied."

oriol_e9g’s picture

dpagini’s picture

I know I published the patch, but we are using this patch in our project as well with a base install profile, so that's one more "real-world base-profile" +1.

jonathanshaw’s picture

I'm not sure we can be RTBC without a strong response to #516, which suggests postponing this issue.

frob’s picture

I disagree, while it would be nice if a consensus is formed in that META issue. I doubt that will be resolved for Drupal 8 as those changes seem to be future forward, or backward compatibility breaking changes (not that Drupal 8 hasn't had any BC breaking changes).

I have viewed this issue as a feature for profiles that distributions can use and not a feature for distributions. Therefore, I do not consider this issue as needing to wait for that issue to be resolved --especially since there is, not only no consensus but also, no movement). It might be different if there was some discussion, but right now #516 points to an empty issue.

effulgentsia’s picture

Re #516, #558, #559:

The issue summary says:

Implementing this would expose or compound existing problems with the way distributions handle config. Specifically how distributions provide low level config bug fixes and new features to existing sites.

I'm unclear on how committing the patch in this issue would expose or compound the problems that #3004662: [META] Standardize the way distributions handle config updates would like to solve? @balsama or anyone else: can you elaborate on that?

jonathanshaw’s picture

I also posted in #2957423: Proposal: Configuration Management 2.0 initiative in case any CMI 2.0 people wanted to speak up on this.

dpagini’s picture

I sort of agree with @frob and @effulgentsia. Reading the related issue... I don't think patch effects this issue by any means. Isn't this a very similar problem that a contrib module has with configuration. If you change, add, or remove configuration, you have to decide how your update hook will handle sites that are already installed and may have changed the existing configuration. Why wouldnt a distribution take the same approaches/challenges? I mean, maybe I'm not thinking of all examples here, and this is probably not the thread to have that discussion, but it does seem like what's going on here isn't directly related.

balsama’s picture

I opened #3004662: [META] Standardize the way distributions handle config updates based on a conversation I had with @alexpott about this issue. I think the main concern he had was that once we commit this patch, we're exposing the situation where a parent profile wants to modify some piece of config that a child profile has specifically overridden. And without a standard system to handle those types of updates, we're setting ourselves up for problems.

Personally (selfishly?), I'd love to see this patch committed. Lightning made a commitment to it a long time ago and it's something that we'd love to get official support for. Lightning (and I think Thunder, OpenSocial, Commerce at least) take config updates into account. We just can't guarantee that a sub-profile of any of them or a new distribution will do the same.

frob’s picture

@balsama, how is that situation handled in the theme system? If a user builds a theme based on Zen and then Zen(or bootstrap or classy) updates something how does that affect the child theme?

My opinion is that is why this patch exists. To allow extending/overriding of the default configuration of a base profile. This sounds like a need for better documentation. Don't get me wrong, this is a great question, but it isn't one that I think needs to hold up or postpone this patch.

DamienMcKenna’s picture

For the record, for the readers at home, this didn't go into 8.6.3 which was just released: https://www.drupal.org/project/drupal/releases/8.6.3

frob’s picture

Isn't our target 8.7? This is a new feature, 8.6 should only be getting bug fixes at this point.

saltednut’s picture

Testing this with the RTBC patch from #549 and I do not believe the ancestry is being calculated correctly, or profile config is not being installed from ancestors?

I have a profile called "Demo Framework" (df) - it declares "lightning" as its base profile.

When I install drush si df I see config from lightning's config/install folder is installed.

For example, we see block_content.type.basic is installed.

I then create another profile called "Dev Demo" (dfs_dev) - it declares "df" as its base profile. We are now assuming 'lightning' is an ancestor that should install configuration first.

From my understanding, config install would be lightning -> df -> dfs_dev

However, when one tries to install the 3rd tier profile (dfs_dev) they see that expected configuration is missing.

[notice] Starting Drupal installation. This takes a while.
In EntityType.php line 910:
                                                                           
  Missing bundle entity, entity type block_content_type, entity id basic. 


This leads me to believe that either a) I am doing something wrong, totally probable! or b) The system is not working as described.

I believe we can disregard this report as the build I was looking at was installing the patch with 8.6.3 not 8.6.x-dev

effulgentsia’s picture

@brantwynn: any chance you can test it with 8.7.x and confirm that the same scenario works as expected?

joachim’s picture

Status: Reviewed & tested by the community » Needs work

At the very least, patch #549 has a load of unneeded import statements:

+use Drupal\Core\Extension\ProfileHandlerInterface;

What I'm more confused about though is that prior patches added ProfileHandlerInterface and ProfileHandler, and #549 no longer has that, but I can't see any discussion about removing it from the patch.

dpagini’s picture

Looks like ProfileHandler fell off in #459 this past June. Maybe @phenaproxima can weigh in if that was on purpose or an oversight?

balsama’s picture

Yes, #441 refactored on top of extension.list.profile which allowed us to completely remove ProfileHandler. Looks like the import statements were never cleaned up though.

balsama’s picture

Status: Needs work » Needs review
FileSize
58.6 KB
954 bytes

I only found two unused use statements in #549. Here's a patch that removes them.

dpagini’s picture

Status: Needs review » Reviewed & tested by the community

New patch is still working for me and my use case and obviously is not much different from what was previously RTBC, so setting it back to that status. There is obviously still some disagreement on this patch and how it relates to #3004662 though. Are there any next steps to making a decision on those concerns?

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. Here is a very incomplete review will one very hard issue to resolve. As a few people know I'm really not a big fan of this patch because of the additional complexity it leverages on top of profile which is already is a messed up concept. As the module dependency issue shows I think it is extremely unlikely that this patch will ever be able to deal with all the complexity it introduces and the edge-cases that suddenly become possible. Hopefully I will have the energy to do further review and find more of those type of issues. Still, regardless of that I feel that profile composition would be better to attempt outside of a running or installing Drupal.
  2. +++ b/core/includes/install.core.inc
    @@ -1660,7 +1665,10 @@ function install_profile_themes(&$install_state) {
    +  // Install all the profiles.
    +  $profiles = \Drupal::service('extension.list.profile')->getAncestors();
    +  \Drupal::service('module_installer')->install(array_keys($profiles), FALSE);
    

    This feels like this should be batched. We have no idea what's going to happen in the install - ideally as little as possible but I think some profiles do a lot in hook_install().

  3. +++ b/core/lib/Drupal/Core/Extension/ProfileExtensionList.php
    @@ -23,13 +23,172 @@ class ProfileExtensionList extends ExtensionList {
    +  public function getAncestors($profile = NULL) {
    

    Let's require the profile and not have any magic getting of the profile here. That can be put on the callers.

  4. +++ b/core/lib/Drupal/Core/Extension/ProfileExtensionList.php
    @@ -23,13 +23,172 @@ class ProfileExtensionList extends ExtensionList {
    +  public function listDistributions() {
    

    This method has one use and does not seem to be a necessary part of the public API.

  5. +++ b/core/lib/Drupal/Core/Extension/ProfileExtensionList.php
    @@ -23,13 +23,172 @@ class ProfileExtensionList extends ExtensionList {
    +        $info['install'] = array_merge($info['install'], $ancestor->info['install']);
    +        $info['themes'] = array_merge($info['themes'], $ancestor->info['themes']);
    +        // Add ancestor dependencies as our dependencies.
    +        $info['dependencies'] = array_merge($info['dependencies'], $ancestor->info['dependencies']);
    

    This unfortunately is not that simple. What happens if one of the profiles has a dependency like view_bulk_operations (>=8.x-2.4) and another one view_bulk_operations. Or they have project_a:funky and in another project_b:funky. All sorts of complexity here.

jonathanshaw’s picture

@alexpott

regardless of that I feel that profile composition would be better to attempt outside of a running or installing Drupal.

Something like a composer post-update command, or a dedicated build script run by the profile maintainer?

nevergone’s picture

And now?

gr8tkicks’s picture

@alexpott Hi I think we should try to separate the dependency issue, which is a composer problem from the profile issue. If the dependencies for the subprofile and the profile both require view_bulk_operations, and one of them has a dependency for view_bulk_operations >= 8.x-2.4 then it should be okay that both profile/subprofile and the parent profile are able to use 8.x-2.4. If the subprofile has a higher requirement for a module then the parent profile, then that should take precedent I think?

If this is never going to be a core item, is there a way to make a module contrib that supports the features we want? Seems unlikely we can hook into the installation process without modifying core though.

nevergone’s picture

Will you be preparing for 8.7.0?

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

nevergone’s picture

Version: 8.8.x-dev » 8.7.x-dev
Pasqualle’s picture

Testing the patch in #549 it seems there is an issue with \Drupal\Core\Config\ExtensionInstallStorage->getAllFolders()

if ($this->includeProfile) {
        // The install profile (and any parent profiles) can override module
        // default configuration. We do this by replacing the config file path
        // from the module/theme with the install profile version if there are
        // any duplicates.
        $this->folders += $this->getComponentNames($this->profileList->getAncestors($this->installProfile));
}

The "replacing" does not work as it is not how the + operator work in PHP. This is how it would replace for real:

$this->folders = $this->getComponentNames($this->profileList->getAncestors($this->installProfile)) + $this->folders
dpagini’s picture

I'm having a hard time assessing the viability of this patch. With @alexpott weighing in as a core maintainer and mentioning he's not a big fan of the idea, where does that leave this? As @gr8kicks mentions, this isn't really something that can be solved by the contrib space either since so much is happening at install time, but to me, there is a lot of value in sharing a base installation profile.

Should we just try to address a few of the review comments and go from there...?

tobybellwood’s picture

I've been looking at this - and for me the major benefit is not having to recreate (and maintain) in our distribution or profile any config items that are present (and maintained) in core - the biggest limitation at this stage seems to be that a lot of the the config items we want (i.e. media) are stored in /optional and therefore we can't load them ahead of our profile-specific items that depend on them - unless there is a workaround i'm not aware of?

joachim’s picture

+    // For each profile, merge in ancestors' module and theme lists.
+    foreach ($profiles as $profile_name => $profile) {

It should be made clear in the code docs & in the change record that if a sub-profile declares dependencies or themes, these have the parent ones merged in -- it's not an override.

nevergone’s picture

Version: 8.7.x-dev » 8.8.x-dev

Go, go, go! :)

nevergone’s picture

dwkitchen’s picture

Re-roll against current 8.8.x

DamienMcKenna’s picture

Rerolled against 8.7.x.

DamienMcKenna’s picture

I've recently ran into a problem with this change whereby modules stored in the codebase of the parent install profile cannot be enabled by the child profile, at least when loading the site via configuration (example.com/core/install.php?langcode=en&existing_config=1&profile=myprofile). Has anyone else seen this?

In my case I'm using the Rain distro, it's set as base profile: rain in my custom install profile's info file. When the configuration load gets to the final step it has this message:

Notice: Undefined index: rain_media_bundle in module_set_weight() (line 194 of core/includes/module.inc).

and this error:

Error: Call to a member function getPath() on null in Drupal\Core\Extension\ModuleHandler->getModuleDirectories() (line 741 of core/lib/Drupal/Core/Extension/ModuleHandler.php).

However, once the installation has finished I can enable the module via the GUI or Drush.

I'm happy to spin this new problem off to a sub-issue if it'd help move this issue along.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

damontgomery’s picture

The patch in #587 does not apply to 8.8-alpha1.

I haven't looked into this to see what has changed.

shaal’s picture

I rerolled patch #588, and since interdiff is not possible, I created a reroll-diff

Edit: Please ignore this one, the correct reroll is in #594

Status: Needs review » Needs work

The last submitted patch, 592: core-base-parent-profile-1356276-592.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

shaal’s picture

Status: Needs work » Needs review
FileSize
58.72 KB
11.08 KB

I misunderstood the patches...

There are 2 separate patches for 2 different Drupal versions - 8.8.x and 8.7.x

I created the wrong one earlier.
Now I rerolled #587 to work with latest 8.8.x (and 8.8.0-alpha1)

Status: Needs review » Needs work

The last submitted patch, 594: 1356276-88x-594.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

damontgomery’s picture

Thanks, Ofer.

I was able to apply that patch and run `drush updb`. The site still works, but I haven't tried to re-install it or anything.

vijaycs85’s picture

Title: Allow profiles to define a base/parent profile and load them in the correct order » Allow profiles to define a base/parent profile

Updating the title as " load them in the correct order" is implicit by the "base/parent" definition.

robpowell’s picture

I rerolled #588 for 8.9.x. When I tried to apply the path via phpstorm, the ProfileExtensionsListTest.php was being created parallel to root. I manually recreated the test file. Let's see if this works.

robpowell’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 598: core-1356276-598-89x.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

DamienMcKenna’s picture

Rerolled for 8.8.x, for any projects that need it.

VVVi’s picture

Rerolled #601 for 8.8.x and applied the fix from @pasqualle #581 about arrays merging. "The keys from the first array will be preserved. If an array key exists in both arrays, then the element from the first array will be used and the matching key's element from the second array will be ignored." (https://www.php.net/manual/en/function.array-merge.php).

In our case, the fix from #581, resolved the problem related to config_update module, where the source configuration file was taken from an incorrect directory/profile. It can also be a fix for other uncovered problems and maybe for the problem mentioned in #589.

VVVi’s picture

nevergone’s picture

Maybe Drupal 8.9.x/9.0.x ?

tolu_’s picture

Thanks! #603 worked for me

nevergone’s picture

Status: Needs work » Needs review

Please review.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

ccarrascal’s picture

After updating to D8.8 and patch #603, looks like the profiles are not installed in the correct order.

I have a structure of parent / child profiles, and the child is supposed to override configuration from the parent.

- Profile 1 (parent): Has configuration file.yml with value 1
- Profile 2 (child, has base profile: profile1): Has configuration file.yml with value 2

After installation of profile 2, the file.yml is supposed to end up with value 2, but it has value 1 (the value from the parent profile)

Our previous setup was working properly with D8.7 using patch in #572

I'll see if I can provide a patch later, as I still don't know where is the problem.

DamienMcKenna’s picture

Having dug my way through massive layers of dependency problems trying to update a codebase that was two years out of date, I'm in agreement on ditching this and building an alternative system to generate a new install profile from upon another for the initial install, and that after the site is built it would then no longer be tied to the parent install profile.

dwkitchen’s picture

@ccarrascal I'm using on 8.9 - but my child profile doesn't have any config that overrides the parent. Let me test and see.

@DamienMcKenna I think there are always two competing uses of "install profiles"

  • To install a set of configuration that the site then diverges from
  • To have a profile of configuration that multiple sites are managed with
nevergone’s picture

Somebody?

sharma.sachin013’s picture

Is this patch compatible for D9 or not?

sharma.sachin013’s picture

Getting error while applying patch 1356276-88x-603.patch

Server configuration: PHP 7.3 and Drupal: 9.2.0

sharma.sachin013’s picture

sharma.sachin013’s picture

I tried to apply patch on D9 but it's not working.

vierlex’s picture

Hello

I tried reapplying / adapting the patch to 9.0.2, had to change like 3-4 lines.
Sadly I was unable to create a interdiff.
I used https://www.drupal.org/documentation/git/interdiff patchutils interdiff command but 1 out of 4 hunks failed.
The provided rejects just confused me. Id love some guidance to be more useful in the future <3!

EDT:
Alright I had another look and my Adaption does not seem to work, regardless, a drupal 9.0.x patch already exists and is used by the Lightning distribution. According to its composer.json it should be attached in this very issue, but I can't seem to find a link to it, but it is reachable through a direct Link https://www.drupal.org/files/issues/2020-03-24/1356276-531-9.0.x-9.patch

The Lightning distribution also documents on how to use this feature, as well as excluding dependencies, which is another issue / has another patch

vierlex’s picture

vierlex’s picture

Alright I did some research, I found a working setup for 8.9 but not 9.0

I am using these 2 patches for now to generate a sub profile for thunder and install its config too
"1356276 - Allow profiles to define a base/parent profile and load them in the correct order": "https://www.drupal.org/files/issues/2019-12-27/1356276-88x-603.patch",
"2914389 - Allow profiles to exclude dependencies of their parent": "https://www.drupal.org/files/issues/2019-10-22/2914389-14-do-not-test.patch"

Do note, the second patch depends on the first one and provides a "exclude" option for excluding some installs or themes from the parent.

When adapting the first patch for 9 or using the one used by the lightning distribution,
the installation didnt run smoothly, I got an error during site install that some config which wanted to be imported, relied on a theme which wouldnt be installed.
https://github.com/acquia/lightning/blob/45485b9eff63d76b87e481540d5f72e...
https://www.drupal.org/files/issues/2020-03-24/1356276-531-9.0.x-9.patch

Comparing drupal 8.9 and 9 I did notice that the order of the installation of config changed!
https://git.drupalcode.org/project/drupal/-/commit/aeae01b35212633544194...

To be honest, I am very confused what the right order should be..
but with as it stands right now, with this change, a subprofile installations do not work for 9

Update one day later with messing with this:
I noticed that my subprofile does not produce a system.site uuid!
I worked around that by generating/setting the system.site uuid in a child profile install task.
I couldn't figure out why this pretty important uuid got lost during installation.
The actual system_install hook was executed though, where the UUID was set.

Update Update:
Disregard the site uuid bug.
My base profile was thunder, which had a system.site.yml in its config/install folder.
This system.site.yml however had default values, but no site_uuid key.
Having this file removed, resulted inhaving a site_uuid again!
https://www.drupal.org/project/thunder/issues/3176823

Pasqualle’s picture

The D9 patch file mentioned in comment #616 is under issue #3090034: phenaproxima-scratch-3253158

joseph.olstad’s picture

Status: Needs review » Needs work

This patch is needed , prevents us from upgrading to Drupal 9.1.x

patch needs a reroll for 9.1.x , 8.9.x and 9.1.x

Erik Frèrejean’s picture

Rerolled on 9.1

Erik Frèrejean’s picture

Testing this patch I noticed that installation tasks of the base profile aren't executed. I can't find whether this is by design but it struck me as unexpected behavior. If the child profile wants to skip certain installation tasks of the parent profile it can implement hook_install_tasks_alter and remove those tasks from the list.

Here is a stab at adding support for this.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

digitaldonkey’s picture

This patch fails for my case at 9.1.x-dev #626ece8

PHP Fatal error: Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245

For reference

~/htdocs/GzEvD/deGovDrupal9/degov_project/docroot (release/9.1.x-evaluate ✘)✹✭ ᐅ patch -p1 < 1356276-91x-622.patch
patching file core/core.services.yml
patching file core/includes/install.core.inc
patching file core/includes/install.inc
patching file core/lib/Drupal/Core/Config/ConfigInstaller.php
patching file core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
patching file core/lib/Drupal/Core/Config/InstallStorage.php
patching file core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
patching file core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
patching file core/lib/Drupal/Core/Extension/ModuleExtensionList.php
patching file core/lib/Drupal/Core/Extension/ProfileExtensionList.php
patching file core/lib/Drupal/Core/Installer/InstallerProfileExtensionList.php
patching file core/modules/config/tests/config_test/src/TestInstallStorage.php
patching file core/modules/config/tests/src/Functional/ConfigImportBaseInstallProfileTest.php
patching file core/modules/system/src/Form/ModulesUninstallForm.php
patching file core/profiles/testing_inherited/config/install/block.block.stable_login.yml
patching file core/profiles/testing_inherited/config/install/system.theme.yml
patching file core/profiles/testing_inherited/modules/child_profile_module/child_profile_module.info.yml
patching file core/profiles/testing_inherited/modules/contrib/contrib_child_profile_module/contrib_child_profile_module.info.yml
patching file core/profiles/testing_inherited/modules/custom/custom_child_profile_module/custom_child_profile_module.info.yml
patching file core/profiles/testing_inherited/testing_inherited.info.yml
patching file core/profiles/testing_inherited/tests/src/Functional/InheritedProfileTest.php
patching file core/profiles/testing_inherited_standard/testing_inherited_standard.info.yml
patching file core/profiles/testing_inherited_standard/tests/src/Functional/InheritedProfileTest.php
patching file core/profiles/testing_subsubprofile/config/install/system.theme.yml
patching file core/profiles/testing_subsubprofile/modules/grandchild_profile_module/grandchild_profile_module.info.yml
patching file core/profiles/testing_subsubprofile/testing_subsubprofile.info.yml
patching file core/profiles/testing_subsubprofile/tests/src/Functional/DeepInheritedProfileTest.php
patching file core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
~/htdocs/GzEvD/deGovDrupal9/degov_project/docroot (release/9.1.x-evaluate ✘)✹✭ ᐅ drush cr
PHP Fatal error:  Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245
Stack trace:
#0 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php(169): Drupal\Core\Extension\ExtensionDiscovery->setProfileDirectoriesFromSettings()
#1 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(298): Drupal\Core\Extension\ExtensionDiscovery->scan('theme')
#2 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(312): Drupal\Core\Extension\ExtensionList->doScanExtensions()
#3 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ThemeExtensionList.php(113): Drupal\Core\Extension\ExtensionList->doList()
#4 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245

Fatal error: Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245
Stack trace:
#0 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php(169): Drupal\Core\Extension\ExtensionDiscovery->setProfileDirectoriesFromSettings()
#1 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(298): Drupal\Core\Extension\ExtensionDiscovery->scan('theme')
#2 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(312): Drupal\Core\Extension\ExtensionList->doScanExtensions()
#3 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ThemeExtensionList.php(113): Drupal\Core\Extension\ExtensionList->doList()
#4 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245
 [warning] Drush command terminated abnormally.
~/htdocs/GzEvD/deGovDrupal9/degov_project/docroot (release/9.1.x-evaluate ✘)✹✭ ᐅ drush cr
PHP Fatal error:  Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245
Stack trace:
#0 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php(169): Drupal\Core\Extension\ExtensionDiscovery->setProfileDirectoriesFromSettings()
#1 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(298): Drupal\Core\Extension\ExtensionDiscovery->scan('theme')
#2 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(312): Drupal\Core\Extension\ExtensionList->doScanExtensions()
#3 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ThemeExtensionList.php(113): Drupal\Core\Extension\ExtensionList->doList()
#4 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245

Fatal error: Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245
Stack trace:
#0 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php(169): Drupal\Core\Extension\ExtensionDiscovery->setProfileDirectoriesFromSettings()
#1 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(298): Drupal\Core\Extension\ExtensionDiscovery->scan('theme')
#2 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(312): Drupal\Core\Extension\ExtensionList->doScanExtensions()
#3 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ThemeExtensionList.php(113): Drupal\Core\Extension\ExtensionList->doList()
#4 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245
 [warning] Drush command terminated abnormally.
~/htdocs/GzEvD/deGovDrupal9/degov_project/docroot (release/9.1.x-evaluate ✘)✹✭ ᐅ com
~/htdocs/GzEvD/deGovDrupal9/degov_project/docroot (release/9.1.x-evaluate ✘)✹✭ ᐅ composer dump-autoload
No composer.json in current directory, do you want to use the one at /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project? [Y,n]?
Generating autoload files
Generated autoload files
~/htdocs/GzEvD/deGovDrupal9/degov_project/docroot (release/9.1.x-evaluate ✘)✹✭ ᐅ drush cr
PHP Fatal error:  Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245
Stack trace:
#0 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php(169): Drupal\Core\Extension\ExtensionDiscovery->setProfileDirectoriesFromSettings()
#1 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(298): Drupal\Core\Extension\ExtensionDiscovery->scan('theme')
#2 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(312): Drupal\Core\Extension\ExtensionList->doScanExtensions()
#3 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ThemeExtensionList.php(113): Drupal\Core\Extension\ExtensionList->doList()
#4 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245

Fatal error: Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php:245
Stack trace:
#0 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php(169): Drupal\Core\Extension\ExtensionDiscovery->setProfileDirectoriesFromSettings()
#1 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(298): Drupal\Core\Extension\ExtensionDiscovery->scan('theme')
#2 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionList.php(312): Drupal\Core\Extension\ExtensionList->doScanExtensions()
#3 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ThemeExtensionList.php(113): Drupal\Core\Extension\ExtensionList->doList()
#4 /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal in /Users/tho/htdocs/GzEvD/deGovDrupal9/degov_project/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245
 [warning] Drush command terminated abnormally.

After revert cache clears as expected.

jrglasgow’s picture

FileSize
30.91 KB

I tested the patch in 622 and found a problem with the ProfileExtensionList class missing a few classes that were in previous patches... specifically I was getting this error when running druch cr

Fatal error: Uncaught Error: Call to undefined method Drupal\Core\Extension\ProfileExtensionList::getAncestors() in /var/www/docroot/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php on line 245

so I have added some methods back in and made some changes to the testing profile info.yml files to remove the core: 8 lines

jrglasgow’s picture

Status: Needs work » Needs review
FileSize
1.35 KB
44.8 KB

the patch I submitted in 625 didn't have some files I forgot to add... this has the files and the patch was generated from the merge request I created in the fork for this issue.

drupalninja99’s picture

I am running into the same issues where dependencies don't appear to be inherited as expected with the latest merge request.

Lukey made their first commit to this issue’s fork.

sylus’s picture

Just adding a patch based on the recent M.R. that applies to the 9.0.x line.

Status: Needs review » Needs work

The last submitted patch, 630: 1356276-adding-patch-in-622-plus-a-few-changes.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

sylus’s picture

Okay I couldn't get any patch to work since #603 so am not too sure what is going on since then.

a) Rerolled #603 to work on 9.0.x branch
b) Added the hook install tasks logic from #622
c) Removed the "core: 8.x" from the testing profiles

With this I am able to use a sub profile calling my base one, and my additional sub profile modules are being enabled after my base, and also all of the base install profiles hook_tasks are working.

I attached an interdiff from #603

Here is my sub-profile:

name: 'CCEI'
description: 'A Drupal distribution for CCEI created to leverage the Web Experience Toolkit.'
type: profile
core_version_requirement: ^8.8 || ^9
distribution:
  name: 'CCEI'

dependencies:
  - drupal:menu_link_content

# Base profile
base profile: wxt

# Exclude from base profile
exclude:
  - lightning_api
  - lightning_contact_form
  - lightning_roles
  - lightning_scheduled_updates
  - lightning_search

# Language
keep_english: true

themes:
  - bartik
  - seven
  - claro

Here is a snippet of the install:

 [notice] Starting Drupal installation. This takes a while.
 [notice] Performed install task: install_select_language
 [notice] Performed install task: install_select_profile
 [notice] Performed install task: install_load_profile
 [notice] Performed install task: install_verify_requirements
 [notice] Performed install task: install_settings_form
 [notice] Performed install task: install_verify_database_ready
 [notice] Performed install task: install_base_system
 [notice] Performed install task: install_bootstrap_full
 [notice] Performed install task: install_profile_modules
 [notice] Performed install task: install_profile_themes
 [notice] Performed install task: install_install_profile
 [notice] Translations imported: 9392 added, 0 updated, 0 removed.
 [notice] Performed install task: install_import_translations
 [notice] Performed install task: wxt_extension_configure_form
 [notice] Performed install task: install_configure_form
 [notice] metatag.metatag_defaults.global rewritten by wxt_ext_metatag
 [notice] metatag.metatag_defaults.node rewritten by wxt_ext_metatag
 [notice] metatag.metatag_defaults.taxonomy_term rewritten by wxt_ext_metatag
vierlex’s picture

Thank you so much sylus!

I adapted your patch for 9.1.0 with very minor adjustments to make the patch apply correctly.
Doing a new install went fine as expected!

I haven't tested a site install but the patch applies cleanly to 9.2.x as well, for anyone in need

The inderdiff patch is hopefully usefull this time around, since I am still not sure how to create one correctly.

For completeness sake: 631 and 633 require the latest patch from https://www.drupal.org/project/drupal/issues/2914389
if you need the 'exclude' functionality for your profile.

Make sure to apply the 'exclude' patch after applying either 631 or 633.

jrglasgow’s picture

I have created a new branch in the fork with the patch in #633 and am currently working on testing in 9.2.x.

jrglasgow’s picture

Status: Needs work » Needs review

The patch #633 applied correctly to 9.2.x and I have successfully tested an install. I have closed the previous pull request and opened a new pull request for the new patch branch.

Please review.

If you find any changes that need to be made it would help if we can put them in the current branch to make testing easier.

jrglasgow’s picture

This is my attempt to resolve some tests issues. I made the changes in the fork that was created and add the patch here in case someone needs it.

Erik Frèrejean’s picture

The last D9.1 patch in #627 misses a use statement in the config installer breaking the drush cim command.

Just added that use statement to the old 91x patch to make it at least work on 9.1. I haven't rerolled the last version of this patch.

vierlex’s picture

#639 this has already been resolved in #632 / #633 with additional fixes, since adding the 'use' statement only didn't resolve all the issues.

Use either this or the latest MR from jrglasgow https://git.drupalcode.org/project/drupal/-/merge_requests/162

hideaway’s picture

is it safe to use the patch? can we rely this will get merged sooner or later? this feature is incredibly useful, but I'm afraid to use the patch in case this won't get merged into core. it could then cause more problems, any advice?

vierlex’s picture

The only thing I can tell you is that the Lightning distribution, which is developed by Acquia, also includes a version of this patch.

I tested it as much as I could for our Use Cases and it seems to run ok.

If your Use Case is, that you want a headstart when using a distribution, you could still create your own custom modules with you configuration / entities, what have you, and activate it after you installed your favorite Distribution.

Which results in probably the same thing.

The one thing which might be more tedious to implement when using this method, is deactivating/deleting modules/config/entities of the distribution which you don't need.

This might be a safe-ish alternative.

nevergone’s picture

How could this be improved?

kreynen’s picture

In just 8 months, this issue will be 10 years old. Anyone considering building on it should do so with caution. You should be aware of how many times an update to Drupal core has required this functionality to be refactored and how long that has taken. A lot of what I would have used this approach for in D7 in a higher ed context, I now do with Config Split.

frob’s picture

Not to mention that the core installer now has an option to include existing configuration now. At least d.o has removed the pager from issue queue pages otherwise this issue would be on its 3rd page by now.

joseph.olstad’s picture

633 seems to be the way to go if you're using D9.1.x

joseph.olstad’s picture

633 seems to be the way to go if you're using D9.1.x

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nevergone’s picture

How could this issue be solved?

kreynen’s picture

@nevergone Are you asking how this feature can get into core?

I personally don't think it be solved that way. We tried to make the case for it during the Unami project showing how that install profile could have be built on top of Standard with https://www.drupal.org/project/demo_umami_subprofile. That didn't get any traction.

While a variation of the this patch has been part of Acquia's Lightning install profile for years, Lightning is EoL along with D8 in November.

Pantheon's custom upstreams combined with managing sites with their "composer integrated" build tools provides similar functionality where an install profile managed upstream can still be customized and overridden at the site level. That + config_split and potentially https://www.drupal.org/project/config_distro, https://www.drupal.org/project/config_profile or https://www.drupal.org/project/profile_split_enable. I'm still trying to figure out when (if ever) to use profiles in D9.

Looking forward to Drupal 10, the new starterkit theming will allow front-end developers to get a copy as a starting point for their theme. Tooling is provided as part of the included Drupal command line interface for automating this.

Starterkit Themeing

Managing a distribution where you allow customization only/mainly at the config and theme level is a much better approach than having duplicate copies of PHP at different levels of D7 where the copy in sites/all/module trumped what was included in /profiles/[PROFILE]/module. It provides different roles different levels of access based on the types of files they are allowed to edit that actually makes sense in most organizations. Allowing users to manage Features or modify themes that could be simple exports... but could also modify any form element or drop any table was just insanity.

Personally, I'm embracing the separations of concerns I get with Twig and Configuration Management and building solutions that achieve similar goals to what I thought I would get with Install Profile Inheritance... mainly sharing solutions to common problems at a base layer that allows people with the skill and knowledge to customize on top of that layer at the site level... and I'm a lot happier with this solution than I was even when install profile inheritance was working.

jay.dansand’s picture

Upgraded from Drupal 9.1.9 to 9.1.10 today, and #633 was rejected by composer-patches.

After 9.5 years it's unlikely this will get into core, but it sure would be nice. We'll probably have to move off of it by Drupal 10 but there's no bandwidth for that right now, so here's a limp-along reroll, changing assertEqual() to assertEquals() and assertText() to assertSession()->pageTextContains() as necessary. I also removed what seemed like a no-op change (it merely flip-flopped expected and actual values in the last assertEquals() call).

KapilV’s picture

Hear a reroll patch.

jcandan’s picture

@kreynen, you may have a limited view of how profiles help the community if you are "still trying to figure out when (if ever) to use profiles in D9."

This feature would be helpful in our SaaS style multisite use-case. We service a specific group of government offices, and provide them a website platform via Drupal multisite and our install profile. We have a handful of "site-types" that share a subset of common features, and managing the differences via sub-profiles seems like a perfect fit.

kreynen’s picture

@jcandan. You might be right. I did develop my first install profile many years ago (in fact it was the first packaged install profile used to test the packaging process on Drupal.org after helping the DA fund that work). Maybe my view would be less limited if I also managed the development of one of the most popular install profiles on Drupal.org used by groups at a university that varied in size from colleges and departments to student groups to build different "site-types" like https://websupport.colorado.edu/? Maybe if I spent years maintaining the Packaging White List I wold have some insight into many of the install profiles maintained on Drupal.org? Maybe if I wrote tools for users to convert sites to use a profile that other groups like Acquia recommended to move users into their Lightning install profile (but ended up being used more often to move sites off of Lightning) like https://www.drupal.org/project/profile_switcher would have a better understanding of install profiles?

Sorry about the snark, but I've done all these things. I don't think there are many people with a more comprehensive view of the vision for how install profiles would be used, how they were really used in the past and why they are no longer as important to the future of Drupal when we can leverage to build and maintain a group of sites based on a common codebase and configuration.

I've reached out to James directly via LinkedIn and D.O. and would be happy to be proven wrong by him (or anyone else) about Install Profiles actually providing functionality (beyond the initial install UX and packaging) that can't now be replicated with a less Drupal specific approach.

jcandan’s picture

Snark warranted. :)

joseph.olstad’s picture

Ok , for Drupal 9.1.x, Drupal 9.2.x and Drupal 9.3.x , use this patch

My simply moving the use statement on ConfigInstaller.php I was able to make this patch work cleanly on all three branches, no collision.

see interdiff and new patch

joseph.olstad’s picture

FileSize
63.52 KB

ok, while patch 656 works on all three branches mentioned no problem, composer is too strict with the fuzz so I'm rolling a D91x same thing , no interdiff needed

just removes fuzz for D91x (applies clean with no *.orig files due to some composer setting I have or some default setting in composer being strict about patches)

**EDIT** some other patch conflict in my composer file, but patches for 656 are good.

Subhransu sekhar’s picture

After applying this
D91x-1356276-656.patch creating issue so created another patch https://www.drupal.org/files/issues/2021-09-30/InstallStorage.patch

joseph.olstad’s picture

Here's a new reroll for D9.3.x

frob’s picture

Issue summary: View changes

I added "Convince someone on the Core Team that this is a good idea" to the To Do list in the IS.

While is commendable that this patch has stayed alive through D7 D8 and now D9, it might be time to realize that this never had much traction with the people that would be, ultimately, the gate-keepers and the maintainers of the feature.

Should this be moved to the Core Ideas queue? Or maybe just open a new issue over their.

shweta__sharma’s picture

Re-rolled the patch #659, fixed custom command failed.
Attached interdiff please review.
Thanks!

joseph.olstad’s picture

The principal reason why 'commands failed' is because of a robot check on the non-english word subsubprofile. I would argue in favour of allowing the property subsubprofile because that is an accurate way of describing what it is. Who cares if this word is not in the Roberts english dictionary!

Since when does shakespeare write computer code?

frob’s picture

Any non-native English (and non-english) speaker who puts a word into a translator to try and find out what it means will care that we are making up words.

joseph.olstad’s picture

@frob, so maybe change subsubprofile to sub_subprofile or sub_sub_profile or subSubProfile

I'd have to check with Drupal coding standards but either snake case or camel case , not sure if the spellchecker would complain still if the correct style was used either camel case or snake case.

nevergone’s picture

rename: "subsubprofile" -> "sub_subprofile"

joseph.olstad’s picture

@nevergone, great effort on that fix (and thank you very much), unfortunately we didn't outsmart the spellcheck sniffer...

22:01:33 core/scripts/dev/commit-code-check.sh --drupalci
22:01:53 /var/www/html/core/profiles/testing_sub_subprofile/tests/src/Functional/DeepInheritedProfileTest.php:3:36 - Unknown word (subprofile)
22:01:53 /var/www/html/core/profiles/testing_sub_subprofile/tests/src/Functional/DeepInheritedProfileTest.php:17:37 - Unknown word (subprofile)
22:01:53 /var/www/html/core/tests/Drupal/KernelTests/Core/Extension/ProfileExtensionListTest.php:40:58 - Unknown word (subprofile)
22:01:53 /var/www/html/core/tests/Drupal/KernelTests/Core/Extension/ProfileExtensionListTest.php:59:58 - Unknown word (subprofile)
22:01:53 /var/www/html/core/tests/Drupal/KernelTests/Core/Extension/ProfileExtensionListTest.php:76:63 - Unknown word (subprofile)

I think we need to open an issue with the drupal ci bot issue queue.

joseph.olstad’s picture

oh, wait, subprofile isn't a word? what kind of dictionary is this?

actually, what will work is sub_sub_profile

we probably don't need to pull the fire alarms just yet.

nevergone’s picture

Ok, try again:
rename: "subprofile" -> "sub_profile"

nevergone’s picture

Fix warnings and errors.

nevergone’s picture

Oh, sorry, fix ExtensionInstallStorage.php

nevergone’s picture

ProfileExtensionList namespace fix

joseph.olstad’s picture

This one should have better test results. Please see interdiff

Fixing my own gaffe introduced in patch 659 , I am correcting the mistake I made during the reroll for 9.3.x.

Thanks to nevergone for the syntax code style work.

Status: Needs review » Needs work

The last submitted patch, 673: 1356276-673.patch, failed testing. View results

saltednut’s picture

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

RoSk0’s picture

ranjith_kumar_k_u’s picture

Fixed custom command failure issue.

RoSk0’s picture

Fixed usage of deprecated stuff in tests:

  • added setUp() return typehint
  • removed deprecated Drupal\Tests\UiHelperTrait::drupalPostForm()
  • removed deprecated AssertLegacyTrait::assertText()
  • removed usage of deprecated app.root service

The last submitted patch, 679: 1356276-679.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 680: 1356276-680.patch, failed testing. View results

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

joseph.olstad’s picture

680 needs a reroll for 9.4.0 due to very recent changes made to core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php

commit 163df489ff3e88fa9aec57fa7ee64e8c3abce20a
Author: catch <catch@35733.no-reply.drupal.org>
Date:   Mon Jun 13 11:40:11 2022 +0100

    Issue #2392815 by alexpott, pooja saraah, bircher, cilefen, pratik_specbee, catch, fago: Module uninstall validators are not used to validate a config import
steinmb’s picture

Issue tags: +Needs reroll
ankithashetty’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
65.5 KB
17.63 KB

Rerolled the patch in #680, thanks!

Status: Needs review » Needs work

The last submitted patch, 686: 1356276-686.patch, failed testing. View results

Rajab Natshah’s picture

Issue summary: View changes
Status: Needs work » Closed (duplicate)

#3266057: Allow profiles to define a base/parent profile [continue of #1356276] is the continuation of this issue.

Due to the high number of attachments, this issue has become unusable. Please post all followups at #3266057: Allow profiles to define a base/parent profile [continue of #1356276].

For additional background information, please see #3291387: Unable to add additional comment or changes to issue number 1356276 (5xx - Server Error).