Release tag version

Hello!

I need your help to correctly define the version numbers for my two branches defined in SonarQube cloud.

On some of my projects, we have a develop branch and a master branch. All of our pull requests are made from develop and merged into it. Once our scope is defined, we merge develop into master.

This action will:

  • Define the version number based on the scope (major/minor/bug fixes)
  • Launch the deployment of our stacks for production.

Within our two projects, we therefore have the two branches present, including the master branch as the main branch.

Our problem is as follows: Currently, the version number in SonarCloud is not the one we have. I thought about adding the following code to my GitHub workflow, but I’m not sure if this is the right way to do it…

name: 'Release a new version from master'

on:
    push:
        branches:
            - master

jobs:
    release:
        name: Release
        runs-on: ubuntu-latest
        steps:
            - name: Checkout
              uses: actions/checkout@v4

            - name: Setup Node.js
              uses: actions/setup-node@v3
              with:
                  node-version: 20

            - name: Install dependencies and release
              env:
                  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
                  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
              run: |
                  cd ci
                  yarn install
                  npx semantic-release

            - name: Get new version from the latest tag
              id: get_version
              run: |
                  git fetch --tags
                  VERSION=$(git describe --tags --abbrev=0)
                  echo "NEW_VERSION=$VERSION" >> $GITHUB_OUTPUT

            - name: Update sonar-project.properties
              run: |
                  sed -i "s/sonar.projectVersion=.*/sonar.projectVersion=${{ steps.get_version.outputs.NEW_VERSION }}/" sonar-project.properties

            - name: Commit and Push changes
              run: |
                  git config --global user.name "github-actions[bot]"
                  git config --global user.email "github-actions[bot]@users.noreply.github.com"
                  git add sonar-project.properties
                  git commit -m "chore(release): update sonar version to ${{ steps.get_version.outputs.NEW_VERSION }}"
                  git push

            - name: Cherry-pick to develop
              run: |
                  git fetch origin develop:develop
                  git checkout develop
                  git cherry-pick master
                  git push origin develop

What we want is for pull requests made from develop to only have the code from the PR as new code, and not code from 2-3 months ago…

To do this, I modified my CI, which is launched on each PR, to add this

name: 'Sonarcloud Scan'

on:
  push:
    branches:
      - master
      - develop

jobs:
  sonarcloud:
    runs-on: ubuntu-latest
    env:
      SYMFONY_ENV: test
      php-version: '7.4'
      php-extensions: xml, ctype, intl, pgsql, redis, amqp, gd, imagick
      ext-cache-key: cache-v1 # can be any string, change to clear the extension cache.
    steps:
      - name: Pin node version
        uses: actions/setup-node@v2
        with:
          node-version: '14'

      - uses: actions/checkout@v4

      - name: Load RP CI stack
        env:
          COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
        run: |
          cp ./ci/env_docker.ci ./.env
          cp ./ci/env.ci ./.env.test
          cp ./ci/docker-compose.yml ./docker-compose.test.yml
          docker compose -v
          docker compose -f docker-compose.test.yml up --build -d

      - name: Setup cache environment
        id: extcache
        uses: shivammathur/cache-extensions@v1
        with:
          php-version: ${{ env.php-version }}
          extensions: ${{ env.php-extensions }}
          key: ${{ env.ext-cache-key }}

      - name: Cache extensions
        uses: actions/cache@v4.2.0
        with:
          path: ${{ steps.extcache.outputs.dir }}
          key: ${{ steps.extcache.outputs.key }}
          restore-keys: ${{ steps.extcache.outputs.key }}

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ env.php-version }}
          extensions: ${{ env.php-extensions }}
          tools: composer:v2

      - name: Check running containers
        run: docker compose -f docker-compose.test.yml ps

      - name: Validate composer.json and composer.lock
        run: composer validate

      - name: Get composer cache directory
        id: composercache
        run: echo "::set-output name=dir::$(composer config cache-files-dir)"

      - name: Cache composer dependencies
        uses: actions/cache@v4.2.0
        id: redpill-composer-cache
        with:
          path: 'vendor'
          key: redpill-composer-${{ hashFiles('composer.lock') }}

      - name: Install composer dependencies
        env:
          COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
        if: steps.redpill-composer-cache.outputs.cache-hit != 'true'
        run: composer install --prefer-dist --no-progress --no-suggest --no-scripts --no-interaction

      - name: Control Symfony installation
        run: php bin/console --env=${{ env.SYMFONY_ENV }}

      - name: Run test suite on whole project (with coverage)
        run: composer test-with-coverage

      - name: SonarCloud Scan
        uses: SonarSource/sonarcloud-github-action@v5.0.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Unfortunately, I’m a little lost and I’m having trouble figuring out if my approach is correct or not :confused:

What do you think?

Thank you in advance for your help. :folded_hands:

Hi,

To be honest, I’m a little confused myself. The versions that show up in SonarQube Cloud are set by the sonar.projectVersion analysis property, which I don’t see in your first pipeline snippet.

What I do see is you making and committing changes in the pipeline, which could be a problem, since analysis uses the SCM metadata available in the CI environment to understand what’s “new”.

Okay, that’s a PR analysis. So you’ll want to trigger analysis on pull_request too.

 
HTH,
Ann

Hello,

We have an other github action for our pull requests :

name: 'Validate pull request'

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review, unlocked]
    branches:
      - develop

jobs:
  validation:
    runs-on: ubuntu-latest
    if: github.event.pull_request.draft == false
    env:
      SYMFONY_ENV: test
      php-version: '7.4'
      php-extensions: xml, ctype, intl, pgsql, redis, amqp, gd, imagick
      ext-cache-key: cache-v1 # can be any string, change to clear the extension cache.
    steps:
      - name: Pin node version
        uses: actions/setup-node@v2
        with:
          node-version: '14'

      - uses: actions/checkout@v4

      - name: Load CI stack
        env:
          COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
        run: |
          cp ./ci/env_docker.ci ./.env
          cp ./ci/env.ci ./.env.test
          cp ./ci/docker-compose.yml ./docker-compose.test.yml
          docker compose -f docker-compose.test.yml up --build -d

      - name: Setup cache environment
        id: extcache
        uses: shivammathur/cache-extensions@v1
        with:
          php-version: ${{ env.php-version }}
          extensions: ${{ env.php-extensions }}
          key: ${{ env.ext-cache-key }}

      - name: Cache extensions
        uses: actions/cache@v4.2.0
        with:
          path: ${{ steps.extcache.outputs.dir }}
          key: ${{ steps.extcache.outputs.key }}
          restore-keys: ${{ steps.extcache.outputs.key }}

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ env.php-version }}
          extensions: ${{ env.php-extensions }}
          tools: composer:v2

      - name: Validate composer.json and composer.lock
        run: composer validate

      - name: Install composer dependencies
        env:
          COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
        if: steps.composer-cache.outputs.cache-hit != 'true'
        run: composer install --prefer-dist --no-progress --no-suggest --no-scripts --no-interaction

      - name: Warmup symfony cache
        run: php bin/console --env=${{ env.SYMFONY_ENV }}

      - name: Run unit tests suite on whole project (with coverage)
        run: composer test-with-coverage

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v5.0.0
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

      - name: Get file changes in PR
        id: file_changes
        uses: tj-actions/changed-files@v41
        with:
          separator: ' '
          files: |
            !vendor
            **/*.php

      - name: Run PHP CS Lint on changed files for new files
        if: steps.file_changes.outputs.added_files_count != 0
        run: composer cs-lint ${{ steps.file_changes.outputs.added_files }}

      - name: Run PHP CS Lint on changed files for modified files
        if: steps.file_changes.outputs.modified_files_count != 0
        run: composer cs-lint ${{ steps.file_changes.outputs.modified_files }}

      - name: Run PHP STAN on whole project for new files
        if: steps.file_changes.outputs.added_files_count != 0
        run: vendor/phpstan/phpstan/phpstan analyse --configuration=phpstan.ci.neon --error-format=prettyJson ${{ steps.file_changes.outputs.added_files }}

      - name: Run PHP STAN on whole project for modified files
        if: steps.file_changes.outputs.modified_files_count != 0
        run: vendor/phpstan/phpstan/phpstan analyse --configuration=phpstan.ci.neon --error-format=prettyJson ${{ steps.file_changes.outputs.modified_files }}

  add-tag:
    needs: validation
    runs-on: ubuntu-latest
    if: github.event.pull_request.draft == false
    steps:
      - name: Add release-ready label
        uses: actions-ecosystem/action-add-labels@v1
        with:
          github_token: ${{ secrets.ACTION_GITHUB_TOKEN }}
          labels: release-ready

So we have 3 Github actions :

  • `Validate pull request` for each PR for our develop branch,
  • `Release a new version from master` when we merge develop into master
  • `Sonarcloud Scan` when we push into develop or master

And this is our sonar-project.properties

sonar.projectKey=xxxxx_yyyyy
sonar.organization=xxxxx

sonar.php.coverage.reportPaths=var/reports/tests/coverage-phpunit.xml
sonar.sources=src/
sonar.tests=tests/
sonar.exclusions=src/**/Resources/**

En fait, voici notre façon de travailler :
Nous avons un repository (upstream) que chaque developpeur Ă  forker chez lui (origin). Nous faisons nos pulls requests de chez nous (origin) vers la branch develop (upstream)

Lors de nos nouvelles releases, nous acceptons et mergons les pull requests dans notre branche develop(upstream) puis nous faisons les commandes suivantes :

git checkout develop
git pull upstream develop
git push origin develop
-- now develop origin is ok
git checkout master
git pull upstream master
git push origin master
-- now master is ok
git merge develop
git push origin master
git push upstream master

After this `Release a new version from master` and `Sonarcloud Scan` has trigger. But we want populate sonar.projectVersion with our release tag and no same like

Thanks :slight_smile:

Hi,

Sorry, you lost me here:

It’s not clear to me what you’re trying to accomplish.

 
Ann

arggg ! I forgot to translate :joy:

In fact, this is how we work:

We have a repository (upstream) that each developer has forked at home (origin). We make our pull requests from home (origin) to the develop branch (upstream).

When we release new versions, we accept and merge the pull requests into our develop branch (upstream), then we run the following commands:
.....

society/project (upstream)

  • epsociety/project (origin)
  • axsociete/project (origin for ax)
  • kosociete/project (origin for ko)
  • …

It’s better ? and sorry for my english

Thanks

Hi,

No worries. Your English is better than my (nonexistent) French. :sweat_smile:

And I’m still not clear on what you’re trying to accomplish.

 
Ann

Sorry, I’ll try to rephrase that a little better.

I want the release version made on the upstream/master branch to be:

- Automatically present in my sonar-project.properties file,

- Automatically defined as the reference for detecting new code in SonarQube, even though our development branches are based on the upstream/develop branch.

And I wanted to know if the following proposal was the best one or not at all ^^

name: 'Release a new version from master'

on:
    push:
        branches:
            - master

jobs:
    release:
        name: Release
        runs-on: ubuntu-latest
        steps:
            - name: Checkout
              uses: actions/checkout@v4

            - name: Setup Node.js
              uses: actions/setup-node@v3
              with:
                  node-version: 20

            - name: Install dependencies and release
              env:
                  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
                  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
              run: |
                  cd ci
                  yarn install
                  npx semantic-release

            - name: Get new version from the latest tag
              id: get_version
              run: |
                  git fetch --tags
                  VERSION=$(git describe --tags --abbrev=0)
                  echo "NEW_VERSION=$VERSION" >> $GITHUB_OUTPUT

            - name: Update sonar-project.properties
              run: |
                  sed -i "s/sonar.projectVersion=.*/sonar.projectVersion=${{ steps.get_version.outputs.NEW_VERSION }}/" sonar-project.properties

            - name: Commit and Push changes
              run: |
                  git config --global user.name "github-actions[bot]"
                  git config --global user.email "github-actions[bot]@users.noreply.github.com"
                  git add sonar-project.properties
                  git commit -m "chore(release): update sonar version to ${{ steps.get_version.outputs.NEW_VERSION }}"
                  git push

            - name: Cherry-pick to develop
              run: |
                  git fetch origin develop:develop
                  git checkout develop
                  git cherry-pick master
                  git push origin develop

Sorry again for the inconvenience.

Hi,

Thanks for clarifying!

Ehm… I don’t know of a good way to do that off-hand. And now I understand the commit in your process.

IMO, you’re going to need to look at making that update part of your release process. What exactly that looks like, I’m not sure. Maven has some magic for that, but given that you’re using a sonar-project.properties file, I’m confident that you’re not writing in Java / analyzing with Maven.

You can set a specific analysis within a branch as the New Code reference. You can’t do it automatically, but you can script it.

So after develop is merged back into master, I would run an analysis on both sides and mark that analysis as the New Code baseline on the develop side.

Does that help?

 
Ann

Hello,

Sorry for my late reply, but I’m currently swamped with work. :sweat_smile:

What we’re currently doing is running a Sonar analysis after each merge in develop and master, which is currently redefining our “New Code Baseline.”

However, what I would like to do is pass our version number v{x.y.z} (which is done during the merge in master) to our develop branch via the proposal made in my CI “Release a new version from master.”

The goal of this is to have the same version number between my project and the one in SonarCloud.

Thank you very much, have a great day, and have a good start to the week! :slightly_smiling_face:

Hi,

In case it helps, you can pass the version string on the analysis command line with -D sonar.projectVersion=[my version].

So I suppose you could just edit that permanently into analysis command and pick up the version string from the environment (I believe interpolation will work there).

 
HTH,
Ann

Hello Ann,

Yes, that is indeed possible, but using GitHub actions, I think there are two solutions:

  • Either, as you suggest, pass it when I launch the analysis via Sonar’s GitHub action
            - name: SonarQube Scan
              uses: SonarSource/sonarqube-scan-action@v5.0.0
              env:
                  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
                  SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  • Or try, as I suggest, to retrieve the version number created during my merge into master and pass it to my develop branch.

The purpose of this topic is to find out if other people have already wanted to implement this and if they had an easy solution. Currently, I do have my new code baseline on my develop branch, but it is not iso with my release number, and I would like it to be.

Have a nice day.

1 Like

Hello,

Here’s a quick update on my topic and on my situation.

As a reminder, I wanted to retrieve the release number of my project to pass it on to Sonar in order to ensure consistency between versions.

Our pull requests are made from develop and then merged into it before merging the develop branch into the master branch. When merging into master, a GitHub action is launched to generate the new release number.

Following @ganncamp’s suggestion, I tried to make the version’s number a parameter, but it didn’t work because my develop branch doesn’t know the version’s number created on master.

So I went back to my idea of doing everything during my release creation action, and here is the result:

name: 'Release a new version from master'

on:
  push:
    branches:
      - master

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      -   name: Checkout
          uses: actions/checkout@v3

      -   name: Get composer cache directory
          id: composer-cache
          run: echo "composer_cache_dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

      -   uses: actions/cache@v4
          with:
            path: ${{ steps.composer-cache.outputs.composer_cache_dir }}
            key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
            restore-keys: ${{ runner.os }}-composer-

      -   name: Setup php, extensions and install tools
          uses: shivammathur/setup-php@v2
          with:
            php-version: '8.2'
            extensions: xml, ctype, intl, pgsql, redis, amqp, soap, gd, imagick
            tools: cs2pr, phpstan:2.1.17, php-cs-fixer:3.75.0
            coverage: none

      -   name: Install composer dependencies
          run: composer install --no-progress --prefer-dist --optimize-autoloader --no-scripts --no-dev
          env:
            COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}

      -   name: Setup Node.js
          uses: actions/setup-node@v1
          with:
            node-version: 18

      -   name: Install dependencies
          run: yarn install --frozen-lockfile

      -   name: Release
          env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
            NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          run: npx semantic-release

      - name: Get new version from the latest tag
        id: get_version
        run: |
          git fetch --tags
          VERSION=$(git describe --tags --abbrev=0)
          echo "NEW_VERSION=$VERSION" >> $GITHUB_OUTPUT

      - name: Update sonar-project.properties on master
        run: |
          # Update the file with the new version number
          sed -i "s/sonar.projectVersion=.*/sonar.projectVersion=${{ steps.get_version.outputs.NEW_VERSION }}/" sonar-project.properties

      - name: Create pull request from master to develop (release tag)
        uses: peter-evans/create-pull-request@v7
        with:
            add-paths: |
                sonar-project.properties
            token: ${{ secrets.GITHUB_TOKEN }}
            commit-message: 'chore(release): update sonar version to ${{ steps.get_version.outputs.NEW_VERSION }}'
            title: 'chore: sync SonarQube version to develop'
            body: |
                This PR automatically syncs `sonar-project.properties` from `master` to `develop` after a new release.

                This ensures the SonarQube analysis for `develop` uses the correct project version.
            branch: 'sync/sonar-version-to-develop'
            delete-branch: true
            base: develop
            reviewers: epeliberty

      - name: Update sonar-project.properties on master
        run: |
            # Update the file with the new version number
            sed -i "s/sonar.projectVersion=.*/sonar.projectVersion=${{ steps.get_version.outputs.NEW_VERSION }}/" sonar-project.properties


      - name: Commit and Push the version update on master
        run: |
            git config --global user.name "github-actions[bot]"
            git config --global user.email "github-actions[bot]@users.noreply.github.com"
            git add sonar-project.properties
            git commit -m "chore(release): update sonar version to ${{ steps.get_version.outputs.NEW_VERSION }}" -n
            git push origin master

I am well aware that this is not necessarily the best solution, but it solves my problem until something better comes along :sweat_smile:
I am sharing it in case someone else is in the same situation.

Have a nice day!

1 Like