Skip to content
This repository has been archived by the owner on Feb 13, 2023. It is now read-only.

Best practices for using Drupal VM in a project repository / with teams #305

Closed
TravisCarden opened this issue Nov 11, 2015 · 42 comments
Closed
Labels
Milestone

Comments

@TravisCarden
Copy link
Contributor

I'm working on a project where drupal-vm has been added to the application repository in a box directory, and I would like to know if that reflects best practices in the Vagrant community. It would make much more sense to me to have the Vagrantfile in the repo root so that I could issue commands against the VM from anywhere inside my project's directory tree rather than having to cd into box. Would I be correct to assume that projects with from scratch Vagrant setups tend to do it that way? Is there a precedent for Vagrant "distributions" like drupal-vm? Is there any way to manage drupal-vm as a dependency, as with Composer--or is it even intended to be included inside other projects in the way I'm talking about it?

@geerlingguy
Copy link
Owner

Would I be correct to assume that projects with from scratch Vagrant setups tend to do it that way?

Yep.

Is there a precedent for Vagrant "distributions" like drupal-vm?

Not so much that I've seen... one pattern some projects use is to have the box in a subdir (as you seem to be using); other patterns are to have Drupal VM installed completely independently, just referencing the project's docroot. There are a couple other projects (like a Node.js UI in front of Drupal VM for a very MAMP-like experience for adding/managing sites) that are trying to set a few different standards too.

Is there any way to manage drupal-vm as a dependency, as with Composer--or is it even intended to be included inside other projects in the way I'm talking about it?

Unfortunately, no; I haven't seen any way to configure a particular Vagrant setup using something like npm, composer, pip, rubygems, etc., though I do think that would be awesome.

I built (and maintain) Drupal VM as a completely independent project divorced from any single project configuration because I develop it first and foremost for myself :)

For my own usage I:

  • Have Drupal docroots or project folders in a separate location on my workstation (e.g. in ~/Sites/projectname).
  • Install copies of Drupal VM (one per project, usually, but sometimes one Drupal VM instance that runs a bunch of sites for things like multisite or when they're a bunch of small/similar sites) inside a separate directory (e.g. in ~/Sites/VMs/projectname).
  • Configure config.yml in Drupal VM to point to the Drupal docroots.
  • I also use Drupal VM for core and contrib work, in which case I just create a clone, build it with the right settings, and start hacking on the default core/contrib it downloads when it builds Drupal.

Would love to hear how other projects and teams are incorporating Drupal VM into their workflow and/or project repositories themselves. I know for a fact that some teams just fork Drupal VM in its entirety and include everything in the root directory of the project.

@geerlingguy
Copy link
Owner

One other note I forgot to mention:

For my real big Drupal sites (e.g. ones that aren't personal, for fun, or for friends, like Server Check.in or Hosted Apache Solr), I actually do fork Drupal VM and create the entire project directory based around Drupal VM.

Of course, I also use the Drupal VM configuration (hacked a bit to just include Nginx, and just include the things/configuration I install on prod servers) to actually build my local, dev (cloud-based) and prod (cloud-based) environments... some teams just use Drupal VM for local environments, so their needs are a bit different.

@oxyc
Copy link
Collaborator

oxyc commented Nov 11, 2015

Our team has set it up with the following structure:

- lib/drupal-vm       # git submodule
- vm/                 # running `make vm` copies the vm files here and symlinks the config
- config/config.yml   # Symlinked into the vm/ directory
- config/Vagrantfile  # A customised version which gets symlinked over drupal-vms version
- Vagrantfile         # simply delegates to vm/Vagrantfile
- Makefile

Makefile

vm:
    cp -r lib/drupal-vm vm
    ln -sf ../config/config.yml vm/config.yml
    ln -sf ../config/Vagrantfile vm/Vagrantfile

Root Vagrantfile

dir = File.dirname(__FILE__) + '/'
load dir + "vm/Vagrantfile"

This way it's somewhat easier to bring in VM updates from upstream, while being able to run vagrantcommands from anywhere in the our main repo.

My wishlist:

  • Get add support for overriding any synced_folder option #293 merged so we dont need to maintain our version of the Vagrantfile
  • Ansible 2.0 as it might be possible to store the actual config.yml outside the drupal-vm directory and therefore remove the need for a make vm step and use the drupal-vm directory as an unmodified git submodule checkout.

Btw, I'll take the opportunity and thank you @geerlingguy for an amazing project! We're currently using it for all our Drupal projects as well as all our Wordpress projects :) It's by far the most flexible VM solution I've come across.

@frob
Copy link
Contributor

frob commented Nov 11, 2015

We are using it as part of a custom gulp based project builder. Gulp downloads all dependencies according to their kind and builds it all and puts it all in its place. This allows us to build things that are not built around any specific tech.

@geerlingguy geerlingguy changed the title Best practices for including drupal-vm in a project repository Best practices for using drupal-vm in a project repository / with teams Nov 13, 2015
@geerlingguy geerlingguy changed the title Best practices for using drupal-vm in a project repository / with teams Best practices for using Drupal VM in a project repository / with teams Nov 13, 2015
@TravisCarden
Copy link
Contributor Author

Well, I've already shared what my team is currently doing. Here's how I would like things to work:

  • The Vagrantfile would be in the root directory of the repo so that vagrant commands could be issued from anywhere within.
  • All support files would be stored in the location(s) an active member of the Vagrant open source community would expect to find them in. I prefer to observe conventions and best practices from the domain a technology belongs to rather than inventing my own paradigms.
  • There would be a clear distinction between files that came from drupal-vm and files that are a part of my project so that people would not assume, for example, that drupal-vm's README is project documentation that can or should be followed exactly in our context. That's one of the nice things about a vendor directory for Composer packages--nobody mistakes its contents for custom project assets.
  • If a team wants to track upstream changes, then the project would be included with a package management solution like Composer. If not (or if the project doesn't wish to support such a mechanism), perhaps a one-time installer would be the way to go.

I'll give some more thought to how these goals might be accomplished in terms of mechanics.

@oxyc
Copy link
Collaborator

oxyc commented Nov 14, 2015

I've got a proof of concept working:

Create a Vagrantfile in your project root directory which delegates all vagrant commands to the real drupal-vm Vagrantfile.

dir = File.dirname(File.expand_path(__FILE__))

# Override the default config.yml location by specifying it's location globally.
$vconfig_file = "#{dir}/config.yml"
# Load the real Vagrantfile, this could also be within a composer vendor directory.
load "#{dir}/vm/Vagrantfile"

Modify drupal-vm Vagrantfile to use the global variable if defined, and pass the path on to Ansible.

diff --git a/Vagrantfile b/Vagrantfile
index 1243c26..0f68471 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -17,10 +17,13 @@ end
 # Use config.yml for basic VM configuration.
 require 'yaml'
 dir = File.dirname(File.expand_path(__FILE__))
-if !File.exist?("#{dir}/config.yml")
+if !defined?($vconfig_file)
+  $vconfig_file = "#{dir}/config.yml"
+end
+if !File.exist?($vconfig_file)
   raise 'Configuration file not found! Please copy example.config.yml to config.yml and try again.'
 end
-vconfig = YAML::load_file("#{dir}/config.yml")
+vconfig = YAML::load_file($vconfig_file)

 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   config.vm.hostname = vconfig['vagrant_hostname']
@@ -86,6 +89,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   if which('ansible-playbook')
     config.vm.provision "ansible" do |ansible|
       ansible.playbook = "#{dir}/provisioning/playbook.yml"
+      ansible.extra_vars = {
+        config_file: $vconfig_file
+      }
       ansible.sudo = true
     end
   # Provision using shell provisioner and JJG-Ansible-Windows otherwise.

Modify the playbook to include the config file dynamically at runtime instead.

diff --git a/provisioning/playbook.yml b/provisioning/playbook.yml
index 60b00de..77a1c15 100644
--- a/provisioning/playbook.yml
+++ b/provisioning/playbook.yml
@@ -1,10 +1,8 @@
 ---
 - hosts: all

-  vars_files:
-    - ../config.yml
-
   pre_tasks:
+    - include_vars: "{{config_file}}"
     - include: tasks/init-debian.yml
       when: ansible_os_family == 'Debian'
     - include: tasks/init-redhat.yml

This could be cleaned up a bit (maybe use an environment variable instead), but would support storing the drupal-vm in an unmodified tree either as a git submodule, or as a composer library. The only thing the user needs to do is to create a secondary Vagrantfile in the project root directory that sets the vconfig path, and delegates everything to the real Vagrantfile. After that vagrant commands can run from anywhere within the project tree.

@frob
Copy link
Contributor

frob commented Nov 14, 2015

I have to say that I disagree with this approach. I my team's workflow
drupalvm is a tool and not the project.

The project is managed by gulp. Gulp downloads drupalvm along with all our
other project repositories. Vagrant commands are wrapped in gulp commands
and thus the vagrant file can be anywhere in our project folder. Gulp
configures vagrant to share from a build directory and all our source
repositories are stored in src.

In the end this keeps projects separate and allow the tools to be updated
independent of the project.

On Sat, Nov 14, 2015, 06:22 Oskar Schöldström notifications@github.com
wrote:

I've got a proof of concept working:

dir = File.dirname(FILE) + '/'

Override the default config.yml location by specifying it's location globally.$vconfig_file = "#{dir}/config.yml"# Load the real Vagrantfile, this could also be within a composer vendor directory.

load "#{dir}/vm/Vagrantfile"

Modify the Vagrantfile to use the global variable if defined, and pass the
path on to Ansible.

diff --git a/Vagrantfile b/Vagrantfile
index 1243c26..0f68471 100644--- a/Vagrantfile+++ b/Vagrantfile@@ -17,10 +17,13 @@ end

Use config.yml for basic VM configuration.

require 'yaml'
dir = File.dirname(File.expand_path(FILE))-if !File.exist?("#{dir}/config.yml")+if !defined?('$vconfig_file')+ $vconfig_file = "#{dir}/config.yml"+end+if !File.exist?($vconfig_file)
raise 'Configuration file not found! Please copy example.config.yml to config.yml and try again.'
end-vconfig = YAML::load_file("#{dir}/config.yml")+vconfig = YAML::load_file($vconfig_file)

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.hostname = vconfig['vagrant_hostname']@@ -86,6 +89,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
if which('ansible-playbook')
config.vm.provision "ansible" do |ansible|
ansible.playbook = "#{dir}/provisioning/playbook.yml"+ ansible.extra_vars = {+ config_file: $vconfig_file+ }
ansible.sudo = true
end

Provision using shell provisioner and JJG-Ansible-Windows otherwise.

Modify the playbook to include the config file dynamically instead.

drupal-vm master*: gddiff --git a/provisioning/playbook.yml b/provisioning/playbook.yml
index 60b00de..77a1c15 100644--- a/provisioning/playbook.yml+++ b/provisioning/playbook.yml@@ -1,10 +1,8 @@


  • hosts: all
    • vars_files:- - ../config.yml-
      pre_tasks:+ - include_vars: "{{config_file}}"
    • include: tasks/init-debian.yml
      when: ansible_os_family == 'Debian'
    • include: tasks/init-redhat.yml

This could be cleaned up a bit maybe, but would support storing the
drupal-vm in an unmodified tree either as a git submodule, or as a composer
library. The only thing the user needs to do is to create a secondary
Vagrantfile in the project root directory that sets the vconfig path, and
delegates everything to the real Vagrantfile. After that vagrant commands
can run from anywhere within the project tree.


Reply to this email directly or view it on GitHub
#305 (comment)
.

@oxyc
Copy link
Collaborator

oxyc commented Nov 14, 2015

@frob if the approach you mentioned is the one I posted, it does exactly that no? Separating drupal-vm into an easily updatable tool instead of having it scattered within the project.

Only difference is it uses a delegating Vagrantfile instead of a delegating gulpfile.

@frob
Copy link
Contributor

frob commented Nov 14, 2015

@oxyc Sorry, I didn't see the vagrantfile delegation, and I didn't know that was possible. If none of those modifications break drupal-vm working as a standalone part, then I think they would make good additions. As it stands my I have gulp commands that modify the config based on the project; this should let us specify an outside location for project specific config.

@TravisCarden "All support files would be stored in the location(s) an active member of the Vagrant open source community would expect to find them in. I prefer to observe conventions and best practices from the domain a technology belongs to rather than inventing my own paradigms"

How about a pull request or some direction as to where these locations are.

@frob
Copy link
Contributor

frob commented Nov 17, 2015

@oxyc I tried your Vagrantfile delegation. I found it lead to unstable results. I am running on osx 10.10. When I ran that, and I provisioned without going through the delegate Vagrant file, vagrant would give me an incorrect status when I ran vagrant status through the delegate.

@oxyc
Copy link
Collaborator

oxyc commented Nov 18, 2015

@frob ah, nice research! Maybe the .vagrant/ directory is created in the subdirectory and therefore not accessible in the root. Or maybe it's a typo somewhere on my part as I posted the patches... I'll try to test it more later this week

@TravisCarden
Copy link
Contributor Author

And, @frob, my remark about wanting things to be stored where an active member of the Vagrant community would expect to find them was not meant to imply that I know where those locations are. I don't, as I'm only starting out with Vagrant myself. My reason for creating this issue was to see if others could supply that knowledge of best practices that I lack in this instance. :)

@frob
Copy link
Contributor

frob commented Nov 19, 2015

@oxyc I think you assumption about the .vagrant directories is correct.

I noticed that there where .vagrant directories in both the drupal-vm directory and the project root.

@geerlingguy
Copy link
Owner

Also, check out a tool like Lunchbox, which @nateswart has been working on as a kind of GUI wrapper around Drupal VM. I know there are a few different tools set up like this to 'wrap' Drupal VM, and it would be interesting to see if there are some ways we can make the core of Drupal VM be flexible and work well with all these tools.

@devekko
Copy link

devekko commented Dec 4, 2015

this is orthogonal to Drupal VM, but its solving the same problem

I've been looking into tsuru.io, a Heroku esque paas
tsuru/tsuru#1321

I noticed Heroku provide dev - prod parity using Docker for local dev

https://blog.heroku.com/archives/2015/5/5/introducing_heroku_docker_release_build_deploy_heroku_apps_with_docker

secondly, I use Aegir 3 git provisioning with direct git remotes to Pantheon from a Vagrant VM using many of the Drupal VM Ansible roles

its a good local development environment and it has a deployment system built in

it also has the advantage of using Aegir and so I have 1 VM, not many.. easier to manage imho
https://github.com/GetValkyrie/valkyrie

@fubarhouse
Copy link

Over the past 12 months, I've created and am currently maintaining fairly complicated DrupalVM setup

The process in which the supported machines work is that a bash script goes and git clone/pull various repositories before copying the configuration files and performing many sed commands to modify and change settings. I've got some interesting things going on such as a random IP address and several custom ansible roles.

The provisioning process isn't configured to build any sites but I've created lots of integrated scripts for various functions such as building new sites from an acquia account, rebuilding, killing off, database download/upload, file download/upload, remaking all the virtual hosts on nginx and apache if the respective file system exists... There are dozens of utility scripts I've created which all communicate with each other and a command line interface menu style script.

During this process it'll also git pull the respective "code bases" on the acquia account so that when commits are made they're up to date...

Reprovisioning is kinda like maintenance, it'll go through and fix anything that shouldn't be as it is, update any packages or software and most importantly update all the scripts stored in git we use for development.

Yeah it's all command line, and a GUI would be incredible, but it's a matter of application to the needs of the user. I get paid to look after this thing as well as develop websites, so I have to commit my time to the best use of my organisation. A web GUI isn't feasible in my case.

@devekko
Copy link

devekko commented Jan 4, 2016

I would also add

Laravel's Homestead and Joomla's Joomla Box are worth looking at

http://laravel.com/docs/4.2/homestead

https://github.com/joomlatools/joomlatools-vagrant

@geerlingguy
Copy link
Owner

Could those involved in this thread have a look at #378 from @frob and give some feedback? This method would allow Drupal VM to exist on its own or within another project inside a directory (e.g. box or something like that). There are still things to work out with the approach, but it doesn't seem too unwieldy to me.

For my own needs, when I have Drupal VM in a project, I add a second example.config.yml for devs to clone inside a box directory, then devs cd into that directory to manage the VM (other work is done within the root directory). Not too much more hassle, but it would be cool to be able to do all the vagrant stuff from the project root.

@oxyc
Copy link
Collaborator

oxyc commented Jan 31, 2016

Had a look at beetbox and saw they loaded a local.config.yml if available.

This could be pretty useful for teams to track a shared config and then let individual developers override things with the untracked local.config.yml.

Edit: Just noticed something similiar was suggested before. #317

@geerlingguy
Copy link
Owner

@oxyc - At a minimum, I like this idea as well. I currently hack example.config.yml when I need to have project-specific overrides shared with a team, and that's not ideal.

I think Drupal VM's solidly used by many teams now, whereas I originally built it only for individual usage patterns.

@oxyc
Copy link
Collaborator

oxyc commented Feb 1, 2016

If we add support for a local.config.yml, storing Drupal VM in a subdirectory (#378) as well as Vagrantfile.local (merged in #401 already), I think we would have solved most issues mentioned here. Except for actually managing drupal vm as a dependency.

Could then merge all the docs from those issues into a Using Drupal VM with teams section.

@ctorgalson
Copy link
Contributor

A big +1 to the idea of support for local.config.yml (as well as Vagrantfile.local--nice addition).

Just to offer another use-case, I usually need to work on several projects concurrently, and (provided the environments don't need to differ substantially) I find an individual VM per project to be too heavy. So I typically have 1-3 VMs containing a couple or several projects, with config.yml (or equivalent) files version-controlled separately.

More on-topic, if my team were all using the same dev environment (we don't...), I think we'd probably structure the files so that we could include at most config.yml in the repository. E.g. like this:

project
  - box
    - config.yml 
    - drupal-vm
      - config.yml -> ../config.yml
      - [ other drupal-vm files ]
  - docroot

...with a .gitignore like this (or just git add -f):

box/*
!box/config.yml

This means setup for anyone to join or test the project is cloning drupal-vm into the boxes directory and creating a symlink. But I'm not even sure we'd want any of the dev environment configuration in the actual repo.

@fubarhouse
Copy link

I've gotten around this problem by adding a local variables file in /provisioning/vars/vars.yml or something to that effect and including it. There's no need for a full new config file when you can simply override everything by redeclaring the variables in question.

It helps with maintainability when you need to upgrade the config files.... Which I need to do again soon!

@frob
Copy link
Contributor

frob commented Feb 2, 2016

@fubarhouse I think that is exactly what they are using the config.local.yml for.

@geerlingguy
Copy link
Owner

I've updated the docs a bit to highlight some of the tools that can help manage Drupal VM (either for individuals or as part of a team): http://docs.drupalvm.com/en/latest/other/management-tools/

But a lot of the work @oxyc and others have been working on will make Drupal VM much more flexible in a team environment, most especially the idea of a 'local' Vagrantfile and a 'local' config.yml (just like Drupal 8 now has a baked in local settings.php option).

@geerlingguy
Copy link
Owner

I'd like to talk specifically about this issue (but also anything that's related) at DrupalCon NOLA—please come to the BoF: Drupal VM and local Drupal development for teams

  • Wednesday, 10:45 - 11:45 p.m.
  • Room 289 (Chromatic)

@oxyc
Copy link
Collaborator

oxyc commented Apr 7, 2016

Thought I'd describe my ideal setup for teams:

repository
  - lib/
    - drupal-vm/ # git submodule
      - example.config.yml
    - company-conf/ # git submodule
      - drupal-vm.config.yml # company specific configurations
  - config/
    - drupal-vm.config.yml # This is a project specific config
    - drupal.make.yml #
    - deploy.rb
    - ....
  - docroot/
    - index.php
    - ....
  - Vagrantfile
  - local.config.yml
  1. The root Vagrantfile would delegate all commands to lib/drupal-vm/Vagrantfile which is a locked checkout of the Drupal VM repository. There's an active PR for this.
  2. The delegating Vagrantfile would also specify that the config.yml file is located in config/drupal-vm.config.yml. This file should somehow also include the config file in lib/company-conf/drupal-vm.config.yml.

Project specific config/drupal-vm.config.yml would only contain project specifc settings and overrides. If the site needs SOLR it would be added here for example.

 vagrant_hostname: project.dev
 vagrant_machine_name: project
 vagrant_ip: 192.168.87.77

Company shared lib/company-conf/drupal-vm.config.yml contains company best-practice configurations to streamline development.

vagrant_box: geerlingguy/ubuntu1404
vagrant_user: vagrant
vagrant_synced_folder_default_type: nfs

... and the rest of the configuration.

User specific local.config.yml which is untracked would contain eg:

vagrant_memory: 2048

This would make it very easy to share configurations across multiple projects and keep them all up to date with Drupal VM. It still is able to lock all versions of everything not to break on updates.

Except for the inheritable config files this is the structure we use where I work at the moment. We just have a make vm task that copies lib/drupal-vm/ into vm/ and symlinks config/drupal-vm.config.yml to vm/config.yml. With this setup the delegating Vagrantfile works already.

@frob
Copy link
Contributor

frob commented Apr 7, 2016

This looks like it is becoming a new project all on its own. I would hope the goal for drupalvm is to be flexible enough to allow for this, but not dictate it.

@oxyc
Copy link
Collaborator

oxyc commented Apr 7, 2016

Yes for sure. It needs to be easy to get started. Once Vagrant 1.8.2 comes out the delegating Vagrantfile PR would be possible. The only other feature needed would be to allow multiple config files to be read. There's a related task for this already #455

@oxyc
Copy link
Collaborator

oxyc commented Apr 7, 2016

I'm still in the process of upgrading our ~20 repos to use php5-fpm instead of mod_php since that became the default in Drupal VM. Having a company wide base config to inherit from would make it a lot easier to maintain :)

@joestewart
Copy link
Contributor

Looking forward to a sprint to get this nailed down at Drupalcon.

I've been testing #378 to ease the upgrade situation across many projects.

@fubarhouse
Copy link

@oxyc I've also adopted the use of php5-fpm when using nginx, and mod_php with apache2 on the drupal vm platform.

I don't actually know if there's an equivalent for php v7, but if in the event there is no equal, a solution will be needed.

@geerlingguy will the speech be available afterwards for us international people who're interested?

@geerlingguy
Copy link
Owner

@fubarhouse - I'll try to do so... will also try to find a way to connect to a Hangout or something like that too, so more people can remotely participate.

@mdrmike
Copy link

mdrmike commented Apr 19, 2016

I wanted to throw yeoman into the discussion, such as drupamvm generator. not sure if @kevinquillen has seen this thread (author or drupalvm generator).

@kevinquillen
Copy link

kevinquillen commented Apr 20, 2016

I have seen this thread - I recently updated the yeoman generator to be in line with the 2.4.0 release of DrupalVM. That yeoman script started as a more friendly assistant to non technical people who don't know much about conf names and values to guide them through setting up a config.yml for DrupalVM.

For us, every new project starts with the 'yo drupalvm' to generate the configuration. It is then committed into the project under tools/drupalvm, so anyone who checks out the project simply navigates to that directory and does vagrant up. These folks have vagrant autonetwork and hostsupdater plugin installed before hand, so 0.0.0.0 in the config.yml poses no conflict to them (which is how I will do any project I start).

Our projects look as such:

- docroot
- tools
--- drupalvm

We don't use one VM to run multiple sites. We run one VM dedicated to the project being worked on. We try to mirror the setup on Acquia, so when it is time to lift from local to dev, it's as smooth as it could be.

We have not run into an instance yet where Vagrantfile needed to be changed for particular team members. The only real pain point at the moment is winnfsd not working on all Windows machines. It only works for certain people and I cannot determine why yet - it causes us to have to use rsync instead in config.yml which I do not particularly enjoy at all - which is not an issue for DrupalVM but in that plugin.

From here it just takes a couple of minutes to hook up PHPStorm to point to the remote PHP interpreter in this vagrant machine, plus any additional things you'd like to set up (Behat, PHPCS, PHPMD, etc).

@thom8
Copy link
Collaborator

thom8 commented Apr 21, 2016

I've been watching this thread with interest as it's the primary reason Drupal VM was not suitable for our use case as we needed a centralised provisioning system across multiple projects each with their own configuration differences. The provisioning system also needed to be independent to each project so all dependencies were available to any single project.

This was the initial concept behind beetbox -- https://github.com/beetboxvm/beetbox
which uses the same roles as Drupal VM.

All provisioning scripts live inside the base box and don't need to be managed within the project, only overrides need to be set, upgrades are managed when updating the base box and project versions are in sync with the box versions. Unprovisioned base boxes are also supported if you need a very customised build.

There was also some unintended benefits - linked clones means we only need a single master VM of the base box and each VM is a lightweight clone + we're able to reuse the configuration to build out our CI environment which immediately fixed "only fails in CI" tests and any failed tests are easy to replicate locally.

Here's an example of a project which implements beetbox -- https://github.com/drupalmel/drupalmel

Only overrides are set in the project's config.yml (as we implement the same roles, almost all Drupal VM config vars are supported here) -- https://github.com/drupalmel/drupalmel/blob/master/.beetbox/config.yml

This project also has a custom post provisioning task to setup behat -- https://github.com/drupalmel/drupalmel/blob/master/.beetbox/tasks/post/behat.yml

And the CI build reuses the same config.yml -- https://circleci.com/gh/drupalmel/drupalmel/3 - (A fork/branch which changes config.yml will be tested with this config.)

Very interested in hearing the outcome of the BoF @ DC, will try to attend via hangouts if possible.

@oxyc
Copy link
Collaborator

oxyc commented Apr 29, 2016

I started playing around with d8 base repo to work from and so far came up with a heavily opinionated fork of drupal-project. In case someone is looking for ideas.

A lot of it is based on the conventions in roots/bedrock. I've learned to enjoy them and as our team uses both Drupal and Wordpress it helps to have a common structure.

  • Database settings and the hash salt are configured in a .env file. A project repo would supply a .env.example file which defaults to Drupal VM configurations. Other environments would have a customized one.

    This is mostly to streamline how we configure this both for Wordpress and for Drupal. But honestly I prefer it over settings.local.php. Now settings.local.php would only do things such as disabling varnish if unavailable in the specific environment.

  • Drupal VM is included as a git submodule with a delegating Vagrantfile. For now we need to run make vm each time we clone the repo.

  • Added a config/environments.yml file containing drush and trusted hosts info for all environments. Combined with our drush/aliases.drushrc.php all remote aliases work out of the box when a team member clones the repo.

  • We add config/environments/{development,production,staging}.php files that are included in settings.php depending on the environment mode. This way we can easily toggle development and production mode on the dev box by setting env: production in our .env file.

    Another bedrock convention mostly for streamlining things, but again I prefer this over adding conditionals to settings.php.

  • We use rsync for native speed, except for config/drupal (the sync config directory) which has NFS to get two-way sync when running drush config-export.

  • We use capistrano for deploying and the remote hosts are read from config/environments.yml as well.

@joestewart
Copy link
Contributor

@oxyc Is the delegating Vagrantfile committed to the project? Seems that this should moved into place as part of the make process.

A couple of things less on-topic -

I like the way the drush aliases read from the yaml file. Slick.

Curious if local drush site-install plays nicely with the .env and config/environments? Seems that Drush/Drupal install overwrite the settings.php file.

good stuff, thanks.

@oxyc
Copy link
Collaborator

oxyc commented Apr 29, 2016

@joestewart yes it's committed as it only contains a single load call to Drupal VMs version. The only thing done with the make task is copying the drupal-vm directory to a separate folder (vm/) and symlinking the config.yml file into that directory. Once we get #378 in, this step isn't needed anymore.

site-install works as the settings.php file already exists and is non-writable. One downside is that I need to change the install_profile variable manually if I change it in config.yml. But this isn't much of a hassle as it's only done once per project.

Yeah I like the environments.yml a lot as well! Eventually I plan to re-use this file for our capistrano deploy tasks. If we get custom includable config files (#559) it could even be re-used for setting vagrant_hostname and drupal_core_path in config.yml but that might just be unnecessarily complex...

@fubarhouse
Copy link

@oxyc with the correct command, you can specify the install profile through site-install.

http://drushcommands.com/drush-7x/core/site-install/

I've actually moved many of my scripts into jenkins on my vm, but I'm yet to approach the issue of getting the jenkins install on any other vms using the same system working with acquia, ssh and everything...

The VM can communicate with almost 200 independent websites and scripts can be made to do exactly that and also make local versions - and ansible could even template one based on variables and run it after completion - if users of drupal-vm are wanting to do something more unique.

I suppose the best way forward for automation would be to have some solid data demonstrating the demands of the users of drupal-vm and then discussing options...

@geerlingguy
Copy link
Owner

Thank you, everyone, for your amazing amount of input in this issue, outside this issue, in the halls of DrupalCon, etc. And thanks especially for @oxyc and @thom8 (among others) in pushing up some of the code to implement suggestions in here.

While we will have an ongoing discussion over ways to optimize Drupal VM for teams moving forward, I think a few of the more recent developments feature-wise will make team-based usage extremely efficient:

  1. Ability to provide a config.yml for the team (version controlled in the team's project repo), then have members override with local.config.yml (docs)
  2. Ability to override settings/provisioning via Vagrantfile.local (docs)
  3. Ansible role requirements file locks in role versions and stores them local to the VM directory, so you can have different VM versions on one computer (no shared roles, no 'always use master and break things' when upgrading).
  4. Projects like Acquia's Bolt, Lunchbox, etc. that add additional wrappers around Drupal VM's initial setup.

I'm missing a few of the other improvements here—forgive me, DrupalCon this year was quite a whirlwind, and I'm still compiling all my notes!—but I'll be wrapping things up a bit more in a blog post soon, and I think any further improvements will be best suited to their own dedicated issues.

Just to add a final summary of what I currently see as the best way of utilizing Drupal VM for a team:

  1. (Once Add composer.json, add Drupal VM to Packagist #628 lands) Add Drupal VM as a project dependency—OR place a copy of Drupal VM (either subtree/submodule/manual copy) in a vm or box directory alongside your docroot.
  2. Copy example.config.yml to config.yml and customize for your team's environment defaults.
  3. Each developer can then override specific settings in a gitignored local.config.yml (and, optionally, Vagrantfile.local.
  4. Generally, its preferable to maintain the building/updating of the Drupal codebase itself outside of Drupal VM, though automatic initial setup via make file or composer.json will be supported as it is now.
  5. For Drupal VM updates/upgrades, copy in all the Drupal VM files, and do a diff between the new example.config.yml and your config.yml, adding/modifying variables as noted in the version Release Notes on GitHub.

@fubarhouse
Copy link

@geerlingguy Thanks for the description above.

The steps you intend on providing will actually allow me to update my system without having to assess each line of code separately on each upgrade. I look forward to this, but it's useful to know the way I've implemented a system like this is already the best possible method to date.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests