Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs/improve actions #170

Merged
merged 3 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 69 additions & 9 deletions docs/content/Getting Started Using.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ dotnet tool install fsharp-analyzers
Next, add the `PackageReference` pointing to your favorite analyzers to the `.fsproj` file of the project you want to analyze:

```xml
<PackageReference Include="G-Research.FSharp.Analyzers" Version="0.3.0">
<PackageReference Include="G-Research.FSharp.Analyzers" Version="0.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>build</IncludeAssets>
<IncludeAssets>analyzers</IncludeAssets>
</PackageReference>
```

At the time of writing, the [G-Research analyzers](https://github.com/g-research/fsharp-analyzers) [package](https://www.nuget.org/packages/G-Research.FSharp.Analyzers) contains the only analyzers compatible with the latest CLI tool.
With the package downloaded, we can run the CLI tool:

```shell
dotnet fsharp-analyzers --project ./YourProject.fsproj --analyzers-path C:\Users\yourusername\.nuget\packages\g-research.fsharp.analyzers\0.3.0\analyzers\dotnet\fs\ --verbose
dotnet fsharp-analyzers --project ./YourProject.fsproj --analyzers-path C:\Users\yourusername\.nuget\packages\g-research.fsharp.analyzers\0.4.0\analyzers\dotnet\fs\ --verbose
```

### Using an MSBuild target
Expand All @@ -44,7 +44,10 @@ Luckily, we can use an MSBuild custom target to take care of the path constructi
Add [FSharp.Analyzers.Build](https://www.nuget.org/packages/FSharp.Analyzers.Build) to your `fsproj`:

```xml
<PackageReference Include="FSharp.Analyzers.Build" Version="0.2.0" PrivateAssets="all" />
<PackageReference Include="FSharp.Analyzers.Build" Version="0.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>build</IncludeAssets>
</PackageReference>
```

This imports a new target to your project file: `AnalyzeFSharpProject`.
Expand Down Expand Up @@ -80,11 +83,14 @@ This adds the package reference to all `.fsproj` files that are in a subfolder o

```xml
<ItemGroup>
<PackageReference Include="FSharp.Analyzers.Build" Version="0.1.0" PrivateAssets="all" />
<PackageReference Include="G-Research.FSharp.Analyzers" Version="0.1.6">
<PackageReference Include="FSharp.Analyzers.Build" Version="0.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>build</IncludeAssets>
</PackageReference>
<PackageReference Include="G-Research.FSharp.Analyzers" Version="0.1.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
```

Expand All @@ -101,10 +107,20 @@ This is effectively the same as adding a property to each `*proj` file which exi
```

⚠️ We are adding the `FSharpAnalyzersOtherFlags` property to our **Directory.Build.targets** and **not to** any **Directory.Build.props** file!
MSBuild will first evaluate `Directory.Build.props` which has no access to the generated nuget.g.props. `$(PkgIonide_Analyzers)` won't be known at this point. `Directory.Build.targets` is evaluated after the project file and has access to `Pkg` generated properties.
MSBuild will first evaluate `Directory.Build.props` which has no access to the generated nuget.g.props. `$(PkgG-Research_FSharp_Analyzers)` won't be known at this point. `Directory.Build.targets` is evaluated after the project file and has access to `Pkg` generated properties.

As we don't want to list all projects of the solution explicitly when analyzing the solution, we create a second custom MSBuild target that calls the project-specific target for all projects.
Add the following custom target to the [Directory.Solution.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-solution-build?view=vs-2022) file to be able to invoke analysis of the whole solution in one simple command:
### All projects in the solution

We can run the `AnalyzeFSharpProject` target against all projects in a solution

```shell
dotnet msbuild YourSolution.sln /t:AnalyzeFSharpProject
```

### Select specific projects

As we don't want to targt all projects of the solution, we create a second custom MSBuild target that calls the project-specific target for all relevant projects.
Add the following custom target to the [Directory.Solution.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-solution-build?view=vs-2022) file to be able to invoke analysis from all selected projects in one simple command:

```xml
<Project>
Expand All @@ -126,4 +142,48 @@ dotnet msbuild /t:AnalyzeSolution

Note: we passed the `--code-root` flag so that the `*.sarif` report files will report file paths relative to this root. This can be imported for certain editors to function properly.

## MSBuild tips and tricks

MSBuild can be overwhelming for the uninitiated. Here are some tricks we've seen in the wild:

### Use well-known properties

Checkout the [MSBuild reserved and well-known properties](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2022) to use existing variables like `$(MSBuildProjectFile)`.

### Wrap path arguments in quotes

As MSBuild is all XML, you can use `&quot;` to wrap evaluated values in quotes:

```xml
<PropertyGroup>
<WithQuotes>&quot;$(SolutionDir)&quot;</WithQuotes>
</PropertyGroup>
```

### Extend `<FSharpAnalyzersOtherFlags>` in multiple lines

You can extend the value of `$(FSharpAnalyzersOtherFlags)` by setting it again in multiple lines:

```xml
<PropertyGroup>
<FSharpAnalyzersOtherFlags>--analyzers-path &quot;$(PkgG-Research_FSharp_Analyzers)/analyzers/dotnet/fs&quot;</FSharpAnalyzersOtherFlags>
<FSharpAnalyzersOtherFlags>--analyzers-path &quot;$(PkgIonide_Analyzers)/analyzers/dotnet/fs&quot;</FSharpAnalyzersOtherFlags>
nojaf marked this conversation as resolved.
Show resolved Hide resolved
<FSharpAnalyzersOtherFlags>$(FSharpAnalyzersOtherFlags) --configuration $(Configuration)</FSharpAnalyzersOtherFlags>
<FSharpAnalyzersOtherFlags>$(FSharpAnalyzersOtherFlags) --exclude-analyzer PartialAppAnalyzer</FSharpAnalyzersOtherFlags>
</PropertyGroup>
```

### Verify parameters are present

It can be a bit confusing to find out if a variable contains the value you think it does.
We often add a dummy target to a project to print out some values:

```xml
<Target Name="Dump">
<Message Importance="high" Text="$(CodeRoot)" />
</Target>
```

Run `dotnet msbuild YourProject.fsproj /t:Dump` and verify that `CodeRoot` has a value or not.

[Next]({{fsdocs-next-page-link}})
26 changes: 25 additions & 1 deletion docs/content/Running during CI.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,39 @@ dotnet fsharp-analyzers /
--report ./analysis.sarif
```

### GitHub Actions
### Code root

Use the `--code-root` flag to specify the root directory where all reported problems should be relative to.
Typically, this should correspond to your source control (git) repository. Some tooling may require this setting to be accurate for easy navigation to the reported problems.

Example when using MSBuild:

```xml
<PropertyGroup>
<CodeRoot>$([System.IO.Path]::GetDirectoryName($(DirectoryBuildTargetsPath)))</CodeRoot>
<SarifOutput>$(CodeRoot)/reports/</SarifOutput>
<FSharpAnalyzersOtherFlags>--analyzers-path &quot;$(PkgG-Research_FSharp_Analyzers)/analyzers/dotnet/fs&quot;</FSharpAnalyzersOtherFlags>
<FSharpAnalyzersOtherFlags>$(FSharpAnalyzersOtherFlags) --code-root &quot;$(CodeRoot)&quot;</FSharpAnalyzersOtherFlags>
<FSharpAnalyzersOtherFlags>$(FSharpAnalyzersOtherFlags) --report &quot;$(SarifOutput)$(MSBuildProjectName)-$(TargetFramework).sarif&quot;</FSharpAnalyzersOtherFlags>
</PropertyGroup>
```

## GitHub Actions

If you are using [GitHub Actions](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/sarif-output) you can easily send the *sarif file* to [CodeQL](https://codeql.github.com/).

```yml
- name: Run Analyzers
run: dotnet msbuild /t:AnalyzeFSharpProject /p:Configuration=Release
# This is important, you want to continue your Action even if you found problems.
# As you always want the report to upload
continue-on-error: true

# checkout code, build, run analyzers, ...
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
with:
# You can also specify the path to a folder for `sarif_file`
sarif_file: analysis.sarif
```

Expand Down