Adding a Local Environment Setup to an Existing Project That Doesn't Have One

I talk a ton on the blog about best practices for development here on the blog, and a big part of that is having a local (or cloud-based) development environment for each developer. But what happens if that doesn’t happen?

I was recently working on a project where all of the “development” work was being done directly in a shared, cloud development environment. When my team came in to do our work, our choices were essentially:

  • all pile into one of the shared, cloud environments (that the customer is also using)

  • setup what we recommend as best practice (which would be a local / personal development environment for each developer).

My preference and the direction we went was setting up the local environments. However, we rapidly ran into some issues with this because…

  • the production environment wasn’t using any sort of configuration management

  • composer was horribly out of date (a couple of years)

  • there were no drush aliases or configuration in the codebase

  • there’s no logic in the codebase for “per environment” settings or configuration.

So, unfortunately this wasn’t just a matter of provisioning a VM and running. This post will run through some of the stuff we had to do to get everything working.

Initial Repository Setup

The very first thing I did was setup a completely new Git repository. This is perhaps, not a critical first step, but looking at the codebase and the state it was in it seemed simpler to me. Also, I’m a huge proponent of using Acquia’s Build and Launch Tools (BLT) and since the prod codebase didn’t have BLT in place, this seemed more straight forward. Finally, the work my team was doing was more of an audit than a development effort. So, any of the risk for getting out of alignment between a new development repository and the hosting repository is mitigated (because we’ll never push any of the work we’re doing).

In this case, the version of Drupal was old enough that I had to use BLT 10.x (several versions back). This command looks something like:

composer create-project acquia/blt-project:^10 <project name>

Once BLT got its template setup, the next step was to retrofit the repository based on the production repository. This included:

  • replicating all of the composer dependencies

  • adding custom modules / themes / profiles

The end state of this portion was a repository that “more or less” resembled the production repo, but using a composer scaffolding that is more compatible with BLT and its view of the world.

A final note here, given the age of the production codebase I had to configure the site to use Composer 1. I wrote a blog post on how to run Composer 1 and Composer 2 simultaneously on the same host machine recently. You can also add additional config to your Lando file to constrain the composer version (which I’ll cover in the next section).

Environment Setup

With composer working the next step was to get an environment up and running that we can actually work in. Normally I would just install my BLT Lando plugin, but in this case the codebase is old enough (no composer 2 support in particular) that I couldn’t do this. Still, I just pulled the .lando.yml file I usually use and provisioned from there with one addition:

config:
  composer_version: '1.10.22'

While the Lando containers provisioned, I also setup the Drush aliases. Acquia gives you the ability to easily download Drush aliases for your project, although there is also a BLT plugin for this.

The last environmental setup / configuration step was making sure that local settings were configured properly for Lando. Remember, this was one of the biggest gaps in the original production repository. BLT ships with environment detection out of the box, and supports local settings files. So, in this case I just ran:

lando blt blt:init:settings 

this generated all of the necessary BLT settings files, and then I manually edited the local.settings.php file to set the database array for my drupal8 Lando recipe.

/**
 * Database configuration.
 */
$databases = [
  'default' =>
    [
      'default' =>
        [
          'database' => 'drupal8',
          'username' => 'drupal8',
          'password' => 'drupal8',
          'host' => 'database',
          'port' => '3306',
          'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
          'driver' => 'mysql',
          'prefix' => '',
        ],
    ],
];

Your miles may vary depending on which Lando recipe you’re using. The BLT Lando plugin also sets this up automatically with the recipe (but again, no plugin).

Working with the Environment

With Lando up, running, and configured, the last step was to replicate production. BLT gives a couple of useful commands for this (but you can totally do it without BLT). The TLDR is:

  • You need the database

    • existing

      • with blt

        • lando blt sync:db

      • OR if you aren’t using BLT

        • lando drush sql-sync (don’t forget to also drush sql-sanitize!)

    • OR if you are pretty confident you just need to install Drupal

      • with blt

        • lando blt setup:drupal:install

      • OR if you aren’t using BLT

        • lando drush site-install

  • You need the files

    • with blt

      • lando blt sync:files

    • OR if you aren’t using BLT

      • lando drush rsync

From here, we just need to log in with lando drush uli.

Now, in our case, we had a lot of module version mismatch issues we had to resolve… but otherwise, we had a local ready to go. We committed the config and shared it amongst the team so that we could all use it, and we’re off to the races!

In Conclusion

Having local environments for your developers is a critical component of a healthy ecosystem. They are expendable, they are dedicated, and they are the right place for devs to experiment, work, etc. If you don’t have them, it’s not the end of the world! You can definitely add them later in the process, but… it’s definitely easier to get off on the right foot and do it right from the start.

Hello, World!

a

Related Content