<p>Azure DevOps allows easier and faster creation of build and release pipelines. It allows you to build, test, and deploy with continuous integration/continuous delivery (CI/CD) that is compatible with any language, platform, and cloud. It connects with GitHub (or any Git provider) and performs continuous deployments. It also provides cloud-hosted pipelines for Linux, macOS, and Windows, and builds for desktop, web, and mobile applications.</p>
<h4 style="text-align: left;">Benefits of using Azure Pipelines with Salesforce Commerce Cloud (SFCC):</h4>
<ul>
<li>Build, test, and deploy Java, PHP, Ruby, C/C++, .NET, Node.js, Python, Android, and iOS apps.</li>
<li>Easily build and deploy the images to containers like Docker Hub and Azure Container Registry. Deploy containers to individual hosts or Kubernetes.</li>
<li>Implement community-built build, test, and deployment tasks, along with hundreds of extensions from Slack and SonarCloud.</li>
<li>Ensure rapid CI/CD pipelines for every open-source project.</li>
<li>Take advantage of chaining builds and multi-phased builds – support for YAML, test integration, release gates, reporting, and more.</li>
<li>Implement continuous delivery of your solution to any cloud, such as Azure, AWS, or GCP.</li>
</ul>
<h4 style="text-align: left;">Creating Azure Pipelines</h4>
<p>The following section explains how to code a build pipeline and create a release pipeline. To build code from a repository (in this case Azure Repos), you must create a YAML file named: <i>azure-pipelines.yml.</i> This YAML file must include steps and tasks to create necessary configuration files and scripts. These tasks and scripts can also be added at different stages.</p>
<p>Let’s consider having a Node.js-based project that uses gulp.js for linting and building. Since this is a Salesforce-based project, the user can utilize a build pipeline to deploy (i.e., upload code to the Salesforce instance) as well as use the following YAML:</p>
<div class="col-md-10">
<code>
<pre style="padding: 0px 20px; margin: 0px; font-size: 15px; text-align: left; border:1px solid #B5B5B5; background-color: #F4F4F4;">
trigger:
batch: true
branches:
include:
- master
- develop
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '12.16.3'
displayName: 'Install Node.js'- script: |
npm install
npm install sgmf-scripts
displayName: 'Install node modules'- task: Bash@3
inputs:
targetType: 'inline'
script: |
echo "Creating dw.json"
echo '{
"hostname": "$(hostname)",
"username": "$(username)",
"password": "$(password)",
"code-version": "$(code-version)"
}' > dw.json
echo "Created dw.json"
failOnStderr: true
displayName: 'Create SFCC Config JSON'- script: |
gulp lint
gulp build
displayName: 'Lint and Build using Gulp'- script: |
npm run uploadCartridge "app*, int*, bc*"
displayName: 'Upload cartridges'
</pre>
</code>
</div><br>
<p>Find the details of each section of this YAML file below:</p>
<ul>
<li><strong>Trigger:</strong> Provides control that allows build to trigger for listed branches, like develop, master, release, etc.</li>
<li><strong>Pool:</strong> Azure Pipelines provide a Microsoft-hosted agent pool, named Azure Pipelines. You can choose from several virtual machine images where each image includes a broad range of tools and software.</li>
</ul>
<h5 style="text-align: left;">Steps to Code a Build Pipeline</h5>
<p>Find the detailed steps below:</p>
<p><strong>Step 1:</strong> Install Node.js (latest LTS as of today)</p>
<div class="col-md-10">
<code>
<pre style="padding: 0px 20px; margin: 0px; font-size: 15px; text-align: left; border:1px solid #B5B5B5; background-color: #F4F4F4;">
task: NodeTool@0
inputs:
versionSpec: '12.16.3'
displayName: 'Install Node.js'
</pre>
</code>
</div><br>
<p><strong>Step 2:</strong> Install script (sgmf-scripts) to install dependencies mentioned in package.json present in the repository at the same level as the YAML file.</p>
<div class="col-md-10">
<code>
<pre style="padding: 0px 20px; margin: 0px; font-size: 15px; text-align: left; border:1px solid #B5B5B5; background-color: #F4F4F4;">
script: |
npm install
npm install sgmf-scripts
displayName: 'Install node modules'
</pre>
</code>
</div><br>
<p>This task is important as it creates a configuration file used by the sgmf-scripts package. Here, dw.json config file is created dynamically using variables — an out-of-the-box feature from Azure DevOps.</p>
<p>Example:</p>
<div class="col-md-10">
<code>
<pre style="padding: 0px 20px; margin: 0px; font-size: 15px; text-align: left; border:1px solid #B5B5B5; background-color: #F4F4F4;">
$(hostname), $(username),…
task: Bash@3
inputs:
targetType: 'inline'
script: |
echo "Creating dw.json"
echo '{
"hostname": "$(hostname)",
"username": "$(username)",
"password": "$(password)",
"code-version": "$(code-version)"
}' > dw.json
echo "Created dw.json"
failOnStderr: true
displayName: 'Create SFCC Config JSON'
</pre>
</code>
</div><br>
<p><strong>Step 3:</strong> The next script to be installed is commonly used for linting and building frontend changes of the project.</p>
<div class="col-md-10">
<code>
<pre style="padding: 0px 20px; margin: 0px; font-size: 15px; text-align: left; border:1px solid #B5B5B5; background-color: #F4F4F4;">
script: |
gulp lint
gulp build
displayName: 'Lint and Build using Gulp'
</pre>
</code>
</div><br>
<p><strong>Step 4:</strong> Execution of the last script uploads SFCC code cartridges.</p>
<div class="col-md-10">
<code>
<pre style="padding: 0px 20px; margin: 0px; font-size: 15px; text-align: left; border:1px solid #B5B5B5; background-color: #F4F4F4;">
script: |
npm run uploadCartridge "app*, int*, bc*"
displayName: 'Upload cartridges'
</pre>
</code>
</div><br>
<p>Once code is pushed to the configured branches, build automatically triggers and uploads code on an SFCC instance.</p>
<h5 style="text-align: left;">Steps to Create a Release Pipeline</h5>
<p>These pipelines provide release power to multiple servers or instances when they are scheduled to be deployed with the same build artifact – example, for Salesforce, there are development (QA), staging (pre-production), and some sandbox (UAT) servers.</p>
<p>Listed below are some more options from Azure DevOps that can be utilized to write the Task(s), which can be executed once and utilized in multiple stages.</p>
<p><strong>Option 1: Library</strong></p>
<p>Variable groups holding multiple variables can be created with a library for different server instances. One such example is given below:</p>
<p><img style="padding: 0px 20px;" width="650px" height="auto" alt="Configuration for Pipeline Variable in Library" src="https://images.prismic.io/gspann/fb4db0a2-64d3-4a41-b246-4dee50220fc8_Image+1_+Configuration+for+Pipeline+Variable+in+Library.jpg?auto=compress,format" /></p>
<p>These variables can be used in Tasks created for the release pipeline. These tasks can also be clubbed together to create a task group, which is explained as Option 2 below.</p>
<p><strong>Option 2: Task Groups</strong></p>
<p>A task group can have two or more tasks clubbed together. It can be used for different release pipelines having common task features and functionality. One such example is given below:</p>
<p><img style="padding: 0px 20px;" width="750px" height="auto" alt="Creation of Task Groups from Tasks" src="https://images.prismic.io/gspann/db968b8b-29db-498a-93e0-47619ec78a48_Image+2_+Creation+of+Task+Groups+from+Tasks.jpg?auto=compress,format" /></p>
<p>Like this task group, there can be multiple task groups and each of them can be used to create a stage for a release pipeline.</p>
<p>How to create a task group?</p>
<ul>
<li>You can select an option to add tasks while adding a release pipeline.</li>
<li>Once the tasks are added, select the tasks that you want to club together for a task group.</li>
<li>Right-click and create a task group.</li>
</ul>
<p>Once all the necessary task groups are created, add different stages to build and deploy the artifact. See how these can be set up in the sequence below:</p>
<p><img style="padding: 0px 20px;" width="750px" height="auto" alt="A Release Pipeline Stages with Artifacts" src="https://images.prismic.io/gspann/2d149ab7-6f23-4292-92b4-067457d1af7f_Image+3_+A+Release+Pipeline+Stages+with+Artifacts.jpg?auto=compress,format" /></p>
<p>You can build and deploy an artifact to QA, UAT, and staging instances of Salesforce with a single release pipeline. An important thing to note here is that you can set up a code branch to trigger the build of your choice while ensuring that each stage has a job with a task.</p>
<p>The screenshot below shows a single task doing the build and deploying within a single task group:</p>
<p><img style="padding: 0px 20px;" width="750px" height="auto" alt="Pre-requisite Variables for the Task Group" src="https://images.prismic.io/gspann/c71f7f45-3d35-4ea0-bf0b-a9ef12b46c61_Image+4_+Pre-requisite+Variables+for+the+Task+Group.jpg?auto=compress,format" /></p>
<p>With these simple steps, the setup becomes easy and flexible.</p>
<h4 style="text-align: left;">Best Practices for Integrating Salesforce Commerce Cloud with Azure DevOps</h4>
<p>Below are some of the best practices for integrating Salesforce Commerce Cloud with Azure DevOps.</p>
<ul>
<li>Ensure that the credentials are secured/locked when adding them to ‘Variables.’</li>
<li>Create instance-specific library details instead of clubbing them into a single library.</li>
<li>Ensure using a single parallel job instead of multiple to avoid additional costs.</li>
<li>Verify task groups before using them and assure that the task variable is appropriately defined.</li>
<li>Avoid creating each stage with separate tasks instead of the task group because it is challenging to maintain and modify.</li>
<li>Never hard-code your credentials in the configuration file. It should not be exposed.</li>
<li>Don’t go with a parallel build and deploy, instead use a sequential process.</li>
</ul>
<p>To integrate Salesforce with Azure DevOps pipelines, a Salesforce account manager access is necessary along with the subscription of Azure DevOps. Since the repository, along with Artifacts and pipelines, lives in a single tool, you do not require a cloud provider other than Azure DevOps. Hence, it’s very easy and efficient to set up as compared to Jenkins on different cloud platforms.</p>