Smarter CDE Setups: One-Time Drupal Database Syncs with Acquia Pipelines π
- 10 minute read
-
Acquia's Cloud Development Environments (CDEs) are a game-changer for developer workflows, spinning up a dedicated environment for every pull request. A common first step is seeding this new environment with a database from a source, like your staging or dev integration environment. But what happens on the second, third, or fourth push to that same pull request? You don't want to overwrite your work every single time!
This article will show you how to build an intelligent post-deploy script that syncs a Drupal database only on the first run for a new CDE. We'll dive into how to detect the CDE's name within Acquia Pipelines and use some simple shell script logic to avoid unnecessary, and potentially destructive, database syncs.
π Securing Your Credentials: API Keys and SSH
Before our script can run, it needs to authenticate with Acquia's services. Hardcoding keys and secrets directly into your acquia-pipelines.yml
file is a major security risk. Instead, you should always use Acquia Pipelines' built-in encryption.
Letβs walk through setting up and encrypting the two types of credentials our script uses: ACLI API tokens and an SSH key.
1. Generating and Encrypting ACLI Tokens
The Acquia CLI (ACLI) needs an API Key and Secret to communicate with your Acquia applications.
First, generate a new API token in the Acquia Cloud UI by navigating to Manage > Profile > API Tokens. You'll receive a **Key** and a **Secret**.
Next, use the pipelines encrypt
command locally to secure these values. This command must be run from within your codebase directory where your acquia-pipelines.yml
file is located.
# Encrypt your ACLI Key
pipelines encrypt --string="YOUR_ACLI_KEY_HERE"
# Encrypt your ACLI Secret
pipelines encrypt --string="YOUR_ACLI_SECRET_HERE"
Each command will output a multi-line secure:
block. Copy these blocks and place them in the global variables
section of your acquia-pipelines.yml
file.
# acquia-pipelines.yml
variables:
global:
ACLI_KEY:
secure: REDACTED
ACLI_SECRET:
secure: REDACTED
2. Generating and Encrypting an SSH Key
Our script also needs an SSH key to authenticate with the server environment. Itβs best practice to generate a dedicated key for Pipelines.
Create a new SSH key pair without a passphrase, as the script needs to use it non-interactively:
# Generates a private key (write-key) and a public key (write-key.pub)
ssh-keygen -t ed25519 -C "pipelines-key" -f ./write-key -N ""
Next Step: You must add the contents of the public key (write-key.pub
) to your Acquia Cloud account's SSH keys before the pipeline can use it.
Now, encrypt the private key file (write-key
) using the same encryption command, but this time with the --file
flag:
# Encrypt the private key file
pipelines encrypt --file=./write-key
Finally, place the resulting secure:
block into the ssh-keys
section of your acquia-pipelines.yml
. The key name here (write-key
) is how you will reference it inside the pipeline environment (e.g., ~/.ssh/write-key
).
# acquia-pipelines.yml
ssh-keys:
write-key:
secure: REDACTED
With these encrypted credentials in place, your pipeline can securely authenticate and execute its tasks without exposing any secrets in your codebase.
The Goal: Sync Once, Then Step Back
The core of our task is to make our deployment process smart. It should ask a simple question: "Is this a brand new, empty CDE?"
- β If yes: It's the first deployment. Go ahead and sync the database from our source environment.
- β If no: A Drupal site is already here. A developer might have made changes. Do not touch the database and let them continue their work.
This approach saves time on subsequent deployments and, more importantly, protects the developer's progress within that CDE.
Connecting the Dots: From Pipelines to Your Script
First, we need to configure our acquia-pipelines.yaml
file to run our script after a deployment finishes. The magic lies in the post-deploy
event. We also need a way to get the unique name of the CDE that was just deployed.
Acquia Pipelines makes this information available in a special file, $PIPELINES_SCRIPT_DATA_FILE
. We can parse this JSON file to extract the environment name and pass it as an argument to our shell script.
The `acquia-pipelines.yaml` Configuration
Hereβs how we set up the post-deploy
step:
# acquia-pipelines.yaml
events:
# The 'post-deploy' event runs AFTER the automatic deployment finishes.
post-deploy:
steps:
- run_post_deploy_tasks:
name: Run tasks after deployment
service: pipelines-deployment
script:
- pipelines-deploy
# This is the key line! We extract the CDE name from the data file.
- CDE_NAME=$(cat $PIPELINES_SCRIPT_DATA_FILE | python3 -c "import sys, json; print(json.load(sys.stdin)['environment']['PIPELINES_DEPLOYMENT_NAME'])")
# Make our script executable and run it with the CDE name as an argument.
- chmod +x ./scripts/pipelines/post-deploy.sh
- ./scripts/pipelines/post-deploy.sh $CDE_NAME
π‘ How it works: We use a short, inline Python script to parse the JSON content provided by Pipelines and print the value of the PIPELINES_DEPLOYMENT_NAME
key. This value is then stored in the $CDE_NAME
shell variable.
The Intelligence: The `post-deploy.sh` Script
Now that our YAML is passing the CDE name to post-deploy.sh
, the script can use that information to check the status of the Drupal installation on that specific environment.
Setting Up the Environment: ACLI and SSH
Before we can check on Drupal, our script needs to prepare its own environment. This involves installing the Acquia CLI, authenticating with both the API and SSH, and linking to the correct application. These steps ensure our script has the authorization and tools needed to interact with the CDE.
Here's what the initial setup block in the script does:
- Install ACLI: It creates a local directory, downloads the latest
acli.phar
executable from GitHub, makes it executable withchmod
, and adds it to the system'sPATH
. - Authenticate and Link: It logs into the API non-interactively using the
$ACLI_KEY
and$ACLI_SECRET
variables we defined in our YAML file. It then links ACLI to the target application using the$PIPELINES_CLOUD_SITE
variable. - Start SSH Agent: It starts the
ssh-agent
and adds our decryptedwrite-key
. This is crucial for allowing ACLI to establish a secure shell connection to the CDE to run remote Drush commands.
# 1. Install Acquia CLI (ACLI)
echo "Installing Acquia CLI (ACLI)..."
mkdir -p "$HOME/.acli/bin"
curl -sSLf -o "$HOME/.acli/bin/acli" "https://github.com/acquia/cli/releases/latest/download/acli.phar"
chmod +x "$HOME/.acli/bin/acli"
export PATH="$HOME/.acli/bin:$PATH"
# Authenticate with acli and link application
acli auth:login -k $ACLI_KEY -s $ACLI_SECRET -n
acli app:link $PIPELINES_CLOUD_SITE
echo "ACLI installed successfully."
# Start SSH agent and propagate keys
echo "π Starting SSH agent and propagating keys..."
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/write-key
echo "SSH keys propagated successfully."
Checking for an Existing Drupal Installation
With the environment set up, the most reliable way to see if Drupal is installed and running is to ask Drush. We can use the now-authenticated ACLI to run a remote Drush command against our CDE.
The command acli remote:drush "$PIPELINES_CLOUD_SITE.$1" -- "status --field=bootstrap"
attempts to get the bootstrap status of the Drupal site.
- If it returns
Successful
and the command exits with code 0, Drupal is installed. - If the command fails (e.g., non-zero exit code), we can safely assume Drupal isn't installed yet.
Hereβs the logic in our script:
#!/bin/bash
set -e
# ... (ACLI installation and other setup happens here) ...
echo "Loading database status for $PIPELINES_CLOUD_SITE.$1"
# Temporarily allow commands to fail so we can capture the exit code
set +e
DRUSH_STATUS=$(acli remote:drush "$PIPELINES_CLOUD_SITE.$1" -- "status --field=bootstrap" 2>/dev/null)
EXIT_CODE=$?
set -e # Re-enable exiting on error
# Trim whitespace from the output for a reliable comparison
DRUSH_STATUS_TRIMMED=$(echo "$DRUSH_STATUS" | xargs)
if [ $EXIT_CODE -eq 0 ] && [ "$DRUSH_STATUS_TRIMMED" == "Successful" ]; then
# If the command succeeds, Drupal is already there.
echo "β
Drupal is already installed. Skipping database sync."
else
# If the command fails, it's a fresh CDE that needs its database.
echo "βΉοΈ Drush command failed. Assuming new CDE and syncing database..."
# Sync the database from your specified source environment.
pipelines-sync-dbs "your-application-alias"
echo "β
Database sync from 'eeearias' completed."
fi
Conclusion
And that's it! By combining the power of the post-deploy
hook in Pipelines, a bit of JSON parsing to get the environment name, and a smart check in a shell script, you can create a seamless and safe workflow for your CDEs. Your developers get a perfectly seeded environment on their first push, and their work is preserved on all subsequent pushes. This small automation adds up to a big improvement in developer experience and productivity.