Skip to content

Goal: take a Cloud Platform Drupal application from “no CI” to one green Pipelines run that produces a deployable artifact branch.

  • The pipelines client installed and authenticated (it is a separate tool from acli; step 1 covers the install and setup).
  • A minimal acquia-pipelines.yaml committed at your repository root.
  • One green run whose artifact landed as a pipelines-build-<branch> branch on your application, ready to deploy with Switch code.
  • A Cloud Platform application you can push to (code-workflow quickstart)
  • A Cloud Platform API token (key + secret) from cloud.acquia.com/a/profile/tokens
  • A local clone of the application’s repository
  • PHP 8.0 or later with the json and Phar extensions enabled. The Pipelines client is a PHP script, so without PHP the install below downloads a file that will not run (env: php: No such file or directory). php --version checks the version and php -m lists extensions.
No PHP on this machine?

If php --version answers command not found: php, Docker can supply the runtime, and the official php image already has json and Phar enabled. In step 1 below, keep the curl download but skip the chmod and the mv into your PATH: the client stays in your repository clone, inside the directory you mount. Mounting ~/.config/acquia as well puts what pipelines configure saves on your machine, where a system PHP would have put it, rather than inside a container that --rm throws away:

Terminal window
mkdir -p ~/.config/acquia
docker run --rm -it \
-v "$PWD":/app -w /app \
-v "$HOME/.config/acquia":/root/.config/acquia \
php:8.3-cli php pipelines configure

Every pipelines command on this page then runs the same way: keep the docker run prefix and swap configure for the command you want, running from the repository clone so set-application-id can read the application from the clone’s git remote. php pipelines --version prints the client’s version from inside the container, the same build a system PHP runs.

For PHP on the machine itself, the php.net install docs cover every platform.

  1. Install and configure the Pipelines client

    Section titled “Install and configure the Pipelines client”

    The Pipelines CLI is its own download, not part of acli (which CLI?):

    Terminal window
    curl -o pipelines https://cloud.acquia.com/pipeline-client/download
    chmod a+x pipelines
    sudo mv pipelines /usr/local/bin/
    pipelines --version
    pipelines configure

    The mv into /usr/local/bin usually needs sudo; pipelines --version printing a version number confirms the install before you invest in configuration. pipelines configure prompts for your API token key and secret. Then, from inside your repository clone, tell the client which application this repository belongs to:

    Terminal window
    pipelines list-applications
    pipelines set-application-id

    configure prompts for the key and secret, then confirms. list-applications prints the applications your token can reach. set-application-id, run from inside the clone, reads the application from the repository’s Cloud Platform git remote and associates it without prompting:

    $ pipelines configure
    Please enter your Acquia Cloud API key:
    Please enter your Acquia Cloud API secret:
    Configuration successful.
    $ pipelines list-applications
    +------------+--------------------------------------+------------------------+
    | Name | Application ID | Acquia Cloud site name |
    +------------+--------------------------------------+------------------------+
    | Brewtal | 04f18e5e-3e19-4698-ac58-c162df025345 | prod:eeschandan1 |
    | ... | ... | ... |
    +------------+--------------------------------------+------------------------+
    $ pipelines set-application-id
    The application id associated with this repository has been set to 04f18e5e-3e19-4698-ac58-c162df025345

    For a repository hosted outside Cloud Platform (or to target a specific application), pass the ID from the table explicitly: pipelines set-application-id --application-id=<uuid>.

  2. Pipelines reads acquia-pipelines.yaml from the root of the branch it builds. The smallest useful Drupal build installs dependencies and runs your tests:

    acquia-pipelines.yaml
    version: 1.3.0
    services:
    - php:
    version: 8.3
    - composer:
    version: 2
    events:
    build:
    steps:
    - install:
    type: script
    script:
    - composer validate --no-check-all --ansi
    - composer install

    version: 1.3.0 selects the current schema; events.build is the one required event; each step’s script runs as Bash with set -e prepended, so the first failing command fails the run.

    Pin the PHP version explicitly: the runner’s default PHP is older than current Drupal supports, and current Drupal needs PHP 8.3, the pin the run in step 3 built green with. Acquia’s published php service versions are 8.2 and 8.4 without a complete enumeration, so confirm a pin outside those three with a test job before relying on it.

    Note that each step runs in its own shell: an export in one step (a PATH tweak, an env var) is gone in the next, so per-step setup belongs in every step that needs it, or in variables. Every key and the full schema: Creating and managing your build definition file on docs.acquia.com.

    Commit and push it:

    Terminal window
    git add acquia-pipelines.yaml
    git commit -m "Add Pipelines build definition"
    git push origin main
  3. Terminal window
    pipelines start
    pipelines status
    pipelines logs

    pipelines start kicks off a job for the current branch; status reports where it is; logs streams the step output, ending in success:

    $ pipelines start
    Successfully started a build:
    VCS path: main
    Target deployment branch: pipelines-build-main
    Job ID: 35e3807b-5622-452f-ae72-1e7ab891c422
    $ pipelines status
    Job ID: 35e3807b-5622-452f-ae72-1e7ab891c422
    Status: succeeded
    Summary: Successfully completed.
    Site: prod:eeschandan1
    VCS path: main
    Submitted: 2026-07-03 22:32:53 (UTC)
    Started: 2026-07-03 22:32:54 (UTC)
    Finished: 2026-07-03 22:34:16 (UTC)
    $ pipelines logs
    Log messages for build job 35e3807b-5622-452f-ae72-1e7ab891c422:
    ================================================================================
    2026-07-03 22:32:54 (UTC) INFO
    --------------------------------------------------------------------------------
    Job is running
    ================================================================================
    2026-07-03 22:33:19 (UTC) INFO
    --------------------------------------------------------------------------------
    Git clone successful
    ================================================================================
    2026-07-03 22:33:31 (UTC) INFO
    --------------------------------------------------------------------------------
    + echo "Executing step install"
    Executing step install
    + composer validate --no-check-all --ansi
    ./composer.json is valid
    + composer install
    Installing dependencies from lock file (including require-dev)
    Verifying lock file contents can be installed on current platform.
    Package operations: 192 installs, 0 updates, 0 removals
    - Downloading drupal/core-composer-scaffold (11.3.8)
    ... (dependency downloads and extraction elided) ...
    Generating autoload files
    99 packages you are using are looking for funding.
    + echo "Exiting step install"
    Exiting step install
    Killing background jobs
    ================================================================================
    2026-07-03 22:34:16 (UTC) INFO
    --------------------------------------------------------------------------------
    Successfully completed.
    ================================================================================

    If you later connect the repository on GitHub, pushes, tags, and pull requests trigger runs automatically and pipelines start becomes optional.

  4. A successful run commits the build output to a branch named pipelines-build-main in your application’s Cloud Platform repository. Point an environment at that branch with acli api:environments:code-switch myapp.dev pipelines-build-main --task-wait: the built code, dependencies installed, is now what that environment serves. That switch is the same deploy mechanic as everywhere else on the platform (code-workflow guide).

Pipelines cloned your branch into a managed container (4 GB memory, 1 CPU, 60-minute ceiling), read acquia-pipelines.yaml, and ran the build event’s steps in order. Because the steps succeeded, it committed the build output to pipelines-build-main on your application. Your source repository stays clean of build output; the artifact branch carries it. From here, CI/CD is a loop of push → run → switch, and the CI/CD guide shows how to promote artifacts through Dev, Stage, and Prod.

The run fails immediately with a missing-file error

acquia-pipelines.yaml (or .yml) isn’t at the root of the branch being built. The file must exist on that branch, at the top level, with exactly that name.

pipelines start fails to authenticate

the API token was mistyped or revoked. Re-run pipelines configure with a fresh token from cloud.acquia.com/a/profile/tokens.

An SSH key you added under ssh-keys is rejected

keys generated with OpenSSH 7.8 or later use a default format Pipelines doesn’t accept. Regenerate the key in PEM format (ssh-keygen -m PEM ...) and re-encrypt it with pipelines encrypt.

The run times out

builds have a hard 60-minute ceiling. Cut work from the build steps or commit heavyweight dependencies rather than downloading them each run.

The build runs an unexpected PHP version, or a command from one step is “not found” in the next

two faces of the same runner behavior. The container’s default PHP is old (pin yours via the php service), and each step is an isolated shell, so exports never carry over. Repeat per-step setup or move it into variables.

A PHPUnit step can’t bootstrap Drupal

Drupal’s test runner reads SIMPLETEST_DB (unit and kernel tests), plus SIMPLETEST_BASE_URL and a running web server (functional tests). Define the variables under variables: global: in the build definition file, with SIMPLETEST_DB matching the mysql service and a database a step created (mysql://root:[email protected]/drupal). A per-step export doesn’t survive into the next step, and a server for functional tests must start in the same step that runs them, because background programs die when their step ends.

Was this page helpful?