From bccfbb5384cec24b3f96d1a15701ef6e5682a33e Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 13:57:14 +0530 Subject: [PATCH 01/23] Initial CI setup --- Jenkinsfile | 148 ++++++++++++++++++++++++++++++++++++++++++ jenkins/Utils.groovy | 150 +++++++++++++++++++++++++++++++++++++++++++ jenkins/build_app.sh | 63 ++++++++++++++++++ 3 files changed, 361 insertions(+) create mode 100644 Jenkinsfile create mode 100644 jenkins/Utils.groovy create mode 100644 jenkins/build_app.sh diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..95aef02 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,148 @@ +/************************************************************************************************* + * + * (c) 2022 All Rights Reserved. + * + * This JenkinsFile calls the real build job to build the DPC/SDK code. This file will live in the + * the repo for Jenkins' hooks to pick it up and start builds for PRs, merges, etc. + * + *************************************************************************************************/ + +import groovy.transform.Field +import jenkins.model.CauseOfInterruption +import hudson.model.* +import net.sf.json.JSONArray +import net.sf.json.JSONObject +import groovy.json.JsonSlurperClassic + +@Field def g_BranchToReleaseTypeMap = [ + 'develop' : 'alpha', + 'staging' : 'beta', + 'master' : 'prod', + 'RelCandidate' : 'Experimental', + 'SHN-15702-ci': 'alpha' +] +@Field def g_BranchToStacksTypeMap = [ + 'develop': 'development', + 'staging': 'staging', + 'master': 'production', + 'RelCandidate': 'rel_candidate', + 'SHN-15702-ci': 'development' +] +@Field def g_branchToFileName = [ + 'develop': 'develop', + 'RelCandidate' : 'Experimental', + 'staging' : 'staging', + 'master' : 'master', + 'SHN-15702-ci': 'development' +] + +@Field def slackMessageTitle = 'DPC Build Notification' +@Field def slackMessageChannel = '#device-deployments' +@Field def ShoonyDpcPublisherCredId = 'shoonya_jenkins_cloud_ui_build_user' +@Field def ShoonyDpcPublisherAwsRegion = 'ap-south-1' +@Field def ShoonyDpcPublisherS3Bucket = 'shoonya-dpc' +@Field def JenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' +@Field def releaseBranch = 'master' + +pipeline +{ + agent { + label 'dpc-builder' + } + + stages { + stage('Initialize') { + steps { + script { + sh 'ls -la' + g_utils = load './jenkins/Utils.groovy' + g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' + time_stamp = new Date().format('yyyyMMddHHmm') + g_buildNumber = [g_releaseChannel, time_stamp].join('-') + echo "Build_Number: ${g_buildNumber}" + } + } + } + stage('Branch indexing: abort') { + when { + allOf { + triggeredBy cause: 'BranchIndexingCause' + not { + changeRequest() + } + } + } + steps { + script { + echo 'Branch discovered by branch indexing. No way this build is gonna run!' + currentBuild.result = 'SUCCESS' + error 'Caught branch indexing...' + } + } + } + stage('Abort running build') { + when { + expression { + return env.BRANCH_NAME ==~ /(develop|RelCandidate|staging|SHN-15702-ci)/ || changeRequest() + } + } + steps { + script + { + def item = Jenkins.instance.getItemByFullName(env.JOB_NAME) + item.getAllJobs().each { job -> + job._getRuns().iterator().each { run -> + def exec = run.getExecutor() + //if the run is not a current build and it has executor (running) then stop it + if ( run.number.toString() != env.BUILD_ID && exec != null ) { + //prepare the cause of interruption + def cause = { "interrupted by build #${run.getId()}" as String } as CauseOfInterruption + exec.interrupt(Result.ABORTED, cause) + } + } + } + } + } + } // stage - Abort running build + + stage("Build") { + steps { + timestamps { + script { + // get a Sampleapp version number + def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) + g_DpcVersionBuildNumber = "${buildJob.number}" + echo "Version_name: ${g_DpcVersionBuildNumber}" + // let the builder library build the code and archive it + g_utils.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) + } + } + } + } //Stage - Build + + stage("Upload APK to S3") { + when { + anyOf { + expression { + env.BRANCH_NAME ==~ /(develop|RelCandidate|staging|SHN-15702-ci)/ + } + branch g_releaseBranch + } + } + steps { + timestamps { + script { + sh "ls -al" + g_buildPathS3 = g_releaseChannel + sh "ls -al app/" + def buildPathS3 = "sampleapp/"+ g_buildPathS3 + def jsonData = readJSON file: 'app/build-output-pg-enabled/outputs/apk/release/output-metadata.json' + g_dpcApkFile = "${pwd()}/app/build-output-pg-enabled/outputs/apk/release/app-release.apk" + g_dpcVersionCode = jsonData.elements[0].versionCode + g_dpcVersionName = jsonData.elements[0].versionName + g_DpcApkFilename = "shoonya_dpc_v${g_dpcVersionCode}_${g_dpcVersionName}.apk" + echo "DPC for has versionCode = ${g_dpcVersionCode} and versionName = ${g_dpcVersionName}" + } + } + } + } \ No newline at end of file diff --git a/jenkins/Utils.groovy b/jenkins/Utils.groovy new file mode 100644 index 0000000..d6db214 --- /dev/null +++ b/jenkins/Utils.groovy @@ -0,0 +1,150 @@ +import groovy.json.JsonOutput +import net.sf.json.JSONArray +import net.sf.json.JSONObject +import groovy.json.JsonSlurperClassic +import groovy.transform.Field +import groovy.json.JsonOutput +import net.sf.json.JSONArray +import net.sf.json.JSONObject +import groovy.json.JsonSlurperClassic + +@Field def g_slackMessageChannel = '#kservcicdjobtest' +@Field def g_ShoonyDpcPublisherCredId = 'shoonya_jenkins_cloud_ui_build_user' +@Field def g_slackMessageTitle = 'Sampleapp Build Notification' + +def sendSlackMessage(titleText, messageText, messageColor, channelName) { + JSONArray attachments = new JSONArray() + JSONObject attachment = new JSONObject() + + attachment.put('title', titleText.toString()) + attachment.put('text', messageText.toString()) + attachment.put('color', messageColor) + + attachments.add(attachment) + slackSend(botUser: true, channel: channelName, attachments: attachments.toString()) +} + +def injectCreds() { + // Copy the secret file locally for inclusion into the container. It will be cleaned up automatically + // during the cleanup() stage + withCredentials([file(credentialsId: 'shoonya-dpc-key-jks-file', variable: 'SECRET_FILE')]) + { + sh "cp ${SECRET_FILE} secret.file" + } + + // Copy the keystore.properties file for inclusion into the container. It already points to the secret file as + // "storeFile=/application/secret.file" + withCredentials([file(credentialsId: 'keystore.properties', variable: 'KS_PROPS_FILE')]) + { + sh "cp ${KS_PROPS_FILE} keystore.properties" + } + + withCredentials([[$class: 'UsernamePasswordMultiBinding', + credentialsId: 'jfrog-artifactorycreds', + usernameVariable: 'USERNAME', + passwordVariable: 'PASSWORD']]) + { + g_arifactoryUsername = "${USERNAME}" + g_arifactoryPassword = "${PASSWORD}" + } + + echo 'Secrets in place, listing files.' + sh 'ls -al' +} + +def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { + def latestCommit = "${env.GIT_COMMIT}" + //SDK Publish is separated into different job + def publishEsperDeviceSDK = false + // ecr vars to use for pull docker image + def dockerEcrUrl = '973484954817.dkr.ecr.us-west-2.amazonaws.com' + def dockerEcrParms = 'ecr:us-west-2:c1981b34-fa8a-4d88-b3ce-a7adb5c7f71c' + + // login into ECR and get ready to pull image + docker.withRegistry("https://${dockerEcrUrl}", dockerEcrParms) + { + // pull image (only if it's not already on the box) + def currImage = docker.image('shoonya-android-builder-image:latest') + currImage.pull() + + // get the current user's id -- we will pass this to the container for gosu to kick it in. Note the trim() + def currUserId = sh(returnStdout: true, script: 'id -u $USER').trim() + echo "Current runner's UID = ${currUserId}" + + // make the requested script executable, before mapping it into the container + sh 'chmod a+x jenkins/build_app.sh' + + // set the docker image & tag for use for the pull/run + def dockerImageNameAndTag = "${dockerEcrUrl}/shoonya-android-builder-image:latest" + echo "dockerImageNameAndTag= ${dockerImageNameAndTag}" + + // massage the build numbers + def buildNumberAsInt = dpcBuildNumber as Integer + def fourDigitBuildNumber = String.format('%04d', buildNumberAsInt) + + // first get cached-files from S3, if any, to prevent unecessary dependency downloads during the build + // note that we are making the cli only compare the size and not the timestamp to prevent unnecessary + // downloads from S3. The size is ~275MB. + dir('/buildspace/gradle_dependency_cache') + { + sh 'aws s3 sync s3://shoonya-devops-bucket/GradleDependencyCache/ . --size-only' + } + + // + // + // Start the main build in the downloaded docker image + // -v /buildspace/gradle_dependency_cache:/gradle_dependency_cache \ + // + + sh "docker run --rm -e BUILD_NUMBER=${buildNumberAsInt} \ + -e FOURDIGIT_BUILD_NUMBER=${fourDigitBuildNumber} \ + -e PUBLISH_ESPER_DEVICE_SDK=${publishEsperDeviceSDK} \ + -e ARTIFACTORY_USERNAME=${g_arifactoryUsername} \ + -e ARTIFACTORY_PASSWORD=${g_arifactoryPassword} \ + -e RELEASE_CHANNEL=${releaseChannel} \ + -e LOCAL_USER_ID=${currUserId} \ + -v /buildspace/gradle_dependency_cache:/gradle_dependency_cache \ + -v ${pwd()}/jenkins/build_app.sh:/build_app.sh \ + -v ${pwd()}:/application '${dockerImageNameAndTag}' \ + sh -c /build_app.sh" + } +} + +def archiveFolders(String buildFolderName, String zipFileSuffix) { + def archiveFolderMap = [ + "espersdksample/${buildFolderName}" : ['esper-sdk-sample' : ['outputs', 'reports', 'test-results']] + ] +} + +def performPostBuildActivities() { + // from the logs, make sure + def buildSuccessful = sh(script: "grep -Fxq 'Build successful' build_status.log", returnStatus: true) == 0 + if (!buildSuccessful) { + error('Build failed.') + } + + //echo 'Running junit on tests..' + //junit '**/TEST-*.xml' + + echo 'Running the lint-analysis tool..' + androidLint() + + // archive all interesting folders and attach it to this build + //archiveFolders('build-output', '') +} + +def buildApps(String dpcBuildNumber, String releaseChannel) { + // + // At this point, we are already in the folder where the entire source code for this app is + // + + // first inject the build-related credentials into the file system + injectCreds() + + // run the build(s) in the designated docker image + runBuildInDocker(dpcBuildNumber, releaseChannel) + + // ensure build succeeded, and activities such as lint-checks. + performPostBuildActivities() +} + diff --git a/jenkins/build_app.sh b/jenkins/build_app.sh new file mode 100644 index 0000000..be23b3d --- /dev/null +++ b/jenkins/build_app.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -xeuo pipefail +APP_DIR=/application +LOG_FILE="$APP_DIR"/build_status.log +curr_script=$(basename -- "$0") +echo "Setting environment variable indicating that this is a Jenkins' build" +export BUILT_BY_JENKINS="yes" +echo "$curr_script started" | tee $LOG_FILE + +echo "Copying cached files into the .gradle folder for faster builds" +mkdir -p ~/.gradle/{caches,temp} +rm -rf ~/.gradle/caches +pushd ~/.gradle/temp +tar -xzf /gradle_dependency_cache/dependency_cache.tar.gz +popd +mv ~/.gradle/temp/home/nala/.gradle/caches ~/.gradle/caches +rm -rf ~/.gradle/temp + +echo "Switching to the app directory" | tee -a $LOG_FILE +cd $APP_DIR +if [ $? -ne 0 ];then + echo 'Failed to change to $APP_DIR directory' | tee -a $LOG_FILE + exit +fi + +echo "Setting the sdk path in local.properties" | tee -a $LOG_FILE +echo "sdk.dir=$ANDROID_SDK_DIR" > $ANDROID_PROJ_DIR/local.properties + +echo "Making gradlew executable" | tee -a $LOG_FILE +chmod +x ./gradlew +if [ $? -ne 0 ];then + echo 'Failed to mark gradlew as executable' | tee -a $LOG_FILE + exit +fi + +echo "Creating the wrapper based on what the app has requested" | tee -a $LOG_FILE +gradle wrapper +if [ $? -ne 0 ];then + echo 'Failed to create wrapper' | tee -a $LOG_FILE + exit +fi + +export OBFUSCATION=true +export BUILD_OUTPUT_DIR=build-output + +echo "Cleaning project" | tee -a $LOG_FILE +./gradlew clean +if [ $? -ne 0 ];then + echo 'Failed to clean project' | tee -a $LOG_FILE + exit +fi + +# all flavours of release artifacts only. +echo "Building project" | tee -a $LOG_FILE +./gradlew assembleRelease --stacktrace +if [ $? -ne 0 ];then + echo 'Failed to build project' | tee -a $LOG_FILE + exit +fi + + +echo 'Build successful' | tee -a $LOG_FILE \ No newline at end of file From e0affa5249ace9f8a6169e96034a7ddcb087b3a6 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:00:43 +0530 Subject: [PATCH 02/23] fixed Indentation in jenkinsfile --- Jenkinsfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 95aef02..f1822f4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -145,4 +145,6 @@ pipeline } } } - } \ No newline at end of file + } + } +} \ No newline at end of file From a68a5fc276e6eb00844459ca9819d14f53eff9d7 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:05:19 +0530 Subject: [PATCH 03/23] Update Jenkinsfile --- Jenkinsfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index f1822f4..db5520c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -43,6 +43,9 @@ import groovy.json.JsonSlurperClassic @Field def ShoonyDpcPublisherS3Bucket = 'shoonya-dpc' @Field def JenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' @Field def releaseBranch = 'master' +@Field def g_utils = '' +@Field def g_releaseChannel = '' +@Field def g_buildNumber = '' pipeline { @@ -133,7 +136,7 @@ pipeline timestamps { script { sh "ls -al" - g_buildPathS3 = g_releaseChannel + def g_buildPathS3 = g_releaseChannel sh "ls -al app/" def buildPathS3 = "sampleapp/"+ g_buildPathS3 def jsonData = readJSON file: 'app/build-output-pg-enabled/outputs/apk/release/output-metadata.json' From f29601519f9ed04a19cf23f0e162d93b9b665fb3 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:10:27 +0530 Subject: [PATCH 04/23] Update Jenkinsfile --- Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index db5520c..d3b15cf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -62,7 +62,7 @@ pipeline g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') - echo "Build_Number: ${g_buildNumber}" + echo "Build_Number: ${g_buildNumber}: ${g_utils}" } } } @@ -117,6 +117,7 @@ pipeline g_DpcVersionBuildNumber = "${buildJob.number}" echo "Version_name: ${g_DpcVersionBuildNumber}" // let the builder library build the code and archive it + echo "${g_utils}" g_utils.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) } } From e7269edfb90dbf49469073a05d6b30144b1442c7 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:10:54 +0530 Subject: [PATCH 05/23] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d3b15cf..b8214aa 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -113,8 +113,8 @@ pipeline timestamps { script { // get a Sampleapp version number - def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) - g_DpcVersionBuildNumber = "${buildJob.number}" + //def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) + g_DpcVersionBuildNumber = "2" echo "Version_name: ${g_DpcVersionBuildNumber}" // let the builder library build the code and archive it echo "${g_utils}" From a92a28260f47dcc8728485e54becc0e7d512172e Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:20:43 +0530 Subject: [PATCH 06/23] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index b8214aa..84e1a5f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -58,7 +58,7 @@ pipeline steps { script { sh 'ls -la' - g_utils = load './jenkins/Utils.groovy' + g_utils=load './jenkins/Utils.groovy' g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') From 93e0794d412282f59c1c2a33eaaed01275258d6b Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:22:20 +0530 Subject: [PATCH 07/23] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 84e1a5f..93cd548 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -57,8 +57,8 @@ pipeline stage('Initialize') { steps { script { - sh 'ls -la' - g_utils=load './jenkins/Utils.groovy' + sh 'ls -la jenkins/' + g_utils = load './jenkins/Utils.groovy' g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') From 4d9cfbac6463885a27988e4059e707734ba8e8a4 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 14:33:53 +0530 Subject: [PATCH 08/23] Update Jenkinsfile --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 93cd548..a382176 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -57,6 +57,7 @@ pipeline stage('Initialize') { steps { script { + checkout(scm) sh 'ls -la jenkins/' g_utils = load './jenkins/Utils.groovy' g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' From 38f7b43bc1c3861202964047a91611d35df2d97b Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Thu, 17 Mar 2022 16:04:46 +0530 Subject: [PATCH 09/23] Update Jenkinsfile --- Jenkinsfile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index a382176..dda871c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -43,7 +43,7 @@ import groovy.json.JsonSlurperClassic @Field def ShoonyDpcPublisherS3Bucket = 'shoonya-dpc' @Field def JenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' @Field def releaseBranch = 'master' -@Field def g_utils = '' +@Field def helperMethods = '' @Field def g_releaseChannel = '' @Field def g_buildNumber = '' @@ -59,11 +59,11 @@ pipeline script { checkout(scm) sh 'ls -la jenkins/' - g_utils = load './jenkins/Utils.groovy' + helperMethods = load './jenkins/Utils.groovy' g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') - echo "Build_Number: ${g_buildNumber}: ${g_utils}" + echo "Build_Number: ${g_buildNumber}" } } } @@ -118,8 +118,7 @@ pipeline g_DpcVersionBuildNumber = "2" echo "Version_name: ${g_DpcVersionBuildNumber}" // let the builder library build the code and archive it - echo "${g_utils}" - g_utils.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) + helperMethods.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) } } } From 77a771d5c4be6bad2938b15fdb4112498ac96318 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 10:59:58 +0530 Subject: [PATCH 10/23] Testing script load --- Jenkinsfile | 4 +++- jenkins/sample.groovy | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 jenkins/sample.groovy diff --git a/Jenkinsfile b/Jenkinsfile index dda871c..aa45d70 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,7 +46,7 @@ import groovy.json.JsonSlurperClassic @Field def helperMethods = '' @Field def g_releaseChannel = '' @Field def g_buildNumber = '' - +@Field def sampleutils = '' pipeline { agent { @@ -60,6 +60,7 @@ pipeline checkout(scm) sh 'ls -la jenkins/' helperMethods = load './jenkins/Utils.groovy' + sampleutils = load('./jenkins/sample.groovy') g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') @@ -117,6 +118,7 @@ pipeline //def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) g_DpcVersionBuildNumber = "2" echo "Version_name: ${g_DpcVersionBuildNumber}" + sampleutils.test() // let the builder library build the code and archive it helperMethods.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) } diff --git a/jenkins/sample.groovy b/jenkins/sample.groovy new file mode 100644 index 0000000..3d7133e --- /dev/null +++ b/jenkins/sample.groovy @@ -0,0 +1,4 @@ +def test() { + sh "ls -al" + echo "Hai" +} \ No newline at end of file From 2ff5c266f196be87b660d48105ea0455b472d53e Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 11:02:00 +0530 Subject: [PATCH 11/23] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index aa45d70..da63415 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,7 +46,7 @@ import groovy.json.JsonSlurperClassic @Field def helperMethods = '' @Field def g_releaseChannel = '' @Field def g_buildNumber = '' -@Field def sampleutils = '' + pipeline { agent { @@ -60,7 +60,6 @@ pipeline checkout(scm) sh 'ls -la jenkins/' helperMethods = load './jenkins/Utils.groovy' - sampleutils = load('./jenkins/sample.groovy') g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') @@ -118,6 +117,7 @@ pipeline //def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) g_DpcVersionBuildNumber = "2" echo "Version_name: ${g_DpcVersionBuildNumber}" + sampleutils = load('./jenkins/sample.groovy') sampleutils.test() // let the builder library build the code and archive it helperMethods.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) From 5b5fa3d81fd91380eb9911b02a6222f8bc5dd0c5 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 11:06:46 +0530 Subject: [PATCH 12/23] Update Jenkinsfile --- Jenkinsfile | 144 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 138 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index da63415..0151c01 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -43,10 +43,145 @@ import groovy.json.JsonSlurperClassic @Field def ShoonyDpcPublisherS3Bucket = 'shoonya-dpc' @Field def JenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' @Field def releaseBranch = 'master' -@Field def helperMethods = '' @Field def g_releaseChannel = '' @Field def g_buildNumber = '' +def sendSlackMessage(titleText, messageText, messageColor, channelName) { + JSONArray attachments = new JSONArray() + JSONObject attachment = new JSONObject() + + attachment.put('title', titleText.toString()) + attachment.put('text', messageText.toString()) + attachment.put('color', messageColor) + + attachments.add(attachment) + slackSend(botUser: true, channel: channelName, attachments: attachments.toString()) +} + +def injectCreds() { + // Copy the secret file locally for inclusion into the container. It will be cleaned up automatically + // during the cleanup() stage + withCredentials([file(credentialsId: 'shoonya-dpc-key-jks-file', variable: 'SECRET_FILE')]) + { + sh "cp ${SECRET_FILE} secret.file" + } + + // Copy the keystore.properties file for inclusion into the container. It already points to the secret file as + // "storeFile=/application/secret.file" + withCredentials([file(credentialsId: 'keystore.properties', variable: 'KS_PROPS_FILE')]) + { + sh "cp ${KS_PROPS_FILE} keystore.properties" + } + + withCredentials([[$class: 'UsernamePasswordMultiBinding', + credentialsId: 'jfrog-artifactorycreds', + usernameVariable: 'USERNAME', + passwordVariable: 'PASSWORD']]) + { + g_arifactoryUsername = "${USERNAME}" + g_arifactoryPassword = "${PASSWORD}" + } + + echo 'Secrets in place, listing files.' + sh 'ls -al' +} + +def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { + def latestCommit = "${env.GIT_COMMIT}" + //SDK Publish is separated into different job + def publishEsperDeviceSDK = false + // ecr vars to use for pull docker image + def dockerEcrUrl = '973484954817.dkr.ecr.us-west-2.amazonaws.com' + def dockerEcrParms = 'ecr:us-west-2:c1981b34-fa8a-4d88-b3ce-a7adb5c7f71c' + + // login into ECR and get ready to pull image + docker.withRegistry("https://${dockerEcrUrl}", dockerEcrParms) + { + // pull image (only if it's not already on the box) + def currImage = docker.image('shoonya-android-builder-image:latest') + currImage.pull() + + // get the current user's id -- we will pass this to the container for gosu to kick it in. Note the trim() + def currUserId = sh(returnStdout: true, script: 'id -u $USER').trim() + echo "Current runner's UID = ${currUserId}" + + // make the requested script executable, before mapping it into the container + sh 'chmod a+x jenkins/build_app.sh' + + // set the docker image & tag for use for the pull/run + def dockerImageNameAndTag = "${dockerEcrUrl}/shoonya-android-builder-image:latest" + echo "dockerImageNameAndTag= ${dockerImageNameAndTag}" + + // massage the build numbers + def buildNumberAsInt = dpcBuildNumber as Integer + def fourDigitBuildNumber = String.format('%04d', buildNumberAsInt) + + // first get cached-files from S3, if any, to prevent unecessary dependency downloads during the build + // note that we are making the cli only compare the size and not the timestamp to prevent unnecessary + // downloads from S3. The size is ~275MB. + dir('/buildspace/gradle_dependency_cache') + { + sh 'aws s3 sync s3://shoonya-devops-bucket/GradleDependencyCache/ . --size-only' + } + + // + // + // Start the main build in the downloaded docker image + // -v /buildspace/gradle_dependency_cache:/gradle_dependency_cache \ + // + + sh "docker run --rm -e BUILD_NUMBER=${buildNumberAsInt} \ + -e FOURDIGIT_BUILD_NUMBER=${fourDigitBuildNumber} \ + -e PUBLISH_ESPER_DEVICE_SDK=${publishEsperDeviceSDK} \ + -e ARTIFACTORY_USERNAME=${g_arifactoryUsername} \ + -e ARTIFACTORY_PASSWORD=${g_arifactoryPassword} \ + -e RELEASE_CHANNEL=${releaseChannel} \ + -e LOCAL_USER_ID=${currUserId} \ + -v /buildspace/gradle_dependency_cache:/gradle_dependency_cache \ + -v ${pwd()}/jenkins/build_app.sh:/build_app.sh \ + -v ${pwd()}:/application '${dockerImageNameAndTag}' \ + sh -c /build_app.sh" + } +} + +def archiveFolders(String buildFolderName, String zipFileSuffix) { + def archiveFolderMap = [ + "espersdksample/${buildFolderName}" : ['esper-sdk-sample' : ['outputs', 'reports', 'test-results']] + ] +} + +def performPostBuildActivities() { + // from the logs, make sure + def buildSuccessful = sh(script: "grep -Fxq 'Build successful' build_status.log", returnStatus: true) == 0 + if (!buildSuccessful) { + error('Build failed.') + } + + //echo 'Running junit on tests..' + //junit '**/TEST-*.xml' + + echo 'Running the lint-analysis tool..' + androidLint() + + // archive all interesting folders and attach it to this build + //archiveFolders('build-output', '') +} + +def buildApps(String dpcBuildNumber, String releaseChannel) { + // + // At this point, we are already in the folder where the entire source code for this app is + // + + // first inject the build-related credentials into the file system + injectCreds() + + // run the build(s) in the designated docker image + runBuildInDocker(dpcBuildNumber, releaseChannel) + + // ensure build succeeded, and activities such as lint-checks. + performPostBuildActivities() +} + pipeline { agent { @@ -58,8 +193,7 @@ pipeline steps { script { checkout(scm) - sh 'ls -la jenkins/' - helperMethods = load './jenkins/Utils.groovy' + sh 'ls -la' g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') g_buildNumber = [g_releaseChannel, time_stamp].join('-') @@ -117,10 +251,8 @@ pipeline //def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) g_DpcVersionBuildNumber = "2" echo "Version_name: ${g_DpcVersionBuildNumber}" - sampleutils = load('./jenkins/sample.groovy') - sampleutils.test() // let the builder library build the code and archive it - helperMethods.buildApps(g_DpcVersionBuildNumber,g_releaseChannel) + buildApps(g_DpcVersionBuildNumber,g_releaseChannel) } } } From 74dd1af722a1028ff744bbe9a402a0bddbb99d8d Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 12:28:39 +0530 Subject: [PATCH 13/23] fixed app directory mount --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0151c01..f387c7f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -139,7 +139,7 @@ def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { -e LOCAL_USER_ID=${currUserId} \ -v /buildspace/gradle_dependency_cache:/gradle_dependency_cache \ -v ${pwd()}/jenkins/build_app.sh:/build_app.sh \ - -v ${pwd()}:/application '${dockerImageNameAndTag}' \ + -v ${pwd()}/app:/application '${dockerImageNameAndTag}' \ sh -c /build_app.sh" } } From bdc6f8271cc0a4edd62b40186417f267f528f7b7 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 15:19:05 +0530 Subject: [PATCH 14/23] Update build.gradle --- app/app/build.gradle | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/app/app/build.gradle b/app/app/build.gradle index 1a9bf10..4f54f8b 100644 --- a/app/app/build.gradle +++ b/app/app/build.gradle @@ -3,17 +3,37 @@ plugins { id 'kotlin-android' } +def keystorePropertiesFile = rootProject.file("keystore.properties") +// Initialize a new Properties() object called keystoreProperties. +def keystoreProperties = new Properties() +// Load your keystore.properties file into the keystoreProperties object. +keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + +def vMajor = 1 +def vMinor = 0 +def buildNum = System.getenv("BUILD_NUMBER") ?: 0 +def fourDigitBuildnumber = System.getenv("FOURDIGIT_BUILD_NUMBER") ?: 0 +def shVersionCode = (vMajor * 10000000) + (vMinor * 10000) + (buildNum as Integer) + android { compileSdkVersion 30 - buildToolsVersion "30.0.3" + buildToolsVersion "29.0.3" + + signingConfigs { + config { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile file(keystoreProperties['storeFile']) + storePassword keystoreProperties['storePassword'] + } + } defaultConfig { applicationId "io.esper.sdksample" minSdkVersion 19 targetSdkVersion 30 - versionCode 1 - versionName "1.0" - + versionCode shVersionCode as Integer + versionName "v${vMajor}.${vMinor}.${fourDigitBuildnumber}" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -21,6 +41,7 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.config } } From 8c64413234580b7ffbe43f10350301d9bbf7e9c8 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 15:41:09 +0530 Subject: [PATCH 15/23] Added archive app folders --- Jenkinsfile | 33 +++++++++++++++++++++++---------- jenkins/build_app.sh | 3 +-- 2 files changed, 24 insertions(+), 12 deletions(-) mode change 100644 => 100755 jenkins/build_app.sh diff --git a/Jenkinsfile b/Jenkinsfile index f387c7f..5523c9b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -63,14 +63,14 @@ def injectCreds() { // during the cleanup() stage withCredentials([file(credentialsId: 'shoonya-dpc-key-jks-file', variable: 'SECRET_FILE')]) { - sh "cp ${SECRET_FILE} secret.file" + sh "cp ${SECRET_FILE} app/secret.file" } // Copy the keystore.properties file for inclusion into the container. It already points to the secret file as // "storeFile=/application/secret.file" withCredentials([file(credentialsId: 'keystore.properties', variable: 'KS_PROPS_FILE')]) { - sh "cp ${KS_PROPS_FILE} keystore.properties" + sh "cp ${KS_PROPS_FILE} app/keystore.properties" } withCredentials([[$class: 'UsernamePasswordMultiBinding', @@ -83,7 +83,7 @@ def injectCreds() { } echo 'Secrets in place, listing files.' - sh 'ls -al' + sh 'ls -al app/' } def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { @@ -145,9 +145,21 @@ def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { } def archiveFolders(String buildFolderName, String zipFileSuffix) { - def archiveFolderMap = [ - "espersdksample/${buildFolderName}" : ['esper-sdk-sample' : ['outputs', 'reports', 'test-results']] - ] + def archiveFoldersList = ['outputs', 'reports', 'test-results'] + def prefix = 'esper-sdk-sample' + + // archive the build-status file--this is at the root of the downloaded code + archiveArtifacts artifacts: 'build_status.log', fingerprint: true, allowEmptyArchive: true + + dir("app/${buildFolderName}") { + archiveFoldersList.each { archiveFolder -> + if (fileExists(archive_folder)) { + def zipFilename = "${prefix}-build-${archive_folder}${zipFileSuffix}.zip" + zip zipFile: zipFilename, dir: archive_folder + archiveArtifacts artifacts: zipFilename, fingerprint: true, allowEmptyArchive: true + } + } + } } def performPostBuildActivities() { @@ -164,7 +176,7 @@ def performPostBuildActivities() { androidLint() // archive all interesting folders and attach it to this build - //archiveFolders('build-output', '') + archiveFolders('build', '') } def buildApps(String dpcBuildNumber, String releaseChannel) { @@ -274,11 +286,12 @@ pipeline def g_buildPathS3 = g_releaseChannel sh "ls -al app/" def buildPathS3 = "sampleapp/"+ g_buildPathS3 - def jsonData = readJSON file: 'app/build-output-pg-enabled/outputs/apk/release/output-metadata.json' - g_dpcApkFile = "${pwd()}/app/build-output-pg-enabled/outputs/apk/release/app-release.apk" + sh "ls -al app/app/build/outputs/apk/release/" + def jsonData = readJSON file: 'app/app/build/outputs/apk/release/output-metadata.json' + g_dpcApkFile = "${pwd()}/app/app/build/outputs/apk/release/app-release.apk" g_dpcVersionCode = jsonData.elements[0].versionCode g_dpcVersionName = jsonData.elements[0].versionName - g_DpcApkFilename = "shoonya_dpc_v${g_dpcVersionCode}_${g_dpcVersionName}.apk" + g_DpcApkFilename = "espersdk_sample_v${g_dpcVersionCode}_${g_dpcVersionName}.apk" echo "DPC for has versionCode = ${g_dpcVersionCode} and versionName = ${g_dpcVersionName}" } } diff --git a/jenkins/build_app.sh b/jenkins/build_app.sh old mode 100644 new mode 100755 index be23b3d..eafba7f --- a/jenkins/build_app.sh +++ b/jenkins/build_app.sh @@ -17,6 +17,7 @@ popd mv ~/.gradle/temp/home/nala/.gradle/caches ~/.gradle/caches rm -rf ~/.gradle/temp + echo "Switching to the app directory" | tee -a $LOG_FILE cd $APP_DIR if [ $? -ne 0 ];then @@ -41,8 +42,6 @@ if [ $? -ne 0 ];then exit fi -export OBFUSCATION=true -export BUILD_OUTPUT_DIR=build-output echo "Cleaning project" | tee -a $LOG_FILE ./gradlew clean From cdf4b976ea16c0208a24086108cf5853edb69d73 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 15:52:59 +0530 Subject: [PATCH 16/23] androidsdk permissionissue fix --- jenkins/build_app.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jenkins/build_app.sh b/jenkins/build_app.sh index eafba7f..f164ae7 100755 --- a/jenkins/build_app.sh +++ b/jenkins/build_app.sh @@ -16,7 +16,10 @@ tar -xzf /gradle_dependency_cache/dependency_cache.tar.gz popd mv ~/.gradle/temp/home/nala/.gradle/caches ~/.gradle/caches rm -rf ~/.gradle/temp - +### Remove after fixing install permission +cp -R /usr/lib/android-sdk /application/androidsdk +export ANDROID_SDK_DIR="/application/androidsdk" +### echo "Switching to the app directory" | tee -a $LOG_FILE cd $APP_DIR From 749be1b94c7d0192564ea41ffe4bac24bea17f12 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 16:09:33 +0530 Subject: [PATCH 17/23] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5523c9b..a49fa45 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -164,7 +164,7 @@ def archiveFolders(String buildFolderName, String zipFileSuffix) { def performPostBuildActivities() { // from the logs, make sure - def buildSuccessful = sh(script: "grep -Fxq 'Build successful' build_status.log", returnStatus: true) == 0 + def buildSuccessful = sh(script: "grep -Fxq 'Build successful' app/build_status.log", returnStatus: true) == 0 if (!buildSuccessful) { error('Build failed.') } From 9c506d8e4f0c27dcc4610bb3ca73030e78ee5531 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 16:30:15 +0530 Subject: [PATCH 18/23] Update Jenkinsfile --- Jenkinsfile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index a49fa45..ceeed1e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -14,7 +14,7 @@ import net.sf.json.JSONArray import net.sf.json.JSONObject import groovy.json.JsonSlurperClassic -@Field def g_BranchToReleaseTypeMap = [ +@Field def branchToReleaseTypeMap = [ 'develop' : 'alpha', 'staging' : 'beta', 'master' : 'prod', @@ -43,7 +43,7 @@ import groovy.json.JsonSlurperClassic @Field def ShoonyDpcPublisherS3Bucket = 'shoonya-dpc' @Field def JenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' @Field def releaseBranch = 'master' -@Field def g_releaseChannel = '' +@Field def releaseChannel = '' @Field def g_buildNumber = '' def sendSlackMessage(titleText, messageText, messageColor, channelName) { @@ -149,12 +149,12 @@ def archiveFolders(String buildFolderName, String zipFileSuffix) { def prefix = 'esper-sdk-sample' // archive the build-status file--this is at the root of the downloaded code - archiveArtifacts artifacts: 'build_status.log', fingerprint: true, allowEmptyArchive: true + archiveArtifacts artifacts: 'app/build_status.log', fingerprint: true, allowEmptyArchive: true - dir("app/${buildFolderName}") { + dir("app/app/${buildFolderName}") { archiveFoldersList.each { archiveFolder -> - if (fileExists(archive_folder)) { - def zipFilename = "${prefix}-build-${archive_folder}${zipFileSuffix}.zip" + if (fileExists(archiveFolder)) { + def zipFilename = "${prefix}-build-${archiveFolder}${zipFileSuffix}.zip" zip zipFile: zipFilename, dir: archive_folder archiveArtifacts artifacts: zipFilename, fingerprint: true, allowEmptyArchive: true } @@ -206,9 +206,9 @@ pipeline script { checkout(scm) sh 'ls -la' - g_releaseChannel = g_BranchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' + releaseChannel = branchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') - g_buildNumber = [g_releaseChannel, time_stamp].join('-') + g_buildNumber = [releaseChannel, time_stamp].join('-') echo "Build_Number: ${g_buildNumber}" } } @@ -264,7 +264,7 @@ pipeline g_DpcVersionBuildNumber = "2" echo "Version_name: ${g_DpcVersionBuildNumber}" // let the builder library build the code and archive it - buildApps(g_DpcVersionBuildNumber,g_releaseChannel) + buildApps(g_DpcVersionBuildNumber,releaseChannel) } } } @@ -276,14 +276,14 @@ pipeline expression { env.BRANCH_NAME ==~ /(develop|RelCandidate|staging|SHN-15702-ci)/ } - branch g_releaseBranch + branch releaseBranch } } steps { timestamps { script { sh "ls -al" - def g_buildPathS3 = g_releaseChannel + def g_buildPathS3 = releaseChannel sh "ls -al app/" def buildPathS3 = "sampleapp/"+ g_buildPathS3 sh "ls -al app/app/build/outputs/apk/release/" From 759c799fe008f1561af2a7031242b2c503cfa3e9 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 16:33:51 +0530 Subject: [PATCH 19/23] Update Jenkinsfile --- Jenkinsfile | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ceeed1e..653f2cf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -61,17 +61,7 @@ def sendSlackMessage(titleText, messageText, messageColor, channelName) { def injectCreds() { // Copy the secret file locally for inclusion into the container. It will be cleaned up automatically // during the cleanup() stage - withCredentials([file(credentialsId: 'shoonya-dpc-key-jks-file', variable: 'SECRET_FILE')]) - { - sh "cp ${SECRET_FILE} app/secret.file" - } - // Copy the keystore.properties file for inclusion into the container. It already points to the secret file as - // "storeFile=/application/secret.file" - withCredentials([file(credentialsId: 'keystore.properties', variable: 'KS_PROPS_FILE')]) - { - sh "cp ${KS_PROPS_FILE} app/keystore.properties" - } withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'jfrog-artifactorycreds', @@ -155,7 +145,7 @@ def archiveFolders(String buildFolderName, String zipFileSuffix) { archiveFoldersList.each { archiveFolder -> if (fileExists(archiveFolder)) { def zipFilename = "${prefix}-build-${archiveFolder}${zipFileSuffix}.zip" - zip zipFile: zipFilename, dir: archive_folder + zip zipFile: zipFilename, dir: archiveFolder archiveArtifacts artifacts: zipFilename, fingerprint: true, allowEmptyArchive: true } } From 58ad9d69eb0fdc1d8151a597d3f73ec5e6d261fb Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 16:51:25 +0530 Subject: [PATCH 20/23] Added s3 upload and cleanup --- Jenkinsfile | 113 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 653f2cf..ea6dd60 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -21,14 +21,14 @@ import groovy.json.JsonSlurperClassic 'RelCandidate' : 'Experimental', 'SHN-15702-ci': 'alpha' ] -@Field def g_BranchToStacksTypeMap = [ +@Field def branchToStacksTypeMap = [ 'develop': 'development', 'staging': 'staging', 'master': 'production', 'RelCandidate': 'rel_candidate', 'SHN-15702-ci': 'development' ] -@Field def g_branchToFileName = [ +@Field def branchToFileName = [ 'develop': 'develop', 'RelCandidate' : 'Experimental', 'staging' : 'staging', @@ -36,15 +36,15 @@ import groovy.json.JsonSlurperClassic 'SHN-15702-ci': 'development' ] -@Field def slackMessageTitle = 'DPC Build Notification' -@Field def slackMessageChannel = '#device-deployments' -@Field def ShoonyDpcPublisherCredId = 'shoonya_jenkins_cloud_ui_build_user' -@Field def ShoonyDpcPublisherAwsRegion = 'ap-south-1' -@Field def ShoonyDpcPublisherS3Bucket = 'shoonya-dpc' -@Field def JenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' +@Field def slackMessageTitle = 'EsperSDK Sample Build Notification' +@Field def slackMessageChannel = '#kservcicdjobtest' +@Field def shoonyDpcPublisherCredId = 'shoonya_jenkins_cloud_ui_build_user' +@Field def shoonyDpcPublisherAwsRegion = 'ap-south-1' +@Field def shoonyDpcPublisherS3Bucket = 'shoonya-dpc' +@Field def jenkinsCloudApiAccessCreds = 'jenkins_cloud_api_access_creds' @Field def releaseBranch = 'master' @Field def releaseChannel = '' -@Field def g_buildNumber = '' +@Field def buildNumber = '' def sendSlackMessage(titleText, messageText, messageColor, channelName) { JSONArray attachments = new JSONArray() @@ -61,19 +61,28 @@ def sendSlackMessage(titleText, messageText, messageColor, channelName) { def injectCreds() { // Copy the secret file locally for inclusion into the container. It will be cleaned up automatically // during the cleanup() stage + withCredentials([file(credentialsId: 'shoonya-dpc-key-jks-file', variable: 'SECRET_FILE')]) + { + sh "cp ${SECRET_FILE} app/secret.file" + } + // Copy the keystore.properties file for inclusion into the container. It already points to the secret file as + // "storeFile=/application/secret.file" + withCredentials([file(credentialsId: 'keystore.properties', variable: 'KS_PROPS_FILE')]) + { + sh "cp ${KS_PROPS_FILE} app/keystore.properties" + } withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'jfrog-artifactorycreds', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { - g_arifactoryUsername = "${USERNAME}" - g_arifactoryPassword = "${PASSWORD}" + arifactoryUsername = "${USERNAME}" + arifactoryPassword = "${PASSWORD}" } echo 'Secrets in place, listing files.' - sh 'ls -al app/' } def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { @@ -123,8 +132,8 @@ def runBuildInDocker(String dpcBuildNumber, String releaseChannel) { sh "docker run --rm -e BUILD_NUMBER=${buildNumberAsInt} \ -e FOURDIGIT_BUILD_NUMBER=${fourDigitBuildNumber} \ -e PUBLISH_ESPER_DEVICE_SDK=${publishEsperDeviceSDK} \ - -e ARTIFACTORY_USERNAME=${g_arifactoryUsername} \ - -e ARTIFACTORY_PASSWORD=${g_arifactoryPassword} \ + -e ARTIFACTORY_USERNAME=${arifactoryUsername} \ + -e ARTIFACTORY_PASSWORD=${arifactoryPassword} \ -e RELEASE_CHANNEL=${releaseChannel} \ -e LOCAL_USER_ID=${currUserId} \ -v /buildspace/gradle_dependency_cache:/gradle_dependency_cache \ @@ -184,6 +193,28 @@ def buildApps(String dpcBuildNumber, String releaseChannel) { performPostBuildActivities() } +def uploadtoS3(apkFile, apkFileName, bucket, s3Path, dpcVersionCode) { + withAWS(credentials:"${shoonyDpcPublisherCredId}", region:"${shoonyDpcPublisherAwsRegion}") + { + s3Upload( + acl:'PublicRead', + bucket:"${bucket}", + cacheControl:'cacheControl:\'public,max-age=86400\'', + file:"${apkFile}", + path:"${s3Path}/${apkFileName}", + pathStyleAccessEnabled: true + ) + def postUploadMessage = "APK upload complete \n ► APKName:`${apkFileName}` \n ► S3Path: ${s3Path} \n ► Version: ${dpcVersionCode}" + sendSlackMessage( + slackMessageTitle, + postUploadMessage, + 'good', + slackMessageChannel + ) + } + return 'success' +} + pipeline { agent { @@ -195,11 +226,10 @@ pipeline steps { script { checkout(scm) - sh 'ls -la' releaseChannel = branchToReleaseTypeMap[env.BRANCH_NAME] ?: 'alpha' time_stamp = new Date().format('yyyyMMddHHmm') - g_buildNumber = [releaseChannel, time_stamp].join('-') - echo "Build_Number: ${g_buildNumber}" + buildNumber = [releaseChannel, time_stamp].join('-') + echo "Build_Number: ${buildNumber}" } } } @@ -251,10 +281,10 @@ pipeline script { // get a Sampleapp version number //def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) - g_DpcVersionBuildNumber = "2" - echo "Version_name: ${g_DpcVersionBuildNumber}" + dpcVersionBuildNumber = "2" + echo "Version_name: ${dpcVersionBuildNumber}" // let the builder library build the code and archive it - buildApps(g_DpcVersionBuildNumber,releaseChannel) + buildApps(dpcVersionBuildNumber,releaseChannel) } } } @@ -272,20 +302,39 @@ pipeline steps { timestamps { script { - sh "ls -al" - def g_buildPathS3 = releaseChannel - sh "ls -al app/" - def buildPathS3 = "sampleapp/"+ g_buildPathS3 - sh "ls -al app/app/build/outputs/apk/release/" + def buildPathS3 = "sampleapp/"+ releaseChannel def jsonData = readJSON file: 'app/app/build/outputs/apk/release/output-metadata.json' - g_dpcApkFile = "${pwd()}/app/app/build/outputs/apk/release/app-release.apk" - g_dpcVersionCode = jsonData.elements[0].versionCode - g_dpcVersionName = jsonData.elements[0].versionName - g_DpcApkFilename = "espersdk_sample_v${g_dpcVersionCode}_${g_dpcVersionName}.apk" - echo "DPC for has versionCode = ${g_dpcVersionCode} and versionName = ${g_dpcVersionName}" + dpcApkFile = "${pwd()}/app/app/build/outputs/apk/release/app-release.apk" + dpcVersionCode = jsonData.elements[0].versionCode + dpcVersionName = jsonData.elements[0].versionName + dpcApkFilename = "espersdk_sample_v${dpcVersionCode}_${dpcVersionName}.apk" + echo "DPC for has versionCode = ${dpcVersionCode} and versionName = ${dpcVersionName}" + uploadtoS3(dpcApkFile, dpcApkFilename, shoonyDpcPublisherS3Bucket, buildPathS3, dpcVersionCode) } } } + } //Stage Upload + } //Stages + + post { + failure { + script { + if (env.CHANGE_ID == null) { + def messageText = "Failed Job Details: \n ► Branch: `${env.BRANCH_NAME}`\n ► Job: `${env.JOB_NAME}`\n ► buildUrl: ${env.BUILD_URL}\n ► Commit: `${env.GIT_COMMIT}` \n " + def messageColor = 'danger' + sendSlackMessage( + slackMessageTitle, + messageText, + messageColor, + slackMessageChannel + ) + } + } } - } -} \ No newline at end of file + cleanup { + echo 'Cleaning workspace..' + cleanWs() + echo "Done. Exiting script" + } + } //post +} //pipeline \ No newline at end of file From ebc3bc4e160f4ddee47cf7db94864b052d70da0b Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 16:58:17 +0530 Subject: [PATCH 21/23] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ea6dd60..460ccea 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -280,8 +280,8 @@ pipeline timestamps { script { // get a Sampleapp version number - //def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) - dpcVersionBuildNumber = "2" + def buildJob = build (job: 'DeviceBuilds/sampleapp-versions', propagate: true) + dpcVersionBuildNumber = "${buildJob.number}" echo "Version_name: ${dpcVersionBuildNumber}" // let the builder library build the code and archive it buildApps(dpcVersionBuildNumber,releaseChannel) From 8e7b32078b6f19806a5aaf1df652ea929be8a587 Mon Sep 17 00:00:00 2001 From: Manoj Murari Date: Fri, 18 Mar 2022 17:05:40 +0530 Subject: [PATCH 22/23] Uploading latest apk file --- Jenkinsfile | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 460ccea..1973ad2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,21 +19,15 @@ import groovy.json.JsonSlurperClassic 'staging' : 'beta', 'master' : 'prod', 'RelCandidate' : 'Experimental', - 'SHN-15702-ci': 'alpha' -] -@Field def branchToStacksTypeMap = [ - 'develop': 'development', - 'staging': 'staging', - 'master': 'production', - 'RelCandidate': 'rel_candidate', - 'SHN-15702-ci': 'development' + 'SHN-15702-ci': 'test' ] + @Field def branchToFileName = [ 'develop': 'develop', 'RelCandidate' : 'Experimental', 'staging' : 'staging', 'master' : 'master', - 'SHN-15702-ci': 'development' + 'SHN-15702-ci': 'test' ] @Field def slackMessageTitle = 'EsperSDK Sample Build Notification' @@ -310,6 +304,9 @@ pipeline dpcApkFilename = "espersdk_sample_v${dpcVersionCode}_${dpcVersionName}.apk" echo "DPC for has versionCode = ${dpcVersionCode} and versionName = ${dpcVersionName}" uploadtoS3(dpcApkFile, dpcApkFilename, shoonyDpcPublisherS3Bucket, buildPathS3, dpcVersionCode) + def fileNameSuffix = branchToFileName[env.BRANCH_NAME] ?: 'test' + finalDpcApkFilename = "espersdk_sample_latest_${fileNameSuffix}.apk" + uploadtoS3(dpcApkFile, finalDpcApkFilename, shoonyDpcPublisherS3Bucket, buildPathS3, dpcVersionCode) } } } From 9d5c222d6d549f650582fd8417ce76e5ee00f1ba Mon Sep 17 00:00:00 2001 From: surendar-rajasekaran <86347927+surendar-rajasekaran@users.noreply.github.com> Date: Tue, 22 Mar 2022 14:29:52 +0530 Subject: [PATCH 23/23] added function return Function return were missing --- jenkins/Utils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins/Utils.groovy b/jenkins/Utils.groovy index d6db214..1f2b3bb 100644 --- a/jenkins/Utils.groovy +++ b/jenkins/Utils.groovy @@ -147,4 +147,4 @@ def buildApps(String dpcBuildNumber, String releaseChannel) { // ensure build succeeded, and activities such as lint-checks. performPostBuildActivities() } - +return this