如何编写 .gitlab-ci.yml 以根据条件构建/部署

时间:2021-03-12 17:56:21

标签: gitlab

我是 CI/CD 和 Gitlab 的新手。我有一个 CI/CD 脚本来测试、构建和部署,我使用 2 个分支和 2 个 EC2。我的目标是有一个轻量级而不是冗余的脚本来构建和部署我对分支功能的更改。 目前我的脚本看起来像这样,但在查看 Gitlab 文档后,我看到了许多条件关键字,例如 rules,但我真的不知道如何在脚本中使用条件格式来优化它。

如果从一个分支或另一个分支合并,有没有办法使用条件并运行一些脚本?提前致谢!

#image: alpine

image: "python:3.7"

before_script:
  - python --version

stages:
  - test
  - build_staging
  - build_prod
  - deploy_staging
  - deploy_prod

test:
  stage: test
  script:
    - pip install -r requirements.txt
    - pytest Flask_server/test_app.py
  only:
    refs:
      - develop

build_staging:
  stage: build_staging
  image: node
  before_script:
    - npm install -g npm
    - hash -d npm
    - nodejs -v
    - npm -v
  script:
    - cd client
    - npm install
    - npm update
    - npm run build:staging
  artifacts:
    paths:
    - client/dist/
    expire_in: 30 minutes
  only:
    refs:
      - develop

build_prod:
  stage: build_prod
  image: node
  before_script:
    - npm install -g npm
    - hash -d npm
    - nodejs -v
    - npm -v
  script:
    - cd client
    - npm install
    - npm update
    - npm run build
  artifacts:
    paths:
    - client/dist/
    expire_in: 30 minutes
  only:
    refs:
      - master

deploy_staging:
  stage: deploy_staging
  image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # gitlab image for awc cli commands
  before_script:
    - apt-get update
    # - apt-get -y install python3-pip
    # - apt-get --assume-yes install awscli
    - apt-get --assume-yes install -y shellcheck
  script:
    - shellcheck .ci/deploy_aws_STAGING.sh
    - chmod +x .ci/deploy_aws_STAGING.sh
    - .ci/deploy_aws_STAGING.sh
    - aws s3 cp client/dist/ s3://......./ --recursive
  only:
    refs:
      - develop

deploy_prod:
  stage: deploy_prod
  image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # gitlab image for awc cli commands
  before_script:
    - apt-get update
    # - apt-get -y install python3-pip
    # - apt-get --assume-yes install awscli
    - apt-get --assume-yes install -y shellcheck
  script:
    - shellcheck .ci/deploy_aws_PROD.sh
    - chmod +x .ci/deploy_aws_PROD.sh
    - .ci/deploy_aws_PROD.sh
    - aws s3 cp client/dist/ s3://........../ --recursive
  only:
    refs:
      - master

1 个答案:

答案 0 :(得分:0)

随着 cicd 变得越来越复杂,一个好的模式是使用包含和扩展关键字。例如,您可以在根级别 .gitlab-ci.yml 文件中实现以下内容:

# best practice is to pin to a specific version of node or build your own image to avoid surprises
image: node:12

# stages don't need an environment appended to them; you'll see why in the included file
stages:  
  - build
  - test
  - deploy

# cache node modules in between jobs on a per branch basis like this
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm/

# include other definitions
includes:
  - './ci-templates/.foo-app-ci.yml'

然后在另一个文件夹(甚至另一个存储库)中,您可以包含其他模板。我没有为您完全重构它,但我希望这不仅能让您了解如何使用规则来触发您的工作,还能让您了解如何开始制作可重用的片段并在它们的基础上构建以降低整体复杂性。有关我为什么以某种方式做事的指导,请参阅 yaml 评论。示例 .foo-app-ci.yml 文件

# this script was repeated so define it once and reference it via anchor
.npm:install: &npm:install
  - npm ci --cache .npm --prefer-offline # to use the cache you'll need to do this before installing dependencies
  - cd client
  - npm install
  - npm update

# you probably want the same rules for each stage.  define once and reuse them via anchor
.staging:rules: &staging:rules
  - if: $CI_COMMIT_TAG
    when: never                                  # Do not run this job when a tag is created manually
  - if: $CI_COMMIT_BRANCH == 'develop'           # Run this job when commits are pushed or merged to the develop branch

.prod:rules: &prod:rules
  - if: $CI_COMMIT_TAG
    when: never                                  # Do not run this job when a tag is created manually
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  # Run this job when commits are pushed or merged to the default branch

# many parts of the build stage were repeated; define it once and lets extend from it
.build:template: &build:template
  stage: build
  before_script:
    - &npm:install
  artifacts:
    paths:
    - client/dist/
    expire_in: 30 minutes

# many parts of the deploy stage were repeated; define it once and lets extend from it
.deploy:template: &deploy:template
  stage: deploy
  image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # gitlab image for awc cli commands
  before_script:
    - apt-get update
    - apt-get --assume-yes install -y shellcheck

# here we extend from the build template to run the staging specific build
build:staging:
  extends: *build:template
  environment: staging
  script:
    - npm run build:staging
  rules:
    - *staging:rules

# this is kind of an oddball... not used to seeing python to test a node app.  we're not able to reuse as much here
test:staging:
  image: "python:3.7"
  stage: test
  script:
    - pip install -r requirements.txt
    - pytest Flask_server/test_app.py
  rules:
    - *staging:rules      # apply staging rules to trigger test stage
  needs:
    - job: build:staging  # normally we want to build before test;  this will trigger test after the build

# here we extend from the build template to run the prod specific build
build:prod:
  extends: *build:template
  environment: prod
  script:
    - npm run build
  rules:
    - *prod:rules

# same thing for the deploy phases... extend from the deploy template for env specific requirements
deploy:staging:
  extends: *deploy:template
  script:
    - shellcheck .ci/deploy_aws_STAGING.sh
    - chmod +x .ci/deploy_aws_STAGING.sh
    - .ci/deploy_aws_STAGING.sh
    - aws s3 cp client/dist/ s3://......./ --recursive
  rules:
    - *staging:rules
  needs:
    - job: build:staging
      artifacts: true

deploy:prod:
  extends: *deploy:template
  script:
    - shellcheck .ci/deploy_aws_PROD.sh
    - chmod +x .ci/deploy_aws_PROD.sh
    - .ci/deploy_aws_PROD.sh
    - aws s3 cp client/dist/ s3://........../ --recursive
  rules:
    - *prod:rules
  needs:
    - job: build:prod
      artifacts: true

我会从基础开始,当您开始熟悉工作流程时,您可以尝试进一步增强并分解成更多片段。希望这会有所帮助!

相关问题