/**
 * Pipeline to build nerve-omb Debian package.
 * 
 * https://industrial.jenkins.tttech.com/view/NERVE/
 *
 * See also: 
 *  https://confluence.tttech.com/display/JENKINS/Pipeline+guides+and+examples
 *  https://confluence.tttech.com/display/INFRA/How+to+Configure+a+Jenkins+Pipeline+job+for+doc-builder+Docker
 */
pipeline {
    agent {label 'nerve && dpkg' }
    environment {
        /* Reusable variable used throughout this file: */
        PACKAGE = "nerve-wisesdk"
    }
    options {
        // keep last 10 builds
        buildDiscarder(logRotator(numToKeepStr:'10'))

        // we checkout in our own step, because we need tags and specific branches
        skipDefaultCheckout()
        timestamps()
    }
    parameters {
        string(
            name: 'VERSION',
            defaultValue: '',
            description: 'Old version to rebuild (must equal a tag present in GIT). Only used when branch is "master" to rebuild an older version. Leave blank to build the latest version.'
        )
        string(
            name: 'DIST',
            defaultValue: 'buster',
            description: 'Release to build for (buster = development)'
        )
        choice(
            name: 'ARCH',
            choices: 'amd64\ni386',
            description: 'Architecture to build on (for now should always be "amd64")'
        )
        booleanParam (
            name : 'UPLOAD',
            defaultValue: false,
            description: 'Upload package to APT repository (always True for integration branch).'
       )
    }
    stages {
        /**
         * Checkout the source code.
         *
         * The code is already checked out by Jenkins, but in a "detached HEAD" state, which will not work
         * with gbp-buildpackage.
         */
        stage ('Git checkout') {
            steps {
                /* see https://jenkins.io/doc/pipeline/steps/git/ */
                script {
                    checkout poll: false,
                    scm: [
                        $class: 'GitSCM',
                        branches: [[name: env.BRANCH_NAME]],
                        extensions: scm.extensions + [
                            [$class: 'LocalBranch'], [$class: 'WipeWorkspace'],

                            // This line makes git also fetch tags
                            [$class: 'CloneOption', noTags: false, shallow: false, depth: 0, reference: '']
                        ],
                        userRemoteConfigs: [[
                            url:  "https://git.tttech.com/scm/nerve/${PACKAGE}.git",
                            branch: env.BRANCH_NAME,
                            credentialsId: '505a28bb-7065-4c02-8a4f-0477dc5275fb',
                        ]]
                    ]
                }
            }
        }
        stage ('check dependencies') {
            steps {
                /* make sure that dependencies are installed. */
                sh "which dpkg-parsechangelog"
                sh "which gbp"

                /* Check if we have a pbuilder chroot to build the package. */
                sh "test -d /var/cache/pbuilder/base-${params.DIST}-${params.ARCH}.cow/"
            }
        }
        stage ('prepare environment') {
            steps {

                script {
                    VERSION = sh(
                        returnStdout: true,
                        script: """
                            if [ "$BRANCH_NAME" != "master" ]; then
                                echo -n `dpkg-parsechangelog -n 1 -S Version`~`date +%Y%m%d%H%M%S`
                            elif [ "${params.VERSION}" ]; then
                                echo -n ${params.VERSION}
                            else
                                echo -n `dpkg-parsechangelog -n 1 -S Version`
                            fi
                        """
                    )
                    UPSTREAM_NAME = sh(
                        returnStdout: true,
                        script: "dpkg-parsechangelog -n 1 -S Source | tr -d '\n'"
                    )
                    CHANGES_FILENAME = sh(
                        returnStdout: true,
                        script: "echo -n ${UPSTREAM_NAME}_${VERSION}_${params.ARCH}.changes"
                    )
                }

                /* If we are on master, we check for the presence of a tag. */
                sh """
                    if [ "$BRANCH_NAME" = "master" ]; then
                        echo "We are building for master, checking for git tag..."

                        if ! git show-ref v${VERSION} > /dev/null; then
                            echo 'No git tag "v${VERSION}" found!'
                            exit 1
                        fi
                    fi
                """

                sh "mkdir -p build/"
            }
        }

        stage ('build package') {
            environment {
                GNUPG_SIGN_KEY = credentials('9dddc074-0903-487c-aa20-7cb6d9de403c')
                GBP_ARGS = "--git-pbuilder --git-export-dir=build/${params.DIST}-${params.ARCH} --git-dist=${params.DIST} --git-arch=${params.ARCH}"
            }
            steps {
                sh """
                    export GNUPGHOME=\$(mktemp -d -p \$(realpath build))
                    gpg --import ${GNUPG_SIGN_KEY}
                    gpg --list-secret-keys

                    if [ "$BRANCH_NAME" = "master" ]; then
                        gbp buildpackage ${GBP_ARGS} --git-export=v${VERSION} -F -nc
                    else
                        gbp buildpackage ${GBP_ARGS} \
                            --git-debian-branch=$BRANCH_NAME --git-upstream-branch=$BRANCH_NAME \
                            --git-postexport="sed -i '1s/(.*)/(${VERSION})/' debian/changelog" -F -nc
                    fi

                    rm -rf \${GNUPGHOME}
                    unset GNUPGHOME
                """

                /* Test if the .changes file was created as we expected it. */
                sh "test -f build/${params.DIST}-${params.ARCH}/${CHANGES_FILENAME}"
            }
        }
        stage ('Upload to Artifactory') {
            steps {
                script {
                    def buildInfo = Artifactory.newBuildInfo()
                    buildInfo.retention maxBuilds: 10, deleteBuildArtifacts:true
                    def server = Artifactory.server 'TTTech Artifactory'
                    def uploadSpec = """{
                      "files": [
                          {
                            "pattern": "build/${params.DIST}-${params.ARCH}/*",
                            "target": "build/nervesw/${PACKAGE}/deb/${BRANCH_NAME}/build$BUILD_NUMBER/"
                          }
                     ]
                    }"""
                    server.upload(uploadSpec, buildInfo)
                    server.publishBuildInfo(buildInfo)
                }
            }
        }
        stage ('Upload to APT') {
            when {
                anyOf {
                    branch 'integration'
                    environment name: 'UPLOAD', value: 'true'
                }
            }
            environment {
                HOST = "apt-upload@apt.nerve.cloud"
                DEST = "incoming/${params.DIST}-${params.ARCH}"
            }
            steps {
                script {
                    withCredentials([sshUserPrivateKey(
                        credentialsId: 'f0b278d1-0874-4b40-886a-c22622342fab',
                        keyFileVariable: 'SSH_KEYFILE',
                        passphraseVariable: '',
                        usernameVariable: 'SSH_USERNAME'
                    )]) {
                        def remote = [:]
                        remote.name = 'infra.svc.nerve.cloud'
                        remote.host = 'infra.svc.nerve.cloud'
                        remote.allowAnyHosts = true
                        remote.user = SSH_USERNAME
                        remote.identityFile = SSH_KEYFILE
                        sshPut remote: remote, from: "build/${params.DIST}-${params.ARCH}", into: "incoming/"
                        sshCommand remote: remote, command: "process-upload -d ${params.DIST} incoming/${params.DIST}-${params.ARCH}/${CHANGES_FILENAME}"
                    }
                }
            }
        }
    }
    post {
        always {
            archiveArtifacts artifacts: "build/${params.DIST}-${params.ARCH}/*", fingerprint: true
            cleanWs()
        }
    }
}
