Code coverage badge and analytics always empty

Summary

No matter what I do I cannot get the coverage badge to show the coverage

https://gitlab.com/timerocket/assistant/public/aws-sns/badges/master/coverage.svg

Here is my pipeline configuration

stages:
  - test
  - docker-build
  - version-push
  - deploy
  - cleanup

variables:
  # The prefix to add to commit messages that only include upgrades of versions
  # Due to the limitations of the workflow expressions. You must also update the workflow rules below if you change this
  # This text is matched with regular expression below. Regex characters such as `[` must be escaped!
  # For more info on the problem see: https://stackoverflow.com/questions/2933474/escape-characters-contained-by-bash-variable-in-regex-pattern
  BUMP_VERSION_MESSAGE: "[bump version]"

  # When a new commit is pushed or merged into master, does that commit get automatically deployed to the development.1 environment
  CD_TO_DEVEOPMENT_1_FROM_MASTER: "true"

  # The prefix to add to each container registry image tag for images that are created for commits. Does not apply to registry tags created for git tags.
  CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX: "commit-"

  # How long container tag that are created for commits will survive. Container registry tags created for git tags will survive forever.
  # Can be in format: `1d` `1h` `1month`
  # See: https://docs.gitlab.com/ee/api/container_registry.html#delete-registry-repository-tags-in-bulk
  CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_LIFETIME: "3month"

# Only run when there is [bump version] in the commit message and rev type is a tag or there is not [bump version] in the commit message
workflow:
  rules:
    - if: $CI_COMMIT_MESSAGE =~ /\[bump version\]/ && $CI_COMMIT_TAG
      when: always
    - if: $CI_COMMIT_MESSAGE =~ /\[bump version\]/ && $CI_COMMIT_BRANCH
      when: never
    - if: $CI_COMMIT_MESSAGE !~ /\[bump version\]/
      when: always

.version-validate: &version-validate
  - >
      echo $CI_PROJECT_ID;
      latest_tag_json=$(curl -X GET --header "Private-Token: $SHARED_CI_ACCESS_TOKEN" "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/repository/tags?per_page=1");
      echo "$latest_tag_json";
      latest_tag_length=$(echo "$latest_tag_json" | jq '. | length');
      latest_tag_name=;
      if (( $latest_tag_length > 0 )); then
        latest_tag_name=$(echo "$latest_tag_json" | jq -r '.[0].name');
        package_version=$(jq -r '.version' app/package.json);
        if [[ "$package_version" != "$latest_tag_name" ]]; then
          echo -e "\e[31mVersion does not match latest tag. Please change version in package.json to '$latest_tag_name'\e[39m";
          exit 1;
        fi;
      fi;

.git-configure: &git-configure
  - echo "$GIT_SSH_PK" | base64 -d > id_rsa
  - chmod 400 id_rsa
  - echo 'ssh -i ./id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $*' > ssh
  - chmod +x ssh
  - git config --global user.name "$GITLAB_USER_NAME"
  - git config --global user.email "$GITLAB_USER_EMAIL"
  - git remote set-url origin git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git

test:
  image: cryptexlabs/ts-node-ci:1.2.0
  stage: test
  allow_failure: false
  except:
    refs:
      - tags
      - schedules
  variables:
    ENV_NAME: ci
  script:
    - *version-validate
    - cd app
    - yarn install
    - yarn lint
    - yarn env-file-validate
    - yarn test:ci
  artifacts:
    paths:
      - app/reports/tests.xml
      - app/coverage/cobertura-coverage.xml
    reports:
      junit: app/reports/tests.xml
      cobertura: app/coverage/cobertura-coverage.xml
  coverage: /Branches\s+:\s(\d+.?\d+)%/

.docker-variables: &docker-variables
  DOCKER_TLS_CERTDIR: ""
  DOCKER_DRIVER: overlay2
  DOCKER_HOST: tcp://docker:2375

docker-build:
  image: cryptexlabs/ts-node-ci:1.2.0
  stage: docker-build
  allow_failure: false
  needs:
    - test
  services:
    - docker:dind
  variables:
    <<: *docker-variables
  except:
    refs:
      - tags
      - schedules
  script:
    - docker build -f docker/Dockerfile --cache-from $CI_REGISTRY_IMAGE:latest . --tag $CI_REGISTRY_IMAGE:$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
    # Don't push docker images for pull requests
    - >
        if [[ $CI_COMMIT_TAG ]] || [[ $CI_COMMIT_BRANCH ]]; then
          docker push $CI_REGISTRY_IMAGE:$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA
        fi

.version-push: &version-push
  image: cryptexlabs/ts-node-ci:1.2.0
  stage: version-push
  needs:
    - test
    - docker-build
  when: manual
  allow_failure: false
  services:
    - docker:dind
  only:
    refs:
      - master
  except:
    refs:
      - schedules
  script:
    - *version-validate
    - *git-configure
    - git checkout master
    - BASE_DIR=$PWD
    - cd app
    - yarn version --$INCREMENT_TYPE --no-git-tag-version --no-commit-hooks
    - version=$(jq -r '.version' package.json)
    - cd $BASE_DIR
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
    - docker pull $CI_REGISTRY_IMAGE:$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:$version
    - docker tag $CI_REGISTRY_IMAGE:$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:latest
    - yq w -i k8s/$CI_PROJECT_NAME/Chart.yaml appVersion "$version"
    - yq w -i k8s/$CI_PROJECT_NAME/values.yaml nodejs.image.tag "$version"
    - git add k8s/$CI_PROJECT_NAME/Chart.yaml k8s/$CI_PROJECT_NAME/values.yaml app/package.json
    - git commit -m "$BUMP_VERSION_MESSAGE $version"
    - git tag $version
    - GIT_SSH='./ssh' git push origin $version
    - GIT_SSH='./ssh' git push origin master
    - docker push $CI_REGISTRY_IMAGE:$version
    - docker push $CI_REGISTRY_IMAGE:latest

patch:
  <<: *version-push
  variables:
    INCREMENT_TYPE: patch
    <<: *docker-variables

minor:
  <<: *version-push
  variables:
    INCREMENT_TYPE: minor
    <<: *docker-variables

major:
  <<: *version-push
  variables:
    INCREMENT_TYPE: major
    <<: *docker-variables

.deploy-script: &deploy-script
  - >
      if [[ -z "$(kubectl get namespace $KUBE_NAMESPACE)" ]]; then
        kubectl create namespace $KUBE_NAMESPACE;
      fi;
  - >
      if [[ -z "$(kubectl get secret gitlab-registry --namespace $KUBE_NAMESPACE)" ]]; then
        kubectl create secret docker-registry gitlab-registry \
        --docker-server=https://registry.gitlab.com \
        --docker-username=$CI_REGISTRY_USER \
        --docker-password=$SHARED_CI_ACCESS_TOKEN \
        --namespace $KUBE_NAMESPACE;
      fi;
  -  helm dep up k8s/$CI_PROJECT_NAME
  - >
      helm upgrade $CI_PROJECT_NAME k8s/$CI_PROJECT_NAME
      --install
      --namespace $KUBE_NAMESPACE
      --values k8s/$CI_PROJECT_NAME/values.yaml
      --values k8s/$CI_PROJECT_NAME/$CI_ENVIRONMENT_NAME.values.yaml
      --set nodejs.annotations.'app\.gitlab\.com/env'=$CI_ENVIRONMENT_SLUG
      --set nodejs.annotations.'app\.gitlab\.com/app'=$CI_PROJECT_PATH_SLUG
      --set nodejs.namespace=$KUBE_NAMESPACE
      --set nodejs.image.tag=$APP_VERSION

.deploy: &deploy
  image:
    name: cryptexlabs/helm-yq:3.2.4
    entrypoint: [""]
  stage: deploy
  allow_failure: false

.rev-deploy: &rev-deploy
  <<: *deploy
  script:
    - yq w -i k8s/$CI_PROJECT_NAME/Chart.yaml appVersion "$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA"
    - APP_VERSION=$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX$CI_COMMIT_SHORT_SHA
    - *deploy-script

.tag-deploy: &tag-deploy
  <<: *deploy
  script:
    - APP_VERSION=$CI_COMMIT_TAG
    - *deploy-script

deploy-development-1-ref:
  <<: *rev-deploy
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: never
    - if: $CI_MERGE_REQUEST_ID
      when: never
    - if: $CI_COMMIT_TAG
      when: never
    - if: $CI_COMMIT_BRANCH == "master" && $CD_TO_DEVEOPMENT_1_FROM_MASTER == "true"
      # Makes continuous deployment to dev environment from master
      when: on_success
    - if: $CI_COMMIT_MESSAGE =~ /\[ship it\]/ && $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "master"
    - when: on_success
    - if: $CI_COMMIT_BRANCH != "master" && $CI_COMMIT_BRANCH
      when: manual
  needs:
    - test
    - docker-build
  environment:
    name: development.1

deploy-development-1:
  <<: *tag-deploy
  # Makes continuous deployment to dev environment from all new tags
  when: on_success
  only:
    refs:
      - tags
  except:
    refs:
      - schedules
  environment:
    name: development.1

deploy-production-1:
  <<: *tag-deploy
  when: manual
  only:
    refs:
      - tags
  except:
    refs:
      - schedules
  environment:
    name: production.1

cleanup-image-tags:
  stage: cleanup
  image: cryptexlabs/ts-node-ci:1.2.0
  rules:
    - if: $SCHEDULE_NAME == 'cleanup-image-tags' && $CI_PIPELINE_SOURCE == "schedule"
      when: on_success
  # Issues regarding "regex" in name_regex_delete https://gitlab.com/gitlab-org/gitlab/-/issues/27072#note_239340436
  # Throttling of bulk delete API: https://gitlab.com/gitlab-org/gitlab/-/issues/32900
  script:
    - >
        registries_json=$(curl -X GET --header "Private-Token: $SHARED_CI_ACCESS_TOKEN" "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/registry/repositories?per_page=1");

        registries_length=$(echo "$registries_json" | jq '. | length');

        if [[ $registries_length > 0 ]]; then
          registry_id=$(echo "$registries_json" | jq -r '.[0].id');
          curl -X DELETE \
          --fail \
          --header "Private-Token: $SHARED_CI_ACCESS_TOKEN" \
          --data "name_regex_delete=^$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_PREFIX.*" \
          --data "older_than=$CONTAINER_REGISTRY_IMAGE_TAG_FOR_COMMIT_LIFETIME" \
          "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/registry/repositories/$registry_id/tags";
        fi;

Here is the badge: coverage report

I can see that the coverage is correctly being captured in the job: enter image description here

I can have the exact same regex in the coverage configuration: enter image description here

I am running the pipeline on the master branch which you can see here: https://gitlab.com/timerocket/assistant/public/aws-sns/-/jobs/655788637

I have tried adding new commits to ensure the coverage gets capture.

I have also disabled colorized output.

Steps to reproduce

Use the above pipeline test step to generate a codecoverage output

Example Project

https://gitlab.com/timerocket/assistant/public/aws-sns

What is the current bug behavior?

No matter what the coverage badge and analytics always show up as unknown

What is the expected correct behavior?

I see the actual code coverage

Relevant logs and/or screenshots

Running with gitlab-runner 13.2.0-rc2 (45f2b4ec)
  on docker-auto-scale ed2dce3a
Preparing the "docker+machine" executor
00:12
Using Docker executor with image cryptexlabs/ts-node-ci:1.2.0 ...
Pulling docker image cryptexlabs/ts-node-ci:1.2.0 ...
Using docker image sha256:fded63d2beb3061687857e18704cbc396ac3e525192c74e893e11cffce5ea928 for cryptexlabs/ts-node-ci:1.2.0 ...
Preparing environment
00:03
Running on runner-ed2dce3a-project-20146310-concurrent-0 via runner-ed2dce3a-srm-1595639223-69495c1c...
Getting source from Git repository
00:02
$ eval "$CI_PRE_CLONE_SCRIPT"
Fetching changes with git depth set to 50...
Initialized empty Git repository in /builds/timerocket/assistant/public/aws-sns/.git/
Created fresh repository.
Checking out 666788ec as master...
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:55
$ echo $CI_PROJECT_ID; latest_tag_json=$(curl -X GET --header "Private-Token: $SHARED_CI_ACCESS_TOKEN" "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/repository/tags?per_page=1"); echo "$latest_tag_json"; latest_tag_length=$(echo "$latest_tag_json" | jq '. | length'); latest_tag_name=; if (( $latest_tag_length > 0 )); then # collapsed multi-line command
20146310
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   724    0   724    0     0   4022      0 --:--:-- --:--:-- --:--:--  4000
[{"name":"0.3.1","message":"","target":"2a5004440e80442c4901cd8df39c2be1a4f7867b","commit":{"id":"2a5004440e80442c4901cd8df39c2be1a4f7867b","short_id":"2a500444","created_at":"2020-07-25T01:02:53.000+00:00","parent_ids":["0a38ff9810da68415532dbf9e062a3803dce64cd"],"title":"[bump version] 0.3.1","message":"[bump version] 0.3.1\n","author_name":"Josh Woodcock","author_email":"ltdwoodcock@gmail.com","authored_date":"2020-07-25T01:02:53.000+00:00","committer_name":"Josh Woodcock","committer_email":"ltdwoodcock@gmail.com","committed_date":"2020-07-25T01:02:53.000+00:00","web_url":"https://gitlab.com/timerocket/assistant/public/aws-sns/-/commit/2a5004440e80442c4901cd8df39c2be1a4f7867b"},"release":null,"protected":false}]
/bin/sh: eval: line 102: 1: not found
$ cd app
$ yarn install
yarn install v1.22.4
[1/4] Resolving packages...
[2/4] Fetching packages...
warning Pattern ["@timerocket/data-model@https://gitlab.com/timerocket/assistant/public/typescript/data-model.git"] is trying to unpack in the same destination "/usr/local/share/.cache/yarn/v6/npm-@timerocket-data-model-0.1.0-c3b15789412c0d96639f28770aed78b98d6c0131/node_modules/@timerocket/data-model" as pattern ["@timerocket/data-model@https://gitlab.com/timerocket/assistant/public/data-model.git"]. This could result in non-deterministic behavior, skipping.
info fsevents@2.1.3: The platform "linux" is incompatible with this module.
info "fsevents@2.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 35.90s.
$ yarn lint
yarn run v1.22.4
$ tslint -p tsconfig.json -c tslint.json
Done in 4.69s.
$ yarn env-file-validate
yarn run v1.22.4
$ env-file-validate
Done in 0.22s.
$ yarn test:ci
yarn run v1.22.4
$ JEST_JUNIT_OUTPUT_NAME=reports/tests.xml jest --ci --coverage --no-colors --reporters=default --reporters=jest-junit --coverageReporters=cobertura --coverageReporters=json-summary --coverageReporters=text --coverageReporters=text-summary
PASS src/app.controller.spec.ts (9.74 s)
  AppController
    notification
      type: Notification
        ✓ should send message to kafka service (5 ms)
        ✓ should return an ok response (4 ms)
      type: SubscriptionConfirmation
        ✓ should confirm the subscription (2 ms)
        ✓ should return an ok response (2 ms)
---------------------------------------|---------|----------|---------|---------|-------------------
File                                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------------------------------|---------|----------|---------|---------|-------------------
All files                              |   85.83 |       75 |      80 |   84.11 |                   
 src                                   |      88 |    66.67 |     100 |   86.36 |                   
  app.controller.ts                    |   82.61 |       50 |     100 |      80 | 55-57,66          
  app.service.ts                       |   91.67 |       75 |     100 |   90.48 | 40-41             
  config.ts                            |     100 |      100 |     100 |     100 |                   
 src/locale                            |     100 |      100 |     100 |     100 |                   
  enum.ts                              |     100 |      100 |     100 |     100 |                   
  locales.ts                           |     100 |      100 |     100 |     100 |                   
 src/notification                      |   93.62 |       75 |    87.5 |   92.86 |                   
  notification-handler.factory.ts      |   91.67 |       50 |     100 |      90 | 20                
  notification.handler.ts              |     100 |      100 |     100 |     100 |                   
  pinpoint-message.ts                  |     100 |      100 |     100 |     100 |                   
  subscription-confirmation.handler.ts |   85.71 |      100 |   66.67 |   84.62 | 18-19             
 src/service                           |   42.86 |      100 |       0 |   33.33 |                   
  kafka.service.ts                     |   42.86 |      100 |       0 |   33.33 | 11-35             
---------------------------------------|---------|----------|---------|---------|-------------------
=============================== Coverage summary ===============================
Statements   : 85.83% ( 103/120 )
Branches     : 75% ( 9/12 )
Functions    : 80% ( 16/20 )
Lines        : 84.11% ( 90/107 )
================================================================================
Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        9.94 s
Ran all test suites.
Done in 10.85s.
Uploading artifacts for successful job
00:04
Uploading artifacts...
app/reports/tests.xml: found 1 matching files and directories 
app/coverage/cobertura-coverage.xml: found 1 matching files and directories 
Uploading artifacts as "archive" to coordinator... ok  id=655788637 responseStatus=201 Created token=CUPgAiYJ
Uploading artifacts...
app/reports/tests.xml: found 1 matching files and directories 
Uploading artifacts as "junit" to coordinator... ok  id=655788637 responseStatus=201 Created token=CUPgAiYJ
Uploading artifacts...
app/coverage/cobertura-coverage.xml: found 1 matching files and directories 
Uploading artifacts as "cobertura" to coordinator... ok  id=655788637 responseStatus=201 Created token=CUPgAiYJ
Job succeeded

Output of checks

This bug happens on GitLab.com

Possible fixes

No idea