~fhusson

How to fix an unknown Sonar error in a TFS build

Here are the steps that I have done to debug and finally to fix my issue.

First we need more logs

Edit file SonarQube.Analysis.xml and set

<Property Name="sonar.verbose">true</Property>

Now in the log we have a more detailed message :

  SonarQube Scanner for MSBuild 2.3.1
  Default properties file was found at D:\SonarQubeScanner\SonarQube.Analysis.xml
  Loading analysis properties from D:\SonarQubeScanner\SonarQube.Analysis.xml
  sonar.verbose=true was specified - setting the log verbosity to 'Debug'
  Pre-processing started.
  Preparing working directories...
  Using environment variables to determine the download directory...
  Removing the existing directory: F:\B\85\XXXX\MY_BUILD_WITH_SONAR\BuildType\.sonarqube
  Failed to create an empty directory 'F:\B\85\XXXX\MY_BUILD_WITH_SONAR\BuildType\.sonarqube'. Please check that there are no open or read-only files in the directory and that you have the necessary read/write permissions.
EXEC : Detailed error message: Access to the path 'SonarQube.Common.dll' is denied. [F:\B\85\XXXX\MY_BUILD_WITH_SONAR\BuildType\TFSBuild.proj]
  Pre-processing failed. Exit code: 1

We have an Access to the path 'SonarQube.Common.dll' is denied !!!

Check file attribute and owner

Check ACL

PS C:\> Get-Acl C:\MyBranch\MyBuild\BuildType\.sonarqube\bin\SonarQube.Common.dll


    Directory: C:\MyBranch\MyBuild\BuildType\.sonarqube\bin


Path                                                               Owner                                                              Access
----                                                               -----                                                              ------
SonarQube.Common.dll                                                              BUILTIN\Administrators                                                       BUILTIN\Administrators Allow  FullControl...

Everything is fine here !

Check Mode

PS C:\> Get-ItemProperty C:\MyBranch\MyBuild\BuildType\.sonarqube\bin\SonarQube.Common.dll


    Directory: C:\MyBranch\MyBuild\BuildType\.sonarqube\bin


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        13/04/2017     12:20      59904 SonarQube.Common.dll

Everything is fine here too !

Check to source of SonarQube.Scanner.MSBuild.exe

Source are on GitHub : https://github.com/SonarSource/sonar-scanner-msbuild

BootstrapperClass.cs

        private int PreProcess()
        {
            Logger.LogInfo(Resources.MSG_PreparingDirectories);
            if (!Utilities.TryEnsureEmptyDirectories(Logger, BootstrapSettings.TempDirectory))
            {
                return ErrorCode;
            }
        ...

Utilities.cs

        /// <summary>
        /// Ensures that the specified directory exists and is empty
        /// </summary>
        public static void EnsureEmptyDirectory(string directory, ILogger logger)
        {
            if (string.IsNullOrWhiteSpace(directory))
            {
                throw new ArgumentNullException("directory");
            }
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            if (Directory.Exists(directory))
            {
                logger.LogDebug(Resources.MSG_DeletingDirectory, directory);
                Directory.Delete(directory, true);
            }
            logger.LogDebug(Resources.MSG_CreatingDirectory, directory);
            Directory.CreateDirectory(directory);
        }

Test with the powershell

[System.IO.Directory]::Delete(“C:\MyBranch\MyBuild\BuildType.sonarqube”, $true)

Delete is ok so someone is using the dll during the build.

Looking at the SonarQube.Integration.targets

  <!-- **************************************************************************** -->
  <!-- Using tasks -->
  <!-- **************************************************************************** -->
  <PropertyGroup Condition=" $(SonarQubeTempPath) != '' AND $(SonarQubeBuildTasksAssemblyFile) == '' ">
    <!-- Assume that the tasks assembly is in the same location as this targets file
         or in a parent directory unless another location has already been specified. -->
    <SonarQubeBuildTasksAssemblyFile>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), SonarQube.Integration.Tasks.dll))\SonarQube.Integration.Tasks.dll</SonarQubeBuildTasksAssemblyFile>
  </PropertyGroup>

  <!-- Unescape the paths to work around the issue "MSBuild 4.0 UsingTask cannot have a path with parentheses".
       See https://connect.microsoft.com/VisualStudio/feedback/details/713690/msbuild-4-0-usingtask-cannot-have-a-path-with-parentheses -->
  <UsingTask TaskName="WriteProjectInfoFile" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
  <UsingTask TaskName="IsTestFileByName" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
  <UsingTask TaskName="GetAnalyzerSettings" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />

Setting the SonarQubeBuildTasksAssemblyFile value to the install bin folder.

    <SonarQubeBuildTasksAssemblyFile>C:\SonarQubeScanner\SonarQube.Integration.Tasks.dll</SonarQubeBuildTasksAssemblyFile>

Now it’s working :)

Discuss on Twitter