0

I've got a Github Action that runs SonarQube scanner:

- name: SonarQube analysis
  continue-on-error: true
  shell: bash
  run: |
    sonar-scanner \
      -Dsonar.cfamily.build-wrapper-output=bw-output
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}

Mostly this works fine, but sometimes it throws an exception because of a hash/checksum error on a downloaded file. I can rerun the action and it'll usually work but because the build takes a while I'd rather rerun just this step.

I tried using Retrying a bash command - Meziantou's blog and removing the continue-on-error: true command:

- name: SonarQube analysis
  shell: bash
  run: |
    # Set the maximum number of attempts
    max_attempts=5
    # Set a counter for the number of attempts
    attempt_num=1
    # Set a flag to indicate whether the command was successful
    success=false
    # Loop until the command is successful or the maximum number of attempts is reached
    while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do
      # Execute the command
      sonar-scanner \
        -Dsonar.cfamily.build-wrapper-output=bw-output
      # Check the exit code of the command
      if [ $? -eq 0 ]; then
        # The command was successful
        success=true
      else
        # The command was not successful
        echo "Attempt $attempt_num failed. Trying again..."
        # Increment the attempt counter
        attempt_num=$(( attempt_num + 1 ))
      fi
    done
    # Check if the command was successful
    if [ $success = true ]; then
      # The command was successful
      echo "sonar-scanner was successful after $attempt_num attempts."
    else
      # The command was not successful
      echo "sonar-scanner failed after $max_attempts attempts."
    fi
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}

but it doesn't work - when an exception is thrown it exits the loop:

03:33:30.088 INFO  Scanner configuration file: /home/runner/.sonar/sonar-scanner-6.2.1.4610-linux-x64/conf/sonar-scanner.properties
03:33:30.102 INFO  SonarScanner CLI 6.2.1.4610
03:33:30.104 INFO  Java 17.0.12 Eclipse Adoptium (64-bit)
03:33:30.104 INFO  Linux 6.5.0-1025-azure amd64
03:33:30.125 INFO  User cache: /home/runner/.sonar/cache
03:33:53.701 INFO  Communicating with SonarQube Server 9.9.7.96285
03:33:53.964 INFO  Load global settings
03:33:54.399 INFO  Load global settings (done) | time=435ms
03:33:54.401 INFO  Server id: 8F6C7167-AW8zf1mS7d4EVV8efcCG
03:33:54.404 INFO  User cache: /home/runner/.sonar/cache
03:33:54.406 INFO  Load/download plugins
03:33:54.407 INFO  Load plugins index
03:33:54.794 INFO  Load plugins index (done) | time=387ms
03:34:20.190 INFO  Load/download plugins (done) | time=25784ms
03:34:20.198 INFO  EXECUTION FAILURE
03:34:20.199 INFO  Total time: 50.113s
03:34:20.199 ERROR Error during SonarScanner CLI execution
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.sonarsource.scanner.lib.internal.IsolatedClassloader@740d2e78-org.sonar.scanner.bootstrap.ScannerPluginRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: Fail to download plugin [cpp]. File /home/runner/.sonar/_tmp/fileCache2060103996137565963.tmp was expected to have checksum 648b7fda1ced5cc3a204981786143349 but had 5c56ae7029503f40ef4e337edf513626
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:187)
    at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167)
    at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:72)
    at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:66)
    at org.sonarsource.scanner.lib.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:41)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.sonarsource.scanner.lib.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:62)
    at jdk.proxy3/jdk.proxy3.$Proxy2.execute(Unknown Source)
    at org.sonarsource.scanner.lib.InProcessScannerEngineFacade.doAnalyze(InProcessScannerEngineFacade.java:39)
    at org.sonarsource.scanner.lib.ScannerEngineFacade.analyze(ScannerEngineFacade.java:61)
    at org.sonarsource.scanner.cli.Main.analyze(Main.java:77)
    at org.sonarsource.scanner.cli.Main.main(Main.java:63)
Caused by: java.lang.IllegalStateException: Fail to download plugin [cpp]. File /home/runner/.sonar/_tmp/fileCache2060103996137565963.tmp was expected to have checksum 648b7fda1ced5cc3a204981786143349 but had 5c56ae7029503f40ef4e337edf513626
    at org.sonar.scanner.bootstrap.PluginFiles.download(PluginFiles.java:105)
    at org.sonar.scanner.bootstrap.PluginFiles.get(PluginFiles.java:82)
    at org.sonar.scanner.bootstrap.ScannerPluginInstaller.loadPlugins(ScannerPluginInstaller.java:78)
    at org.sonar.scanner.bootstrap.ScannerPluginInstaller.installRemotes(ScannerPluginInstaller.java:61)
    at org.sonar.scanner.bootstrap.ScannerPluginRepository.start(ScannerPluginRepository.java:63)
    at org.sonar.core.platform.StartableBeanPostProcessor.postProcessBeforeInitialization(StartableBeanPostProcessor.java:33)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
    ... 23 common frames omitted
03:34:20.200 ERROR 
03:34:20.200 ERROR Re-run SonarScanner CLI using the -X switch to enable full debug logging.
Error: Process completed with exit code 1.

How can I get this step to repeat if it fails? Note I'd prefer to do this without a thirdparty solution because that would require approval from our security team.

1
  • That should just work. Maybe something else is going on here. What is the output of set -o | grep errexit. It should be something like: errexit off Commented Dec 8, 2024 at 20:30

2 Answers 2

3

Setting shell: bash results in this command being run internally:

bash --noprofile --norc -eo pipefail {0}

(see documentation).

It includes -e, "error on exit", so when your scanner hits an error, the entire step is aborted.

You can prevent that from happening by executing the command in an if-clause, which exempts it from the set -e effects:

# Execute the command
if sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output; then
    success=true
else
    # The command was not successful

As a side note, there is a dedicated SonarQube action provided by SonarSource; using it might simplify your setup.

Sign up to request clarification or add additional context in comments.

2 Comments

<cmd> || true isn't useful here, as it hides the exit code of the command. You probably want something like set +e at the top of the script.
@Dunes You're right, || true doesn't work. The command isn't a script, though, it's a Java executable. I have updated to running it in an if-clause, which prevents a non-successful exit status from triggering "error on exit".
0

I've marked @benjamin-w's answer as correct, but just for completeness here's the final code I'm using. The continue-on-error: true line means that if this step still fails it doesn't fail the whole build - you can remove this and make it fail if you want.

- name: SonarQube analysis
  continue-on-error: true
  shell: bash
  run: |
    # Disable exit on error.
    set +e
    cd oclea-yocto-sdk/source/motorola-app
    # Set the maximum number of attempts
    max_attempts=5
    # Set a counter for the number of attempts
    attempt_num=1
    # Set a flag to indicate whether the command was successful
    success=false
    # Loop until the command is successful or the maximum number of attempts is reached
    while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do
      # Execute the command
      sonar-scanner \
        -Dsonar.cfamily.build-wrapper-output=bw-output
      # Check the exit code of the command
      if [ $? -eq 0 ]; then
        # The command was successful
        success=true
      else
        # The command was not successful
        echo "Attempt $attempt_num failed. Trying again..."
        # Increment the attempt counter
        attempt_num=$(( attempt_num + 1 ))
      fi
    done
    # Check if the command was successful
    if [ $success = true ]; then
      # The command was successful
      echo "sonar-scanner was successful after $attempt_num attempts."
    else
      # The command was not successful
      echo "sonar-scanner failed after $max_attempts attempts."
    fi
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.