Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions ADOPTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ The script [`Adopt-StarterKit.ps1`](Adopt-StarterKit.ps1) needs [PowerShell 7](h
* the solution file, unless your repository doesn't have one.
* It never overwrites an existing file, unless you pass `-Overwrite`. Files that are the same as the template version are skipped silently. Files that are different are listed, so you can compare them. If you prefer to merge using `git diff`, run it again with `-Overwrite`.
* If your repository has one solution file, it:
* points `.nuke/parameters.json` and `Build/Build.cs` to that solution;
* points `.fallout/parameters.json` and `Build/Build.cs` to that solution;
* adds the API verification test project to it;
* adds the build project to it (for `.slnx` files only), excluded from the solution build.
* It checks your repository and prints the steps you still need to do by hand, for example:
Expand All @@ -84,7 +84,7 @@ The script contains no hard-coded list of template files. Whatever the installed

| What | Files |
|--------------------------|-----------------------------------------------------------------------------------------------------|
| Build script | `Build/`, `build.ps1`, `build.sh`, `build.cmd`, `.nuke/`, `global.json`, `GitVersion.yml` |
| Build script | `Build/`, `build.ps1`, `build.sh`, `build.cmd`, `.fallout/`, `global.json`, `GitVersion.yml` |
| Code style and analyzers | `.editorconfig`, `<Name>.sln.DotSettings`, and the analyzer settings in `Directory.Build.props` |
| API verification | `<Name>.ApiVerificationTests/` without the `ApprovedApi` folder, `AcceptApiChanges.ps1`, `AcceptApiChanges.sh` |
| Pipelines | `.github/` (GitHub) or `Build/azure-pipelines.yaml` (Azure DevOps) |
Expand All @@ -97,7 +97,7 @@ The script contains no hard-coded list of template files. Whatever the installed
Don't copy the library project folder, the `.Specs` folder or the solution file. Instead, compare them with your own and take over what you need.

1. Merge the properties from the template's library project (for example `<Name>/<Name>.csproj`) into yours. The package metadata, such as `PackageIcon`, `PackageReadmeFile`, `PackageLicenseFile` and the `Package files` item group, is what makes `dotnet pack` produce a complete package.
1. If your solution file has a different name than `<Name>.slnx`, update `.nuke/parameters.json` and the `InspectCode` call in `Build/Build.cs`.
1. If your solution file has a different name than `<Name>.slnx`, update `.fallout/parameters.json` and the `InspectCode` call in `Build/Build.cs`.
1. Add `<Name>.ApiVerificationTests` to your solution. Optionally, also add `Build/_build.csproj`, but exclude it from the solution build.
1. Read [After adopting](#after-adopting) below.

Expand Down
4 changes: 2 additions & 2 deletions Adopt-StarterKit.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@ if ($solutions.Count -eq 0) {
$FollowUps.Add("No solution was found, so $Name.slnx was copied from the template. Make sure its project paths match your repository.")
}
elseif ($solutions.Count -gt 1) {
$FollowUps.Add("Found more than one solution file. Update .nuke/parameters.json and the InspectCode call in Build/Build.cs to point to the one the build should use.")
$FollowUps.Add("Found more than one solution file. Update .fallout/parameters.json and the InspectCode call in Build/Build.cs to point to the one the build should use.")
}
else {
$solution = $solutions[0]

if ($solution.Name -ne "$Name.slnx") {
foreach ($file in @(".nuke/parameters.json", "Build/Build.cs") | Where-Object { $copied -contains $_ }) {
foreach ($file in @(".fallout/parameters.json", "Build/Build.cs") | Where-Object { $copied -contains $_ }) {
$fullPath = Join-Path $Path $file
if ($PSCmdlet.ShouldProcess($file, "Point to $($solution.Name)")) {
(Get-Content $fullPath -Raw).Replace("`"$Name.slnx", "`"$($solution.Name)") |
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ It includes:
* Support for both GitHub and Azure DevOps Repositories/Pipelines
* Can create projects for binary or source-only packages
* Code coverage using [Coverlet](https://github.com/coverlet-coverage/coverlet) and [Coveralls.io](https://coveralls.io/)
* Optional static analysis and quality gates through [SonarCloud](https://sonarcloud.io) (just add a `SONAR_TOKEN` secret to opt in)
* Static code analysis using Roslyn analyzers [StyleCopAnalyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers), [Roslynator](https://github.com/dotnet/roslynator), [CSharpGuidelinesAnalyzer](https://github.com/bkoelman/CSharpGuidelinesAnalyzer) and [Meziantou](https://github.com/meziantou/Meziantou.Framework).
* Auto-formatting using (a slightly opinionated) `.editorconfig` and settings honored by [JetBrains Rider](https://www.jetbrains.com/rider/) and [ReSharper](https://www.jetbrains.com/resharper/)
* A [Fallout](https://fallout.build/) C# build script that you can run locally as well as in your CI/CD pipeline
Expand Down Expand Up @@ -162,7 +163,7 @@ The `ApiVerificationTests` will generate a `.txt` file containing a representati
## Building

To build this repository locally, you need the following:
* The [.NET SDKs](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) for .NET 10.0 (see `global.json`).
* The [.NET SDK](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) for .NET 10.0 (see `global.json`).
* Visual Studio, JetBrains Rider or Visual Studio Code with the C# DevKit

You can also build, run the unit tests and package the code using the following command-line:
Expand Down
13 changes: 13 additions & 0 deletions templates/Source/.github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,24 @@ jobs:
with:
fetch-depth: 0

- name: Setup .NET SDK
uses: actions/setup-dotnet@v5
with:
global-json-file: global.json

- name: Setup Java (required by SonarCloud's scanner)
uses: actions/setup-java@v5
if: ${{ secrets.SONAR_TOKEN != '' }}
with:
distribution: 'temurin'
java-version: '17'

- name: Run Fallout
run: ./build.ps1
env:
NuGetApiKey: ${{ secrets.NUGETAPIKEY }}
GitHubApiKey: ${{ secrets.GITHUB_TOKEN }}
SonarToken: ${{ secrets.SONAR_TOKEN }}

- name: Check for 'lcov.info' existence
id: check_files
Expand Down
60 changes: 59 additions & 1 deletion templates/Source/Build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
using Fallout.Common.Tools.DotNet;
using Fallout.Common.Tools.GitVersion;
using Fallout.Common.Tools.ReportGenerator;
{{~ if !azdo ~}}
using Fallout.Common.Tools.SonarScanner;
{{~ end ~}}
using Fallout.Common.Utilities;
using Fallout.Common.Utilities.Collections;
using static Fallout.Common.Tools.DotNet.DotNetTasks;
using static Fallout.Common.Tools.ReportGenerator.ReportGeneratorTasks;
{{~ if !azdo ~}}
using static Fallout.Common.Tools.SonarScanner.SonarScannerTasks;
{{~ end ~}}
using static Serilog.Log;

class Build : FalloutBuild
Expand Down Expand Up @@ -57,6 +63,23 @@ class Build : FalloutBuild
[Secret]
readonly string GitHubApiKey;

{{~ if !azdo ~}}
[Parameter("The token used to authenticate with SonarCloud. Leave empty to skip SonarCloud analysis entirely.")]
[Secret]
readonly string SonarToken;

// Defaults to the GitHub repository owner and "owner_repo", so no extra
// dotnet-new parameters are required to opt in to SonarCloud analysis.
string SonarOrganization => GitHubActions?.RepositoryOwner;

string SonarProjectKey => GitHubActions?.Repository.Replace('/', '_');

[Parameter("The URL of the SonarQube/SonarCloud server to analyze against.")]
readonly string SonarHostUrl = "https://sonarcloud.io";

bool UseSonarCloud => !string.IsNullOrWhiteSpace(SonarToken);
{{~ end ~}}

[Solution(GenerateProjects = true)]
readonly Solution Solution;

Expand Down Expand Up @@ -107,9 +130,30 @@ class Build : FalloutBuild
.EnableNoCache());
});

{{~ if !azdo ~}}
Target SonarBegin => _ => _
.DependsOn(Restore)
.OnlyWhenDynamic(() => UseSonarCloud)
.Executes(() =>
{
Information("Starting SonarCloud analysis for project {ProjectKey}", SonarProjectKey);

SonarScannerBegin(s => s
.SetProjectKey(SonarProjectKey)
.SetOrganization(SonarOrganization)
.SetServer(SonarHostUrl)
.SetToken(SonarToken)
.SetVersion(GitVersion.SemVer)
.SetGenericCoveragePaths(TestResultsDirectory / "reports" / "SonarQube.xml"));
});
{{~ end ~}}

Target Compile => _ => _
.DependsOn(CalculateNugetVersion)
.DependsOn(Restore)
{{~ if !azdo ~}}
.DependsOn(SonarBegin)
{{~ end ~}}
.Executes(() =>
{
ReportSummary(s => s
Expand Down Expand Up @@ -226,7 +270,7 @@ class Build : FalloutBuild
{{~ else ~}}
ReportGenerator(s => s
.AddReports(TestResultsDirectory / "**/coverage.cobertura.xml")
.AddReportTypes(ReportTypes.lcov, ReportTypes.Html)
.AddReportTypes(ReportTypes.lcov, ReportTypes.Html, ReportTypes.SonarQube)
.SetTargetDirectory(TestResultsDirectory / "reports")
.AddFileFilters("-*.g.cs"));

Expand Down Expand Up @@ -283,6 +327,17 @@ class Build : FalloutBuild
(ArtifactsDirectory / "Readme.md").WriteAllText(readmeContent);
});

{{~ if !azdo ~}}
Target SonarEnd => _ => _
.DependsOn(RunTests, GenerateCodeCoverageReport, ApiChecks)
.OnlyWhenDynamic(() => UseSonarCloud)
.Executes(() =>
{
SonarScannerEnd(s => s
.SetToken(SonarToken));
});
{{~ end ~}}

Target Pack => _ => _
.DependsOn(ScanPackages)
.DependsOn(GenerateSbom)
Expand All @@ -291,6 +346,9 @@ class Build : FalloutBuild
.DependsOn(ApiChecks)
.DependsOn(GenerateCodeCoverageReport)
{{~ if azdo }}.DependsOn(PublishTestResults){{~ end ~}}
{{~ if !azdo ~}}
.DependsOn(SonarEnd)
{{~ end ~}}
.Executes(() =>
{
ReportSummary(s => s
Expand Down
6 changes: 5 additions & 1 deletion templates/Source/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{{~ if !azdo ~}}
[![](https://img.shields.io/github/actions/workflow/status/your-github-username/mypackage/build.yml?branch=main)](https://github.com/your-github-username/mypackage/actions?query=branch%3amain)
[![Coveralls branch](https://img.shields.io/coverallsCoverage/github/your-github-username/mypackage?branch=main)](https://coveralls.io/github/your-github-username/mypackage?branch=main)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=your-github-username_mypackage&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=your-github-username_mypackage)
[![](https://img.shields.io/github/release/your-github-username/mypackage.svg?label=latest%20release&color=007edf)](https://github.com/your-github-username/mypackage/releases/latest)
[![](https://img.shields.io/nuget/dt/mypackage.svg?label=downloads&color=007edf&logo=nuget)](https://www.nuget.org/packages/mypackage)
[![](https://img.shields.io/librariesio/dependents/nuget/mypackage.svg?label=dependent%20libraries)](https://libraries.io/nuget/mypackage)
Expand Down Expand Up @@ -64,6 +65,9 @@ The template makes a lot of assumptions, so after generating the project, there'
* For the source-only packages, update the `.nuspec` file so it represents your information.
{{~ end ~}}
* Alter the coverage service that is being used.
{{~ if !azdo ~}}
* Optionally enable [SonarCloud](https://sonarcloud.io) analysis: create a project on sonarcloud.io for this repository, then add a `SONAR_TOKEN` secret to the GitHub repository. The build silently skips SonarCloud analysis when this secret isn't set.
{{~ end ~}}
* Determine if you want to use API verification against snapshots
<!--#if (benchmarks) -->
* Replace the example benchmark in `MyPackage.Benchmarks` with benchmarks for your library and run them using `build.ps1 RunBenchmarks`
Expand Down Expand Up @@ -142,7 +146,7 @@ Then, install the package using the following command-line:
## Building

To build this repository locally, you need the following:
* The [.NET SDKs](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) for .NET 10.0 (see `global.json`) and the .NET Framework 4.7 developer pack.
* The [.NET SDK](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) for .NET 10.0 (see `global.json`) and the .NET Framework 4.7 developer pack.
* Visual Studio, JetBrains Rider or Visual Studio Code with the C# DevKit

You can also build, run the unit tests and package the code using the following command-line:
Expand Down
Loading