在GitLab-CI中动态设置全局变量

19
我希望能够通过读取pom.xml文件来设置一些变量。这些变量需要是全局的,因为它们将在多个阶段和任务中被使用。
根据GitLab-CI文档,有两种不同的方法可以设置全局变量:
1.使用变量语句:
variable:  
 pom_artifactID: $(grep -m1 '<artifactId>' pom.xml | cut -d '<' -f2  |cut -d '>' -f2)
  • 使用“before”脚本:

     before_script:
       - pom_artifactID=$(grep -m1 '<artifactId>' pom.xml | cut -d '<' -f2  |cut -d '>' -f2)
       - pom_artifactVersion=$(grep -m1 '<version>' pom.xml | cut -d '<' -f2  |cut -d '>' -f2)
       - pom_packaging=$(grep -m1 '<packaging>' pom.xml | cut -d '<' -f2  |cut -d '>' -f2)
       - pom_finalName=$({ grep -m1 '<finalName>' pom.xml |  cut -d '<' -f2 | cut -d '>' -f2; [ ${PIPESTATUS[0]} -eq 0 ] && true || echo ${pom_artifactID}-${pom_artifactVersion}.$pom_packaging}; })
    
  • 第一种方法无法工作,因为gitlab-ci不会评估$(command),所以pom_artifactID成为字面意思"$(grep -m1 '' pom.xml | cut -d '<' -f2 |cut -d '>' -f2)"。

    第二种方法也无法工作,因为"before_script"依赖于"grep"命令,而我流程中使用的一些docker镜像具有旧版本的grep。

    还有其他方法来设置全局变量或在阶段和作业之间传递变量吗?

    3个回答

    30

    在作业和阶段之间传递值

    目前GitLab中没有办法在不同阶段或作业之间传递环境变量。
    但是,有一个相关的请求:https://gitlab.com/gitlab-org/gitlab/-/issues/22638

    目前的解决方法是使用artifact文件来传递数据。
    我们曾经遇到相似的问题——从pom.xml获取Java应用程序版本,并将其传递给管道中后续的各个作业。

    以下是我们在.gitlab-ci.yml文件中的具体实现:

    stages:
      - build
      - package
    
    variables:
      VARIABLES_FILE: ./variables.txt  # "." is required for image that have sh not bash
    
    get-version:
      stage: build
      script:
        - APP_VERSION=... # $CI_COMMIT_TAG
        - echo "export APP_VERSION=$APP_VERSION" > $VARIABLES_FILE
      artifacts:
        paths:
          - $VARIABLES_FILE
    package:
      stage: package
      script:
        - source $VARIABLES_FILE
        - echo "Use env var APP_VERSION here as you like ..."
    
    

     
     

    pom.xml文件中提取数值

    顺便说一句,最好把xml.pom视为XML来从pom.xml中提取值,而不是使用普通的grep命令,因为XML元素可能跨越多行。

    至少有几个选项可供选择,例如:

    1. libxml2-utils中使用xmllint工具中的XPath表达式。
    get-version:
      image: ubuntu
      script:
        - apt-get update
        - apt-get install -y libxml2-utils
        - APP_VERSION=`xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' $POM_FILE`
    
    1. 使用 python 处理XML
    get-version:
      image: python3
      script:
        - APP_VERSION=$(python3 -c "import xml.etree.ElementTree as ET; print(ET.parse(open('pom.xml')).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)")
    

    pom.xml中提取值也可以使用_mvn_命令本身来实现,只需借助_maven-help-plugin_插件的一点帮助,即APP_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) - undefined

    4

    我还使用过另一种选项。您可以在CI / CD设置中设置变量,然后从作业内部发出PUT请求返回到API,将它们设置为要在作业之间共享的值。

    script:
    - >- 
      curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_PROJ_TOKEN" 
      "https://someinstance.gitlab.com/api/v4/projects/$CI_PROJECT_ID/variables/MY_VARIABLE"
      --form "value=0"
    

    在上面的示例中,它调用了一个自定义的gitlab实例,我还在项目中定义了一个名为GITLAB_PROJ_TOKEN的项目访问令牌。我的变量名是MY_VARIABLE。

    2
    自从GitLab 13.0版本以来,可以将变量保存在dotenv文件格式中,并在其他阶段加载。
    build-job:
      stage: build
      script:
        - echo "BUILD_VARIABLE=value_from_build_job" >> build.env
      artifacts:
        reports:
          dotenv: build.env
    
    test-job:
      stage: test
      script:
        - echo "$BUILD_VARIABLE"  # Output is: 'value_from_build_job'
    

    仍然与接受的答案非常相似,但现在在新的阶段/作业开始之前不需要显式加载带有变量的文件,但如果你想要的话,可以使用needsdependencies关键字来实现。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接