Sonarcloud 显示新代码的覆盖率为 0%,并且还显示 gitlab 的 master 分支的覆盖率为 0% ci

Sonarcloud shows 0% coverage on new code, and also shows 0% coverage on master branch with gitlab ci

我正在使用GitLabci对代码进行运行SonarCloud代码分析

这是我的gitlab-ci.yaml

stages:
  - test

before_script:
  - mkdir -p ~/.ssh &&
    cp $gitlab_private_key ~/.ssh/id_ed25519 &&
    chmod 600 ~/.ssh/id_ed25519 &&
    touch ~/.ssh/known_hosts &&
    ssh-keyscan gitlab.com >> ~/.ssh/``known_hosts

variables:
  SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
  GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
  GITLAB_PROJECT_ID: ${CI_PROJECT_ID} # needed to be exported to the project's environments
  FLASK_APP: manage.py

sonarcloud-check:
  image:
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script:
    - sonar-scanner
  only:
    - merge_requests
    - master

test-merge-request-changes:
  stage: test
  only:
    - merge_requests
  image:
    name: docker:19.03.13-git
  services:
    - name: docker:19.03.0-dind
      entrypoint: ["env", "-u", "DOCKER_HOST"]
      command: ["dockerd-entrypoint.sh"]
  variables:
    DOCKER_HOST: tcp://localhost:2375
    DOCKER_TLS_CERTDIR: ""
    DOCKER_DRIVER: overlay2
    ENV: test
    CI_DEBUG_TRACE: "true"
  before_script:
    - echo $CI_BUILD_TOKEN | docker login -u gitlab-ci-token --password-stdin ${CI_REGISTRY}
  script:
    - echo "Running Tests..."
    - cp ${group_shared_vars} ${CI_PROJECT_DIR}/.env
    - docker build . -f Dockerfile-testing -t test_merge_req --build-arg GITLAB_PROJECT_ID=${GITLAB_PROJECT_ID}
    - docker run --cidfile="my-package.txt" test_merge_req:latest

  after_script:
    - touch text2.txt
    - docker cp $(cat my-package.txt):/app/tests/coverage/coverage.xml coverage.xml
    - docker cp $(cat my-package.txt):/app/tests/coverage/junit.xml junit.xml
  timeout: 2h
  artifacts:
    when: always
    reports:
      cobertura:
        - coverage.xml
      junit:
        - junit.xml
  coverage: '/TOTAL.*\s+(\d+%)$/'

这是我的 sonar-project.properties

sonar.projectKey=my_app-key
sonar.organization=my_org

sonar.sources=lib
sonar.tests=tests
sonar.exclusions=tests
sonar.language=python
sonar.python.version=3.8

我想获取在每个合并请求上由 sonarcloud 分析的容器中生成的报告。

另外,当一个代码被推送到master分支时,我想获取要更新的项目在sonarcloud上的覆盖率,但它只显示0%。

有没有办法在合并请求运行之后,我们得到docker容器的报告上的sonarcloud分析?

并且无需将 coverage.xml 提交到存储库就可以更新主分支覆盖范围?

在深入研究了 Gitlab CI 阶段和作业的工作方式以及 this thread 带来的洞察力之后,我对上面的 GitLab ci 进行了调整,以便它:

  1. 首先运行测试
  2. 然后将覆盖率输出上传到为工件
  3. 指定的路径ci
  4. 然后在下一阶段,它会拉取那些工件
  5. sed命令替换<source>...</source>中被pytest-cov替换的path。 (此步骤是由于放置到源元素中的路径与 docker 容器相关,然后在下载覆盖率报告后无法在 GitLab ci 容器内工作)
  6. 运行 覆盖率报告中的 sonar-scanner

GitLab ci:

stages:
  - build_test
  - analyze_test

before_script:
  - mkdir -p ~/.ssh &&
    cp $gitlab_private_key ~/.ssh/id_ed25519 &&
    chmod 600 ~/.ssh/id_ed25519 &&
    touch ~/.ssh/known_hosts &&
    ssh-keyscan gitlab.com >> ~/.ssh/``known_hosts

variables:
  SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
  GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
  GITLAB_PROJECT_ID: ${CI_PROJECT_ID} # needed to be exported to the projects environments

include:
  - template: Code-Quality.gitlab-ci.yml

test-merge-request:
  stage: build_test
  only:
    - merge_requests
    - master
  image:
    name: docker:19.03.13-git
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - build
  services:
    - name: docker:19.03.0-dind
      entrypoint: ["env", "-u", "DOCKER_HOST"]
      command: ["dockerd-entrypoint.sh"]
  variables:
    DOCKER_HOST: tcp://localhost:2375
    DOCKER_TLS_CERTDIR: ""
    DOCKER_DRIVER: overlay2
    ENV: test
    CI_DEBUG_TRACE: "true"
  before_script:
    - echo $CI_BUILD_TOKEN | docker login -u gitlab-ci-token --password-stdin ${CI_REGISTRY}
  script:
    - echo "Running Tests..."
    - cp ${group_shared_vars} ${CI_PROJECT_DIR}/.env
    - docker build . -f Dockerfile-testing -t test_merge_req --build-arg GITLAB_PROJECT_ID=${GITLAB_PROJECT_ID}
    - docker run --cidfile="my-package.txt" test_merge_req:latest
  after_script:
    - docker cp $(cat my-package.txt):/app/tests/coverage/coverage.xml build/coverage.xml
    - docker cp $(cat my-package.txt):/app/tests/coverage/junit.xml build/junit.xml
  timeout: 2h
  artifacts:
    when: always
    paths:
      - build
    reports:
      cobertura:
        - build/coverage.xml
      junit:
        - build/junit.xml
    expire_in: 30 min
  coverage: '/TOTAL.*\s+(\d+%)$/'

sonarcloud-check:
  stage: analyze_test
  image:
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script:
    - echo "Logging coverage..."
    - sed -i "s|<source>\/app\/my_app<\/source>|<source>$CI_PROJECT_DIR\/my_app<\/source>|g" ./build/coverage.xml
    - sonar-scanner
  only:
    - merge_requests
    - master
  dependencies:
    - test-merge-request-changes

从我的问题中得出的结论是,Gitlab 不会在一个 GitLab ci 阶段中的作业之间共享工件,而是在不同阶段之间共享它们。

所以,我刚刚创建了两个独立的阶段,一个用于构建测试 (build_test),一个用于分析测试 (analyze_test)。然后,使 sonnar-cloud 作业依赖于 test-merge-request-changes 作业。这样,我们确保首先在 test-merge-request-changes 中运行测试,然后在 sonar-cloud 阶段使用上传的工件。