pipeline {
    agent { label 'linux-testing-package-builder' }

    options { 
        buildDiscarder(logRotator(numToKeepStr: '25', daysToKeepStr: '30'))
        gitLabConnection('GitLabConnectionJenkins')
    }
    parameters {
        booleanParam(name: 'IS_RELEASE_CANDIDATE', defaultValue: false, description: 'Is it a Release Candidate?')
        string(name: 'RELEASE_CANDIDATE_NAME', defaultValue: '', description: 'i.e: RC2, RC3 (only needed if IS_RELEASE_CANDIDATE is true)')
        booleanParam(name: 'CUSTOM_BUILD', defaultValue: true, description: 'If true, will use DISTRO_TO_BUILD and ARCH_TO_BUILD. If false, will build all distributions')
        string(name: 'DISTRO_TO_BUILD', defaultValue: 'xUbuntu_22.04', description: 'Only used if CUSTOM_BUILD is true')
        choice(name: 'ARCH_TO_BUILD', choices: ['amd64', '386'], description: 'Only used if CUSTOM_BUILD is true')        
        string(name: 'MEGASYNC_BRANCH', defaultValue: "${env.BRANCH_NAME}", description: 'Which version of MEGAsync should we build? Default is current branch.')
        string(name: 'SDK_BRANCH', defaultValue: ' ', description: 'Optionally, define a custom SDK branch.')
    }
    environment {
        gitlab_token = credentials('jenkins_sdk_token')
        MEGASYNC_BRANCH = "${params.MEGASYNC_BRANCH}"
        SDK_BRANCH = "${params.SDK_BRANCH}"
    }

    stages {
        stage('Clean previous runs'){
            steps{
                deleteDir()
            }
        }

        stage('Checkout linux'){
            steps {
                checkout([
                    $class: 'GitSCM', 
                    branches: [[name: "${env.MEGASYNC_BRANCH}"]],
                    userRemoteConfigs: [[ url: "${env.GIT_URL_DESKTOP}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1" ]],
                    extensions: [
                        [$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"]
                        ]
                ])
                script {
                    linux_sources_workspace = WORKSPACE
                    def branchToCheckout = ''
                    if (env.SDK_BRANCH && env.SDK_BRANCH != ' ') {
                        branchToCheckout = env.SDK_BRANCH
                    } else if (env.MEGASYNC_BRANCH in ['develop', 'master']) {
                        branchToCheckout = "develop"
                    } else {
                        env.SDK_BRANCH = sh(script: "grep 'branch =' ${linux_sources_workspace}/.gitmodules | sed 's/.*= //'", returnStdout: true).trim()
                        branchToCheckout = env.SDK_BRANCH
                    }

                    dir('src/MEGASync/mega') {
                        sh "echo Cloning SDK branch ${branchToCheckout}"
                        checkout([
                            $class: 'GitSCM',
                            branches: [[name: branchToCheckout]],
                            userRemoteConfigs: [[url: "${env.GIT_URL_SDK}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1"]],
                            extensions: [
                                [$class: "UserIdentity", name: "jenkins", email: "jenkins@jenkins"]
                            ]
                        ])
                    }
                }
            }
        }
        stage ('Build custom distribution'){
            when { 
                beforeAgent true
                expression { params.CUSTOM_BUILD == true } 
            }
            steps {
                echo "Do Build for ${params.DISTRO_TO_BUILD}"
                dir(linux_sources_workspace) {
                    lock(resource: "${params.DISTRO_TO_BUILD}-${params.ARCH_TO_BUILD}-MEGAsync-build", quantity: 1) {
                        buildAndSignPackage("${params.DISTRO_TO_BUILD}", "${params.ARCH_TO_BUILD}", "megasync")
                    }
                    script{
                        if ( params.IS_RELEASE_CANDIDATE == true) {
                            def MEGASYNC_VERSION = getVersionFromHeader("src/MEGASync/control/Version.h")
                            sh "cd ${env.INTERNAL_REPO_PATH}/repo/private/$DISTRO_TO_BUILD && jf rt upload --regexp '((x86_64|amd64|i386)/megasync.*deb\$|(x86_64|amd64|i386)/megasync.*rpm\$|(x86_64|amd64|i386)/megasync.*\\.pkg\\.tar\\.zst\$|(x86_64|amd64|i386)/megasync.*\\.pkg\\.tar\\.xz\$)' MEGAsync-releases/$MEGASYNC_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO_TO_BUILD/"
                            echo "Packages successfully uploaded. URL: [${env.REPO_URL}/MEGAsync-releases/$MEGASYNC_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO/]"
                        }
                    }
                }
            }
        }
        stage ('Build all distributions'){
            when {
                beforeAgent true
                expression { params.CUSTOM_BUILD == false }
            }
            matrix {
                axes {
                    axis { 
                        name 'ARCHITECTURE'; 
                        values 'amd64', '386' 
                    }
                    axis { 
                        name 'DISTRO'; 
                        values  'xUbuntu_24.04', 'xUbuntu_23.10', 'xUbuntu_23.04','xUbuntu_22.04', 'xUbuntu_20.04',
                                'Debian_10','Debian_11','Debian_12','Debian_testing',
                                'DEB_Arch_Extra',
                                'Fedora_37', 'Fedora_38', 'Fedora_39', 'Fedora_40',
                                'openSUSE_Leap_15.4','openSUSE_Leap_15.5','openSUSE_Leap_15.6', 'openSUSE_Tumbleweed'
                    }
                }
                excludes {
                    exclude {   
                        axis { 
                            name 'ARCHITECTURE'; 
                            values '386' 
                        }
                                
                        axis { 
                            name 'DISTRO'; 
                            values  'xUbuntu_24.04', 'xUbuntu_23.10', 'xUbuntu_23.04', 'xUbuntu_22.04', 'xUbuntu_20.04',
                                    'Debian_11','Debian_12','Debian_testing',
                                    'DEB_Arch_Extra',
                                    'CentOS_8','CentOS_7',
                                    'Fedora_37', 'Fedora_38', 'Fedora_39', 'Fedora_40',
                                    'openSUSE_Leap_15.4','openSUSE_Leap_15.5', 'openSUSE_Leap_15.6', 'openSUSE_Tumbleweed'
                        }
                    }
                }
                stages {
                    stage('Build') {
                        agent { label 'docker && ci-debian-11-64-2' }
                        steps {
                            echo "Do Build for ${DISTRO} - ${ARCHITECTURE}"
                            dir(linux_sources_workspace) {
                                lock(resource: "${DISTRO}-${ARCHITECTURE}-MEGAsync-build", quantity: 1) {
                                    buildAndSignPackage("${DISTRO}", "${ARCHITECTURE}", "megasync")
                                }
                            }
                        }
                    }
                    stage('Upload packages') {
                        when {
                            beforeAgent true
                            expression { params.IS_RELEASE_CANDIDATE == true }
                        }
                        steps {
                            dir(linux_sources_workspace) {
                                script{
                                    def MEGASYNC_VERSION = getVersionFromHeader("src/MEGASync/control/Version.h")
                                    sh "jf rt del MEGAsync-releases/$MEGASYNC_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO"
                                    sh "cd ${env.INTERNAL_REPO_PATH}/repo/private/$DISTRO && jf rt upload --regexp '((x86_64|amd64|i386)/megasync.*deb\$|(x86_64|amd64|i386)/megasync.*rpm\$|(x86_64|amd64|i386)/megasync.*\\.pkg\\.tar\\.zst\$|(x86_64|amd64|i386)/megasync.*\\.pkg\\.tar\\.xz\$)' MEGAsync-releases/$MEGASYNC_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO/"  
                                    echo "Packages successfully uploaded. URL: [${env.REPO_URL}/MEGAsync-releases/$MEGASYNC_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO/]"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}


def buildAndSignPackage(String distro, String architecture, String packageName) {
    sh "${env.BUILDTOOLS_PATH}/build/buildManager.sh -a ${architecture} -j 1 build ${distro} . ${packageName}"
    sh "${env.BUILDTOOLS_PATH}/repo/repoManager.sh add ${env.INTERNAL_REPO_PATH}/builder/results/${distro}/${architecture}/${packageName}/ ${distro}"
    sh "SIGN_KEY_PATH=${env.INTERNAL_REPO_PATH}/sign_test/ ${env.BUILDTOOLS_PATH}/repo/repoManager.sh build -n ${distro}"
}

def getVersionFromHeader(String versionFilePath) {
    return sh(script: "awk -F'\"' '/VER_PRODUCTVERSION_STR/ {split(\$2, a, \".\"); print a[1]\".\"a[2]\".\"a[3]}' ${versionFilePath}", returnStdout: true).trim()
}