【问题标题】:GitLab CI preserve environment between build stagesGitLab CI 在构建阶段之间保留环境
【发布时间】:2016-12-16 15:10:46
【问题描述】:

我正在开发一个 python 项目并使用miniconda 来管理我的环境。我正在使用具有以下运行器配置的 GitLab 进行 CI

stages:
  - build
  - test 

build:
  stage: build
  script:
    - if hash $HOME/miniconda/bin/conda 2>/dev/null; 
      then
         export PATH="$HOME/miniconda/bin:$PATH";
      else
        wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
        bash miniconda.sh -b -p $HOME/miniconda;
        export PATH="$HOME/miniconda/bin:$PATH";
      fi
    - conda update --yes conda

test:
  stage: test
  script:
    - conda env create --quiet --force --file environment.yml
    - source activate myenv
    - nosetests --with-coverage --cover-erase --cover-package=mypackage --cover-html
    - pylint --reports=n tests/test_final.py
    - pep8 tests/test_final.py
    - grep pc_cov cover/index.html | egrep -o "[0-9]+\%" | awk '{ print "covered " $1;}'

我假设(错误地)我的build 阶段会设置正确的环境,我可以在其中运行我的test 阶段。看着this questionthis GitLab issue 我明白了

.gitlab-ci.yml 中定义的每个作业都作为单独的构建运行(我们 假设没有历史)

但是将所有内容集中在一个阶段的替代方法并不吸引人

stages:
  - test 

test:
  stage: test
  script:
    - if hash $HOME/miniconda/bin/conda 2>/dev/null; 
      then
         export PATH="$HOME/miniconda/bin:$PATH";
      else
        wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
        bash miniconda.sh -b -p $HOME/miniconda;
        export PATH="$HOME/miniconda/bin:$PATH";
      fi
    - conda update --yes conda
    - conda env create --quiet --force --file environment.yml
    - source activate myenv
    - nosetests --with-coverage --cover-erase --cover-package=mypackage --cover-html
    - pylint --reports=n tests/test_final.py
    - pep8 tests/test_final.py
    - grep pc_cov cover/index.html | egrep -o "[0-9]+\%" | awk '{ print "covered " $1;}'

我能想到的唯一其他选择是将环境创建步骤放在before_script 阶段,但在每个阶段之前不断重新创建相同的环境似乎是多余的。

【问题讨论】:

    标签: gitlab gitlab-ci gitlab-ci-runner


    【解决方案1】:

    您可以将常用命令放在before_script 下。它将应用于所有子阶段。这样,你就不需要重复你的代码了。

    您可以使用以下内容:

    stages:
      - build
      - test
      - deploy 
    
    before_script:
      - if hash $HOME/miniconda/bin/conda 2>/dev/null; 
          then
             export PATH="$HOME/miniconda/bin:$PATH";
          else
            wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
            bash miniconda.sh -b -p $HOME/miniconda;
            export PATH="$HOME/miniconda/bin:$PATH";
          fi
        - conda update --yes conda
    
    build:
      stage: build
      script:
        - << Your build script >>
    
    test:
      stage: test
      script:
        - conda env create --quiet --force --file environment.yml
        - source activate myenv
        - nosetests --with-coverage --cover-erase --cover-package=mypackage --cover-html
        - pylint --reports=n tests/test_final.py
        - pep8 tests/test_final.py
        - grep pc_cov cover/index.html | egrep -o "[0-9]+\%" | awk '{ print "covered " $1;}'
    
    deploy:
      stage: deploy
      before_script:
        - << Override to global before_script >>
        - << DO something else >>
    

    【讨论】:

      【解决方案2】:

      您可以使用artifacts 在构建阶段之间传递文件。

      但是,如果共享部分是环境内容(即不是您编写的代码),那么您可能应该使用缓存。

      【讨论】:

        【解决方案3】:

        工作的独立性是一种设计特征。您可能已经注意到 GitLab 的界面允许您重新运行单个作业,如果作业相互依赖,这是不可能的。

        我不知道 Miniconda 究竟执行了什么,但如果它在特定文件夹中构建虚拟环境,您可以使用 cache 在作业之间保留这些文件夹的内容。但是,您不能完全依赖它,因为文档指出...

        缓存是尽最大努力提供的,所以不要期望 缓存将始终存在。实现细节请查看 GitLab Runner。

        考虑到您的工作完全取决于正在构建的环境,您需要一种机制来检测(缓存的)环境是否存在并仅在需要时重新创建它。

        我认为您正在尝试将环境设置和作业分开的好方法,因为如果您决定有一天运行不同的测试同时,它可能会节省大量时间>(同一阶段的作业并行运行)。

        【讨论】:

        • 请注意,Gitlab 的更新文档中缺少上述警告
        猜你喜欢
        • 2019-04-26
        • 2021-10-29
        • 2023-03-22
        • 2016-01-29
        • 1970-01-01
        • 2022-11-14
        • 1970-01-01
        • 1970-01-01
        • 2012-08-18
        相关资源
        最近更新 更多