From dedb5204f6cf085e0a2ed14812e3106cde2fdfa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Sch=C3=B6ldstr=C3=B6m?= Date: Fri, 3 Jun 2016 13:06:17 -0400 Subject: [PATCH 1/2] Add support for composer-based drupal site builds --- .travis.yml | 2 + README.md | 2 +- default.config.yml | 27 +++++-- docs/deployment/composer.md | 71 +++++++++++++++++++ example.drupal.composer.json | 35 +++++++++ mkdocs.yml | 1 + provisioning/playbook.yml | 13 ++++ provisioning/tasks/build-composer-project.yml | 15 ++++ provisioning/tasks/build-composer.yml | 29 ++++++++ provisioning/tasks/build-makefile.yml | 10 +-- tests/ubuntu-16-nginx.config.yml | 5 ++ 11 files changed, 197 insertions(+), 13 deletions(-) create mode 100644 docs/deployment/composer.md create mode 100644 example.drupal.composer.json create mode 100644 provisioning/tasks/build-composer-project.yml create mode 100644 provisioning/tasks/build-composer.yml diff --git a/.travis.yml b/.travis.yml index 4fd1c1096..3a8ab7b07 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ env: global: - CONFIG: tests/config.yml MAKEFILE: example.drupal.make.yml + COMPOSERFILE: example.drupal.composer.json HOSTNAME: drupalvm.dev MACHINE_NAME: drupalvm IP: 192.168.88.88 @@ -57,6 +58,7 @@ script: # Copy configuration files into place. - 'sudo docker exec "$(cat ${container_id})" cp ${DRUPALVM_DIR}/${CONFIG} ${config_dir:-$DRUPALVM_DIR}/config.yml' - 'sudo docker exec "$(cat ${container_id})" cp ${DRUPALVM_DIR}/${MAKEFILE} ${config_dir:-$DRUPALVM_DIR}/drupal.make.yml' + - 'sudo docker exec "$(cat ${container_id})" cp ${DRUPALVM_DIR}/${COMPOSERFILE} ${config_dir:-$DRUPALVM_DIR}/drupal.composer.json' # Override configuration variables. - '[[ ! -z "${local_config}" ]] && sudo docker exec "$(cat ${container_id})" bash -c "cp ${DRUPALVM_DIR}/${local_config} ${config_dir:-$DRUPALVM_DIR}/local.config.yml" || true' diff --git a/README.md b/README.md index d0b684e46..9a81d8c56 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you want to switch from Drupal 8 (default) to Drupal 7 on the initial install ## Quick Start Guide -This Quick Start Guide will help you quickly build a Drupal 8 site on the Drupal VM using the included example Drush make file. You can also use the Drupal VM with a [Local Drupal codebase](http://docs.drupalvm.com/en/latest/deployment/local-codebase/) or even a [Drupal multisite installation](http://docs.drupalvm.com/en/latest/deployment/multisite/). +This Quick Start Guide will help you quickly build a Drupal 8 site on the Drupal VM using the included example Drush make file. You can also use the Drupal VM with a [Composer based installation](http://docs.drupalvm.com/en/latest/deployment/composer/), with a [Local Drupal codebase](http://docs.drupalvm.com/en/latest/deployment/local-codebase/) or even a [Drupal multisite installation](http://docs.drupalvm.com/en/latest/deployment/multisite/). ### 1 - Install Vagrant diff --git a/default.config.yml b/default.config.yml index 4b2e46e05..212fa082e 100644 --- a/default.config.yml +++ b/default.config.yml @@ -21,7 +21,8 @@ vagrant_public_ip: "" # http://docs.drupalvm.com/en/latest/extras/syncing-folders/ for more info. vagrant_synced_folders: # The first synced folder will be used for the default Drupal installation, if - # build_makefile: is 'true'. By default it's set to the drupal-vm folder. + # any of the build_* settings are 'true'. By default the folder is set to + # the drupal-vm folder. - local_path: . destination: /var/www/drupalvm type: nfs @@ -34,17 +35,29 @@ vagrant_cpus: 2 # The web server software to use. Can be either 'apache' or 'nginx'. drupalvm_webserver: apache -# Set this to false if you are using a different site deployment strategy and +# Set this to 'false' if you are using a different site deployment strategy and # would like to configure 'vagrant_synced_folders' and 'apache_vhosts' manually. build_makefile: true drush_makefile_path: "{{ config_dir }}/drupal.make.yml" -# Set this to false if you don't need to install drupal (using the drupal_* +# Set 'build_makefile' to 'false' and this to 'true' if you are using a +# composer based site deployment strategy. +build_composer: false +drupal_composer_path: "{{ config_dir }}/drupal.composer.json" +drupal_composer_install_dir: "/var/www/drupalvm/drupal" +drupal_composer_dependencies: [] + +# Set this to 'true' and 'build_makefile', 'build_composer' to 'false' if you +# are using Composer's create-project as a site deployment strategy. +build_composer_project: false +drupal_composer_project_package: "" +drupal_composer_project_options: "--prefer-dist --stability dev --no-interaction" + +# Set this to 'false' if you don't need to install drupal (using the drupal_* # settings below), but instead copy down a database (e.g. using drush sql-sync). install_site: true -# Settings for building a Drupal site from a makefile (if 'build_makefile:' -# is 'true'). +# Settings for installing a Drupal site (if 'install_site:' is 'true'). drupal_major_version: 8 drupal_core_path: "/var/www/drupalvm/drupal" drupal_domain: "{{ vagrant_hostname }}" @@ -138,8 +151,8 @@ nginx_hosts: nginx_remove_default_vhost: true nginx_ppa_use: true -# MySQL Databases and users. If build_makefile: is true, first database will -# be used for the makefile-built site. +# MySQL Databases and users. If 'install_site' is 'true', first database will +# be used for the site. mysql_databases: - name: "{{ drupal_mysql_database }}" encoding: utf8 diff --git a/docs/deployment/composer.md b/docs/deployment/composer.md new file mode 100644 index 000000000..49841b209 --- /dev/null +++ b/docs/deployment/composer.md @@ -0,0 +1,71 @@ +Drupal VM is configured to use [Drush make](drush-make.md) by default but supports building Drupal from a custom composer.json or creating a project from a composer package (`composer create-project`). + +## Using composer.json + +1. Copy `example.drupal.composer.json` to `drupal.composer.json` and modify it to your liking. +2. Switch the build system by setting `build_makefile: false` and `build_composer: true` in your `config.yml`. +3. Configure `drupal_core_path` to point to the webroot directory: `drupal_core_path: {{ drupal_composer_install_dir }}/docroot` + +```yaml +build_makefile: false +build_composer: true +drupal_core_path: "{{ drupal_composer_install_dir }}/docroot" +``` + +_The file set in `drupal_composer_path` (which defaults to `drupal.composer.json`) will be copied from your host computer into the VM's `drupal_composer_install_dir` and renamed `composer.json`. If you already have a composer.json within that directory, you can set `drupal_composer_path: false`._ + +## Using Composer when [Drupal VM is a composer dependency itself](../other/drupalvm-composer-dependency.md) + +In the scenario where you already have an existing `composer.json` in the root of your project, follow the usual steps for installing with a composer.json but instead of creating a `drupal.composer.json` file, disable the transfering of the file by setting `drupal_composer_path` to `false`, and change `drupal_composer_install_dir` to point to the the directory where it will be located. If `drupal_composer_path` is not truthy, Drupal VM assumes it already exists. + +```yaml +build_makefile: false +build_composer: true +drupal_composer_path: false +drupal_composer_install_dir: "/var/www/drupalvm" +drupal_core_path: "{{ drupal_composer_install_dir }}/docroot" +``` + +## Creating a project from a composer package: `composer create-project` + +There's a couple of things you need to configure in your `config.yml`: + +- Switch the build system by setting `build_makefile: false`, `build_composer: false` and `build_composer_project: true`. +- Configure the composer package in `drupal_composer_project_package`. +- Additionally you can adjust the create-project CLI options in `drupal_composer_project_options` as well as add additional dependencies in `drupal_composer_dependencies`. +- Ensure that the webroot configured in the composer package matches the one set in `drupal_core_path`. + +With [drupal-composer/drupal-project](https://github.com/drupal-composer/drupal-project) as an example your `config.yml` overrides would be: + +```yaml +build_makefile: false +build_composer: false +build_composer_project: true + +drupal_composer_project_package: "drupal-composer/drupal-project:8.x-dev" +# Added `--no-dev` to avoid installing development dependencies. +drupal_composer_project_options: "--prefer-dist --stability dev --no-interaction --no-dev" +drupal_composer_dependencies: + - "drupal/devel:8.*" + +drupal_core_path: "{{ drupal_composer_install_dir }}/web" +``` + +## Improving composer build performance + +Opting for composer based installs will most likely increase your VM's time to provision considerably. + +If you manage multiple VM's own your computer, you can use the [`vagrant-cachier` plugin](http://fgrehm.viewdocs.io/vagrant-cachier/) to share Composer's package cache across all VM's. The first build will be as slow as before but subsequent builds with the same `vagrant_box` (eg `geerlingguy/ubuntu1604`) will be much faster. + +1. Install the plugin on your host computer: `vagrant plugin install vagrant-cachier` +2. Create a `Vagrantfile.local` next to your `config.yml` with the following: + +```rb +config.cache.scope = :box +config.cache.auto_detect = false +config.cache.enable :generic, { :cache_dir => "/home/vagrant/.composer/cache" } +``` + +_Note: Out of the box, sharing the Composer cache is not supported as the plugin requires PHP to be installed when the VM first boots up. This is why the generic cache bucket is used instead._ + +_You can also use this plugin to share other package manager caches. For more information read the [documentation](http://fgrehm.viewdocs.io/vagrant-cachier/usage/)._ diff --git a/example.drupal.composer.json b/example.drupal.composer.json new file mode 100644 index 000000000..528047ef7 --- /dev/null +++ b/example.drupal.composer.json @@ -0,0 +1,35 @@ +{ + "name": "custom-project/drupal-vm", + "description": "", + "type": "project", + "license": "MIT", + "authors": [ + { + "name": "", + "role": "" + } + ], + "repositories": [ + { + "type": "composer", + "url": "https://packagist.drupal-composer.org" + } + ], + "require": { + "composer/installers": "^1.0.20", + "drupal-composer/drupal-scaffold": "^2.0.1", + "drupal/core": "~8.0", + "drupal/devel": "8.*" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "installer-paths": { + "docroot/core": ["type:drupal-core"], + "docroot/modules/contrib/{$name}": ["type:drupal-module"], + "docroot/profiles/contrib/{$name}": ["type:drupal-profile"], + "docroot/themes/contrib/{$name}": ["type:drupal-theme"], + "drush/contrib/{$name}": ["type:drupal-drush"] + } + } +} diff --git a/mkdocs.yml b/mkdocs.yml index a802b3eee..681311816 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,6 +12,7 @@ pages: - Home: 'index.md' - Drupal Deployment Strategies: - 'Drush Make file': 'deployment/drush-make.md' + - 'Composer': 'deployment/composer.md' - 'Local Drupal codebase': 'deployment/local-codebase.md' - 'Drupal multisite': 'deployment/multisite.md' - Extra Software and Setup: diff --git a/provisioning/playbook.yml b/provisioning/playbook.yml index 453fcc50a..df50ee94c 100644 --- a/provisioning/playbook.yml +++ b/provisioning/playbook.yml @@ -80,6 +80,11 @@ - name: Check if Drupal is already set up. stat: "path={{ drupal_core_path }}/index.php" register: drupal_site + ignore_errors: true + + - name: Define drupal_site_exists + set_fact: + drupal_site_exists: "{{ drupal_site.stat.exists|default(false) }}" - include: tasks/sshd.yml - include: tasks/extras.yml @@ -91,6 +96,14 @@ - include: tasks/build-makefile.yml when: build_makefile + # Build with composer if configured. + - include: tasks/build-composer.yml + when: build_composer + + # Build a composer project if configured. + - include: tasks/build-composer-project.yml + when: build_composer_project + # Install site if configured. - include: tasks/install-site.yml when: install_site diff --git a/provisioning/tasks/build-composer-project.yml b/provisioning/tasks/build-composer-project.yml new file mode 100644 index 000000000..9964be1ff --- /dev/null +++ b/provisioning/tasks/build-composer-project.yml @@ -0,0 +1,15 @@ +--- +- name: Generate Drupal project with composer package. + command: > + {{ composer_path }} create-project + {{ drupal_composer_project_package }} {{ drupal_composer_install_dir }} + {{ drupal_composer_project_options|default('--prefer-dist --no-interaction') }} + when: not drupal_site_exists + become: no + +- name: Install dependencies with composer require. + command: > + {{ composer_path }} require {{ item }} + chdir={{ drupal_composer_install_dir }} + with_items: "{{ drupal_composer_dependencies|default([]) }}" + become: no diff --git a/provisioning/tasks/build-composer.yml b/provisioning/tasks/build-composer.yml new file mode 100644 index 000000000..7602a3a7c --- /dev/null +++ b/provisioning/tasks/build-composer.yml @@ -0,0 +1,29 @@ +--- +- name: Ensure drupal_composer_install_dir directory exists. + file: + path: "{{ drupal_composer_install_dir }}" + state: directory + mode: 0775 + become: no + when: drupal_composer_path and not drupal_site_exists + +- name: Copy composer.json into place. + copy: + src: "{{ drupal_composer_path }}" + dest: "{{ drupal_composer_install_dir }}/composer.json" + when: drupal_composer_path and not drupal_site_exists + become: no + +- name: Run composer install. + command: > + composer install + chdir={{ drupal_composer_install_dir }} + when: not drupal_site_exists + become: no + +- name: Install dependencies with composer require. + command: > + {{ composer_path }} require {{ item }} + chdir={{ drupal_composer_install_dir }} + with_items: "{{ drupal_composer_dependencies|default([]) }}" + become: no diff --git a/provisioning/tasks/build-makefile.yml b/provisioning/tasks/build-makefile.yml index c74c9ce6f..862cb5acc 100644 --- a/provisioning/tasks/build-makefile.yml +++ b/provisioning/tasks/build-makefile.yml @@ -3,7 +3,7 @@ copy: src: "{{ drush_makefile_path }}" dest: /tmp/drupal.make.yml - when: drupal_site.stat.exists == false + when: not drupal_site_exists - name: Ensure drupal_core_path directory exists. file: @@ -12,23 +12,23 @@ recurse: yes mode: 0775 become: no - when: drupal_site.stat.exists == false + when: not drupal_site_exists - name: Generate Drupal site with drush makefile. command: > {{ drush_path }} make -y /tmp/drupal.make.yml --no-gitinfofile chdir={{ drupal_core_path }} - when: drupal_site.stat.exists == false + when: not drupal_site_exists become: no - name: Check if a composer.json file is present. stat: "path={{ drupal_core_path }}/composer.json" register: drupal_core_composer_file - when: drupal_site.stat.exists == false + when: not drupal_site_exists - name: Run composer install if composer.json is present. command: > composer install chdir={{ drupal_core_path }} - when: drupal_site.stat.exists == false and drupal_core_composer_file.stat.exists == true + when: not drupal_site_exists and drupal_core_composer_file.stat.exists become: no diff --git a/tests/ubuntu-16-nginx.config.yml b/tests/ubuntu-16-nginx.config.yml index 44ee51312..f1499c644 100644 --- a/tests/ubuntu-16-nginx.config.yml +++ b/tests/ubuntu-16-nginx.config.yml @@ -1,2 +1,7 @@ --- drupalvm_webserver: nginx + +# Test composer based installation. +build_makefile: false +build_composer: true +drupal_core_path: "{{ drupal_composer_install_dir }}/docroot" From c5c8c8a19b87c09efd85fbcf3ec80211ce9b8025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Sch=C3=B6ldstr=C3=B6m?= Date: Sat, 4 Jun 2016 13:44:37 -0400 Subject: [PATCH 2/2] Add prestissimo as a default global composer package --- default.config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.config.yml b/default.config.yml index 212fa082e..a9080bef6 100644 --- a/default.config.yml +++ b/default.config.yml @@ -240,8 +240,8 @@ composer_path: /usr/bin/composer composer_home_path: "/home/{{ drupalvm_user }}/.composer" composer_home_owner: "{{ drupalvm_user }}" composer_home_group: "{{ drupalvm_user }}" -# composer_global_packages: -# - { name: phpunit/phpunit, release: '@stable' } +composer_global_packages: + - { name: hirak/prestissimo, release: '^0.2' } # Run specified scripts before or after VM is provisioned. Path is relative to # the `provisioning/playbook.yml` file.