Cloud Build Process and Artifacts

As part of every deployment, Craft Cloud assembles all the code and configuration required to run your PHP application and build front-end assets.

Everything about the build process is dictated by your repository, and the craft-cloud.yaml config file.

PHP #

Your project’s composer.json and composer.lock files determine what PHP packages are installed. By default, Cloud expects both files to be at the root of your repository—but your Composer root can be customized. If either file is missing, the build will fail.

Cloud installs packages by running composer install.

Node #

Similarly, Cloud looks for package.json and package-lock.json files at the root of your repository (or at a path set in your config file). Unlike the PHP build step, if package-lock.json is missing, this step is skipped (but the deployment will continue).

The builder also requires that you set a node-version in your Cloud config file.

Build Command #

Cloud executes the build script via npm run build after installing the listed packages with npm clean-install. You can change which script is run with the npm-script setting in craft-cloud.yaml—or the directory the command is run in with node-path.

Special environment variables are exposed to your Node build process:

  • CRAFT_CLOUD_CDN_BASE_URL: The root URL of your environment’s storage bucket.
  • CRAFT_CLOUD_BUILD_ID: This build’s UUID. You will receive a new build ID for each deployment—even if they have the same GIT_SHA.
  • GIT_SHA: The current commit hash being built.
  • CRAFT_CLOUD_ARTIFACT_BASE_URL: See Artifact URLs, below.

Artifacts #

At the end of the build step, the contents of the project’s “artifact path” (the web root, by default) are copied to your storage bucket.

You can specify a different artifact-path in craft-cloud.yaml, but when using something other than your web root, files in your web root will no longer be published or accessible. Generally speaking, you should only change the webroot, and let Cloud keep the settings synchronized.

Artifact URLs #

If you need to refer to the final, published URL of a build artifact from your build script, a file it generates, or at runtime, a special CRAFT_CLOUD_ARTIFACT_BASE_URL is provided to your environment (including the Node build container). On Cloud, it will always look something like this:

https://cdn.craft.cloud/{environment-uuid}/builds/{build-uuid}/artifacts

Within that artifacts/ directory, the file structure of your existing artifact path will be preserved. This means that—in most cases—a relative path will work as you’d expect (say, for ES6 modules or CSS @import statements).

There is no need for filename-based cache-busting, as all artifact URLs will change with every build!

The Cloud extension also provides the artifactUrl() Twig function for generating URLs to files published during your build. If you have historically used the siteUrl() or url() functions to link a stylesheet or JavaScript file (or any other static asset) in your web root, use this function instead.

Outside of Cloud, artifactUrl() falls back to your normal @web URL—and anything in your web root will resolve normally. The special @artifactBaseUrl alias mirrors this behavior, and can be used in Project Config—or anywhere else that evaluates aliases:

{# Register a `script` tag to a static asset: #}
{% js '@artifactBaseUrl/dist/js/app.js' %}

{# Equivalent to: #}
<script src="{{ artifactUrl('dist/js/app.js') }}"></script>

If your local development setup serves assets at a different host (like a webpack dev server, running on a different port), you may want to explicitly set the CRAFT_CLOUD_ARTIFACT_BASE_URL variable:

CRAFT_CLOUD_ARTIFACT_BASE_URL="http://my-project.ddev.site:9000/"

This will override the default @web base URL when using the artifactUrl() helper.

Reading Files #

In the event you need to read the contents of a build artifact from the web runtime, you have two options:

Split the artifact generation into two steps. One would be run in development environments, the results of which would be committed to Git; the second would run normally, during Cloud deployments.

Read the file from the CDN. (Not recommended!) Use file_get_contents()to load the contents of a remote file into memory. You can get a URL to any artifact with the Cloud extension’s Helper class: craft\cloud\Helper::artifactUrl('path/to/artifact.json'). This is generally inadvisable, as it introduces additional latency for every request—unless it is an infrequent operation, or is relegated to a queue job or console command.

If such an artifact is committed to Git, it will already be accessible on the function’s disk, and can be used normally. Only artifacts that are created during deployment must be requested from the CDN!

Applies to Craft Cloud.