configMergeTest.php

  • Test config-merge, that merges configuration changes from one site to another.

Namespace

Unish

Classes

Namesort descending Description
configMergeTest @group slow @group commands

File

tests/configMergeTest.php
View source
  1. <?php
  2. /**
  3. * @file
  4. * Test config-merge, that merges configuration changes from one site to another.
  5. */
  6. namespace Unish;
  7. /**
  8. * @group slow
  9. * @group commands
  10. */
  11. class configMergeTest extends CommandUnishTestCase {
  12. /**
  13. * Covers the following responsibilities.
  14. * - The site name configuration property is set on the 'stage' site.
  15. * - config-merge is used to merge the change into the 'dev' site.
  16. * - The site name is tested to confirm that it changed.
  17. *
  18. * General handling of site aliases will be in sitealiasTest.php.
  19. */
  20. public function testConfigMergeMultisite() {
  21. if (UNISH_DRUPAL_MAJOR_VERSION != 8) {
  22. $this->markTestSkipped('config-merge only works with Drupal 8.');
  23. return;
  24. }
  25. $sites = $this->setUpDrupal(2, TRUE);
  26. $stage_options = array(
  27. 'root' => $this->webroot(),
  28. 'uri' => 'stage',
  29. 'yes' => NULL,
  30. 'tool' => '0',
  31. 'strict' => '0',
  32. );
  33. $dev_options = array(
  34. 'root' => $this->webroot(),
  35. 'uri' => 'dev',
  36. 'yes' => NULL,
  37. );
  38. // Both sites must be based off of the same install; otherwise, the uuids
  39. // for the initial configuration items will not match, which will cause
  40. // problems.
  41. $this->drush('sql-sync', array('@self', 'stage'), $dev_options);
  42. // Export initial configuration
  43. $this->drush('config-export', array(), $dev_options);
  44. $this->drush('config-export', array(), $stage_options);
  45. // Make a git repository
  46. $this->createGitRepository($this->webroot());
  47. // 'config-merge' only supports 'rsync' for mutisites, so that is all we
  48. // are going to test here.
  49. // Make a configuration change on 'stage' site
  50. $this->drush('config-set', array('system.site', 'name', 'config_test'), $stage_options);
  51. // Run config-merge to merge the configuration change from 'stage' into the 'dev' site's configuration
  52. $this->drush('config-merge', array('stage'), $dev_options);
  53. // Verify that the configuration change we made on 'stage' now exists on 'dev'
  54. $this->drush('config-get', array('system.site', 'name'), $dev_options);
  55. $this->assertEquals("'system.site:name': config_test", $this->getOutput(), 'Config set, merged and fetched.');
  56. // Make a second configuration change on 'stage' site
  57. $this->drush('config-set', array('system.site', 'name', 'second_test'), $stage_options);
  58. // Run config-merge again to insure that the second pass also works
  59. $this->drush('config-merge', array('stage'), $dev_options);
  60. // Verify that the configuration change we made on 'stage' now exists on 'dev'
  61. $this->drush('config-get', array('system.site', 'name'), $dev_options);
  62. $this->assertEquals("'system.site:name': second_test", $this->getOutput(), 'Config set, merged and fetched a second time.');
  63. }
  64. public function testConfigMergeSeparateSites() {
  65. if (UNISH_DRUPAL_MAJOR_VERSION != 8) {
  66. $this->markTestSkipped('config-merge only works with Drupal 8.');
  67. return;
  68. }
  69. // Create a dev site; we will copy this site to create our stage site
  70. $sites = $this->setUpDrupal(1, TRUE);
  71. $dev_options = array(
  72. 'root' => $sites['dev']['root'],
  73. 'uri' => 'default',
  74. 'yes' => NULL,
  75. );
  76. // Export initial configuration for dev site
  77. $this->drush('config-export', array(), $sites['dev'] + array('yes' => NULL, 'strict' => 0));
  78. // Copy the dev state to make a stage site
  79. $sites = $this->setUpStagingWorkflow($sites);
  80. $dev_options = $sites['dev'] + array(
  81. 'yes' => NULL,
  82. 'strict' => 0,
  83. );
  84. $stage_options = $sites['stage'] + array(
  85. 'yes' => NULL,
  86. 'tool' => '0',
  87. 'strict' => '0',
  88. );
  89. // Part one: test config-merge using the git push / pull mechanism
  90. // We have to test 'git' first, because it requires both sites to stay
  91. // in sync with the upstream repository. In contrast, the
  92. // rsync mechanism presumes that the remote site cannot reach the
  93. // central repository, so it does not attempt to keep the remote side
  94. // in sync. Doing this tests later means that we do not need to clean
  95. // up the repository.
  96. // Get the last commit hash
  97. $this->execute("git log --pretty=format:%h -1", CommandUnishTestCase::EXIT_SUCCESS, $sites['dev']['root']);
  98. $base = $this->getOutput();
  99. // Make a configuration change on 'stage' site
  100. $this->drush('config-set', array('system.site', 'name', 'git'), $stage_options);
  101. // Run config-merge to copy the configuration change to the 'dev' site
  102. $this->drush('config-merge', array('@stage'), $dev_options + array('git' => NULL, 'base' => $base));
  103. // Verify that the configuration change we made on 'stage' now exists on 'dev'
  104. $this->drush('config-get', array('system.site', 'name'), $dev_options);
  105. $this->assertEquals("'system.site:name': git", $this->getOutput(), 'Config set, merged and fetched via git.');
  106. // Make a second configuration change on 'stage' site
  107. $this->drush('config-set', array('system.site', 'name', 'git-2'), $stage_options);
  108. // Run config-merge again
  109. $this->drush('config-merge', array('@stage'), $dev_options + array('git' => NULL, 'base' => $base));
  110. // Verify that the configuration change we made on 'stage' now exists on 'dev'
  111. $this->drush('config-get', array('system.site', 'name'), $dev_options);
  112. $this->assertEquals("'system.site:name': git-2", $this->getOutput(), 'Config set, merged and fetched via git a second time.');
  113. // Part two: test config-merge using the rsync mechanism
  114. // Make a configuration change on 'stage' site
  115. $this->drush('config-set', array('system.site', 'name', 'config_test'), $stage_options);
  116. // Run config-merge to copy the configuration change to the 'dev' site
  117. $this->drush('config-merge', array('@stage'), $dev_options);
  118. // Verify that the configuration change we made on 'stage' now exists on 'dev'
  119. $this->drush('config-get', array('system.site', 'name'), $dev_options);
  120. $this->assertEquals("'system.site:name': config_test", $this->getOutput(), 'Config set, merged and fetched via rsync.');
  121. $this->execute("git reset --hard", CommandUnishTestCase::EXIT_SUCCESS, $sites['dev']['root']);
  122. // Make a second configuration change on 'stage' site
  123. $this->drush('config-set', array('system.site', 'name', 'config_test_2'), $stage_options);
  124. // Run config-merge to copy the configuration change to the 'dev' site
  125. $this->drush('config-merge', array('@stage'), $dev_options);
  126. // Verify that the configuration change we made on 'stage' now exists on 'dev'
  127. $this->drush('config-get', array('system.site', 'name'), $dev_options);
  128. $this->assertEquals("'system.site:name': config_test_2", $this->getOutput(), 'Config set, merged and fetched via rsync.');
  129. // Finally, make sure that we have all of the commits we should
  130. // in the 'dev' site
  131. $this->execute("git log", CommandUnishTestCase::EXIT_SUCCESS, $sites['dev']['root']);
  132. // First, we remove blank lines, and lines that do not begin with a space.
  133. // This gets rid of all of the header lines, like "commit" and "Date:" that
  134. // contain variable data.
  135. $outputList = array_filter($this->getOutputAsList(),
  136. function($line) {
  137. if (empty($line)) {
  138. return FALSE;
  139. }
  140. return ($line[0] == ' ');
  141. });
  142. // Next, convert all runs of spaces into a single space, and trim.
  143. $outputList = array_map(
  144. function($line) {
  145. return trim(preg_replace("/ */", " ", $line));
  146. }, $outputList);
  147. // Test to see if the compressed result matches our expectations.
  148. $this->assertEquals("Merged configuration from @stage in config_test_2
  149. Collection Config Operation
  150. system.site update
  151. Merged configuration from @stage in config_test
  152. Collection Config Operation
  153. system.site update
  154. Exported configuration.
  155. Collection Config Operation
  156. system.site update
  157. Exported configuration.
  158. Collection Config Operation
  159. system.site update
  160. Initial commit.", implode("\n", $outputList));
  161. }
  162. function setUpStagingWorkflow($sites) {
  163. // Copy settings.php from sites/dev to sites/default.
  164. $dev_settings = file_get_contents($sites['dev']['root'] . '/sites/' . $sites['dev']['uri'] . '/settings.php');
  165. $sites['dev']['uri'] = 'default';
  166. file_put_contents($sites['dev']['root'] . '/sites/' . $sites['dev']['uri'] . '/settings.php', $dev_settings);
  167. // Rewrite the alias file for the dev site
  168. $this->writeSiteAlias('dev', $sites['dev']['root'], 'default');
  169. // Create a site alias for the staging site.
  170. $sites['stage']['root'] = $sites['dev']['root'] . '-stage';
  171. $sites['stage']['uri'] = 'default';
  172. $sites['stage']['db_url'] = str_replace('dev', 'stage', $sites['dev']['db_url']);
  173. $this->writeSiteAlias('stage', $sites['stage']['root'], 'default');
  174. // Create a root directory for the staging site
  175. mkdir($sites['stage']['root']);
  176. // Write a .gitignore file for the dev site, to ignore settings.php and the files/php directory.
  177. file_put_contents($sites['dev']['root'] . '/.gitignore', "sites/default/settings.php\nsites/default/files/php");
  178. // Make a git repository for the dev site.
  179. $this->createGitRepository($sites['dev']['root']);
  180. // We have to check out the files in the 'stage' site from
  181. // the git repository of the 'dev' site so that we can
  182. // use git to transfer configuration.
  183. // make a bare repository, push the dev site up to it, and clone from there.
  184. $central_repo = dirname($sites['dev']['root']) . '/repository.git';
  185. mkdir($central_repo, 0777, TRUE);
  186. $this->execute("git init --bare", CommandUnishTestCase::EXIT_SUCCESS, $central_repo);
  187. $this->execute("git remote add origin file://" . $central_repo . " && git push origin master", CommandUnishTestCase::EXIT_SUCCESS, $sites['dev']['root']);
  188. $this->execute("git clone file://" . $central_repo . " " . $sites['stage']['root']);
  189. $this->execute("git config user.email 'unish@drush.org' && git config user.name 'Unish'", CommandUnishTestCase::EXIT_SUCCESS, $sites['stage']['root']);
  190. // Change the db settings in $stage_settings
  191. $stage_settings = str_replace("_dev", "_stage", $dev_settings);
  192. file_put_contents($sites['stage']['root'] . '/sites/default/settings.php', $stage_settings);
  193. // Both sites must be based off of the same install; otherwise, the uuids
  194. // for the initial configuration items will not match, which will cause
  195. // problems.
  196. $this->drush('sql-sync', array('@self', '@stage'), $sites['dev'] + array('yes' => NULL, 'strict' => 0));
  197. return $sites;
  198. }
  199. protected function createGitRepository($dir) {
  200. unish_file_delete_recursive($dir . '/.git');
  201. $this->execute("git init && git config user.email 'unish@drush.org' && git config user.name 'Unish' && git add . && git commit -m 'Initial commit.'", CommandUnishTestCase::EXIT_SUCCESS, $dir);
  202. }
  203. }