Learn how to set up your project so you can manage and deploy it with Cloud Manager.
Existing AEM projects need to adhere to some basic rules in order to be built and deployed successfully with Cloud Manager.
pom.xml
file in the root of the git repository.
pom.xml
file can refer to as many sub-modules (which in turn may have other sub-modules) as necessary.pom.xml
files.target
.
zip
files contained subdirectories of target
named conf
and conf.d
.In some limited cases, you may need to vary your build process slightly when running inside Cloud Manager as opposed to when it runs on developer workstations. For these cases, Maven Profiles can be used to define how the build should be different in different environments, including Cloud Manager.
Activation of a Maven Profile inside the Cloud Manager build environment should be done by looking for CM_BUILD
environment variable environment variable. Conversely, a profile intended to be used only outside of the Cloud Manager build environment should be done by looking for the absence of this variable.
For example, if you wanted to output a simple message only when the build is run inside Cloud Manager, you would do this:
<profile>
<id>cmBuild</id>
<activation>
<property>
<name>env.CM_BUILD</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<target>
<echo>I'm running inside Cloud Manager!</echo>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
To test this profile on a developer workstation, you can either enable it on the command line (with -PcmBuild
) or in your Integrated Development Environment (IDE).
And if you wanted to output a simple message only when the build is run outside of Cloud Manager, you would do this:
<profile>
<id>notCMBuild</id>
<activation>
<property>
<name>!env.CM_BUILD</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<target>
<echo>I'm running outside Cloud Manager!</echo>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
Artifacts from a password-protected Maven repository should only be used very cautiously as code deployed through this mechanism is not run through all of the quality rules implemented in Cloud Manager’s quality gates. It is advised to also deploy the Java sources as well as the whole project source code alongside with the binary.
Artifacts from password-protected Maven repositories should only be used in rare cases and for code not tied to AEM.
In order to use a password-protected Maven repository from Cloud Manager, specify the password (and optionally, the username) as a secret Pipeline Variable and then reference that secret inside a file named .cloudmanager/maven/settings.xml
in the git repository. This file follows the Maven Settings File schema.
When the Cloud Manager build process starts, the <servers>
element in this file will be merged into the default settings.xml
file provided by Cloud Manager. Server IDs starting with adobe
and cloud-manager
are considered reserved and should not be used by custom servers. Server IDs not matching one of these prefixes or the default ID central
will never be mirrored by Cloud Manager.
With this file in place, the server ID would be referenced from inside a <repository>
and/or <pluginRepository>
element inside the pom.xml
file. Generally, these <repository>
and/or <pluginRepository>
elements would be contained inside a Cloud Manager-specific profile, although that is not strictly necessary.
As an example, let’s say that the repository is at https://repository.myco.com/maven2
, the username Cloud Manager should use is cloudmanager
and the password is secretword
.
First, set the password as a secret on the pipeline:
$ aio cloudmanager:set-pipeline-variables PIPELINEID --secret CUSTOM_MYCO_REPOSITORY_PASSWORD secretword
Then reference this from the .cloudmanager/maven/settings.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>myco-repository</id>
<username>cloudmanager</username>
<password>${env.CUSTOM_MYCO_REPOSITORY_PASSWORD}</password>
</server>
</servers>
</settings>
And finally reference the server id inside the pom.xml
file:
<profiles>
<profile>
<id>cmBuild</id>
<activation>
<property>
<name>env.CM_BUILD</name>
</property>
</activation>
<build>
<repositories>
<repository>
<id>myco-repository</id>
<name>MyCo Releases</name>
<url>https://repository.myco.com/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>myco-repository</id>
<name>MyCo Releases</name>
<url>https://repository.myco.com/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</build>
</profile>
</profiles>
It is a good practice to deploy the Java sources alongside with the binary to a Maven repository.
Configure the maven-source-plugin
in your project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
It is a good practice to deploy the whole project source alongside with the binary to a Maven repository. This allows rebuilding the exact artifact.
Configure the maven-assembly-plugin
in your project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>project-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>project</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
In Cloud Manager, builds may produce any number of content packages. For a variety of reasons, it may be desirable to product a content package but not deploy it. This may be useful, for example, when building content packages used only for testing or which will be repackaged by another step in the build process, that is, as a sub-package of another package.
To accommodate these scenarios, Cloud Manager will look for a property named cloudManagerTarget
in the properties of built content packages. If this property is set to none
, the package will be skipped and not deployed. The mechanism to set this property depends upon the way the build is producing the content package. For example, with the filevault-maven-plugin
you would configure the plugin like this:
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<properties>
<cloudManagerTarget>none</cloudManagerTarget>
</properties>
<!-- other configuration -->
</configuration>
</plugin>
With the content-package-maven-plugin
it is similar:
<plugin>
<groupId>com.day.jcr.vault</groupId>
<artifactId>content-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<properties>
<cloudManagerTarget>none</cloudManagerTarget>
</properties>
<!-- other configuration -->
</configuration>
</plugin>
In many cases, the same code is deployed to multiple AEM environments. Where possible, Cloud Manager will avoid rebuilding the code base when it detects that the same git commit is used in multiple full-stack pipeline executions.
When an execution is started, the current HEAD commit for the branch pipeline is extracted. The commit hash is visible in the UI and via the API. When the build step completes successfully, the resulting artifacts are stored based on that commit hash and may be reused in subsequent pipeline executions.
Packages are reused across pipelines if they are in the same program. When looking for packages that can be reused, AEM disregards branches and reuses artifacts across branches.
When a reuse occurs, the build and code quality steps are effectively replaced with the results from the original execution. The log file for the build step will list the artifacts and the execution information which was used to build them originally.
The following is an example of such log output.
The following build artifacts were reused from the prior execution 4 of pipeline 1 which used commit f6ac5e6943ba8bce8804086241ba28bd94909aef:
build/aem-guides-wknd.all-2021.1216.1101633.0000884042.zip (content-package)
build/aem-guides-wknd.dispatcher.cloud-2021.1216.1101633.0000884042.zip (dispatcher-configuration)
The log of the code quality step will contain similar information.
Consider that your program has two development pipelines:
foo
bar
Both branches are on the same commit ID.
Consider that your program has two branches:
foo
bar
Both branches have the same commit ID.
foo
.bar
.In this case, the artifact from foo
will be reused for the production pipeline since the same commit hash was identified.
If desired, the reuse behavior can be disabled for specific pipelines by setting the pipeline variable CM_DISABLE_BUILD_REUSE
to true
. If this variable is set, the commit hash is still extracted and the resulting artifacts will be stored for later use, but any previously stored artifacts will not be reused. To understand this behavior, consider the following scenario.
becdddb
. The execution is successful and the resulting artifacts are stored.CM_DISABLE_BUILD_REUSE
variable is set.becdddb
, they are not reused due to the CM_DISABLE_BUILD_REUSE
variable.f6ac5e6
. The execution is successful and the resulting artifacts are stored.CM_DISABLE_BUILD_REUSE
variable is deleted.f6ac5e6
, those artifacts are reused.CM_DISABLE_BUILD_REUSE
are not considered when Cloud Manager decides to reuse previously created build artifacts.Adobe Engineering and Consulting teams have developed a comprehensive set of best practices for AEM developers.