We wanted to style checking process on our C# projects using Bitbucket pipelines. The reason was to make sure the code conforms to our coding standards. We asked Gabor Szabo our Docker / Build Engineer to look into how it could be done. He came up with the following solution.
The problem
When we started looking into it we were hoping the solution would be similar to how JavaScript / TypeScript is verified but it wasn’t the case. As it turns out there isn’t a simple linter for C#.
Another obstacle is that as the CI systems we use tend to be using Linux as the underlying OS, it is not feasible to run windows based containers on them.
Our generic solution is to create a docker container from an image that has the required dependencies installed. Then copy the source code into it. On larger projects, we bind the folder containing the source code to the container. The last step then is to run the lint process. This is what we wanted to replicate as closely as possible.
Solution
The solution we ended up with is to build C# and use the output from the process to report styling errors.
Performing Style Checking
StyleCop has been around for a while. It is an extremely diligent code styling check utility. In the past, we used it as a Visual Studio plugin but with the newer versions and alternative IDEs, we needed a solution that can run independently. The SyleCop.Analysers GitHub project contains an implementation of the StyleCop rules using the .NET Compiler Platform. This tighter integration enables allows running these rules on other platforms than Windows as well as providing automatic in-editor fixes if need be.
Modify the C# project
To prepare the C# project for style checking we had to add the Stylecop.Analyzers
and Microsoft.CodeAnalysis.FxCopAnalyzers
packages to it and reference the rules JSON file.
<!-- Both packages are needed -->
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<!-- StyleCop ruleset file location -->
<PropertyGroup>
<CodeAnalysisRuleSet>StyleCop.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
Code language: HTML, XML (xml)
After making this change, depending on the state of the code-base, MSBuild will include styling errors.

Run all this in a Container
We started off by referencing this image from docker hub. It already has the .NET SDK installed. We chose this one but there are official images from Microsoft as well. This allowed us to simply copy our code into our new container and run dotnet build
. By processing the output we were able to catch all the errors. You can see this in the following snippet showing our docker file.
FROM mcblair/dotnet-ci-image
WORKDIR /usr/src
COPY --chown=root:root . /usr/src
ENTRYPOINT [ "dotnet", "build" ]
Code language: Shell Session (shell)
We put together the following shell script that builds a new container, runs the build command and checks if it was successful.
#!/bin/bash
LOGFILE_NAME=error.log
PROJECT_FILES=$@
if [[ $@ == "" ]]
then
echo 'Please specify at least one project file.'
exit 1
fi
docker build --force-rm -t csharplinter . && docker run csharplinter "$PROJECT_FILES" | grep -e 'error' -e 'warning' -- > "$LOGFILE_NAME"
ERROR_CODE=$?
FILESIZE=$(stat -c%s "$LOGFILE_NAME")
if [ "$ERROR_CODE" -ne 0 ]
then
echo "Something went wrong...Exiting"
exit 1
elif [ "$FILESIZE" -eq 0 ]
Code language: Shell Session (shell)
This script can be run as part of a CI a pipeline (for example Bitbucket pipelines). It writes the output to a file called error.log file. If errors are present the pipeline reports failure by exiting with code 1.
Conclusion
This is only to show how to get started. There are several improvements that can be made including not needing root
for copying code in, handling docker errors, and filtering warnings and errors using grep
.
If you have any comments, ideas or personal experiences, feel free to share with us. We are curious to hear new ideas, solutions, and perspectives regarding the above. Don’t forget to follow us on our social media!
You can also find the rest of our blog here!