Removing BLT on Acquia - How to get started
- Last updated
- 2 minute read
Goal
This document addresses the most common uses of BLT and provides guidance in how to replace them. If you use more advanced BLT feature you can reach out to Acquia PS.
Prerequisites
- https://dev.acquia.com/tutorial/you-dont-need-blt-acquia-cloud
Overview
BLT has been an invaluable tool for developers, offering a structured and opinionated approach to navigating various workflows in the development cycle. It provided a suite of commands such as sync
, deploy
, and others, along with Cloud hooks to automate tasks post-code deployment or database copy. Additionally, BLT's "command hooks" allowed users to extend functionality as needed, such as building frontend requirements and assets.
Acquia BLT also introduced some settings "magic," enabling configuration splits, including Memcached configuration, and the addition of extra configuration-oriented files through organized *.settings.php files. While our documentation provides basic examples and reflects some of the necessary changes, this guide aims to be a comprehensive resource to help you transition smoothly from BLT.
Using ACLI and Composer Scripts
For most cases, the tools that you are going to need are ACLI and Composer scripts. Here are some useful links:
Your local dev environment may have easy-install options for ACLI. Lando, DDEV, and Docksal all integrate nicely with ACLI. More info about this here.
It is important to make sure ACLI is installed and configured correctly. Typing lando acli
, ddev acli
, fin acli
will confirm that ACLI is working correctly
-
The BLT Settings goodies
To continue benefiting from the configuration enhancements of BLT, Acquia recommends using the Drupal Recommended Settings Plugin (DRS). In the linked docs, you can also find specific information on migrating this part of BLT to the DRS plugin. Once the migration is done, you should have most of the functionality of BLT already in your codebase. If you are using Acquia Site Factory, check the specific section about using DRS with ACSF.
- Confirm that you are on the latest version of BLT 13.
- Install the new BLT 14:
composer require acquia/blt:^14
- Run the blt migrate command:
./vendor/bin/blt blt:migrate
- You should see this message:
[WARNING] This script will update following files from site [default] with following changes. -------------------- ----------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- File Snippet to remove Snippet to add -------------------- ----------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- settings.php require DRUPAL_ROOT . "/../vendor/acquia/blt/settings/blt.settings.php"; require DRUPAL_ROOT . "/../vendor/acquia/drupal-recommended-settings/settings/acquia-recommended.settings.php"; settings.php /** /** * IMPORTANT. * IMPORTANT. * * * Do not include additional settings here. Instead, add them to settings * Do not include additional settings here. Instead, add them to settings * included by `blt.settings.php`. See BLT's documentation for more detail. * included by `acquia-recommended.settings.php`. See Acquia's documentation for more detail. * * * @link https://docs.acquia.com/blt/ * @link https://docs.acquia.com/ */ */ settings.php use Acquia\Blt\Robo\Common\EnvironmentDetector; use Acquia\Drupal\RecommendedSettings\Helpers\EnvironmentDetector; local.settings.php blt_override_config_directories drs_override_config_directories -------------------- ----------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------
- Respond
yes.
- Celebrate the beginning of the removal of BLT.
🎉
-
Syncing the site(s) down [BLT sync and BLT dsa commands]
BLT provides ways to pull the site down and files with blt sync (dsa) command:
Description: Synchronize local env from remote (remote --> local). Usage: drupal:sync:default:site [options] ds drupal:sync drupal:sync:default sync sync:refresh Options: --sync-public-files --sync-private-files -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -D, --define=DEFINE Define a configuration item value. (multiple values allowed) --environment=ENVIRONMENT Set the environment to load config from blt/[env].yml file. --site=SITE The multisite to execute this command against. -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Help: Copies remote db to local db, re-imports config, and executes db updates for each multisite.
To replace this action we are going to need ACLI, and the
pull:database
command.While BLT uses configuration to determine the source environment in
blt.yml
, we are not going to cover that here, instead we will call the environment directly. The command is simply:acli pull:db [site].[env]
This will clear caches and sanitize the database afterward. However, there are some limitations compared to BLT:
- BLT uses Drush directly, and you could try the same, but in this example, ACLI will only copy the latest backup of the database. This can be solved by using
--on-demand
when calling the command. ACLI will create a backup and then pull it down. - BLT will run
update:db
andconfig:import
right after pulling the database down, which is very important if you are testing your production database against your current code. For this, we are going to use bash scripts and Composer scripts.
Lets do this! We can use this example scripts to run a combination of commands to have similar functionality. All examples assume all scripts are in the scripts folder.
Full disclosure: I am not a BASH expert, so these scripts were AI-aided, and while I worked to make sure they are right. These scripts are not officially supported by Acquia, and serve only as examples.
The scripts we use depend on whether the application is single or multisite.
Using ACLI directly and having a composer script to run Drush commands (Single site).
Run the ACLI command.
acli pull:db [site].[env]
Add a composer script to your composer.json to run Drush commands.
"scripts": { "post-acli-pull-database": [ "./scripts/drush-common.sh site.prod" ] }
Using the executor script (Single site or Multisite)
In the example scripts I mention early there is a folder that allows the scripts to run in a "modular" form; We have 3 of them:
- The executor.sh Orchestrates the call.
- The pull-db.sh pulls the DB using ACLI.
- The drush-common.sh runs the necessary drush commands.
There are 2 versions of the executor script: one for single sites, another for multisites. Both are called with a single parameter which is the [site].[env] which indicates where to get the DBs from, the command: pulldb or drush-common.
Copy these 3 scripts to you script folder and use the executor command that fits your application. Then you can run:
./scripts/executor pulldb site.dev
- BLT uses Drush directly, and you could try the same, but in this example, ACLI will only copy the latest backup of the database. This can be solved by using
-
The most common BLT Command hooks: frontend-reqs and frontend-assets
The most common command hooks used with BLT are the ones needed to compile your theme automatically, before a deployment, when yoi pull the DB down, or anytime you need something locally.
In the example scripts you will find 2 scripts:
- installthemes.sh that runs as the frontend-reqs.
- compileassets.sh that runs as frontend-assets.
These two scripts go through your
theme/custom
folder and run the command that you need to install the requirements or compile the theme. To use them we are going to create some composer scripts:{ "scripts": { "frontend-reqs": [ // This script installs dependencies for the custom themes. "./scripts/installthemes.sh" ], "frontend-assets": [ // This script compiles the assets for the custom themes. "./scripts/compileassets.sh" ], "frontend-build": [ // This script installs dependencies and compiles the assets for the custom themes. "@frontend-reqs", "@frontend-assets" ] } }
Suggestion: You can call these commands after pulling database(s) to compile your theme immediately.
composer run-script frontend-build
-
Blt deploy alternative
BLT provided a deploy command, which was useful for customers using external CI products (in other words not Acquia Pipelines or Acquia Code Studio). To replace the deploy command we are going to use ACLI. Here are some considerations:
- The recommended command is acli push:artifact.
- There are some limitations for this command, basically on the compiled files for your theme (CSS and JS mostly). Read the caveat in our known issues with ACLI.
- We will be using some Composer scripts and configs for this to work as expected.
- We will take advantage of our frontend scripts.
As of this writing, here is how it works (Note: I will update it if things change).
Lets start:
- Create a script called
post-install-cmd
in yourcomposer.json
to compile your theme assets.
"scripts": { "frontend-reqs": [ "./scripts/installthemes.sh" ], "frontend-assets": [ "./scripts/compileassets.sh" ], "frontend-build": [ "@frontend-reqs", "@frontend-assets" ], "post-install-cmd": [ "@frontend-build" ] }
- Add a Installer Path in your composer.json for the custom theme folder, such as
"docroot/themes/custom/": [ "type:drupal-custom-theme" ],
Disclaimer: The Composer entries are a workaround until this issue is solved. The use of
post-install-cmd
makes the theme install and compilation run every time composer install
is run, which can be a burden in your daily development tasks. There is an example here, which is a workaround that will enable you to have the frontend scripts run only when in a CI environment.- Finally, run the
push:artifact
command.
acli push:artifact site.dev --no-interaction -v
- Note: You can use the
acli push:artifact
parameters to personalize how the branches or tags are created in your Acquia repository:
> acli help push:artifact Description: Build and push a code artifact to a Cloud Platform environment Usage: push:artifact [options] [--] [<environmentId>] push:artifact [<environmentAlias>] push:artifact myapp.dev push:artifact prod:myapp.dev push:artifact 12345-abcd1234-1111-2222-3333-0e02b2c3d470 push:artifact --destination-git-branch=main-build push:artifact --source-git-tag=foo-build --destination-git-tag=1.0.0 push:artifact [email protected]:example.git [email protected]:example.git --destination-git-branch=main-build Arguments: environmentId The Cloud Platform environment ID or alias (i.e. an application and environment name optionally prefixed with the realm) Options: --dir=DIR The directory containing the Drupal project to be pushed --no-sanitize Do not sanitize the build artifact --dry-run Deprecated: Use no-push instead --no-push Do not push changes to Acquia Cloud --no-commit Do not commit changes. Implies no-push --no-clone Do not clone repository. Implies no-commit and no-push -u, --destination-git-urls=DESTINATION-GIT-URLS The URL of your git repository to which the artifact branch will be pushed. Use multiple times for multiple URLs. (multiple values allowed) -b, --destination-git-branch=DESTINATION-GIT-BRANCH The destination branch to push the artifact to -t, --destination-git-tag=DESTINATION-GIT-TAG The destination tag to push the artifact to. Using this option requires also using the --source-git-tag option -s, --source-git-tag=SOURCE-GIT-TAG The source tag from which to create the tag artifact -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
-
The Post deploy code hook
BLT provided two different types of hooks for your repository: one for Acquia Site Factory and another for Acquia Cloud Classic. I have added a couple of examples for each one of these.
If you are on Acquia Cloud Classic you should be moving soon to Acquia Cloud Next, which is recommended and you should use Acquia Cloud Actions to execute the tasks that before were done by the post-deploy-code hook. The examples here are primarily for Acquia Cloud Classic.
Post Deploy code for Acquia Site Factory
BLT replaced the post-site-install and the db-update Factory Hooks to run the
drupal:update
task, I have some example scripts here.Note: This scripts are an example and should be tested before going into production.
This is just an example, use the one from the repo for the latest fixes.
#!/bin/bash # # Factory Hook: db-update # # This is an example script to perform necessary tasks using Drush # commands during a database update on ACSF. # Note: This is a starting point and may need customization. # # Usage: db-update.sh sitegroup env db-role domain custom-arg # Exit immediately on error and enable verbose log output. set -ev # Map the script inputs to convenient names: sitegroup="$1" env="$2" db_role="$3" domain="$4" # Get the internal domain name based on the site, environment, and db role arguments uri=$(/usr/bin/env php /mnt/www/html/$sitegroup.$env/hooks/acquia/uri.php $sitegroup $env $db_role) IFS='.' read -a name <<< "$uri" # Drush executable drush="/mnt/www/html/$sitegroup.$env/vendor/bin/drush" echo "Running Drush deploy tasks on $uri domain in $env environment on the $sitegroup subscription." # Execute the updates using Drush. $drush --uri=$domain/ updatedb -y result=$? [ $result -ne 0 ] && exit $result $drush --uri=$domain/ config-import -y result=$? [ $result -ne 0 ] && exit $result $drush --uri=$domain/ config-import -y result=$? [ $result -ne 0 ] && exit $result # Check config status config_status_output=$($drush --uri=$domain/ config-status 2>&1) if [[ "$config_status_output" != *"No differences"* ]]; then echo "Error: Config status check failed for site: $domain" echo "Details: $config_status_output" exit 1 fi $drush --uri=$domain/ cache-rebuild result=$? [ $result -ne 0 ] && exit $result $drush --uri=$domain/ deploy:hook -y result=$? [ $result -ne 0 ] && exit $result # Clean up the Drush cache directory echo "Removing temporary Drush cache files." # Add any necessary cleanup commands here, for example: # rm -rf /tmp/drush* set +v # Exit with the status of the last Drush command exit $result
Post code deploy hook for Acquia Cloud Classic
BLT creates a post deploy code to ensure that Drush commands are run after new code is deployed. Remember, If you move into Acquia Cloud Next, this is done via Acquia Cloud Actions.
I have created and example here, test this code to see if it works for you. There are two examples:
Here is the example of a monolithic hook:
#!/bin/bash # Set the root directory relative to the script location HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DRUPAL_ROOT="$(dirname "$(dirname "$HOOKS_DIR")")/docroot" # Check if DRUPAL_ROOT exists and is a directory if [ ! -d "$DRUPAL_ROOT" ]; then echo "Error: DRUPAL_ROOT directory does not exist: $DRUPAL_ROOT" exit 1 fi # Set the path to the Drush command DRUSH_CMD="$(dirname "$(dirname "$HOOKS_DIR")")/vendor/bin/drush" # Check if the Drush command exists and is executable if [ ! -x "$DRUSH_CMD" ]; then echo "Error: Drush command not found or not executable: $DRUSH_CMD" exit 1 fi # Function to run Drush command for a given multisite run_drush_for_multisite() { local site_path=$1 local command=$2 echo "Running Drush command for site: $site_path: $command" result=$($DRUSH_CMD --root="$DRUPAL_ROOT" --uri="$site_path" "$command" -y 2>&1) echo "$result" # Debug statement to see the output # Check if the Drush command succeeded if [ $? -ne 0 ]; then echo "Error: Drush command '$command' failed for site: $site_path" exit 1 fi # Special handling for config-status if [ "$command" == "config-status" ]; then if ! printf "%s" "$result" | grep -q "No differences"; then echo "Error: Config status check failed for site: $site_path" echo "Details: $result" exit 1 fi fi } # Detect multisites by looking for settings.php files MULTISITE_URIS=() # Always ensure 'default' site is included if [ -f "$DRUPAL_ROOT/sites/default/settings.php" ]; then MULTISITE_URIS+=("default") else echo "Error: Default site settings.php not found in $DRUPAL_ROOT/sites/default" exit 1 fi for site_path in "$DRUPAL_ROOT/sites"/*/; do if [ -f "${site_path}settings.php" ]; then site_uri=$(basename "$site_path") # Exclude 'default' as it's already added if [ "$site_uri" != "default" ]; then MULTISITE_URIS+=("$site_uri") fi fi done # Define the Drush commands to be executed for each multisite DRUSH_COMMANDS=( "updatedb" "config-import" "config-import" "config-import" "config-status" "cache-rebuild" "deploy:hook" ) # Run the Drush commands for each detected multisite for site in "${MULTISITE_URIS[@]}"; do for command in "${DRUSH_COMMANDS[@]}"; do run_drush_for_multisite "$site" "$command" done done echo "Drush commands completed for all sites."
-
External CI services
Some customers want to use their own CI server: GitHub Actions, Gitlab CI, Azure Pipelines, etc. Here are some considerations:
- All acli commands must be authenticated via acli auth:login.
- If possible make sure it runs on an Ubuntu Box, if not, any Linux box will do.
- On the build stage, install ACLI per our documentation.
- Do not forget to also install node, NPM, and anything needed for theme compilation.
- On the test stage, run any test you are using. You can also test pulling down your production database against your new code to ensure a successful deployment. Make sure your CI box has MySQL configured and you can connect to it from Drupal; this sometimes requires creating a manual settings.local.php.
- For the deployment stage use
acli push:artifact
.
If you use Github Actions and Lando or DDEV, and you have everything working on your local using
lando|ddev acli
, and you can run every command that you need to have a successful artifact in Acquia.You can use the official actions for Lando and DDEV to make your life easier.