// Enables SDK auto-install, and uses it to run the given block def withAndroidSdk(String sdkDir = '/tmp/android-sdk', Closure body) { // Create the SDK directory, and accept the licences // (see: d.android.com/r/studio-ui/export-licenses.html) writeFile file: "${sdkDir}/licenses/android-sdk-license", text: '8933bad161af4178b1185d1a37fbf41ea5269c55\nd56f5187479451eabf01fb78af6dfcb131a6481e\n24333f8a63b6825ea9c5514f83c2829b004d1fee' writeFile file: "${sdkDir}/licenses/android-sdk-preview-license", text: '\n504667f4c0de7af1a06de9f4b1727b84351f2910\n84831b9409646a918e30573bab4c9c91346d8abd' // Run the given closure with this SDK directory withEnv(["ANDROID_HOME=${sdkDir}"]) { body() } } def getVersion() { def files = findFiles(glob: 'app/**/buildConfig/release/**/BuildConfig.java') if (files.length == 0) return null; def content = readFile(file: files[0].path) return (content =~ /VERSION_NAME\s?=\s?"([^"]+)"/)[0][1] } def renameApk(String newName) { def files = findFiles(glob: 'app/build/outputs/**/*.apk') if (files.length == 0) return null; def parentPath = new File(files[0].path).getParent() sh 'mv "' + files[0].path + '" "' + parentPath + '/' + newName + '.apk"'; } def renameBundle(String newName) { def files = findFiles(glob: 'app/build/outputs/**/*.aab') if (files.length == 0) return null; def parentPath = new File(files[0].path).getParent() sh 'mv "' + files[0].path + '" "' + parentPath + '/' + newName + '.aab"'; } def uploadDropBox(String glob, String destination) { def files = findFiles(glob: glob) files.each { sh '/var/jenkins_home/dropbox_uploader.sh -f /var/jenkins_home/.dropbox_uploader upload "' + it.path + '" "' + destination + '"' } } def notifyBuild(String buildStatus = 'STARTED') { // build status of null means successful buildStatus = buildStatus ?: 'SUCCESSFUL' // Default values def colorName = 'RED' def colorCode = '#FF0000' def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'" def summary = "${subject} (${env.BUILD_URL})" def details = """

STARTED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':

Check console output at "${env.JOB_NAME} [${env.BUILD_NUMBER}]"

""" // Override default values based on build status if (buildStatus == 'STARTED') { color = 'YELLOW' colorCode = '#FFFF00' } else if (buildStatus == 'SUCCESSFUL') { color = 'GREEN' colorCode = '#00FF00' } else { color = 'RED' colorCode = '#FF0000' } // Send notifications //slackSend (color: colorCode, message: summary) //hipchatSend (color: color, notify: true, message: summary) emailext ( subject: subject, body: details, recipientProviders: [[$class: 'DevelopersRecipientProvider']] ) } node { try { stage('Checkout') { // Check out the source code checkout([ $class: 'GitSCM', branches: [[name: 'dev']], browser: [ $class: 'GithubWeb', repoUrl: 'https://github.com/arcao/Geocaching4Locus' ], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[ credentialsId: 'GITHUB', url: 'https://github.com/arcao/Geocaching4Locus.git' ]] ]) } stage('Build') { // Build the app using the 'debug' build type, // and allow SDK components to auto-install withAndroidSdk { sh './gradlew clean assembleRelease bundleRelease' } } stage('Rename APK & Bundle') { def buildDate = new java.text.SimpleDateFormat('yyyy-MM-dd').format(new Date()) renameApk 'Geocaching4Locus-' + getVersion() + '_' + buildDate renameBundle 'Geocaching4Locus-' + getVersion() + '_' + buildDate } stage('Upload APK & Bundle') { uploadDropBox 'app/build/outputs/**/*.apk', '_projects/g4l/apk/night-builds/' uploadDropBox 'app/build/outputs/**/*.aab', '_projects/g4l/apk/night-builds/' } stage('Archive APK & Bundle') { // Store the APK that was built archive 'app/build/outputs/**/*.apk' archive 'app/build/outputs/**/*.aab' } } catch (e) { // If there was an exception thrown, the build failed currentBuild.result = "FAILED" throw e } finally { // Success or failure, always send notifications notifyBuild(currentBuild.result) } }