gimpBuildPipeline.groovy 8.29 KB
Newer Older
Sam Gleske's avatar
Sam Gleske committed
1 2 3 4 5 6 7 8 9 10 11
/*
 * This build pipeline is designed to automatically run builds for the following projects:
 *
 *   - BABL
 *   - GEGL
 *   - libmypaint
 *   - mypaint-brushes
 *   - GIMP
 *
 * The pipeline will select appropriate build scripts depending on the project calling it.
 */
Sam Gleske's avatar
Sam Gleske committed
12

13 14
import jenkins.model.Jenkins

Sam Gleske's avatar
Sam Gleske committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/**
  Does nothing except return a static Map.
 */
@NonCPS
Map projectEnvMap() {
    [
        gimp: [
            master: [
                GEGL_BRANCH: 'master'
            ],
            'gimp-2-10': [
                GEGL_BRANCH: 'master'
            ],
            'gimp-2-8': [
                GEGL_BRANCH: 'gegl-0-2'
            ]
Sam Gleske's avatar
Sam Gleske committed
31 32
        ]
    ]
Sam Gleske's avatar
Sam Gleske committed
33
}
Sam Gleske's avatar
Sam Gleske committed
34

35 36 37 38 39 40 41 42
/**
  List of projects and branches in which to copy dependencies from.
 */
@NonCPS
List<String> projectDependencies(String project, String branch) {
    [
        gegl: [
            master: [
43
                'babl/master'
Sam Gleske's avatar
Sam Gleske committed
44 45
            ],
            'gegl-0-2': [
46
                'babl/master'
47 48 49 50
            ]
        ],
        libmypaint: [
            'v1.3.0': [
51 52
                'babl/master',
                'gegl/master'
53 54 55
            ]
        ],
        'mypaint-brushes': [
Sam Gleske's avatar
Sam Gleske committed
56
            'v1.3.x': [
57 58 59
                'babl/master',
                'gegl/master',
                'libmypaint/v1.3.0'
60 61 62 63
            ]
        ],
        gimp: [
            'master': [
64 65 66 67
                'babl/master',
                'gegl/master',
                'libmypaint/v1.3.0',
                'mypaint-brushes/v1.3.x'
68 69
            ],
            'gimp-2-10': [
70 71 72 73
                'babl/master',
                'gegl/master',
                'libmypaint/v1.3.0',
                'mypaint-brushes/v1.3.x'
74 75
            ],
            'gimp-2-8': [
76 77 78 79
                'babl/master',
                'gegl/gegl-0-2',
                'libmypaint/v1.3.0',
                'mypaint-brushes/v1.3.x'
80 81 82 83 84
            ]
        ]
    ].get(project)?.get(branch) ?: []
}

Sam Gleske's avatar
Sam Gleske committed
85 86 87 88 89 90 91 92 93
@NonCPS
String getFriendlyName(String name) {
    [
        'babl': 'BABL',
        'gegl': 'GEGL',
        'gimp': 'GIMP'
    ].get(name) ?: name
}

Sam Gleske's avatar
Sam Gleske committed
94 95 96 97 98
/**
  References the project environment map and converts variables into Docker
  arguments for environment variables.
 */
@NonCPS
Sam Gleske's avatar
Sam Gleske committed
99
String getDockerEnv(String project, branch) {
Sam Gleske's avatar
Sam Gleske committed
100
    projectEnvMap().get(project)?.get(branch)?.collect { k, v ->
Sam Gleske's avatar
Sam Gleske committed
101
        "-e ${k}=${v}"
102
    }?.join(' ') ?: ''
Sam Gleske's avatar
Sam Gleske committed
103
}
Sam Gleske's avatar
Sam Gleske committed
104

105 106 107 108 109 110 111 112 113
/**
  Check to see if a dependency is ready.  Only used during first time build on
  a new Jenkins instance.
 */
@NonCPS
Boolean isDependentBuildReady(String dependency) {
    Jenkins.instance.getItemByFullName(dependency)?.lastSuccessfulBuild ? true : false
}

114 115 116
/**
  This is the main execution.
 */
Sam Gleske's avatar
Sam Gleske committed
117
def call() {
118 119 120 121 122 123
    properties([
        //discard builds when counts goes above 50
        buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '50')),
        //do not resume pipelines if Jenkins restarts mid-build, consider it failed
        disableResume()
    ])
Sam Gleske's avatar
Sam Gleske committed
124
    //e.g. project = gimp
Sam Gleske's avatar
Sam Gleske committed
125
    String project = env.JOB_NAME.tokenize('/')[0]
126
    //e.g. -e GIMP_BRANCH=master -e GEGL_BRANCH=master
127
    String myEnv = "-e ${project.toUpperCase()}_BRANCH=${env.BRANCH_NAME} " + getDockerEnv(project, env.BRANCH_NAME)
128
    String reference_repo = "${Jenkins.instance.root}/export/${project}.git"
129 130 131 132 133 134 135
    if(Integer.parseInt(env.BUILD_NUMBER) == 1) {
        //wait for dependent builds to finish when Jenkins is bootstrapped for the first time
        while(false in projectDependencies(project, env.BRANCH_NAME).collect { isDependentBuildReady(it) }) {
            echo "Waiting on first build of ${projectDependencies(project, env.BRANCH_NAME).find { !isDependentBuildReady(it) }}."
            sleep 60
        }
    }
Sam Gleske's avatar
Sam Gleske committed
136
    node('master') {
Sam Gleske's avatar
Sam Gleske committed
137
        stage("Environment") {
138
            docker.image('gimp/gimp:latest').inside("${myEnv}") {
139 140 141 142 143 144
                sh '''
                    |head -n1 /etc/issue
                    |id
                    |uname -rms
                    |bash --version | head -n1
                   '''.stripMargin().trim()
Sam Gleske's avatar
Sam Gleske committed
145 146 147
                //environment_string = sh(script: 'env | LC_ALL=C sort', returnStdout: true).split('\n').join('\n    ')
                grep_expr = 'BRANCH|^BUILD_|^JOB_|PATH|^DEBIAN_FRONTEND|^PREFIX|ACLOCAL_FLAGS|^PWD'
                environment_string = sh(script: "env | LC_ALL=C sort | grep -E \'${grep_expr}\'", returnStdout: true).split('\n').join('\n    ')
Sam Gleske's avatar
Sam Gleske committed
148
                echo "DOCKER ENVIRONMENT:\n    ${environment_string}"
149
            }
Sam Gleske's avatar
Sam Gleske committed
150
        }
151
        stage("Update git cache") {
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
            lock('update-git-cache') {
                sh """
                    |#!/bin/bash
                    |echo 'Updating local git cache for faster checkouts'
                    |function update_cached_scm {
                    |    name="\$1"
                    |    repoUrl="\$2"
                    |    localRepo="${Jenkins.instance.root}/export/\${name}.git"
                    |    if [ ! -d "\${localRepo}" ]; then
                    |        git clone --mirror "\${repoUrl}" "\${localRepo}"
                    |    fi
                    |    cd "\${localRepo}"
                    |    git remote update --prune
                    |}
                    |set -exo pipefail
167
                    |update_cached_scm "docker-gimp" "https://gitlab.gnome.org/World/gimp-ci/docker-gimp.git"
168 169 170 171 172 173 174
                    |update_cached_scm "${project}" "${scm.userRemoteConfigs[0].url}"
                   """.stripMargin().trim()
            }
            //check out project to subdirectory for build
            dir(project) {
                checkout scm
            }
175
        }
176
        docker.image('gimp/gimp:latest').inside("${myEnv} -v ${reference_repo}:${reference_repo}:ro") {
177
            if(projectDependencies(project, env.BRANCH_NAME)) {
Sam Gleske's avatar
Sam Gleske committed
178 179
                stage('Copy Dependencies') {
                    for(String dependency : projectDependencies(project, env.BRANCH_NAME)) {
180 181
                        copyArtifacts filter: '**/*-internal.tar.gz', fingerprintArtifacts: true, flatten: true, projectName: dependency, selector: lastSuccessful()
                        sh 'mv *-internal.tar.gz /data/'
Sam Gleske's avatar
Sam Gleske committed
182
                    }
183 184
                }
            }
185 186 187
            catchError {
                stage("Build ${getFriendlyName(project)}") {
                    //automatically generated checkout command from pipeline syntax generator
188
                    checkout poll: false, scm: [$class: 'GitSCM', branches: [[name: 'refs/heads/master']], browser: [$class: 'GitLab', repoUrl: 'https://gitlab.gnome.org/World/gimp-ci/docker-gimp', version: '10.8'], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'ChangelogToBranch', options: [compareRemote: 'origin', compareTarget: 'master']], [$class: 'RelativeTargetDirectory', relativeTargetDir: 'docker-gimp'], [$class: 'CloneOption', depth: 0, noTags: true, reference: "${Jenkins.instance.root}/export/docker-gimp.git", shallow: false]], submoduleCfg: [], userRemoteConfigs: [[url: 'https://gitlab.gnome.org/World/gimp-ci/docker-gimp.git']]]
189
                    //end automatically generated checkout
190
                    sh "SKIP_MAKE_CHECK=1 bash ./docker-gimp/debian-testing/${project}.sh"
191
                }
Sam Gleske's avatar
Sam Gleske committed
192
            }
193
            if((project in ['babl', 'gegl', 'gimp']) && Integer.parseInt(env.BUILD_NUMBER) > 1) {
194 195
                catchError {
                    stage("Test ${getFriendlyName(project)}") {
196
                        sh "SKIP_MAKE_BUILD=1 bash ./docker-gimp/debian-testing/${project}.sh"
197 198
                    }
                }
199 200
                catchError {
                    stage("${getFriendlyName(project)} distcheck") {
201
                        sh "SKIP_MAKE_BUILD=1 SKIP_MAKE_CHECK=1 INCLUDE_DISTCHECK=1 bash ./docker-gimp/debian-testing/${project}.sh"
202 203 204
                    }
                }
            }
Sam Gleske's avatar
Sam Gleske committed
205
            stage("Publish artifacts") {
206 207
                //archive artifacts relative to project directory
                dir(project) {
208 209 210 211 212 213
                    if(project == 'gegl') {
                        archiveArtifacts artifacts: "${project}-internal.tar.gz,*.tar.bz2,**/test-suite.log,tests/mipmap/*.png", fingerprint: true, onlyIfSuccessful: false
                    }
                    else {
                        archiveArtifacts artifacts: "${project}-internal.tar.gz,*.tar.bz2,**/test-suite.log", fingerprint: true, onlyIfSuccessful: false
                    }
214
                }
Sam Gleske's avatar
Sam Gleske committed
215
            }
Sam Gleske's avatar
Sam Gleske committed
216
        }
Sam Gleske's avatar
Sam Gleske committed
217
        deleteDir()
Sam Gleske's avatar
Sam Gleske committed
218 219
    }
}