只有在事情发生变化时才构建项目

时间:2017-06-29 07:19:08

标签: node.js git jenkins jenkins-pipeline

我们希望将项目分成更小的部分。我们当前的CI流程经历了一个短暂的测试阶段,然后运行部署脚本。但是,如果其中一个子项目没有任何变化,我们不希望为此进行构建。

没有管道的Jenkins支持SCM配置中的排除(我们使用git),基于此,您可以配置要运行的特定作业。但是,在使用管道时,我怎么知道,我是否应该构建这个部分?如何访问受上次推送影响的路径?

目前我们的脚本非常简单,我们希望尽可能简单。

我们正在使用scripteddeclarative语法,但无法找到一个好的解决方案。

声明:

#!groovy​
pipeline {
    agent any
    tools {
        nodejs '8.1'
    }
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        # Only continue, if something has changed

        stage('Install') {
            steps {
                sh 'npm install'
            }
        }

        stage('Test') {
            steps {
                sh 'npm run test-jenkins'
            }
            post {
                always {
                    junit "artifacts/test/report.xml"
                }
            }
        }
    }
}

脚本:

#!groovy​
node {
    def nodejs = tool name: '8.1', type: 'jenkins.plugins.nodejs.tools.NodeJSInstallation'
    env.PATH = "${nodejs}/bin:${env.PATH}"

    stage('Checkout') {
        checkout scm
    }

    # Only continue, if something has changed


    stage('Install') {
        sh 'npm install'
    }

    stage('Test') {
        try {
            sh 'npm run test-jenkins'
        } finally {
            junit "artifacts/test/report.xml"
        }
    }
}

1 个答案:

答案 0 :(得分:2)

感谢我提问ElpieKay's fast comment,我们现在有一个优雅的解决方案:

  1. 为成功构建的当前提交制作标记
  2. 在下一个版本中,比较新提交和更改标记
  3. 我们正在为同一源根目录下的多个项目使用multi-branch pipeline和并行构建。我们遍历项目(serviceX)并在相应的目录中检查更改:

    def projects = ['service1', 'service2']
    def builders = [:]
    for (p in projects) {
        def label = p
    
        builders[label] = {
            def tag = "${BRANCH_NAME}_last"
            node {
                echo "Checking for changes compared to ${tag} in directory ${label}"
                try {
                    sh "./check-for-changes ${tag} ${label}"
                } catch (ignored) {
                    echo "Nothing to do"
                    return
                }
                dir (label) {
                    stage(label + ": Install") {
                        sh "npm install"
                    }
    
                    stage(label + ": Test") {
                        try {
                            sh "npm run test-jenkins"
                        } finally {
                            junit 'artifacts/test/report.xml'
                        }
                    }
    
                    echo "Setting tag for the last build on this branch"
                    sh "git tag -f ${tag}"
                }
            }
        }
    }
    
    parallel builders
    

    ...以及检查更改的脚本:

    #!/bin/bash
    SHA_PREV=$1
    if [ -z ${SHA_PREV} ]; then
        echo "Usage: `basename $0` <tag> <path>"
        exit 1
    fi
    
    CHECK_PATH=$2
    if [ -z ${CHECK_PATH} ]; then
        echo "Usage: `basename $0` <tag> <path>"
        exit 1
    fi
    
    if `git rev-parse ${SHA_PREV} >/dev/null 2>&1`; then
        echo "Found previous tag: ${SHA_PREV}"
    else
        SHA_PREV=`git rev-list --max-parents=0 HEAD`
        echo "Using initial commit: ${SHA_PREV}"
    fi
    
    changes=`git diff --name-only ${SHA_PREV} HEAD | grep ${CHECK_PATH}/`
    if [ ! -n "${changes}" ]; then
        echo "No changes found"
        exit 2 # no changes found
    fi