diff --git a/.travis.yml b/.travis.yml
index 66ff907aa4731471d453ce109a1e97a18ec8f569..b40dbc55ea55bf20e8589e3aac8fc96ee358c8c0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ cache:
   directories:
     - "$HOME/.composer/cache"
     - "$HOME/.drush/cache"
-    - "$HOME/.npm"
+
 php:
   - 7.1
 
@@ -26,38 +26,33 @@ addons:
   chrome: stable
 
 before_install:
-  # Tweak PHP configuration.
-  - phpenv config-add ./tests/travis.php.ini
-  - phpenv rehash
-
   - composer self-update
   - composer --version
   - google-chrome-stable --version
 
   - export ORCA=$TRAVIS_BUILD_DIR/../orca
   - export ORCA_FIXTURE=$ORCA-build
-  - export ORCA_SUT=drupal/lightning_workflow
+  - export ORCA_SUT_NAME=drupal/lightning_workflow
+  - export ORCA_SUT_BRANCH=8.x-3.x
+  - export ORCA_PACKAGES_CONFIG_ALTER=../lightning-workflow/tests/packages.yml
 
   - export PATH="$HOME/.composer/vendor/bin:$PATH"
   - export PATH="$ORCA/bin:$PATH"
   - export PATH="$ORCA/vendor/bin:$PATH"
   - export PATH="$ORCA_FIXTURE/vendor/bin:$PATH"
 
-  # Add the ORCA repository.
-  - composer config --global repositories.orca vcs "https://github.com/acquia/orca"
-  # Use a personal access token to authenticate with GitHub, to avoid being
-  # rate-limited. The token is configured in the Travis CI repository settings.
-  - composer config --global github-oauth.github.com $GITHUB_API_TOKEN
+  # Install ORCA and prepare the environment.
+  - git clone --branch develop --depth 1 https://github.com/acquia/orca.git $ORCA
+  - $ORCA/bin/travis/before_install.sh
 
 install:
-  - composer create-project --stability dev --no-dev acquia/orca $ORCA
-  - "$ORCA/bin/travis/install 8.x-3.x"
+  - $ORCA/bin/travis/install.sh
 
   # Run ORCA static analysis tools.
   - orca static-analysis:run ./
 
   # Use ORCA to build the code base.
-  - orca fixture:init -f --sut $ORCA_SUT $ORCA_FIXTURE_FLAGS
+  - orca fixture:init -f --sut $ORCA_SUT_NAME --core 8.7.x-dev $ORCA_FIXTURE_FLAGS
   - # Install dev dependencies.
   - composer require --dev drupal/inline_entity_form --working-dir $ORCA_FIXTURE
 
@@ -66,7 +61,7 @@ before_script:
   - $TRAVIS_BUILD_DIR/update.sh $VERSION
 
 script:
-  - orca tests:run --sut $ORCA_SUT $ORCA_TEST_FLAGS
+  - orca tests:run --sut $ORCA_SUT_NAME $ORCA_TEST_FLAGS
 
 after_failure:
   - cd docroot
diff --git a/config/optional/views.view.moderation_history.yml b/config/dynamic/views.view.moderation_history.yml
similarity index 99%
rename from config/optional/views.view.moderation_history.yml
rename to config/dynamic/views.view.moderation_history.yml
index 4e80e1638912400aed79a4b24ece088f67675c41..00e25a80604252a4e1f535aa7e31def1f880acab 100644
--- a/config/optional/views.view.moderation_history.yml
+++ b/config/dynamic/views.view.moderation_history.yml
@@ -1,10 +1,5 @@
 langcode: en
 status: true
-dependencies:
-  module:
-    - content_moderation
-    - node
-    - user
 id: moderation_history
 label: 'Moderation history'
 module: views
diff --git a/lightning_workflow.module b/lightning_workflow.module
index 99e351002305654291e2159275f5346310880f08..ed8049ad797409db0a300642500e962ac27be3e5 100644
--- a/lightning_workflow.module
+++ b/lightning_workflow.module
@@ -12,11 +12,13 @@ use Drupal\Core\Entity\EntityPublishedInterface;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Serialization\Yaml;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\lightning_core\Element;
 use Drupal\lightning_core\Routing\RouteSubscriber;
 use Drupal\lightning_workflow\Plugin\views\field\NodeBulkForm;
 use Drupal\node\NodeTypeInterface;
+use Drupal\views\Entity\View;
 use Drupal\views\ViewEntityInterface;
 use Drupal\views\ViewExecutable;
 use Drupal\workflows\Entity\Workflow;
@@ -42,10 +44,25 @@ function lightning_workflow_node_type_insert(NodeTypeInterface $node_type) {
 
   $plugin = $workflow->getTypePlugin();
   if ($plugin instanceof ContentModerationInterface) {
-    // We need to rebuild all routes because Content Moderation needs to ensure
-    // that edit forms load the latest revision.
     $plugin->addEntityTypeAndBundle('node', $node_type->id());
     $workflow->save();
+
+    // The moderation_history view depends on the existence of the
+    // moderation_state base field, which is only defined once a content type
+    // has been opted into moderation. Now that's done, so create the
+    // moderation_history view if it doesn't already exist.
+    if (Drupal::moduleHandler()->moduleExists('views')) {
+      $view = View::load('moderation_history');
+
+      if (empty($view)) {
+        $values = file_get_contents(__DIR__ . '/config/dynamic/views.view.moderation_history.yml');
+        $values = Yaml::decode($values);
+        View::create($values)->save();
+      }
+    }
+    // We need to rebuild all routes because Content Moderation needs to ensure
+    // that edit forms load the latest revision, and that the moderation_history
+    // view's routes are registered if needed.
     Drupal::service('router.builder')->rebuild();
   }
 }
diff --git a/modules/lightning_scheduler/lightning_scheduler.module b/modules/lightning_scheduler/lightning_scheduler.module
index 482098d343c1984c846a37a2b607fec1708a53f9..2733c76a8c3d25e074d78304cc947f69fea0b6ab 100644
--- a/modules/lightning_scheduler/lightning_scheduler.module
+++ b/modules/lightning_scheduler/lightning_scheduler.module
@@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Extension\Extension;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Update\UpdateKernel;
 use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
 use Drupal\lightning_core\OverrideHelper;
 use Drupal\lightning_scheduler\Plugin\Field\FieldWidget\ModerationStateWidget;
@@ -42,6 +43,13 @@ function lightning_scheduler_system_info_alter(array &$info, Extension $extensio
  * Implements hook_cron().
  */
 function lightning_scheduler_cron() {
+  // Do not execute during database updates. This hook could be invoked if, for
+  // example, Automated Cron is triggered at the end of one of the many HTTP
+  // requests that are made during an update.php process.
+  if (Drupal::service('kernel') instanceof UpdateKernel) {
+    return;
+  }
+
   $field_map = Drupal::service('entity_field.manager')->getFieldMap();
 
   /** @var \Drupal\lightning_scheduler\TransitionManager $transition_manager */
@@ -76,6 +84,7 @@ function lightning_scheduler_cron() {
  */
 function lightning_scheduler_entity_base_field_info(EntityTypeInterface $entity_type) {
   $fields = [];
+  /** @var \Drupal\content_moderation\ModerationInformationInterface $moderation_info */
   $moderation_info = Drupal::service('content_moderation.moderation_information');
 
   $migrations = Drupal::service('lightning_scheduler.migrator')->getMigrations();
diff --git a/modules/lightning_scheduler/tests/fixtures/BaseFieldMigrationTest.php.gz b/modules/lightning_scheduler/tests/fixtures/BaseFieldMigrationTest.php.gz
index ceeb80171b550add3d3de245c1ce942f13fee949..b62ce56f9bdbc10bfd4039c12e388bf70821b4ae 100644
Binary files a/modules/lightning_scheduler/tests/fixtures/BaseFieldMigrationTest.php.gz and b/modules/lightning_scheduler/tests/fixtures/BaseFieldMigrationTest.php.gz differ
diff --git a/modules/lightning_scheduler/tests/src/Functional/MigrationTestBase.php b/modules/lightning_scheduler/tests/src/Functional/MigrationTestBase.php
index 071b7f47770139d3fe88add72c7ede5b2aa27f78..8ca82472666ce6a841761604da9098c2855bfe88 100644
--- a/modules/lightning_scheduler/tests/src/Functional/MigrationTestBase.php
+++ b/modules/lightning_scheduler/tests/src/Functional/MigrationTestBase.php
@@ -16,16 +16,6 @@ abstract class MigrationTestBase extends UpdatePathTestBase {
   }
 
   public function test() {
-    // Forcibly uninstall Lightning Dev. It is mentioned in the fixture, but not
-    // physically present in ORCA fixtures.
-    $this->config('core.extension')
-      ->clear('module.lightning_dev')
-      ->save();
-    $this->container
-      ->get('keyvalue')
-      ->get('system.schema')
-      ->deleteMultiple(['lightning_dev']);
-
     $this->runUpdates();
 
     $migrations = $this->container->get('state')->get('lightning_scheduler.migrations');
diff --git a/tests/packages.yml b/tests/packages.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1a4b983963b64d9206c297f79450bf118068c64d
--- /dev/null
+++ b/tests/packages.yml
@@ -0,0 +1,5 @@
+drupal/lightning_api:
+  version_dev: 4.x-dev
+
+drupal/lightning_core:
+  version_dev: 4.x-dev
diff --git a/tests/src/Functional/ModerationHistoryTest.php b/tests/src/Functional/ModerationHistoryTest.php
index 2655d250896549f7824ff2c4992562e6c40450eb..fd11cdef9b83dc9198b972b7681a1eed94a2cfbf 100644
--- a/tests/src/Functional/ModerationHistoryTest.php
+++ b/tests/src/Functional/ModerationHistoryTest.php
@@ -21,22 +21,9 @@ class ModerationHistoryTest extends BrowserTestBase {
     'views',
   ];
 
-  /**
-   * The content type created during the test.
-   *
-   * @var \Drupal\node\NodeTypeInterface
-   */
-  private $nodeType;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->nodeType = $this->createContentType();
-  }
-
   public function testModerationHistory() {
+    $node_type = $this->createContentType();
+
     $user_permissions = [
       'administer nodes',
       'bypass node access',
@@ -48,10 +35,12 @@ class ModerationHistoryTest extends BrowserTestBase {
     $user_a = $this->createUser($user_permissions, 'userA');
     $user_b = $this->createUser($user_permissions, 'userB');
 
-    $this->enableModeration();
+    // Enable moderation for the content type.
+    $node_type->setThirdPartySetting('lightning_workflow', 'workflow', 'editorial');
+    lightning_workflow_node_type_insert($node_type);
 
     $node = $this->createNode([
-      'type' => $this->nodeType->id(),
+      'type' => $node_type->id(),
       'title' => 'Foo',
       'moderation_state' => 'draft',
     ]);
@@ -71,16 +60,6 @@ class ModerationHistoryTest extends BrowserTestBase {
     $this->assertSession()->pageTextContainsOnce('Set to published on ' . $date_formatter->format($timestamp_b, 'long') . ' by ' . $user_b->getUsername());
   }
 
-  /**
-   * Enables moderation for the content type under test.
-   */
-  private function enableModeration() {
-    $this->nodeType->setThirdPartySetting('lightning_workflow', 'workflow', 'editorial');
-
-    \Drupal::moduleHandler()
-      ->invoke('lightning_workflow', 'node_type_insert', [ $this->nodeType ]);
-  }
-
   /**
    * Creates a new revision of the given $node.
    *
diff --git a/tests/travis.php.ini b/tests/travis.php.ini
deleted file mode 100644
index 9e6040815ad0f0d38e624f20661487e3c1f6fa2c..0000000000000000000000000000000000000000
--- a/tests/travis.php.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-; PHP configuration for Travis CI.
-; This file must be named travis.php.ini in order to override travis.ini, which
-; is created by Travis CI.
-max_execution_time = 120
-sendmail_path = /bin/true