From db5022a4ffc58496f89364fc0d21e3b98bc95c52 Mon Sep 17 00:00:00 2001 From: Marcus Holl Date: Tue, 15 Jan 2019 13:32:01 +0100 Subject: [PATCH] New Scenario Step: SAP UI5 on SAP Cloud Platform (#388) This scenario builds a UI5 app and deploys it to SAP Cloud Platform (neo). --- .codeclimate.yml | 2 +- .../docs/scenarios/ui5-sap-cp/Readme.md | 87 +++++++++++ .../docs/scenarios/ui5-sap-cp/files/.npmrc | 11 ++ .../scenarios/ui5-sap-cp/files/Gruntfile.js | 10 ++ .../docs/scenarios/ui5-sap-cp/files/mta.yaml | 16 +++ .../scenarios/ui5-sap-cp/files/package.json | 10 ++ .../scenarios/ui5-sap-cp/images/pipeline.jpg | Bin 0 -> 18507 bytes documentation/mkdocs.yml | 2 + .../FioriOnCloudPlatformPipelineTest.groovy | 136 ++++++++++++++++++ vars/fioriOnCloudPlatformPipeline.groovy | 50 +++++++ 10 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 documentation/docs/scenarios/ui5-sap-cp/Readme.md create mode 100644 documentation/docs/scenarios/ui5-sap-cp/files/.npmrc create mode 100644 documentation/docs/scenarios/ui5-sap-cp/files/Gruntfile.js create mode 100644 documentation/docs/scenarios/ui5-sap-cp/files/mta.yaml create mode 100644 documentation/docs/scenarios/ui5-sap-cp/files/package.json create mode 100644 documentation/docs/scenarios/ui5-sap-cp/images/pipeline.jpg create mode 100644 test/groovy/FioriOnCloudPlatformPipelineTest.groovy create mode 100644 vars/fioriOnCloudPlatformPipeline.groovy diff --git a/.codeclimate.yml b/.codeclimate.yml index bb0336727..a7d27c56a 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -10,7 +10,7 @@ plugins: editorconfig: .editorconfig # https://docs.codeclimate.com/docs/advanced-configuration#section-exclude-patterns exclude_patterns: - - "documentation/docs/images/" + - "documentation/**/images/" - "cfg/id_rsa.enc" fixme: enabled: true diff --git a/documentation/docs/scenarios/ui5-sap-cp/Readme.md b/documentation/docs/scenarios/ui5-sap-cp/Readme.md new file mode 100644 index 000000000..c5ed59514 --- /dev/null +++ b/documentation/docs/scenarios/ui5-sap-cp/Readme.md @@ -0,0 +1,87 @@ +# Create a Pipeline for SAP UI5 or SAP Fiori on SAP Cloud Platform + +Create an application based on SAP UI5 or SAP Fiori and deploy the build result into an SAP Cloud Platform account in the Neo environment. + +This document describes a scenario step, which means that it combines various different steps to create a complete pipeline. + + +## Prerequisites + +* You have installed the Java Runtime Environment 8. +* You have installed Jenkins 2.60.3 or higher. +* You have set up Project “Piper”. See [README](https://github.com/SAP/jenkins-library/blob/master/README.md). +* You have installed the Multi-Target Application (MTA) Archive Builder 1.0.6 or newer. See [SAP Development Tools](https://tools.hana.ondemand.com/#cloud). +* You have installed Node.js including node and npm. See [Node.js](https://nodejs.org/en/download/). +* You have installed the SAP Cloud Platform Neo Environment SDK. See [SAP Development Tools](https://tools.hana.ondemand.com/#cloud). + + +### Project Prerequisites + +This scenario step requires additional files in your project and the execution environment on your Jenkins instance. On the project level, provide and adjust the following template: + +| File Name | Description | +|-----|-----| +| [`.npmrc`](https://github.com/marcusholl/jenkins-library/tree/pr/scenarioUI5SAPCP/documentation/docs/scenarios/ui5-sap-cp/files/.npmrc) | This file contains a reference to the SAP NPM registry (`@sap:registry https://npm.sap.com`), which is required to fetch dependencies to build the application. Place it in the root directory of your project. | +| [`mta.yaml`](https://github.com/marcusholl/jenkins-library/tree/pr/scenarioUI5SAPCP/documentation/docs/scenarios/ui5-sap-cp/files/mta.yaml) | This file controls the behavior of the MTA toolset. Place it in your application root folder and adjust the values in brackets with your data. | +| [`package.json`](https://github.com/marcusholl/jenkins-library/tree/pr/scenarioUI5SAPCP/documentation/docs/scenarios/ui5-sap-cp/files/package.json) | This file lists the required development dependencies for the build. Add the content to your existing `package.json` file. | +| [`Gruntfile.js`](https://github.com/marcusholl/jenkins-library/tree/pr/scenarioUI5SAPCP/documentation/docs/scenarios/ui5-sap-cp/files/Gruntfile.js) | This file controls the grunt build. By default the tasks `clean`, `build`, and `lint` are executed. Place it in the root directory of your project. | + + +## Context + +In this scenario step, we want to show how to build an application based on SAP UI5 or SAP Fiori by using the multi-target application (MTA) concept and how to deploy the build result into an SAP Cloud Platform account in the Neo environment. This document comprises the [mtaBuild](https://sap.github.io/jenkins-library/steps/mtaBuild/) and the [neoDeploy](https://sap.github.io/jenkins-library/steps/neoDeploy/) steps. + +![This pipeline in Jenkins Blue Ocean](images/pipeline.jpg) + +## Example + +### Jenkinsfile + +Following the convention for pipeline definitions, use a `Jenkinsfile` which resides in the root directory of your development sources. + +```groovy +@Library('piper-lib-os') _ + +fioriOnCloudPlatformPipeline script:this +``` + +### Configuration (`.pipeline/config.yml`) + +This is a basic configuration example, which is also located in the sources of the project. + +```yaml +steps: + mtaBuild: + buildTarget: 'NEO' + mtaJarLocation: '/opt/sap/mta.jar' + neoDeploy: + neoCredentialsId: 'NEO_DEPLOY' + neoHome: '/opt/sap/neo-sdk/' + account: 'your-account-id' + host: 'hana.ondemand.com' +``` + +#### Configuration for the MTA Build + +| Parameter | Description | +| -----------------|----------------| +| `buildTarget` | The target platform to which the mtar can be deployed. Possible values are: `CF`, `NEO`, `XSA` | +| `mtaJarLocation` | The location of the multi-target application archive builder jar file, including file name and extension. | + + +#### Configuration for the Deployment to SAP Cloud Platform + +| Parameter | Description | +| -------------------|-------------| +| `account` | The SAP Cloud Platform account to deploy to. | +| `host` | The SAP Cloud Platform host to deploy to. | +| `neoCredentialsId` | The Jenkins credentials that contain the user and password which are used for the deployment on SAP Cloud Platform. | +| `neoHome` | The path to the `neo-java-web-sdk` tool that is used for the deployment. | + + +### Parameters + +For the detailed description of the relevant parameters, see: + +* [mtaBuild](https://sap.github.io/jenkins-library/steps/mtaBuild/) +* [neoDeploy](https://sap.github.io/jenkins-library/steps/neoDeploy/) diff --git a/documentation/docs/scenarios/ui5-sap-cp/files/.npmrc b/documentation/docs/scenarios/ui5-sap-cp/files/.npmrc new file mode 100644 index 000000000..b744be289 --- /dev/null +++ b/documentation/docs/scenarios/ui5-sap-cp/files/.npmrc @@ -0,0 +1,11 @@ +# This file can be ommitted in the project if it is ensured +# that the corresponding configuration is provided on a +# higher level in the npm config (either on user level ~/.npmrc or +# globally). For more details with regards to configuring npm check +# man pages for npm-config/npmrc + +# The public npm registry from where to fetch e.g. Grunt +registry=https://registry.npmjs.org + +# The SAP npm registry from where to fetch SAP specific Grunt modules +@sap:registry=https://npm.sap.com diff --git a/documentation/docs/scenarios/ui5-sap-cp/files/Gruntfile.js b/documentation/docs/scenarios/ui5-sap-cp/files/Gruntfile.js new file mode 100644 index 000000000..2075e5995 --- /dev/null +++ b/documentation/docs/scenarios/ui5-sap-cp/files/Gruntfile.js @@ -0,0 +1,10 @@ +module.exports = function (grunt) { + 'use strict'; + grunt.loadNpmTasks('@sap/grunt-sapui5-bestpractice-build'); + + grunt.registerTask('default', [ + 'lint', + 'clean', + 'build' + ]); +}; diff --git a/documentation/docs/scenarios/ui5-sap-cp/files/mta.yaml b/documentation/docs/scenarios/ui5-sap-cp/files/mta.yaml new file mode 100644 index 000000000..a21553035 --- /dev/null +++ b/documentation/docs/scenarios/ui5-sap-cp/files/mta.yaml @@ -0,0 +1,16 @@ +_schema-version: "2.0.0" +ID: "" +version: + +parameters: + hcp-deployer-version: "1.0.0" + +modules: + - name: "" + type: html5 + path: . + parameters: + version: -${timestamp} + build-parameters: + builder: grunt + build-result: dist diff --git a/documentation/docs/scenarios/ui5-sap-cp/files/package.json b/documentation/docs/scenarios/ui5-sap-cp/files/package.json new file mode 100644 index 000000000..1fd106c7e --- /dev/null +++ b/documentation/docs/scenarios/ui5-sap-cp/files/package.json @@ -0,0 +1,10 @@ +{ + "name": "", + "version": "", + "description": "", + "private": true, + "devDependencies": { + "grunt": "1.0.1", + "@sap/grunt-sapui5-bestpractice-build": "1.3.17" + } +} diff --git a/documentation/docs/scenarios/ui5-sap-cp/images/pipeline.jpg b/documentation/docs/scenarios/ui5-sap-cp/images/pipeline.jpg new file mode 100644 index 0000000000000000000000000000000000000000..09efda5db572c96a94cb0a02524d459a47740e1c GIT binary patch literal 18507 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 literal 0 HcmV?d00001 diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml index e141fbbfa..ca1287f92 100644 --- a/documentation/mkdocs.yml +++ b/documentation/mkdocs.yml @@ -34,6 +34,8 @@ nav: - transportRequestCreate: steps/transportRequestCreate.md - transportRequestRelease: steps/transportRequestRelease.md - transportRequestUploadFile: steps/transportRequestUploadFile.md + - 'Scenarios': + - 'Fiori (MTA) build and deployment to SAP Cloud Platform': scenarios/ui5-sap-cp/Readme.md - 'Required Plugins': jenkins/requiredPlugins.md theme: diff --git a/test/groovy/FioriOnCloudPlatformPipelineTest.groovy b/test/groovy/FioriOnCloudPlatformPipelineTest.groovy new file mode 100644 index 000000000..ac324c9c9 --- /dev/null +++ b/test/groovy/FioriOnCloudPlatformPipelineTest.groovy @@ -0,0 +1,136 @@ +import static org.hamcrest.Matchers.allOf +import static org.hamcrest.Matchers.containsString +import static org.hamcrest.Matchers.equalTo +import static org.hamcrest.Matchers.hasItem +import static org.hamcrest.Matchers.is +import static org.hamcrest.Matchers.subString +import static org.junit.Assert.assertThat + +import org.hamcrest.Matchers +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain + +import com.sap.piper.JenkinsUtils + +import util.BasePiperTest +import util.JenkinsCredentialsRule +import util.JenkinsReadYamlRule +import util.JenkinsShellCallRule +import util.JenkinsStepRule +import util.Rules + +class FioriOnCloudPlatformPipelineTest extends BasePiperTest { + + /* This scenario builds a fiori app and deploys it into an neo account. + The build is performed using mta, which delegates to grunt. grunt in + turn makes use of the 'sap/grunt-sapui5-bestpractice-build' plugin. + The dependencies are resolved via npm. + + In order to run the scenario the project needs to fullfill these + prerequisites: + + Build tools: + * mta.jar available + * npm installed + + Project configuration: + * sap registry `@sap:registry=https://npm.sap.com` configured in + .npmrc (either in the project or on any other suitable level) + * dependency to `@sap/grunt-sapui5-bestpractice-build` declared in + package.json + * npmTask `@sap/grunt-sapui5-bestpractice-build` loaded inside + Gruntfile.js and configure default tasks (e.g. lint, clean, build) + * mta.yaml + */ + + JenkinsStepRule jsr = new JenkinsStepRule(this) + JenkinsReadYamlRule jryr = new JenkinsReadYamlRule(this) + JenkinsShellCallRule jscr = new JenkinsShellCallRule(this) + + @Rule + public RuleChain ruleChain = Rules + .getCommonRules(this) + .around(jryr) + .around(jsr) + .around(jscr) + .around(new JenkinsCredentialsRule(this) + .withCredentials('CI_CREDENTIALS_ID', 'foo', 'terceSpot')) + + @Before + void setup() { + // + // needed since we have dockerExecute inside mtaBuild + JenkinsUtils.metaClass.static.isPluginActive = {def s -> false} + + // + // Things we validate: + jscr.setReturnValue(JenkinsShellCallRule.Type.REGEX, '.*echo \\$JAVA_HOME.*', '/opt/sap/java') + jscr.setReturnValue(JenkinsShellCallRule.Type.REGEX, '.*echo \\$MTA_JAR_LOCATION.*', '/opt/sap') + jscr.setReturnValue(JenkinsShellCallRule.Type.REGEX, '.*echo \\$NEO_HOME.*', '/opt/sap/neo') + jscr.setReturnValue(JenkinsShellCallRule.Type.REGEX, ".*bin/java -version.*", '1.8.0') // the java version + jscr.setReturnValue(JenkinsShellCallRule.Type.REGEX, ".*bin/java -jar .*mta.jar", '1.36.0') // the mta version + + // + // there is a check for the mta.yaml file and for the deployable test.mtar file + helper.registerAllowedMethod('fileExists', [String],{ + + it -> + + // called inside mtaBuild, this file contains build config + it == 'mta.yaml' || + + // called inside neo deploy, this file gets deployed + it == 'test.mtar' + }) + + // + // the properties below we read out of the yaml file + jryr.registerYaml('mta.yaml', (''' + |ID : "test" + |PATH : "." + |''' as CharSequence).stripMargin()) + + // + // we need the path variable since we extend the path in the mtaBuild step. In order + // to be able to extend the path we have to have some initial value. + binding.setVariable('PATH', '/usr/bin') + + } + + @Test + void straightForwardTest() { + + nullScript + .commonPipelineEnvironment + .configuration = [steps: + [neoDeploy: + [ host: 'hana.example.com', + account: 'myTestAccount', + ] + ] + ] + + jsr.step.fioriOnCloudPlatformPipeline(script: nullScript) + + // + // the mta build call: + assertThat(jscr.shell, hasItem( + allOf( containsString('java -jar /opt/sap/mta.jar'), + containsString('--mtar test.mtar'), + containsString('--build-target=NEO'), + containsString('build')))) + + // + // the deployable is exchanged between the involved steps via this property: + assertThat(nullScript.commonPipelineEnvironment.getMtarFilePath(), is(equalTo('test.mtar'))) + + // + // the neo deploy call: + assertThat(jscr.shell, hasItem('#!/bin/bash "/opt/sap/neo/tools/neo.sh" deploy-mta --source "test.mtar" ' + + '--host \'hana.example.com\' --account \'myTestAccount\' --synchronous ' + + '--user \'foo\' --password \'terceSpot\'')) + } +} diff --git a/vars/fioriOnCloudPlatformPipeline.groovy b/vars/fioriOnCloudPlatformPipeline.groovy new file mode 100644 index 000000000..8003c36b9 --- /dev/null +++ b/vars/fioriOnCloudPlatformPipeline.groovy @@ -0,0 +1,50 @@ +import static com.sap.piper.Prerequisites.checkScript + +import groovy.transform.Field + +@Field def STEP_NAME = getClass().getName() + +@Field def GENERAL_CONFIG_KEYS = [] +@Field def PARAMETER_KEYS = [] +@Field def STEP_CONFIG_KEYS = [] + +/** The Scenario is intended for building and uploading a fiori application. + * + * It needs to be called from a pipeline script (Jenkinsfile) like: + * ``` + * @Library('piper-lib-os') _ + * @Library('your-additional-lib') __ // optional + * + * // parameter 'customDefaults' below is optional + * fioriOnCloudPlatformPipeline(script: this, customDefaults: '') + * ``` + */ +void call(parameters = [:]) { + + checkScript(this, parameters) + + node(parameters.label) { + + // + // Cut and paste lines below in order to create a pipeline from this scenario + // In this case `parameters` needs to be replaced by `script: this`. + + stage('prepare') { + + setupCommonPipelineEnvironment(parameters) + } + + stage('build') { + + mtaBuild(parameters) + } + + stage('deploy') { + + neoDeploy(parameters) + } + + // Cut and paste lines above in order to create a pipeline from this scenario + // + } +}