From 54945994a8e6be388b7d02a18d6ed347094f135f Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 08:33:10 +0100 Subject: [PATCH 1/9] Optimize NUKE build pipeline's spell check --- Build/Build.cs | 41 ++++++++++++++++++++++++++++++++++++++++- Build/_build.csproj | 1 + package.json | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Build/Build.cs b/Build/Build.cs index a5f76d2205..88266eb120 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using LibGit2Sharp; using Nuke.Common; using Nuke.Common.Execution; +using Nuke.Common.Git; using Nuke.Common.IO; using Nuke.Common.ProjectModel; using Nuke.Common.Tooling; @@ -28,7 +30,7 @@ class Build : NukeBuild - Microsoft VSCode https://nuke.build/vscode */ - public static int Main() => Execute(x => x.Push); + public static int Main() => Execute(x => x.SpellCheck, x => x.Push); [Parameter("A branch specification such as develop or refs/pull/1775/merge")] readonly string BranchSpec; @@ -45,6 +47,9 @@ class Build : NukeBuild [GitVersion(Framework = "net6.0")] readonly GitVersion GitVersion; + [GitRepository] + readonly GitRepository GitRepository; + [PackageExecutable("nspec", "NSpecRunner.exe", Version = "3.1.0")] Tool NSpec3; @@ -65,6 +70,7 @@ class Build : NukeBuild string YarnCli => ToolPathResolver.GetPackageExecutable("Yarn.MSBuild", "yarn.js", "1.22.19"); Target Clean => _ => _ + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { EnsureCleanDirectory(ArtifactsDirectory); @@ -72,6 +78,7 @@ class Build : NukeBuild }); Target CalculateNugetVersion => _ => _ + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { SemVer = GitVersion.SemVer; @@ -91,6 +98,7 @@ class Build : NukeBuild Target Restore => _ => _ .DependsOn(Clean) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { DotNetRestore(s => s @@ -101,6 +109,7 @@ class Build : NukeBuild Target Compile => _ => _ .DependsOn(Restore) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { DotNetBuild(s => s @@ -115,6 +124,7 @@ class Build : NukeBuild Target ApiChecks => _ => _ .DependsOn(Compile) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { DotNetTest(s => s @@ -126,6 +136,7 @@ class Build : NukeBuild Target UnitTests => _ => _ .DependsOn(Compile) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { Project[] projects = new[] @@ -172,6 +183,7 @@ class Build : NukeBuild Target CodeCoverage => _ => _ .DependsOn(TestFrameworks) .DependsOn(UnitTests) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { ReportGenerator(s => s @@ -188,6 +200,7 @@ class Build : NukeBuild Target TestFrameworks => _ => _ .DependsOn(Compile) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { var testCombinations = @@ -227,6 +240,7 @@ from framework in supportedFrameworks .DependsOn(UnitTests) .DependsOn(CodeCoverage) .DependsOn(CalculateNugetVersion) + .OnlyWhenDynamic(() => SourceChangesDetected()) .Executes(() => { DotNetPack(s => s @@ -258,11 +272,36 @@ from framework in supportedFrameworks }); Target SpellCheck => _ => _ + .OnlyWhenDynamic(() => DocumentationChangesDetected()) .Executes(() => { Node($"{YarnCli} install --silent", workingDirectory: RootDirectory); Node($"{YarnCli} --silent run cspell --no-summary", workingDirectory: RootDirectory, customLogger: (_, msg) => Error(msg)); }); + + bool DocumentationChangesDetected() + { + return Changes.Any(x => x.StartsWith("docs")); + } + + bool SourceChangesDetected() + { + return Changes.Any(x => !x.StartsWith("docs")); + } + + IEnumerable Changes + { + get + { + using var repo = new Repository(GitRepository.LocalDirectory); + + return repo.Diff.Compare(repo.Branches["develop"].Tip.Tree, + repo.Branches[repo.Head.FriendlyName].Tip.Tree) + .Where(x => x.Exists) + .Select(x => x.Path); + } + } + bool IsTag => BranchSpec != null && BranchSpec.Contains("refs/tags", StringComparison.InvariantCultureIgnoreCase); } diff --git a/Build/_build.csproj b/Build/_build.csproj index b73d4f73d0..e60e653e3a 100644 --- a/Build/_build.csproj +++ b/Build/_build.csproj @@ -22,6 +22,7 @@ + diff --git a/package.json b/package.json index 4c21a44ce7..6d8b3d61b5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "version": "1.0.0", "scripts": { - "cspell": "cspell --config ./cSpell.json ./**/*.md --no-progress" + "cspell": "cspell --config ./cSpell.json ./docs/**/*.md --no-progress" }, "dependencies": { "cspell": "^6.18.1" From a5da7641f33636d7f050d8caf1c205227ced85a0 Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 12:04:08 +0100 Subject: [PATCH 2/9] Minor code structure improvements --- Build/Build.cs | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Build/Build.cs b/Build/Build.cs index 88266eb120..6f770713f2 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -70,7 +70,7 @@ class Build : NukeBuild string YarnCli => ToolPathResolver.GetPackageExecutable("Yarn.MSBuild", "yarn.js", "1.22.19"); Target Clean => _ => _ - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { EnsureCleanDirectory(ArtifactsDirectory); @@ -78,7 +78,7 @@ class Build : NukeBuild }); Target CalculateNugetVersion => _ => _ - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { SemVer = GitVersion.SemVer; @@ -98,7 +98,7 @@ class Build : NukeBuild Target Restore => _ => _ .DependsOn(Clean) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { DotNetRestore(s => s @@ -109,7 +109,7 @@ class Build : NukeBuild Target Compile => _ => _ .DependsOn(Restore) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { DotNetBuild(s => s @@ -124,7 +124,7 @@ class Build : NukeBuild Target ApiChecks => _ => _ .DependsOn(Compile) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { DotNetTest(s => s @@ -136,7 +136,7 @@ class Build : NukeBuild Target UnitTests => _ => _ .DependsOn(Compile) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { Project[] projects = new[] @@ -183,7 +183,7 @@ class Build : NukeBuild Target CodeCoverage => _ => _ .DependsOn(TestFrameworks) .DependsOn(UnitTests) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { ReportGenerator(s => s @@ -200,7 +200,7 @@ class Build : NukeBuild Target TestFrameworks => _ => _ .DependsOn(Compile) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { var testCombinations = @@ -240,7 +240,7 @@ from framework in supportedFrameworks .DependsOn(UnitTests) .DependsOn(CodeCoverage) .DependsOn(CalculateNugetVersion) - .OnlyWhenDynamic(() => SourceChangesDetected()) + .OnlyWhenDynamic(() => HasSourceChanges) .Executes(() => { DotNetPack(s => s @@ -272,7 +272,7 @@ from framework in supportedFrameworks }); Target SpellCheck => _ => _ - .OnlyWhenDynamic(() => DocumentationChangesDetected()) + .OnlyWhenDynamic(() => HasDocumentationChanges) .Executes(() => { Node($"{YarnCli} install --silent", workingDirectory: RootDirectory); @@ -280,26 +280,26 @@ from framework in supportedFrameworks customLogger: (_, msg) => Error(msg)); }); - bool DocumentationChangesDetected() - { - return Changes.Any(x => x.StartsWith("docs")); - } + bool HasDocumentationChanges => + Changes.Any(x => x.StartsWith("docs")); - bool SourceChangesDetected() - { - return Changes.Any(x => !x.StartsWith("docs")); - } + bool HasSourceChanges => + Changes.Any(x => !x.StartsWith("docs")); - IEnumerable Changes + string[] Changes { get { using var repo = new Repository(GitRepository.LocalDirectory); - return repo.Diff.Compare(repo.Branches["develop"].Tip.Tree, - repo.Branches[repo.Head.FriendlyName].Tip.Tree) - .Where(x => x.Exists) - .Select(x => x.Path); + Tree targetBranch = repo.Branches["develop"].Tip.Tree; + Tree workingDir = repo.Branches[repo.Head.FriendlyName].Tip.Tree; + + return repo.Diff + .Compare(targetBranch, workingDir) + .Where(x => x.Exists) + .Select(x => x.Path) + .ToArray(); } } From 1f83aacf7f48fab1a5c3e7c7f2aac9400e308bfc Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 12:08:09 +0100 Subject: [PATCH 3/9] Remove spellcheck.yml --- .github/workflows/spellcheck.yml | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 .github/workflows/spellcheck.yml diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml deleted file mode 100644 index 18fc1a93b7..0000000000 --- a/.github/workflows/spellcheck.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Documentation Checks - -on: - push: - branches: - - develop - paths: - # This ensures the check will only be run when something changes in the docs content - - "docs/**/*" # or whatever the path to the markdown / docs files happens to be - pull_request: - branches: - - develop - paths: - - "docs/**/*" -jobs: - spellcheck: - name: "Docs: Spellcheck" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Check out the code - - name: Run NUKE spell check - run: ./build.sh --target SpellCheck From 7aceff22f59fb557ec881b414a1ed2b468376563 Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 12:08:37 +0100 Subject: [PATCH 4/9] Use a additional parameter to get the PR target branch --- .github/workflows/build.yml | 1 + Build/Build.cs | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a865c8a28..33b52df22e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,6 +35,7 @@ jobs: env: BranchSpec: ${{ github.ref }} BuildNumber: ${{ github.run_number }} + BaseRef: ${{ github.event.pull_request.base.ref }} ApiKey: ${{ secrets.NUGETAPIKEY }} - name: coveralls diff --git a/Build/Build.cs b/Build/Build.cs index 6f770713f2..5c35686bc4 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -38,6 +38,9 @@ class Build : NukeBuild [Parameter("An incrementing build number as provided by the build engine")] readonly string BuildNumber; + [Parameter("The target branch for the pull request")] + readonly string BaseRef; + [Parameter("The key to push to Nuget")] readonly string ApiKey; @@ -292,9 +295,9 @@ string[] Changes { using var repo = new Repository(GitRepository.LocalDirectory); - Tree targetBranch = repo.Branches["develop"].Tip.Tree; + Tree targetBranch = repo.Branches[BaseRef].Tip.Tree; Tree workingDir = repo.Branches[repo.Head.FriendlyName].Tip.Tree; - + return repo.Diff .Compare(targetBranch, workingDir) .Where(x => x.Exists) From 035e80140c1c3e352de42698ab0cc62289d7da20 Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 12:14:15 +0100 Subject: [PATCH 5/9] Add missing env variable on the test jobs --- .github/workflows/build.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 33b52df22e..34d6a41074 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,12 +1,6 @@ name: build -on: - pull_request: - paths-ignore: - - docs/** - push: - paths-ignore: - - docs/** +on: [push, pull_request] jobs: build: @@ -72,3 +66,5 @@ jobs: - name: Run NUKE run: ./build.sh UnitTests + env: + BaseRef: ${{ github.event.pull_request.base.ref }} From d9bb3002813d26a12d3d0074438960b01c85aa7f Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 12:34:35 +0100 Subject: [PATCH 6/9] Use default branch name --- .nuke/build.schema.json | 4 ++++ Build/Build.cs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index a917c108cb..5e6746b63e 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -10,6 +10,10 @@ "type": "string", "description": "The key to push to Nuget" }, + "BaseRef": { + "type": "string", + "description": "The target branch for the pull request" + }, "BranchSpec": { "type": "string", "description": "A branch specification such as develop or refs/pull/1775/merge" diff --git a/Build/Build.cs b/Build/Build.cs index 5c35686bc4..a9279d43b4 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -295,7 +295,9 @@ string[] Changes { using var repo = new Repository(GitRepository.LocalDirectory); - Tree targetBranch = repo.Branches[BaseRef].Tip.Tree; + string baseRef = BaseRef ?? "develop"; + + Tree targetBranch = repo.Branches[baseRef].Tip.Tree; Tree workingDir = repo.Branches[repo.Head.FriendlyName].Tip.Tree; return repo.Diff From 112dd2c01d8df02a83ebd1001b81b5ef9df8b4f4 Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 14:05:20 +0100 Subject: [PATCH 7/9] Fix misleading naming of source branch --- Build/Build.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Build/Build.cs b/Build/Build.cs index a9279d43b4..d2d9b4b9e5 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -298,10 +298,10 @@ string[] Changes string baseRef = BaseRef ?? "develop"; Tree targetBranch = repo.Branches[baseRef].Tip.Tree; - Tree workingDir = repo.Branches[repo.Head.FriendlyName].Tip.Tree; + Tree sourceBranch = repo.Branches[repo.Head.FriendlyName].Tip.Tree; return repo.Diff - .Compare(targetBranch, workingDir) + .Compare(targetBranch, sourceBranch) .Where(x => x.Exists) .Select(x => x.Path) .ToArray(); From 37fbe54d44adb4fd2d7be944ce320cb843db8bef Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 14:32:28 +0100 Subject: [PATCH 8/9] Run all targets if pull request base ref is `null` --- .github/workflows/build.yml | 2 +- .nuke/build.schema.json | 8 ++++---- Build/Build.cs | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 34d6a41074..64b8c85c28 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: env: BranchSpec: ${{ github.ref }} BuildNumber: ${{ github.run_number }} - BaseRef: ${{ github.event.pull_request.base.ref }} + PullRequestBase: ${{ github.event.pull_request.base.ref }} ApiKey: ${{ secrets.NUGETAPIKEY }} - name: coveralls diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 5e6746b63e..37dcfce118 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -10,10 +10,6 @@ "type": "string", "description": "The key to push to Nuget" }, - "BaseRef": { - "type": "string", - "description": "The target branch for the pull request" - }, "BranchSpec": { "type": "string", "description": "A branch specification such as develop or refs/pull/1775/merge" @@ -70,6 +66,10 @@ "type": "string" } }, + "PullRequestBase": { + "type": "string", + "description": "The target branch for the pull request" + }, "Root": { "type": "string", "description": "Root directory during build execution" diff --git a/Build/Build.cs b/Build/Build.cs index d2d9b4b9e5..2925167435 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -39,7 +39,7 @@ class Build : NukeBuild readonly string BuildNumber; [Parameter("The target branch for the pull request")] - readonly string BaseRef; + readonly string PullRequestBase; [Parameter("The key to push to Nuget")] readonly string ApiKey; @@ -73,7 +73,7 @@ class Build : NukeBuild string YarnCli => ToolPathResolver.GetPackageExecutable("Yarn.MSBuild", "yarn.js", "1.22.19"); Target Clean => _ => _ - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { EnsureCleanDirectory(ArtifactsDirectory); @@ -81,7 +81,7 @@ class Build : NukeBuild }); Target CalculateNugetVersion => _ => _ - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { SemVer = GitVersion.SemVer; @@ -101,7 +101,7 @@ class Build : NukeBuild Target Restore => _ => _ .DependsOn(Clean) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { DotNetRestore(s => s @@ -112,7 +112,7 @@ class Build : NukeBuild Target Compile => _ => _ .DependsOn(Restore) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { DotNetBuild(s => s @@ -127,7 +127,7 @@ class Build : NukeBuild Target ApiChecks => _ => _ .DependsOn(Compile) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { DotNetTest(s => s @@ -139,7 +139,7 @@ class Build : NukeBuild Target UnitTests => _ => _ .DependsOn(Compile) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { Project[] projects = new[] @@ -186,7 +186,7 @@ class Build : NukeBuild Target CodeCoverage => _ => _ .DependsOn(TestFrameworks) .DependsOn(UnitTests) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { ReportGenerator(s => s @@ -203,7 +203,7 @@ class Build : NukeBuild Target TestFrameworks => _ => _ .DependsOn(Compile) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { var testCombinations = @@ -243,7 +243,7 @@ from framework in supportedFrameworks .DependsOn(UnitTests) .DependsOn(CodeCoverage) .DependsOn(CalculateNugetVersion) - .OnlyWhenDynamic(() => HasSourceChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasSourceChanges) .Executes(() => { DotNetPack(s => s @@ -275,7 +275,7 @@ from framework in supportedFrameworks }); Target SpellCheck => _ => _ - .OnlyWhenDynamic(() => HasDocumentationChanges) + .OnlyWhenDynamic(() => RunAllTargets || HasDocumentationChanges) .Executes(() => { Node($"{YarnCli} install --silent", workingDirectory: RootDirectory); @@ -295,9 +295,7 @@ string[] Changes { using var repo = new Repository(GitRepository.LocalDirectory); - string baseRef = BaseRef ?? "develop"; - - Tree targetBranch = repo.Branches[baseRef].Tip.Tree; + Tree targetBranch = repo.Branches[PullRequestBase].Tip.Tree; Tree sourceBranch = repo.Branches[repo.Head.FriendlyName].Tip.Tree; return repo.Diff @@ -308,5 +306,7 @@ string[] Changes } } + bool RunAllTargets => PullRequestBase == default; + bool IsTag => BranchSpec != null && BranchSpec.Contains("refs/tags", StringComparison.InvariantCultureIgnoreCase); } From e46e75ca26f4b18c02afbcfa1fd4df9437df3cd4 Mon Sep 17 00:00:00 2001 From: Lukas Gasselsberger Date: Sat, 7 Jan 2023 20:53:21 +0100 Subject: [PATCH 9/9] Clean up Build.cs --- Build/Build.cs | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/Build/Build.cs b/Build/Build.cs index 2925167435..41980e1044 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -87,14 +87,14 @@ class Build : NukeBuild SemVer = GitVersion.SemVer; if (IsPullRequest) { - Serilog.Log.Information( + Information( "Branch spec {branchspec} is a pull request. Adding build number {buildnumber}", BranchSpec, BuildNumber); SemVer = string.Join('.', GitVersion.SemVer.Split('.').Take(3).Union(new[] { BuildNumber })); } - Serilog.Log.Information("SemVer = {semver}", SemVer); + Information("SemVer = {semver}", SemVer); }); bool IsPullRequest => BranchSpec != null && BranchSpec.Contains("pull", StringComparison.InvariantCultureIgnoreCase); @@ -198,7 +198,7 @@ class Build : NukeBuild .SetAssemblyFilters("+FluentAssertions")); string link = TestResultsDirectory / "reports" / "index.html"; - Serilog.Log.Information($"Code coverage report: \x1b]8;;file://{link.Replace('\\', '/')}\x1b\\{link}\x1b]8;;\x1b\\"); + Information($"Code coverage report: \x1b]8;;file://{link.Replace('\\', '/')}\x1b\\{link}\x1b]8;;\x1b\\"); }); Target TestFrameworks => _ => _ @@ -289,23 +289,16 @@ from framework in supportedFrameworks bool HasSourceChanges => Changes.Any(x => !x.StartsWith("docs")); - string[] Changes - { - get - { - using var repo = new Repository(GitRepository.LocalDirectory); - - Tree targetBranch = repo.Branches[PullRequestBase].Tip.Tree; - Tree sourceBranch = repo.Branches[repo.Head.FriendlyName].Tip.Tree; - - return repo.Diff - .Compare(targetBranch, sourceBranch) - .Where(x => x.Exists) - .Select(x => x.Path) - .ToArray(); - } - } + string[] Changes => + Repository.Diff + .Compare(TargetBranch, SourceBranch) + .Where(x => x.Exists) + .Select(x => x.Path) + .ToArray(); + Repository Repository => new Repository(GitRepository.LocalDirectory); + Tree TargetBranch => Repository.Branches[PullRequestBase].Tip.Tree; + Tree SourceBranch => Repository.Branches[Repository.Head.FriendlyName].Tip.Tree; bool RunAllTargets => PullRequestBase == default; bool IsTag => BranchSpec != null && BranchSpec.Contains("refs/tags", StringComparison.InvariantCultureIgnoreCase);