Newer
Older
DummyAnd / Jenkinsfile
@Benoit Donneaux Benoit Donneaux on 18 Mar 2018 7 KB Fix wrong dryrun condition
#!groovy

/*
 * This work is protected under copyright law in the Kingdom of
 * The Netherlands. The rules of the Berne Convention for the
 * Protection of Literary and Artistic Works apply.
 * Digital Me B.V. is the copyright owner.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Load Jenkins shared libraries common to all projects
def libCmn = [
    remote:           'https://code.in.digital-me.nl/git/DEVops/JenkinsLibLazy.git',
    branch:           env.BRANCH_NAME,
    credentialsId:    null,
]

library(
    identifier: "libCmn@${libCmn.branch}",
    retriever: modernSCM([
        $class: 'GitSCMSource',
        remote: libCmn.remote,
        credentialsId: libCmn.credentialsId
    ])
)

// Initialize lazyConfig for this pipeline
lazyConfig(
    name: 'DummyAnd',
)

// Define a method to run Fastlane from the later lazyStages 
def fastlane(platform, lane) {
    // Lookup the relevant credentials first
    if (platform == 'android') {
        usernamePasswordMap = [
            credentialsId: 'dappre-google',
            passwordVariable: 'ANDROID_KEYPASSWORD',
            usernameVariable: 'ANDROID_KEYALIAS'
        ]
    } else {
        error "Unknown platform '${plateform}'"
    }

    // With the credentials, prepare the relevant environment
    withCredentials([usernamePassword(usernamePasswordMap)]){
    	if (platform == 'android' ) {
            envMap = [
                'SKIP_SLOW_FASTLANE_WARNING=YES',
                'FASTLANE_SKIP_UPDATE_CHECK=YES',
                'FASTLANE_OPT_OUT_USAGE=YES',
                "ANDROID_STOREFILE=/opt/certificates/${ANDROID_KEYALIAS}.jks",
                "ANDROID_STOREPASSWORD=${ANDROID_KEYPASSWORD}",
                'JAVA_HOME=/usr/java/latest',
                'SLAVE_AAPT_TIMEOUT=15',
            ]
    	} else {
	        error "Unknown platform '${plateform}'"
    	}

        // Now only calling Fastlane
        withEnv(envMap) {
            sh "bundle install"
            sh "bundle exec fastlane ${platform} ${lane}"
        }
    }
}

def getVersion(part, returnGroup = false) {
    def gradleFile = readFile(encoding: 'UTF-8', file: 'app/build.gradle')
    def m = gradleFile =~ /([^\n]*(?:${part})(?:[^:]*:?\s+|\s*=\s*)"?)([.0-9]+)("?\s*(?:(?:\/\/|#)[^\n]*)?[\n])/
    if (m) returnGroup ? m[0] : m[0][2]
    else return null
}

def withGitPassword(id, body = { sh 'git version' }) {
    withCredentials([usernamePassword([credentialsId: id, passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USER'])]) {
        // TODO: Move git_askpass.sh as a library resource 
        withEnv(["GIT_ASKPASS=/opt/jenkins-scripts/git_askpass.sh"]) {
            sh("git fetch --all --quiet")
            body()
        }
    }
}

def gitLog(bottom = null, top = 'HEAD') {
    def from = bottom ?: 'tags/' + sh(script: "git tag -l | tail -1", returnStdout: true).trim()
    sh(script: "git --no-pager log ${from}...${top} --pretty=format:'- %s' --reverse", returnStdout: true)
}


def prepareChangelogs(versionCode) {
    lDir = 'fastlane/metadata/android'
    // TODO: Test if latest changelogs have changed since last tag and use gitLog if not
    sh("""
for LOCALE in \$(ls -1d ${lDir}/??-??); do 
    cp -vf \${LOCALE}/changelogs/latest.txt \${LOCALE}/changelogs/${versionCode}.txt
done
""")
}

def gitUpdateChangelogs(versionCode, remote = 'origin', branch = 'master') {
    def dryRun = ( env.DRYRUN == 'true' ) ? '--dry-run' : ''
    def lDir = 'fastlane/metadata/android'
    sh("""
git status --porcelain ${lDir} | grep -q 'changelogs/${versionCode}\\.txt\$' \
|| { echo 'Nothing to update'; exit 0; }
git stash save --quiet --include-untracked changelogs
git checkout --quiet ${branch}
git stash pop
git add ${lDir}/*/changelogs/${versionCode}.txt
git commit --quiet -s -m 'Provide changelogs for this version' ${lDir}
git push ${dryRun} ${remote} ${branch}
""")
}

def gitTag(version, remote = 'origin' ) {
    def dryRun = ( env.DRYRUN == 'true' ) ? '--dry-run' : ''
    sh("""
git tag -a '${version}' -m 'Create new tag for version ${version}'
git push ${dryRun} ${remote} ${version}
""")
}

def gitUpdateVersion(versionName, versionCode, remote = 'origin', branch = 'master') {
    def dryRun = ( env.DRYRUN == 'true' ) ? '--dry-run' : ''
    def gradleFilePath = 'app/build.gradle'
    def gradleFile = readFile(encoding: 'UTF-8', file: gradleFilePath)
    gName = getVersion('versionName', true)
    gCode = getVersion('versionCode', true)
    gradleFile = gradleFile.replace(gName[0], gName[1] + versionName + gName[3])
    gradleFile = gradleFile.replace(gCode[0], gCode[1] + versionCode + gCode[3])
    writeFile(encoding: 'UTF-8', file: gradleFilePath, text: gradleFile)
    sh("""
git status --porcelain ${gradleFilePath} | grep -q '${gradleFilePath}\$' \
|| { echo 'Nothing to update'; exit 0; }
git stash save --quiet versions
git checkout --quiet ${branch}
git stash pop
git commit --quiet -s -m 'Update version from ${gName[2]}-${gCode[2]} to ${versionName}-${versionCode}' app/build.gradle
git push ${dryRun} ${remote} ${branch}
""")
}

// Define lazyStages
lazyStage {
    name = 'validate'
    tasks = [
        run: {
            fastlane('android', 'test')
        },
        on: 'android',
    ]
}

lazyStage {
    name = 'package'
    tasks = [
        run: {
            fastlane('android', 'build')
        },
        post: {
            archiveArtifacts(artifacts: 'app/build/outputs/apk/**', allowEmptyArchive: false)
        },
        on: 'android',
    ]
}

if (env.BRANCH_NAME == 'master') {
	lazyStage {
	    name = 'release'
	    tasks = [
	        pre: {
	    	    unarchive(mapping:['app/build/outputs/apk/' : '.'])
	    	    sh("ls -lA app/build/outputs/apk")
	    	},
	        run: { env ->
	            def currentVersion = [ name: getVersion('versionName') as String, code: getVersion('versionCode') as Integer ]
	            def nextVersion =  [ name: currentVersion.name, code: currentVersion.code + 1]
	            echo("currentVersion = ${currentVersion.toString()} / nextVersion = ${nextVersion.toString()}")
	            withGitPassword('bot-ci-dgm', {
	                echo("Git logs since last tag:\n" + gitLog())
	                prepareChangelogs(currentVersion.code)
	                if ( env.DRYRUN != 'true' ) fastlane('android', 'alpha')
	                gitUpdateChangelogs(currentVersion.code)
	                gitTag("${currentVersion.name}-${currentVersion.code}")
	                gitUpdateVersion(nextVersion.name, nextVersion.code)
	            })
	        },
	        on: 'android',
	    ]
	}
	
	lazyStage {
	    name = 'acceptance'
	    tasks = [
	        run: { env ->
	            input('Promote alpha to beta ?')
	            if ( env.DRYRUN != 'true' ) fastlane('android', 'beta')
	        }
	    ]
	}
	
	lazyStage {
	    name = 'production'
	    tasks = [
	        run: { env ->
	            input('Promote beta to production ?')
	            if ( env.DRYRUN != 'true' ) fastlane('android', 'production')
	        }
	    ]
	}
}