Skip to content

Commit 605c186

Browse files
committed
Merge branch 'release/0.6.0'
2 parents 9288cac + be411e1 commit 605c186

File tree

5 files changed

+130
-37
lines changed

5 files changed

+130
-37
lines changed

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.6.0] / 2023-08-15
11+
### 🚀 New features
12+
- Added CLI options to push mutation reports to stryker dashboard when possible.
13+
14+
### 🔧 Fixes
15+
- Reduced the number of CLI options sent when `IUnitTest.UnitTests` target runs and the current build does not need to collect code coverage.
16+
- Made `IMutationTest.MutationTests` target to run before `IPack.Pack` does.
17+
- Added CLI option `--project` to the options output when running mutation tests
18+
- Changed output directory for mutation report files to save them into a directory named after the source project that was mutated.
19+
So now `{MutationTestDirectory}/[{framework}]` is now changed to `{MutationTestDirectory}/{ProjectName}/[{framework}]` ([#88](https://github.com/candoumbe/pipelines/issues/88))
20+
- Fixed the name of the parameters emitted for the [project version](https://stryker-mutator.io/docs/stryker-net/configuration/#project-infoversion-committish) when using `dashboard` reporter ([#89](https://github.com/candoumbe/pipelines/issues/89))
21+
- Removed `--dashboard.module` parameter as it cannot be defined at CLI level with Stryker version 3.10.0 ([#89](https://github.com/candoumbe/pipelines/issues/89))
22+
23+
1024
## [0.5.0] / 2023-07-24
1125
### 🚀 New features
1226
- Added `ConfigName` parameter to specify the name of the configuration to use when pushing nuget packages ([#37](https://github.com/candoumbe/Pipelines/issues/37)).
@@ -168,3 +182,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
168182
[0.3.0]: https://github.com/candoumbe/Pipelines/compare/0.2.0...0.3.0
169183
[0.2.0]: https://github.com/candoumbe/Pipelines/compare/0.1.0...0.2.0
170184
[0.1.0]: https://github.com/candoumbe/Pipelines/tree/0.1.0
185+
186+
[Unreleased]: https://github.com/candoumbe/Pipelines/compare/0.6.0...HEAD
187+
[0.6.0]: https://github.com/candoumbe/Pipelines/compare/0.5.0...0.6.0
188+
[0.5.0]: https://github.com/candoumbe/Pipelines/compare/0.4.5...0.5.0
189+
[0.4.5]: https://github.com/candoumbe/Pipelines/compare/0.4.4...0.4.5
190+
[0.4.4]: https://github.com/candoumbe/Pipelines/compare/0.4.3...0.4.4
191+
[0.4.3]: https://github.com/candoumbe/Pipelines/compare/0.4.2...0.4.3
192+
[0.4.2]: https://github.com/candoumbe/Pipelines/compare/0.4.1...0.4.2
193+
[0.4.1]: https://github.com/candoumbe/Pipelines/compare/0.4.0...0.4.1
194+
[0.4.0]: https://github.com/candoumbe/Pipelines/compare/0.3.0...0.4.0
195+
[0.3.0]: https://github.com/candoumbe/Pipelines/compare/0.2.0...0.3.0
196+
[0.2.0]: https://github.com/candoumbe/Pipelines/compare/0.1.0...0.2.0
197+
[0.1.0]: https://github.com/candoumbe/Pipelines/tree/0.1.0

core.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
</When>
3434
</Choose>
3535
<ItemGroup>
36-
<PackageReference Include="Roslynator.Analyzers" Version="4.3.0">
36+
<PackageReference Include="Roslynator.Analyzers" Version="4.4.0">
3737
<PrivateAssets>all</PrivateAssets>
3838
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
3939
</PackageReference>

src/Candoumbe.Pipelines/Components/Extensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Nuke.Common;
2+
using Nuke.Common.ProjectModel;
23

34
using System;
45

@@ -32,4 +33,14 @@ public static T WhenNotNull<T, TObject>(this T settings, TObject obj, Func<T, TO
3233
/// <exception cref="InvalidCastException">if <paramref name="nukeBuild"/> is not convertible to <typeparamref name="T"/>.</exception>
3334
public static T Get<T>(this INukeBuild nukeBuild) where T : INukeBuild
3435
=> (T)(object)nukeBuild;
36+
37+
/// <summary>
38+
/// Uses various heuristics to tests if <paramref name="project"/> has <see href="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/dotnet/sourcelink">SourceLink</see>
39+
/// enabled .
40+
/// </summary>
41+
/// <param name="project"></param>
42+
/// <returns><see langword="true"/> if <see href="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/dotnet/sourcelink">SourceLink</see>
43+
/// enabled and <see langword="false"/> otherwise</returns>
44+
public static bool IsSourceLinkEnabled(this Project project) => false;
45+
3546
}

src/Candoumbe.Pipelines/Components/IMutationTest.cs

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ namespace Candoumbe.Pipelines.Components;
2424
[NuGetPackageRequirement("dotnet-stryker")]
2525
public interface IMutationTest : IUnitTest
2626
{
27+
/// <summary>
28+
/// Name of the property set when <see href="SourceLink">SourceLink</see> is enabled on a projet.
29+
/// </summary>
30+
private const string ContinuousIntegrationBuild = nameof(ContinuousIntegrationBuild);
31+
2732
/// <summary>
2833
/// Directory where mutattion test results should be published
2934
/// </summary>
@@ -32,11 +37,9 @@ public interface IMutationTest : IUnitTest
3237
/// <summary>
3338
/// Api Key us
3439
/// </summary>
35-
[Parameter]
40+
[Parameter("API KEY used to submit mutation report to a stryker dashboard")]
3641
public string StrykerDashboardApiKey => TryGetValue(() => StrykerDashboardApiKey);
3742

38-
39-
4043
/// <summary>
4144
/// Defines projects onto which mutation tests will be performed
4245
/// </summary>
@@ -52,6 +55,7 @@ public interface IMutationTest : IUnitTest
5255
public Target MutationTests => _ => _
5356
.Description("Runs mutation tests using Stryker tool")
5457
.TryDependsOn<IClean>(x => x.Clean)
58+
.TryBefore<IPack>()
5559
.DependsOn(Compile)
5660
.Produces(MutationTestResultDirectory / "*")
5761
.Executes(() =>
@@ -68,12 +72,15 @@ public interface IMutationTest : IUnitTest
6872
.Distinct()
6973
.ToArray();
7074

75+
7176
if (frameworks.AtLeast(2))
7277
{
7378
MutationTestsProjects.ForEach(tuple =>
7479
{
7580
mutationProjectCount++;
7681
(Project sourceProject, IEnumerable<Project> testsProjects) = tuple;
82+
AbsolutePath mutationTestOutputDirectory = MutationTestResultDirectory / sourceProject.Name;
83+
7784
IReadOnlyCollection<string> testedFrameworks = testsProjects.Select(csproj => csproj.GetTargetFrameworks())
7885
.SelectMany(x => x)
7986
.Distinct()
@@ -88,7 +95,7 @@ public interface IMutationTest : IUnitTest
8895
.Apply(StrykerArgumentsSettings);
8996

9097
args.Add("--target-framework {value}", framework)
91-
.Add("--output {value}", MutationTestResultDirectory / framework);
98+
.Add("--output {value}", mutationTestOutputDirectory / framework);
9299

93100
RunMutationTestsForTheProject(sourceProject, testsProjects, args);
94101
});
@@ -98,7 +105,7 @@ public interface IMutationTest : IUnitTest
98105
args = new();
99106
string framework = testedFrameworks.Single();
100107
args.Add("--target-framework {value}", framework)
101-
.Add("--output {value}", MutationTestResultDirectory / framework);
108+
.Add("--output {value}", mutationTestOutputDirectory / framework);
102109

103110
RunMutationTestsForTheProject(sourceProject, testsProjects, args);
104111
}
@@ -110,16 +117,17 @@ public interface IMutationTest : IUnitTest
110117
args.Apply(StrykerArgumentsSettingsBase)
111118
.Apply(StrykerArgumentsSettings);
112119

113-
args.Add("--target-framework {value}", frameworks.Single())
114-
.Add("--output {value}", MutationTestResultDirectory);
120+
args.Add("--target-framework {value}", frameworks.Single());
115121

116122
MutationTestsProjects.ForEach(tuple =>
117123
{
118124
mutationProjectCount++;
125+
args = args.Add("--output {value}", MutationTestResultDirectory / tuple.SourceProject.Name);
119126
RunMutationTestsForTheProject(tuple.SourceProject, tuple.TestProjects, args);
120127
});
121128
}
122129
});
130+
123131
/// <summary>
124132
/// Run mutation tests for the specified project using the specified arguments
125133
/// </summary>
@@ -128,35 +136,76 @@ private void RunMutationTestsForTheProject(Project sourceProject, IEnumerable<Pr
128136
Verbose("{ProjetName} will run mutation tests for the following frameworks : {@Frameworks}", sourceProject.Name, sourceProject.GetTargetFrameworks());
129137

130138
Arguments strykerArgs = new();
131-
strykerArgs.Add("stryker");
132-
strykerArgs.Concatenate(args);
139+
strykerArgs = strykerArgs.Add("stryker");
140+
strykerArgs = strykerArgs.Concatenate(args);
133141

134-
testsProjects.ForEach(project => strykerArgs.Add(@"--test-project {value}", project.Path));
142+
strykerArgs.Add(@"--project {value}", sourceProject.Name);
143+
144+
testsProjects.ForEach(project =>
145+
{
146+
strykerArgs = strykerArgs.Add(@"--test-project {value}", project.Path);
147+
});
148+
149+
if (this is IGitFlow gitFlow && gitFlow.GitRepository is { } gitflowRepository)
150+
{
151+
strykerArgs = strykerArgs.Add("--version {value}", gitflowRepository.Commit ?? gitflowRepository.Branch);
152+
switch (gitflowRepository.Branch)
153+
{
154+
case string branchName when string.Equals(branchName, IGitFlow.DevelopBranchName, StringComparison.InvariantCultureIgnoreCase):
155+
{
156+
// we are in git flow so comparison we can compare develop against main branch
157+
strykerArgs = strykerArgs.Add("--with-baseline:{value}", IGitFlow.MainBranchName);
158+
159+
}
160+
break;
161+
case string branchName when branchName.Like($"{gitFlow.FeatureBranchPrefix}/*", true):
162+
{
163+
strykerArgs = strykerArgs.Add("--with-baseline:{value}", gitFlow.FeatureBranchSourceName);
164+
}
165+
break;
166+
case string branchName when branchName.Like($"{gitFlow.ColdfixBranchPrefix}/*", true):
167+
{
168+
strykerArgs = strykerArgs.Add("--with-baseline:{value}", gitFlow.ColdfixBranchSourceName);
169+
}
170+
break;
171+
default:
172+
break;
173+
}
174+
}
175+
else if (this is IGitHubFlow gitHubFlow && gitHubFlow.GitRepository is { } githubFlowRepository)
176+
{
177+
strykerArgs = strykerArgs.Add("--version {value}", githubFlowRepository.Commit ?? githubFlowRepository.Branch);
178+
if (githubFlowRepository.Branch is { Length: > 0 } branchName && !string.Equals(branchName, IGitHubFlow.MainBranchName, StringComparison.InvariantCultureIgnoreCase))
179+
{
180+
strykerArgs = strykerArgs.Add("--with-baseline:{0}", IGitHubFlow.MainBranchName);
181+
}
182+
}
183+
else if (!sourceProject.IsSourceLinkEnabled())
184+
{
185+
if (this is IHaveGitVersion gitVersion)
186+
{
187+
strykerArgs = strykerArgs.Add("--version {value}", gitVersion.MajorMinorPatchVersion);
188+
}
189+
else if (this is IHaveGitRepository gitRepository)
190+
{
191+
strykerArgs = strykerArgs.Add("--version {value}", gitRepository.GitRepository?.Commit ?? gitRepository?.GitRepository?.Branch);
192+
}
193+
}
135194

136195
DotNet(strykerArgs.RenderForExecution(), workingDirectory: sourceProject.Path.Parent);
196+
197+
137198
}
138199

139200
internal Configure<Arguments> StrykerArgumentsSettingsBase => _
140201
=> _
141-
.When(IsLocalBuild, args => args.Add("--open-report:{0}", "html"))
202+
.When(IsLocalBuild, args => args.Add("--open-report:{value}", "html"))
142203
.WhenNotNull(StrykerDashboardApiKey,
143204
(args, apiKey) => args.Add("--dashboard-api-key {value}", apiKey, secret: true)
144205
.Add("--reporter dashboard"))
145206
.Add("--reporter markdown")
146207
.Add("--reporter html")
147-
.When(IsLocalBuild, args => args.Add("--reporter progress"))
148-
.WhenNotNull(this.As<IGitFlow>()?.GitRepository,
149-
(args, repository) => args.Add("--with-baseline:{0}", repository.Branch.ToLowerInvariant() switch
150-
{
151-
string branchName when branchName == IGitFlow.MainBranchName || branchName == IGitFlow.DevelopBranchName => branchName,
152-
string branchName when branchName.Like($"{this.As<IGitFlow>()?.FeatureBranchPrefix}/*", true) => this.As<IWorkflow>().FeatureBranchSourceName,
153-
string branchName when branchName.Like($"{this.As<IGitFlow>()?.HotfixBranchPrefix}/*", true) => this.As<IWorkflow>().HotfixBranchSourceName,
154-
string branchName when branchName.Like($"{this.As<IGitFlow>()?.ColdfixBranchPrefix}/*", true) => this.As<IGitFlow>().ColdfixBranchSourceName,
155-
_ => IGitFlow.MainBranchName
156-
})
157-
.Add("--version:{0}", repository.Commit ?? repository.Branch))
158-
.WhenNotNull(this.As<IGitHubFlow>(), (args, flow) => args.Add("--with-baseline:{0}", IGitHubFlow.MainBranchName)
159-
.Add("--version:{0}", flow.GitRepository?.Commit ?? flow.GitRepository?.Branch));
208+
.When(IsLocalBuild, args => args.Add("--reporter progress"));
160209

161210
/// <summary>
162211
/// Configures arguments that will be used by when running Stryker tool

src/Candoumbe.Pipelines/Components/IUnitTest.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,26 +53,32 @@ public interface IUnitTest : ICompile, IHaveTests, IHaveCoverage
5353
.Apply<DotNetTestSettings, (Project, string)>(ProjectUnitTestSettings, (project, framework))
5454
)));
5555

56-
TestResultDirectory.GlobFiles("*.trx")
57-
.ForEach(testFileResult => AzurePipelines.Instance?.PublishTestResults(title: $"{Path.GetFileNameWithoutExtension(testFileResult)} ({AzurePipelines.Instance.StageDisplayName})",
58-
type: AzurePipelinesTestResultsType.VSTest,
59-
files: new string[] { testFileResult })
60-
);
56+
if (AzurePipelines.Instance is not null)
57+
{
58+
TestResultDirectory.GlobFiles("*.trx")
59+
.ForEach(testFileResult => AzurePipelines.Instance?.PublishTestResults(title: $"{Path.GetFileNameWithoutExtension(testFileResult)} ({AzurePipelines.Instance.StageDisplayName})",
60+
type: AzurePipelinesTestResultsType.VSTest,
61+
files: new string[] { testFileResult })
62+
);
6163

62-
TestResultDirectory.GlobFiles("*.xml")
63-
.ForEach(file => AzurePipelines.Instance?.PublishCodeCoverage(coverageTool: AzurePipelinesCodeCoverageToolType.Cobertura,
64-
summaryFile: file,
65-
reportDirectory: CoverageReportDirectory));
64+
if (this is IReportCoverage reportCoverage)
65+
{
66+
TestResultDirectory.GlobFiles("*.xml")
67+
.ForEach(file => AzurePipelines.Instance?.PublishCodeCoverage(coverageTool: AzurePipelinesCodeCoverageToolType.Cobertura,
68+
summaryFile: file,
69+
reportDirectory: reportCoverage.CoverageReportDirectory));
70+
}
71+
}
6672
});
6773

6874
internal sealed Configure<DotNetTestSettings> UnitTestSettingsBase => _ => _
6975
.SetConfiguration(Configuration.ToString())
7076
.ResetVerbosity()
71-
.EnableCollectCoverage()
7277
.EnableUseSourceLink()
7378
.SetNoBuild(SucceededTargets.Contains(Compile))
7479
.SetResultsDirectory(UnitTestResultsDirectory)
75-
.SetCoverletOutputFormat(CoverletOutputFormat.lcov)
80+
.WhenNotNull(this.As<IReportCoverage>(), (settings, _) => settings.EnableCollectCoverage()
81+
.SetCoverletOutputFormat(CoverletOutputFormat.lcov))
7682
.AddProperty("ExcludeByAttribute", "Obsolete");
7783

7884
/// <summary>
@@ -82,7 +88,7 @@ public interface IUnitTest : ICompile, IHaveTests, IHaveCoverage
8288

8389
internal Configure<DotNetTestSettings, (Project project, string framework)> ProjectUnitTestSettingsBase => (settings, tuple) => settings.SetFramework(tuple.framework)
8490
.AddLoggers($"trx;LogFileName={tuple.project.Name}.{tuple.framework}.trx")
85-
.SetCoverletOutput(UnitTestResultsDirectory / $"{tuple.project.Name}.{tuple.framework}.xml");
91+
.WhenNotNull(this.As<IReportCoverage>(), (settings, _) => settings.SetCoverletOutput(UnitTestResultsDirectory / $"{tuple.project.Name}.{tuple.framework}.xml"));
8692

8793
/// <summary>
8894
/// Configure / override unit test settings at project level

0 commit comments

Comments
 (0)