Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Development Automation with Composer, Robo and Docker

The technology that powers the Ballast project

Shawn Duncan, Technical Architect
Digital Pulp

Introduction

Developer Tasks

  • Classic CMS Needs
    • Web server
    • Database
    • PHP
  • Dependency Management
    • New frontend tools: npm
    • Javascript libraries (production)
    • Drupal core
    • Drupal contributed modules
    • PHP libraries beyond Drupal
  • Sync with a remote server
  • Compile the theme
  • Manage Drupal from the command line

Composer

Composer

The hub technology of this project.

  • Core purpose is dependency management
  • Builds the autoloader
  • Event system is the foundation for automation
  • Installation and other documentation: getcomposer.org

Composer

Managing Dependencies

Snippet from composer.json for Formassembly module

{
  "require": {
    "fathershawn/oauth2-formassembly": "^1.0"
  }
}
                
The key section for dependency is the require section. Let's follow the chain...

Composer

Managing Dependencies

Snippet from composer.json for fathershawn/oauth2-formassembly

{
  "require": {
    "php": "^5.6 || ^7.0",
    "league/oauth2-client": "^2.0"
  }
}
                

Composer

Events

  • Full list at https://getcomposer.org/doc/articles/scripts.md
  • Ballast uses:
    post-install-cmd
    Occurs after the install command has been executed with a lock file present.
    post-update-cmd
    occurs after the update command has been executed, or after the install command has been executed without a lock file present.
  • Inherited from the drupal-composer/drupal-project to verify Composer version.
    pre-install-cmd
    Occurs before the install command has been executed with a lock file present.
    pre-update-cmd
    occurs before the update command has been executed, or after the install command has been executed without a lock file present.

Composer

Events

Snippet from composer.json for digitalpulp/ballast

{
 "scripts": {
        "drupal-scaffold": "DrupalComposer\\DrupalScaffold\\Plugin::scaffold",
        "robo": "@php scripts/robo/BallastRunner.php --ansi",
        "pre-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "pre-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "post-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
            "composer robo setup:drupal",
            "composer robo setup:prerequisites"
        ],
        "post-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
            "composer robo setup:drupal",
            "composer robo setup:prerequisites"
        ]
    },
}
            

Composer

Adding new Drupal modules

composer require drupal/module_name

Composer

Upgrade Core

composer update drupal/core webflo/drupal-core-require-dev webflo/drupal-core-strict --with-all-dependencies

Robo

Robo

  • Written in PHP by Greg Anderson, Michael Bodnarchuk and Moshe Weitzman
  • Task runner
  • Installed with Composer
  • Documentation: robo.li

Robo

Base Usage

Robo creates the command file
robo init

Robo

Base Usage

Public methods become executable commands

  /**
   * Prints the database connection info for use in SQL clients.
   */
  public function connectSql() {
    $ip = $this->getDockerMachineIp();
    $port = $this->getSqlPort();
    $this->io()->title('Database Info');
    $this->io()->text("The Docker Machine host is: $ip");
    $this->io()->text("Connect to port: $port");
    $this->io()->text("Username, password, and database are all 'drupal'");
    $this->io()->note("Both the ip and port can vary between re-boots");
  }
            
on the command line:
robo connect:sql

Robo

Usage in Ballast

Commands can be split into multiple classes with a front controller

-| scripts
      BallastRunner.php
----| src
------| Commands
          DeployCommands.php
          DockerCommands.php
          DockerMachineTrait.php
          FrontEndTrait.php
          RemoteRebuildCommands.php
          SetupCommands.php
------| Utilities
          Config.php
            

Robo

Usage in Ballast

Dynamic Configuration

  $collection->addTask(
      $this->taskReplaceInFile("$root/setup/docker/docker-compose.yml")
        ->from('{site_shortname}')
        ->to($this->config->get('site_shortname'))
    );
            

Robo

Usage in Ballast


/**
   * Builds separate artifact and pushes to remote as a branch.
   *
   * @param array $options
   *   Options from the command line or internal call.
   *
   * @return \Robo\Result
   *   The result of the final push.
   */
  public function deployBranch(array $options = [
    'branch' => InputOption::VALUE_REQUIRED,
    'commit-msg' => InputOption::VALUE_REQUIRED,
    'remote-branch' => NULL,
    'remote' => NULL,
    'build_id' => NULL,
  ]) {
    $this->setConfig();
    $this->setDeploymentOptions($options);
    $this->say('Deploying to branch ' . $options['branch']);
    $this->setDeploymentVersionControl($options);
    $this->getDeploymentDependencies();
    $this->getSanitizedBuild();
    $this->setDeploymentCommit($options);
    $this->setCleanMerge($options);
    return $this->getPushResult($options);
  }         

Codeship

  • Codeship Pro has a free level
  • Use essentially the same containers

code-quality:
  image: digitalpulp/code-quality
  working_dir: /var/www
  volumes_from:
    - deploy
front-end:
  image: digitalpulp/front-end:codeship
  working_dir: /var/www/docroot/themes/custom/YOUR_THEME
  volumes_from:
    - deploy
  environment:
    THEME_NAME: CHANGE_ME
deploy:
  image: digitalpulp/cli:codeship
  working_dir: /var/www
  encrypted_env_file: env.encrypted
  volumes:
    - .:/var/www
  environment:
    DEPLOY_TARGET: CHANGE_ME

                 

- name: pull_dependencies
  tag: develop
  service: deploy
  command: composer install --no-dev --no-interaction --optimize-autoloader
- name: code_quality
  service: code-quality
  command: pre-commit.sh
- name: build_front
  tag: develop
  service: front-end
  command: entrypoint.sh
- name: deploy
  tag: develop
  service: deploy
  command: php scripts/robo/BallastRunner.php deploy
                 

Docker

Docker whale logo

Docker

Virtual Process vs. Virtual Machine

  • Convention: Like OOP, set just one purpose per container
  • Inject commands into the container

Docker

Compose

  • Define multiple containers in a yaml file
  • All share a network, start and stop together
Snippet from docker-compose-template

services:
  web:
    image: digitalpulp/nginx:stable-alpine-1.0.1
    # image: digitalpulp/apache
    depends_on:
      - database
      - php
    volumes:
      - .:/var/www
    working_dir: /var/www/docroot/
    environment:
      VIRTUAL_HOST: {site_shortname}.dpulp
      DOCROOT: /var/www/docroot
      SERVER_NAME: {site_shortname}.dpulp
    networks:
      - internal
      - proxy

Docker

Multi-project services

  • Nginx Proxy
  • DNS

Ahoy

Ahoy

  • An abstraction layer for DX
  • Written in Go
  • macOS, Linux, basic Windows
  • Commands work everywhere in the subtree below the project root.

Ahoy

Shell commands and scripts in a yaml file

Snippet from .ahoy.yml

drush:
  usage: Run drush commands within the drupal site. Follow `ahoy drush` with the drush command to be run.
  cmd: docker-compose $(docker-machine config dp-docker) exec cli drush "$@"
cast-off:
  usage: Launch the global tools needed for local development. Run this command once after you boot your computer.
  cmd: |
    php scripts/robo/BallastRunner.php boot && #make sure boot is successful
    php scripts/robo/BallastRunner.php "boot:dns"

Ahoy

Example ahoy usage
ahoy drush cache:rebuild

Ballast

Just use Ballast
composer create-project digitalpulp/ballast  your_project
I like my dev tool but I want to use Composer
composer create-project drupal-composer/drupal-project:8.x-dev your_project --stability dev --no-interaction

Open Q & A

“Heeded my words not, did you? Pass on what you have learned. Strength, mastery.”

“But weakness, folly, failure also. Yes, failure most of all. The greatest teacher, failure is.”

References

Composer
https://getcomposer.org
Robo
https://robo.li
Docker
https://docs.docker.com/engine/docker-overview
Ahoy
http://www.ahoycli.com/en/latest
Contribute to Ballast
https://github.com/digitalpulp/ballast
Ballast on Packagist
https://packagist.org/packages/digitalpulp/ballast
Drupal Composer on Github
https://github.com/drupal-composer/drupal-project
Add composer build support to core
https://www.drupal.org/project/drupal/issues/2982674
Docker for Mac filesystem issue on Github
https://github.com/docker/for-mac/issues/1592
This slide is online at http://talks.shawnduncan.org/automation/#/references