20

I'm using Gitlab and Sonarqube and the Sonarqube Plugin SVG Badges.
To represent the Sonarqube state on gitlab I have something like this in my README.md file:

[![coverage](https://sonar.domain.com/api/badges/measure?key=com.domain:projectname&metric=coverage)](https://sonar.domain.com/component_measures/metric/coverage/list?id=de.domain:projectname)

This works perfect. My badge is shown, the link is working, everything is fine.

Is there some way to build something like:

[![coverage](https://sonar.domain.com/api/badges/measure?key={MYDOMAIN}:{THIS}&metric=coverage)](https://sonar.domain.com/component_measures/metric/coverage/list?id={MYDOMAIN}:{THIS})

I want to provide a skeleton that every Developer just can copy and paste into their README.md file and the variables are filled into the README automatically, with something like .gitlab-ci.yml

I also tried the permanent Gitlab Variables mentioned here but that wasn't working too!

 [![coverage](https://sonar.domain.com/api/badges/measure?key=com.mydomain:$CI_PROJECT_NAME&metric=coverage)](https://sonar.domain.com/component_measures/metric/coverage/list?id={MYDOMAIN}:$CI_PROJECT_NAME)

Anyone has some idea?

Joergi
  • 1,527
  • 3
  • 39
  • 82

2 Answers2

12

The variables in https://gitlab.com/help/ci/variables/README.md are present only in a CI environment (i.e. a job), so you can't use them in the Markdown viewer when displaying the file. - That's a great idea for a feature proposal, though. I opened one - https://gitlab.com/gitlab-org/gitlab-ce/issues/32255. Feel free to chime in.

What you could do is add a placeholder where you want those variables to go and then create a job which sed's them.

update_readme:
  script:
    - echo $CI_PROJECT_NAME # Sanity check
    - sed -ie "s/{THIS}/$CI_PROJECT_NAME/g" README.md

Note the use of double-quotes (") and not single quotes ('). Using double-quotes will interpolate $CI_PROJECT_NAME while single-quotes would just retain it's literal value.

Elgayed
  • 1,129
  • 9
  • 16
matteeyah
  • 855
  • 11
  • 24
  • but is the `README.me` than really the one I should see? because it's not really changing some content... so i used something like: `[![coverage](https://sonar.domain.com/api/badges/measure?key=com.mydomain:${THIS}&metric=coverage)](https://sonar.domain.com/component_measures/metric/coverage/list?id=com.mydomain:${THIS})` and your script – Joergi May 15 '17 at 17:00
  • a `cat README.md` is showing the correct version aber this is (of course) not showing in the Gitlab – Joergi May 15 '17 at 17:03
  • I marked the question as correct and give you the bounty, because I see that this could be a way to the solution. but still: the `README.md` is of course not replaced in the gitlab. And if i commit it automatically, than the original is gone... so not a good idea. Also with the normal README and a template file, it will still make some confusion for developers, which Readme should be edited... any Idea @Rex ? – Joergi May 17 '17 at 08:48
  • 1
    @Joerg you could have a `README_TEMPLATE.md` file, edit the placeholder in that file and output the result into `README.md`. To avoid duplication you can also put a guard clause at the beginning of the script, which ends it if there's already a `README.md` in it. – matteeyah May 18 '17 at 18:50
  • The issue on gitlab has unfortunately been automatically closed when they moved everything to the new repo. This seems to be a similar one: https://gitlab.com/gitlab-org/gitlab/-/issues/14389 – Philzen Feb 11 '22 at 02:30
2

IMPORTANT!

You should implement a branch/logic to avoid triggering the .gitlab-ci.yml in an infinite loop because you are asking to update a repository file from the CI itself

The approach is:

  1. Prepare README.md with special delimiters around the badge
  2. Substitute old/initial badge by payload (you should build it, not shown here) in the repository loaded README.md
  3. urlencode the substituted content
  4. Update the repository with the Gitlab API

README.md

Hello
[//]: # (-- start --)
Initial non working badge
[//]: # (-- end --)
World

.gitlab-ci.yml

update_readme:
  script:
  - curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/README%2Emd?branch=master&content=$(urlencode "$(sed 's_\[//\]: # (-- end --)_\n&_g;s_\(\[//\]: # (-- start --)\)[^\n]*\n_\1\npayload\n_g' README.md)")&commit_message=update%20file'

In sed command, substitute payload with your actual badge (you should build it, not shown here)

  • The solution is to write the README.md using the Update existing file in repository API
  • The README.md should use the special string delimiters that do not appear rendered (they are like hidden comments). These delimiters are always in the file, they do not get substituted. Only what it is in between them get subtituted. This way you can automatically update the badge each time you run the .gitlab-ci.yml (only the badge get updated)
  • The substitution is done by the sed command so you need to add the path to the README.md
  • The update API needs the content to be urlencoded (so the sed command is wrapped by a bash urlencode() function that should be loaded first (loading not shown):

urlencode()

urlencode() {
    # urlencode <string>
    old_lc_collate=$LC_COLLATE
    LC_COLLATE=C

    local length="${#1}"
    for (( i = 0; i < length; i++ )); do
        local c="${1:i:1}"
        case $c in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            *) printf '%%%02X' "'$c" ;;
        esac
    done

    LC_COLLATE=$old_lc_collate
}

Notes: The [//]: # (-- start --) does not affect the render of your README.md so you can use it like hidden comments

Replace your private token with a Gitlab CI Secret variable

elingerojo
  • 354
  • 2
  • 6