使用Spring Boot设置GitLab CI/CD管道 - Marcus


当我们将项目放在 GitLab 存储库中时,我们需要做的第一件事。我们需要创建一个.gitlab-ci.yml来初始化管道:

# Adding workflow rules to avoid other branches to use the pipeline 
# since we only want to use the master branch
workflow:
  rules:
    - if: $CI_COMMIT_TAG
      when: never
    - if: $CI_COMMIT_BRANCH == 'master'

variables:
  IMAGE_OPENJDK_GRADLE: gradle:7.3.3-jdk17-alpine

stages:
  - clean
  - build
  - test
  - build-image
  - publish-image
  - deploy

clean:
  image: $IMAGE_OPENJDK_GRADLE
  stage: clean
  script:
    - echo "Cleaning leftovers from previous builds"
    - sh $CI_PROJECT_DIR/gradlew clean

build:
  image: $IMAGE_OPENJDK_GRADLE
  stage: build
  script:
    - echo "Compiling the code..."
    - sh $CI_PROJECT_DIR/gradlew assemble
  artifacts:
    paths:
      - build/libs/blog-*.war

static-code-analysis:
  image: $IMAGE_OPENJDK_GRADLE
  stage: test
  script:
    - echo "Running Static Code Analysis..."
    - echo "Checking style..."
    - sh $CI_PROJECT_DIR/gradlew checkstyleMain
    - echo "Checking duplicated code..."
    - sh $CI_PROJECT_DIR/gradlew cpdCheck
    - echo "Checking bugs..."
    - sh $CI_PROJECT_DIR/gradlew spotbugsMain
    - echo "Checking code standard..."
    - sh $CI_PROJECT_DIR/gradlew pmdMain

unit-test:
  image: $IMAGE_OPENJDK_GRADLE
  stage: test
  script:
    - echo "Running unit tests..."
    - sh $CI_PROJECT_DIR/gradlew test -Dspring.profiles.active=test

coverage-test:
  image: $IMAGE_OPENJDK_GRADLE
  stage: test
  needs:
    - job: unit-test
  script:
    - echo "Running coverage tests..."

build-image:
  stage: build-image
  script:
    - echo "Building Docker Image..."
    - docker build -t $CI_REGISTRY/mjovanc/blog-api:$CI_COMMIT_SHORT_SHA .
    - docker build -t $CI_REGISTRY/mjovanc/blog-api:latest .

publish-image:
  stage: publish-image
  script:
    - echo "Publishing Docker Image..."
    - docker login -u mjovanc -p $MJOVANC_CONTAINER_REGISTRY_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY/mjovanc/blog-api:$CI_COMMIT_SHORT_SHA
    - docker push $CI_REGISTRY/mjovanc/blog-api:latest

# Alternative down stream pipeline to be triggered
deploy:
#  stage: deploy
#  trigger: mjovanc/blog-iac

 
以下是上述配置解释:
1. 首先,我们定义工作流workflow规则,只有当新的代码进入主分支时,我们才进行构建。这样我们就可以推送功能分支,即使它们处于失败的状态,也可以在上面工作。这样我们就不需要每次都去构建,也不需要在构建后推送到容器注册表。

workflow:
  rules:
    - if: $CI_COMMIT_TAG
      when: never
    - if: $CI_COMMIT_BRANCH == 'master'

也许你可以删除它并设置检查器,如果不在主分支上,我们将在构建和测试后跳过其他阶段。但现在我们将使用它所定义的阶段。

2. 然后,我们定义一个变量,其中包含将用于构建我们的应用程序的Docker镜像,这将是带有OpenJDK17的Gradle。
variables:IMAGE_OPENJDK_GRADLE: gradle:7.3.3-jdk17-alpine
 
3. 然后我们定义这个管道中的所有阶段。这个阶段是clean、构建、测试、构建镜像(docker)、发布镜像(docker)和部署。我们在底部注释掉deploy,因为它不会工作,因为我们现在没有其他管道。我们将只通过它,以便我们知道如何触发另一个管道,来完成部署我们的容器的工作。

stages:
  - clean
  - build
  - test
  - build-image
  - publish-image
  - deploy


你可以添加另一条管道,使用Kubernetes进行部署,或者使用Ansible在服务器上手动部署。

4. 在每个作业上,我们都会定义它应该与哪个阶段连接。

clean:
  image: $IMAGE_OPENJDK_GRADLE
  stage: clean
  script:
    - echo "Cleaning leftovers from previous builds"
    - sh $CI_PROJECT_DIR/gradlew clean

我们也有一个脚本定义,应该在GitLab运行器上执行。
GitLab有共享的、群组的或特定的运行器,我们可以使用。如果我们需要比GitLab提供的更多的CPU、内存等或软件,我们可以建立自己的运行器。但现在我们将使用自动添加的共享GitLab运行器。非常方便!
 
5. 你可以看到在GitLab的流水线配置中,我们有一个叫做 "needs "的配置项,它告诉流水线,在另一项工作完成之前,这个阶段不能运行。在这个例子中,我们不会在单元测试通过之前运行覆盖率测试。如果我们把许多工作放在同一个阶段,就像我们在阶段测试中做的那样,它将并行运行。所以它将尝试在同一时间做所有的工作。
coverage-test:
  image: $IMAGE_OPENJDK_GRADLE
  stage: test
  needs:
    - job: unit-test
  script:
    - echo "Running coverage tests..."

 
6. 为了构建docker镜像,我们需要进行如下配置。

build-image:
  stage: build-image
  script:
    - echo "Building Docker Image..."
    - docker build -t $CI_REGISTRY/mjovanc/blog-api:$CI_COMMIT_SHORT_SHA .
    - docker build -t $CI_REGISTRY/mjovanc/blog-api:latest .

我们使用docker命令在当前目录下构建,并寻找我们的Docker文件,我们通过内置的环境变量$CI_REGISTRY来标记它,并添加company/organization/user和应用程序的名称。

我们还添加了提交的SHA256哈希值(短版本,不是完整的值),这样我们就可以有一个唯一的构建ID。

然后,我们还建立了第二个镜像,但使用latest作为ID,所以如果我们只是想抓取最新的版本,我们总是可以拉到那个镜像。如果需要回滚,我们仍然有旧的构建,所以我们可以回到早期的提交。
  
7. 然后我们只需将新构建的镜像推送到GitLab容器注册中心即可。

publish-image:
  stage: publish-image
  script:
    - echo "Publishing Docker Image..."
    - docker login -u mjovanc -p $MJOVANC_CONTAINER_REGISTRY_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY/mjovanc/blog-api:$CI_COMMIT_SHORT_SHA
    - docker push $CI_REGISTRY/mjovanc/blog-api:latest

 
8. 最后,我们添加一个部署阶段,将触发另一个管道的运行(可选)。

deploy:
  stage: deploy
  trigger: mjovanc/blog-iac


 
为了使这个管道工作,我们需要在GitLab中添加一些配置。我们首先需要生成一个个人访问令牌。你可以在右上角你的个人资料图片的地方选择偏好preferences。然后导航到访问令牌,把名字写成MJOVANC_CONTAINER_REGISTRY_TOKEN,然后选择api,read_registry,write_registry。
 
现在我们的管道可以通过.gitlab-ci.yml文件中的变量获得该令牌,并能够推送新构建的镜像。
我们可以在侧边栏 Packages & Registries > Container Registry下找到我们所有的镜像(最新的在最后一页,每当我们做新的推送时它就会更新)。
 
源码: https://github.com/mjovanc/medium-gitlab-cicd-springboot