Thumbnail

Deploy to Acquia with a composer script

Thumbnail

Si Hobbs

|

This tutorial shows you how to create a neat script for deploying your code to Acquia, without needing BLT or Pipelines.

When Acquia first launched its hosting platform, most of the projects I was involved in used the Acquia git repository as the canonical origin. With Drupal 7, we committed all our code and pushed it to Acquia. 

Practices have changed a lot since then, we are much more likely to use Bitbucket or Github as the canonical Git repo, and we usually don't commit our dependencies such as the vendor directory - we have build tools to do this for us.

A number of tools have evolved at Acquia, such as BLT and Pipelines, that give us a way to automate processes across their infrastructure, but they're not always the best choice for a project, usually because they add a lot of Acquia-specific complexity.

The challenge

What we'll do is take a project that is built with composer, and provide a mechanism to push the code to our Git repository on Acquia.

In this example, I'm not fussy about the Git repo on Acquia because I am keep the full history on Github. To me, the Acquia Git repo is just a part of the Acquia hosting mechanism.

The process I want is something like this:

  1. Add the Acquia remote
  2. Create a new branch
  3. Change the .gitignore so we can commit all the things (vendor directory etc)
  4. Remove any deep nested .git directories (Composer related)
  5. Optionally remove any other non-production stuff we don't want
  6. Commit
  7. (Force) push to Acquia
  8. Run some Drush commands to rebuild caches and run updates

Now let's implement a solution for this.

Assumptions

  • I'm using composer to manage my Drupal (7 or 8) codebase
  • I have access to push code to Acquia
  • I have downloaded my Acquia Drush aliases file.
  • I have downloaded my cloudapi.conf from Acquia
  • I want to push whatever branch I'm on into the Acquia master branch.
  • I have Acquia's Dev environment pointing to the Acquia master branch.
  • I don't want deployment related commits in Github, but I do want the Acquia repo to show the commit history from Github.

Setup

1. Add robo-git-artefact

There's a new tool that does most of what I need: integratedexperts/robo-git-artefact. Integrated Experts is a Drupal consulting company led by Alex Skrypnyk in Melbourne. "Robo" is a framework for writing custom PHP CLI commands, and doing fancy things like chaining commands together. Run this command to add the package:

php composer.phar require vendor/package

2. Add .gitignore.artefact

You need a file to tell robo-git-artefact which directories it can and can't commit. Add .gitignore.artefact to the repo root.

# Replaces standard gitignore when artefact is built.
*.jar
*.out
*.log
node_modules
screenshots
.data
default.settings.php
settings.local.php
composer.lock
package-lock.json
.buildkite
.drupal-vm
.vagrant
Vagrantfile
drush.wrapper
*.retry

3. Config the Acquia remote

This is pretty handy way to store project variables:

  "extra": {
    "deploy": {
      "git-remote": "someproject@svn-12345.prod.hosting.acquia.com:someproject.git"
    }
  } 

You can then get this value (or any values like it) in a bash script like:

ACQUIA_REMOTE=composer config extra.deploy.git-remote

4. Add custom composer script

I want to run this as a custom composer command, with composer deploy-acquia, so in the scripts section of the composer.json, I also add this:

"scripts": {
  "deploy-acquia": [
    "PROJECT_PATH=pwd BUILD_PATH=/tmp/anywhere REMOTE_BRANCH=master REMOTE_ALIAS=@dev scripts/deploy-acquia.sh"
  ]
}

Modify the above script definition to match the desired Drush alias for Acquia Dev. Run drush site-alias to see the list of Acquia aliases.

5. Create a script file

Now create a script in your codebase at scripts/deploy-acquia.sh, this might get you started:

mkdir -p scripts && echo 'echo "Hello world"' > scripts/acquia-deploy.sh && chmod +x scripts/acquia-deploy.sh

​​​​​​Now you should be able to run composer deploy-acquia and get "Hello world" as output.

The script

#!/usr/bin/env bash

if [ ! -f ~/.acquia/cloudapi.conf ]; then
  echo "Please download and place your Acquia cloudapi.conf"
  exit 1
fi

# Example of getting a variable from the composer.json.
ACQUIA_REMOTE=composer config extra.deploy.git-remote

echo "Source: $PROJECT_PATH"
echo "Build: $BUILD_PATH"

# Workaround for https://github.com/integratedexperts/robo-git-artefact/issues/17
if [ git branch --list $REMOTE_BRANCH-artefact ]; then
  git branch -D $REMOTE_BRANCH-artefact
fi

# Copy the project directory to a build location.
rm -Rf $BUILD_PATH
mkdir -p $BUILD_PATH
rsync -rtl --include ".*" "$PROJECT_PATH"/ "$BUILD_PATH"/
cd $BUILD_PATH

# Remove any deep .git directories so their contents can be committed.
# Robo-git-artefact should do this, but I'm  investigating an edge-case where it's still needed. 
find ./* -name '.git' -type d -prune -exec rm -rf "{}" \;

# Use integratedexperts/robo-git-artefact to force push the code to Acquia.
./vendor/bin/robo --ansi \
  --load-from $BUILD_PATH/vendor/integratedexperts/robo-git-artefact/RoboFile.php \
  artefact $ACQUIA_REMOTE --branch=$REMOTE_BRANCH \
  --push --mode=force-push \
  --message "Deploy [branch]" \
  --gitignore=.gitignore.artefact \
  --no-cleanup

# Do whatever you want here.
echo "Updates and cache clears"
cd "$PROJECT_PATH"
./vendor/bin/drush --alias-path=./drush $REMOTE_ALIAS cr
./vendor/bin/drush --alias-path=./drush $REMOTE_ALIAS updb -y

Next steps

The next steps are up to you. There are a lot of places here were you can customise, or connect these scripts to parts of your CI workflow.

Remember if you need to deploy from a service like Travis or Circle, then you need to ensure that you are deploying a cloudapi.conf file securely to these services. If you look in BLT's configuration for Travis, you'll see similar problems being solved.

Let me know in the comments if this script helped you, and ideas for future articles.

Add new comment

Comments

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <blockcode> <ul type> <ol start type> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
  • Use [gist:#####] where ##### is your gist number to embed the gist
    You may also include a specific file within a multi-file gist with [gist:####:my_file].

Spread the word