bingoogolapple.github.io icon indicating copy to clipboard operation
bingoogolapple.github.io copied to clipboard

Pipeline 备忘

Open bingoogolapple opened this issue 7 years ago • 8 comments

  • 查看内置的环境变量,域名/pipeline-syntax/globals#env
  • 用 echo 输出日志,用 error 使当前的 stage 返回失败
stage('test') {
    // echo "用 echo 输出日志"
    // error "用 error 使当前的 stage 返回失败"
    test()
}
def test() {
    echo "用 echo 输出日志"
    error "用 error 使当前的 stage 返回失败"
}
wrap([$class: 'BuildUser']) {
    echo "BUILD_USER 为 ${BUILD_USER}"
    echo "BUILD_USER_ID 为 ${BUILD_USER_ID}"
    echo "BUILD_USER_EMAIL 为 ${BUILD_USER_EMAIL}"
}
  • 参数化构建时,参数会放入 params 中,params 中不会包含 BUILD_NUMBER,params 实际上就是 map
echo "参数 ${params}"
参数 [isSdf:true, branch:develop]
  • 当前 job 的构建版本号可以通过 ${BUILD_NUMBER} 或 ${BUILD_ID} 来获取
  • 当前 job 的工作目录可通过 ${WORKSPACE} 来获取
  • 可以直接通过 ${isSdf} 来取值,但是建议都通过 params.isSdf 来取值,如果直接 isSdf,if 判断会有问题
if (isSdf) { // 不管 isSdf 是否为 true,都为真
    echo "直接取值,需要"
} else {
    echo "直接取值,不需要"
}
if (params.isSdf) { // 只有 isSdf 为 true 是才为真
    echo "需要"
} else {
    echo "不需要"
}
  • 变量名不能以减号 - 分隔
  • 不管是在外部、stage 内、方法内,定义变量时加了 def 就是局部变量,不加 def 就是全局变量
  • 如果想在 sh 中使用 groovy 中定义的变量,可以在 groovy 中通过 env.xxxx 来定义变量
stage('test') {
    env.CUSTOM_PARAM = "自定义参数"
    def cmd = '''echo ${CUSTOM_PARAM}
    echo ${CUSTOM_PARAM}
    echo ${CUSTOM_PARAM}
    '''
    sh cmd
}
  • 创建目录和判断文件是否存在
def currentDirectory = pwd()
echo "当前目录 ${currentDirectory}"
sh "ls"
def testDir = currentDirectory + "/testDir"
if (!fileExists(testDir)) {
    sh "mkdir ${testDir}"
}
sh "ls"
  • 日志中不输出 sh 命令
def shWhithoutLog(cmd) {
    sh('#!/bin/sh -e\n' + cmd)
}
  • 获取 shell 的输出和状态
stage('test') {
    env.CUSTOM_PARAM = "自定义参数"
    def cmd = '''echo ${CUSTOM_PARAM}
    echo ${CUSTOM_PARAM}
    '''
    output = sh (
        script: cmd,
        returnStdout: true
    ).trim()
    echo "输出为:${output}"
    result = sh (
        script: cmd,
        returnStatus: true
    )
    echo "结果为:${result}"
}
  • 触发其他 job
build job: 'other_job_name', parameters: [string(name: 'channels', value: 'a,b,c'), string(name: 'apk_url', value: 'xxxxx'), string(name: 'app_name', value: 'xxx')]

bingoogolapple avatar Dec 22 '17 03:12 bingoogolapple

  • 获取版本号
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package
// awk '{print $4}'     空格 split,从1开始,取第4个
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $4}'
// sed s/versionName=//g   将 versionName= 替换成功空串,如果要将 versionName= 替换成 BGA,则写成 sed s/versionName=/BGA/g
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $4}' | sed s/versionName=//g
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $4}' | sed s/versionName=//g | sed s/\'//g
env.DUMP_BADGING_CMD = "${ANDROID_HOME}/build-tools/27.0.1/aapt dump badging ${ORIGIN_APK_FILE}"
// APK_VERSION_NAME=`${DUMP_BADGING_CMD} | grep package | awk '{print $4}' | sed s/versionName=//g | sed s/\'//g`
def getApkVersionNameCmd = '''
APK_VERSION_NAME=`${DUMP_BADGING_CMD} | grep package | awk '{print $4}' | sed s/versionName=//g | sed s/\\'//g`
echo "${APK_VERSION_NAME}"
'''
env.APK_VERSION_NAME = sh (
    script: getApkVersionNameCmd,
    returnStdout: true
).trim()
echo "版本号为 ${APK_VERSION_NAME}"
  • 获取中文名称
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep application-label-zh-CN
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep application-label-zh-CN: | sed s/application-label-zh-CN://g
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep application-label-zh-CN: | sed s/application-label-zh-CN://g | sed s/\'//g
// APP_CHINESE_NAME=`${DUMP_BADGING_CMD} | grep application-label-zh-CN: | sed s/application-label-zh-CN://g | sed s/\'//g`
def getAppChineseNameCmd = '''
APP_CHINESE_NAME=`${DUMP_BADGING_CMD} | grep application-label-zh-CN: | sed s/application-label-zh-CN://g | sed s/\\'//g`
echo "${APP_CHINESE_NAME}"
'''
env.APP_CHINESE_NAME = sh (
    script: getAppChineseNameCmd,
    returnStdout: true
).trim()
echo "中文名称为 ${APP_CHINESE_NAME}"
  • 获取英文名称
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $2}'
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $2}' | sed s/name=//g | sed s/\'//g
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $2}' | sed s/name=//g | sed s/\'//g | sed s/\\./\ /g
// awk '{print $NF}'  空格 split,从1开始,取第最后
/Applications/develop/AndroidSDK/build-tools/27.0.1/aapt dump badging /Users/wanghao/Desktop/sdf.apk | grep package | awk '{print $2}' | sed s/name=//g | sed s/\'//g | sed s/\\./\ /g | awk '{print $NF}'
// APP_NAME=`${DUMP_BADGING_CMD} | grep package | awk '{print $2}' | sed s/name=//g | sed s/\'//g | sed s/\\./\ /g | awk '{print $NF}'`
def getPackageNameCmd = '''
PACKAGENAME=`${DUMP_BADGING_CMD} | grep package | awk '{print $2}' | sed s/name=//g | sed s/\\'//g`
echo "${PACKAGENAME}"
'''
def packageName = sh (
    script: getPackageNameCmd,
    returnStdout: true
).trim()
echo "包名为 ${packageName}"
env.APP_NAME = "${packageName.substring(packageName.lastIndexOf('.') + 1)}"
echo "英文名称为 ${APP_NAME}"

bingoogolapple avatar Dec 22 '17 20:12 bingoogolapple

#!/usr/bin/env groovy
node('xxxx') {
    try {
        def language = "Java,Kotlin"
        def testArr = language.split(",")
        def testMap = ["key1": "value1", "key2": "value2"]

        stage('测试字符串') {
            echo "添加前数组的值为 ${testArr}"
            language += ",Python"
            testArr = language.split(",")
            echo "添加后数组的值为 ${testArr}"
            echo "tokenize 的结果为 ${language.tokenize(',')}"
            echo "split 的结果为 ${language.split(',')}"
            echo "最后一个元素为 ${language.substring(language.lastIndexOf(',') + 1)}"
            echo "转换为大写 ${language.toUpperCase()} 转换为小写 ${language.toLowerCase()}"
            echo "是否包含 ${language.contains('Java')} ${language.contains('java')}"
        }

        stage('测试map') {
            echo "${testMap.key1}"
            echo "${testMap['key2']}"
            echo "${testMap.keySet()}"
            echo "${testMap.values()}"
        }

        stage('测试 for 循环') {
            // 可以
            for (def test : testArr) {
                echo "测试 ${test}"
            }
            // 可以
            for (def i = 0; i < 3; i++) {
                echo "测试 ${i}"
            }
        }
        
        // 可以
        for (def i = 0; i < testArr.length; i++) {
            stage("${testArr[i]}") {
                echo "${testArr[i]}"
            }
        }

        currentBuild.result = 'SUCCESS'
    } catch (e) {
        currentBuild.result = 'FAILURE'
        def errorMsg = "========================================= 错误信息 START =========================================\n"
        errorMsg += "${e.toString()}|${e.message}\n"
        errorMsg += "========================================= 错误信息 END ========================================="
        echo "${errorMsg}"
        sh 'exit 1'
    } finally {
        // 清空工作空间,notFailBuild: true 设置失败时也清除工作空间
        cleanWs notFailBuild: true
    }
}

bingoogolapple avatar Feb 05 '18 10:02 bingoogolapple

多选

image

image

node('xxx_agent') {
    try {
        stage('build') {
            echo "job参数为 ${params.flavors}"
            
            def flavorArr = params.flavors.split(",")
            
            for(def flavor : flavorArr) {
                echo "flavor is ${flavor}"
            }
        }

        currentBuild.result = 'SUCCESS'
    } catch (e) {
        currentBuild.result = 'FAILURE'
        // 打印错误信息
        def errorMsg = "========================================= 错误信息 START =========================================\n"
        errorMsg += "${e.toString()}\n"
        errorMsg += "========================================= 错误信息 END ========================================="
        echo "${errorMsg}"
        sh 'exit 1'
    } finally {
        if (currentBuild.result == null || currentBuild.result == 'SUCCESS') {
            echo '构建成功'
        } else {
            echo '构建失败'
        }

        // 清空工作空间,notFailBuild: true 设置失败时也清除工作空间
        cleanWs notFailBuild: true
    }
}

bingoogolapple avatar Sep 04 '18 04:09 bingoogolapple

隐藏域

image

bingoogolapple avatar Sep 04 '18 05:09 bingoogolapple

闭包,MissingPropertyException、并发

#!/usr/bin/env groovy

def ignoreError(def closure) {
    try {
        closure.call("Hello", 3333)
    } catch(e) {
        echo "${e.toString()}\n"
    }
}

def testClosureParams(def closure) {
    closure.call('bingoogolapple', 27, '男')
}

node('xxx_agent') {
    try {
        stage('测试闭包1') {
            testClosureParams { name, age, gender ->
                echo "name is $name, age is $age, gender is $gender"
            }

            ignoreError { p1, p2 ->
                echo "参数21 is $p1, 参数22 is $p2" 
                if (Boolean.valueOf("${IS_XXX}")) {
                    echo "启用"
                } else {
                    echo "不启用"
                }
            }

            ignoreError { p1, p2 ->
                echo "参数11 is $p1, 参数12 is $p2" 
                // 要加上 params. 前缀,不然会报 groovy.lang.MissingPropertyException: No such property: IS_XXX for class: groovy.lang.Binding
                if (Boolean.valueOf("${params.IS_XXX}")) {
                    echo "启用"
                } else {
                    echo "不启用"
                }
            }
        }

        stage('测试闭包2') {
            def aClosure = { innerIt ->
                echo "aClosure:param1 is ${innerIt[0]}, param2 is ${innerIt[1]}" 
            }
            aClosure.call(["hello", 100])

            def bClosure = {
                echo "bClosure:param1 is ${it[0]}, param2 is ${it[1]}" 
            }
            bClosure.call(["hello", 100])

            def cClosure = { p1, p2 ->
                echo "cClosure:param1 is $p1, param2 is $p2" 
            }
            cClosure.call("hello", 100)
        }

        stage('测试并发1') {
            def jobs=["init":{echo "init"}]
            def languageStr = "Java,Kotlin,C,Swift"
            def languageArr = languageStr.split(",")
            for(def i = 0; i < languageArr.length; i++){
                def language = "${languageArr[i]}"
                jobs["$language"] = {
                    echo "执行 $language"
                }
            }
            parallel(jobs)
        }

        stage('测试并发2') {
            parallel(['check one': {
                echo "start one"
                sleep 1
                echo "finish one"
            }, 'check two': {
                echo "start two"
                sleep 2
                echo "finish two"
            }, 'check three': {
                echo "start three"
                sleep 3
                echo "finish three"
            }])
        }

        stage('测试并发3') {
            parallel 'check one': {
                echo "start one"
                sleep 1
                echo "finish one"
            }, 'check two': {
                echo "start two"
                sleep 2
                echo "finish two"
            }, 'check three': {
                echo "start three"
                sleep 3
                echo "finish three"
            }
        }
        stage('测试JSON解析') {
            echo "job参数为 ${params}"

            def jsonStr = '{ "key1": "value1", "key2": 999999}'
            def jsonSlurper = new groovy.json.JsonSlurper()
            def jsonObject = jsonSlurper.parseText(jsonStr)
            echo "key1 is ${jsonObject.key1}, key2 is ${jsonObject.key2}"
            
            jsonObject = readJSON text: "${jsonStr}"
            echo "key1 is ${jsonObject.key1}, key2 is ${jsonObject.key2}"
        }

        currentBuild.result = 'SUCCESS'
    } catch (e) {
        currentBuild.result = 'FAILURE'
        
        // 打印错误信息
        def errorMsg = "========================================= 错误信息 START =========================================\n"
        errorMsg += "${e.toString()}\n"
        errorMsg += "========================================= 错误信息 END ========================================="
        echo "${errorMsg}"
        sh 'exit 1'
    } finally {
        if (currentBuild.result == null || currentBuild.result == 'SUCCESS') {
            echo '构建成功'
        } else {
            echo '构建失败'
        }
        // 清空工作空间,notFailBuild: true 设置失败时也清除工作空间
        cleanWs notFailBuild: true
    }
}

bingoogolapple avatar Sep 18 '18 03:09 bingoogolapple

  • 获取 git 仓库名称
git remote -v | grep push | grep origin | awk '{print $2}' | sed 's/.*\///g' | sed 's/.git//g'

bingoogolapple avatar Jan 08 '19 07:01 bingoogolapple