From 1a80448dba33c3f7d98a54118ee987dc0bac9c8d Mon Sep 17 00:00:00 2001 From: AliReZa Sabouri Date: Wed, 11 Mar 2026 23:17:30 +0100 Subject: [PATCH 1/3] chore: update husky version to 0.9.0 in dotnet-tools.json --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 52da066..80c7f26 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "husky": { - "version": "0.8.0", + "version": "0.9.0", "commands": [ "husky" ], From df7dd098fcc8e32f62b4123e3108fdd355b8b224 Mon Sep 17 00:00:00 2001 From: Matt Kotsenas <51421+MattKotsenas@users.noreply.github.com> Date: Fri, 13 Mar 2026 07:15:37 -0700 Subject: [PATCH 2/3] fix: condition Touch on successful install to prevent race on first run (#168) When multiple MSBuild nodes run concurrently on first checkout, the mutex losers skip the install but the Touch task still tried to create install.stamp in the not-yet-created .husky/_/ directory, causing MSB3371 errors. Fix: capture the ExitCode from the install Exec and condition Touch on both exit code 0 and the .husky/_/ directory existing. Losers skip Touch entirely - no premature stamp, no error. --- docs/guide/automate.md | 3 ++- docs/guide/submodules.md | 9 ++++++++- src/Husky/Cli/AttachCommand.cs | 2 ++ src/Husky/Husky.csproj | 6 +++--- tests/HuskyTest/Cli/AttachCommandTests.cs | 10 ++++++---- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/guide/automate.md b/docs/guide/automate.md index d2eedad..099da89 100644 --- a/docs/guide/automate.md +++ b/docs/guide/automate.md @@ -31,7 +31,8 @@ To manually attach husky to your project, add the below code to one of your proj - + diff --git a/docs/guide/submodules.md b/docs/guide/submodules.md index 20070d4..002f095 100644 --- a/docs/guide/submodules.md +++ b/docs/guide/submodules.md @@ -34,10 +34,17 @@ The `attach` command offers a `--ignore-submodule` options that generates an MsB The generated block will look something like this, If you're attaching husky manually copy the target to your `.csproj` and adjust `WorkingDirectory` accordingly. ```xml:no-line-numbers:no-v-pre - + + + + + ``` diff --git a/src/Husky/Cli/AttachCommand.cs b/src/Husky/Cli/AttachCommand.cs index fc1f25f..09e45fa 100644 --- a/src/Husky/Cli/AttachCommand.cs +++ b/src/Husky/Cli/AttachCommand.cs @@ -83,9 +83,11 @@ private XElement GetTarget(string condition, string rootRelativePath) exec.SetAttributeValue("WorkingDirectory", rootRelativePath); target.Add(exec); + var huskyDir = Path.Combine(rootRelativePath, ".husky", "_"); var touch = new XElement("Touch"); touch.SetAttributeValue("Files", sentinelPath); touch.SetAttributeValue("AlwaysCreate", "true"); + touch.SetAttributeValue("Condition", $"Exists('{huskyDir}')"); target.Add(touch); var itemGroup = new XElement("ItemGroup"); diff --git a/src/Husky/Husky.csproj b/src/Husky/Husky.csproj index 4a1bf36..c31effb 100644 --- a/src/Husky/Husky.csproj +++ b/src/Husky/Husky.csproj @@ -68,12 +68,12 @@ - - - + + diff --git a/tests/HuskyTest/Cli/AttachCommandTests.cs b/tests/HuskyTest/Cli/AttachCommandTests.cs index 12f59a6..af66282 100644 --- a/tests/HuskyTest/Cli/AttachCommandTests.cs +++ b/tests/HuskyTest/Cli/AttachCommandTests.cs @@ -61,14 +61,16 @@ public async Task Attach_WhenParametersProvided_ShouldAddHuskyTargetElement() huskyTarget!.Descendants("Exec").Should().HaveCount(2); huskyTarget.Attribute("Inputs").Should().NotBeNull(); huskyTarget.Attribute("Outputs").Should().NotBeNull(); + + // Verify Touch is conditioned on directory existence huskyTarget.Descendants("Touch").Should().HaveCount(1); - huskyTarget.Descendants("Touch").First().Attribute("AlwaysCreate")?.Value.Should().Be("true"); + var touch = huskyTarget.Descendants("Touch").First(); + touch.Attribute("AlwaysCreate")?.Value.Should().Be("true"); + touch.Attribute("Condition")?.Value.Should().Contain("Exists("); + huskyTarget.Descendants("ItemGroup").Descendants("FileWrites").Should().HaveCount(1); _console.ReadOutputString().Trim().Should().Be("Husky dev-dependency successfully attached to this project."); - - huskyTarget.Attribute("AfterTargets")?.Value.Should().Be("Restore"); - huskyTarget.Attribute("BeforeTargets").Should().BeNull(); } [Fact] From 26d6487a6f98c5304a9e2ffbf75abcfd15c18f22 Mon Sep 17 00:00:00 2001 From: AliReZa Sabouri Date: Fri, 13 Mar 2026 15:16:42 +0100 Subject: [PATCH 3/3] build: bump to v0.9.1 --- docs/.vuepress/configs/version.ts | 2 +- src/Husky/Husky.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/.vuepress/configs/version.ts b/docs/.vuepress/configs/version.ts index b257d05..41236e3 100644 --- a/docs/.vuepress/configs/version.ts +++ b/docs/.vuepress/configs/version.ts @@ -1 +1 @@ -export const version: string = '0.9.0' +export const version: string = '0.9.1' diff --git a/src/Husky/Husky.csproj b/src/Husky/Husky.csproj index c31effb..c992fcc 100644 --- a/src/Husky/Husky.csproj +++ b/src/Husky/Husky.csproj @@ -7,7 +7,7 @@ enable latest Husky - 0.9.0 + 0.9.1 Husky AliReza Sabouri Git hooks made easy, woof!