With SAP Continuous Integration and Delivery, we like to keep things simple and easy to use. That’s why we’ve created preconfigured CI/CD pipelines for SAP-specific development scenarios. These pipelines consist of several building blocks, so-called stages. Each stage describes a task such as build this app, run these tests, and deploy this to pre-production. When running a pipeline job, each stage performs various smaller tasks - that is, steps - one after the other to meet its purpose.
Our goal was to cover standard scenarios to onboard you as quickly as possible. But sometimes, standard scenarios aren't sufficient. We’ve therefore already implemented the option to add additional credentials and variables to most stages within our CI/CD pipelines (see We Made Our CI/CD Pipelines More Flexible). As a second step in our journey to more flexibility, we’ve now added extension points that let you add your own commands before or after any other step within a stage.
You can extend our pipelines with any kind of additional JavaScript tasks, which will then be executed within a Node.js Docker image. Of course, you also can combine additional commands with additional credentials and variables.
For more information on why and how we want to make our CI/CD pipelines more flexible, see Extensible Pipelines for SAP Continuous Integration and Delivery.
When does it make sense to enhance our standard pipeline functionality? Let’s have a look at an example:
Add a command for a GitHub release with an attached .mtar
file to the Release stage of your job.
In this example, you will add a GitHub release as last step to the Release stage of your SAP Continuous Integration and Delivery job. This GitHub release contains the .mtar
file that results from the Build stage. To reuse files in later stages of a job, they must be placed into the so-called cloudcitransfer
folder in your project sources. This folder is created automatically at the start of a pipeline run.
In your project in your source code repository, create a file called create-release/create-release.js
and paste the following content into it:
const { Octokit } = require("@octokit/core");
const fs = require("fs");
const dateFormat = require('date-and-time')
//
// 1.) Retrieve all parameters from the environment.
// The corresponding environment variables are defined
// in the job.
// If the GITHUB_TOKEN is a basic auth credential, the
// user and password are exposed with a trailing
// '_user' and '_password'.
var githubToken = process.env.GITHUB_TOKEN
var releaseNamePrefix = process.env.RELEASE_NAME_PREFIX;
var releaseTagPrefix = process.env.RELEASE_TAG_PREFIX;
var additionalAssetLabel = process.env.ADDITIONAL_ASSET_LABEL
// CLOUDCI_GIT_COMMIT is not defined as additional environment variable
// for the stage. CLOUDCI_GIT_COMMIT is always injected into the environment
// for run-first and run-last commands.
var targetCommitish = process.env.CLOUDCI_GIT_COMMIT;
// We expect the additional asset in the transfer folder one folder level above,
// since the script is launched from a subfolder.
var additionalAssetName = `../${process.env.ADDITIONAL_ASSET_PATH}`;
//
// 2.) Use a suitable stategy for release suffixes
// to ensure that the same release does not already exist. A simple and
// straight-forward approach is to use a time stamp.
var releaseSuffix = dateFormat.format(new Date(), 'YYYY-MM-DD-HH-mm-ss')
// 1: protocol
// 2: host
// 3: owner
// 4: repo
var gitRepoUrlParts = process.env.GIT_URL.match(/(.*):\/\/(.*)\/(.*)\/(.*).git/)
var githubApiUrl=`${gitRepoUrlParts[1]}://${gitRepoUrlParts[2]}/api/v3/`
var owner=gitRepoUrlParts[3]
var repo=gitRepoUrlParts[4]
//
// 3.) Define the client for communicating with the GitHub-API.
const octokit = new Octokit({
auth: githubToken,
baseUrl: githubApiUrl,
});
//
// 4.) Create the GitHub release.
octokit
.request("POST repos/{owner}/{repo}/releases", {
owner: owner,
repo: repo,
target_commitish: targetCommitish,
tag_name: `${releaseTagPrefix}-${releaseSuffix}`,
name: `${releaseNamePrefix}-${releaseSuffix}`,
draft: false,
prerelease: false,
generate_release_notes: false,
})
.then((res) => {
// response status code check not required. In case of an issue octokit throws an error
console.log(`Release created: status: '${res.status}', url: '${res.data.html_url}'`)
//
// 5.) ... and we attach the additional asset
octokit.request(`POST ${res.data.upload_url}`, {
name: additionalAssetName,
label: additionalAssetLabel,
data: fs.readFileSync(additionalAssetName),
});
console.log(`additional asset "${additionalAssetName}" uploaded`)
})
create-release/package.json
with the following content:{
"dependencies": {
"@octokit/core": "^4.2.0",
"date-and-time": "^3.0.0",
"fs": "^0.0.1-security"
}
}
.mtar
file that results from the build, is created.In SAP Continuous Integration and Delivery, create a new or edit an existing SAP Cloud Application Programming Model job.
In the Build stage, choose + (Add command step) next to Additional Commands and then Run Last in Stage.
As Command, enter: cp <PATH_TO_MTAR_FILE> cloudcitransfer
In the Release stage, choose + (Add command step) next to Additional Commands and then Run Last in Stage.
As Command, enter: cd create-release && npm install && node create-release.js
Choose + (Add credentials variable) next to Additional Credentials.
Enter a name for your credentials variable.
From the Credentials Name drop-down list, choose Create Credentials.
Enter the necessary information for your GitHub token and choose Create.
Choose OK.
Choose + (Add variable) next to Additional Variables.
Add the following variables:
Name | Value |
RELEASE_NAME_PREFIX | A prefix for the name of the release. A timestamp will be appended. |
RELEASE_TAG_PREFIX | A prefix for the tag used for the release. A timestamp will be appended. |
ADDITIONAL_ASSET_LABEL | The label for the additional asset |
ADDITIONAL_ASSET_PATH | The path to the file, in which the additional asset is located. Provide the file which was copied into the cloudcitransfer folder in run-last of the build stage. |
The configuration for this example looks as follows:
---
general:
buildTool: "mta"
service:
buildToolVersion: "MBTJ11N16"
stages:
Build:
runLast:
command: "cp BAS_Sample_App.mtar cloudcitransfer"
Release:
credentialVariables:
- name: "GITHUB_TOKEN"
credentialId: "<YOUR_GITHUB_TOKEN>"
stringVariables:
- name: "RELEASE_NAME_PREFIX"
value: "experimental"
- name: "RELEASE_TAG_PREFIX"
value: "v0.0.1"
- name: "ADDITIONAL_ASSET_PATH"
value: "cloudcitransfer/BAS_Sample_App.mtar"
- name: "ADDITIONAL_ASSET_LABEL"
value: "BAS_Sample_App.mtar"
runLast:
command: "cd create-release && npm install && node create-release.js"
stages:
Build:
npmExecuteLint: false
Additional Unit Tests:
npmExecuteScripts: false
Malware Scan:
malwareExecuteScan: true
Acceptance:
cloudFoundryDeploy: false
npmExecuteEndToEndTests: fals
Compliance:
sonarExecuteScan: false
Release:
cloudFoundryDeploy: true
cfApiEndpoint: "<YOUR_CF_ENDPOINT>"
cfOrg: "<YOUR_CF_ORG>"
cfSpace: "<YOUR_CF_SPACE>"
cfCredentialsId: "<YOUR_CF_CREDENTIAL_ID>"
deployType: "standard"
tmsUpload: false
steps:
artifactPrepareVersion:
versioningType: "cloud_noTag"
cloudFoundryDeploy:
mtaDeployParameters: "-f --version-rule ALL"
You have now extended our preconfigured pipeline for SAP Cloud Application Programming Model projects by a GitHub release with an additional asset.
How do you extend your SAP Continuous Integration and Delivery jobs? Try it out and let us know!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
20 | |
13 | |
12 | |
10 | |
7 | |
6 | |
6 | |
6 | |
5 | |
5 |