From 92eebb0750e135be54fdea44631aa4ef604d101c Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Fri, 28 Aug 2026 11:13:38 -0400 Subject: [PATCH 1/4] docs: Record the Windows commit-message hang as a known issue 1.0.0 ships #167 unfixed, so consumers should find that in the release notes rather than by waiting on a build that never starts. On Windows a build hangs with no output and no error when the HEAD commit message is large. The cause is a deadlock in BuildHelpers\Invoke-Git, which redirects git's output streams and waits for the process to exit before reading them; Get-BuildVariable calls it to populate $env:BHCommitMessage, so the payload is the whole commit message body. Initialize-PSBuild calls Set-BuildEnvironment, so any consumer building on Windows can reach it. The note carries the workaround and, more usefully, the reason continuous integration will not warn anyone: on a pull_request event the checked-out merge commit has a short message, so the build is green and the real message only becomes HEAD on the push to the default branch. Without that detail a consumer reasonably concludes their pipeline is fine. The fix belongs in BuildHelpers rather than in a workaround here, so that every consumer of Invoke-Git benefits rather than only this module. The diagnosis has been posted to the upstream issue, open since 2018 with the symptom but not the cause, and #167 moved to v1.1.0 because it is gated on the PowerShell org's adoption of BuildHelpers completing. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01U1Jhu7fgTRJq7LK5MuKteE --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84b6dd4..4678293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,36 @@ code coverage percentages were truncated to zero so coverage gating could not be used at all, and under Invoke-Build the coverage report was written in a format the threshold gate could not read. +### Known issue: Windows builds can hang on a large commit message + +On Windows, a build can hang **with no output and no error** when the HEAD +commit message is large — roughly 5.7 KB in measurement, though the exact +threshold is a pipe-buffer size rather than a fixed number. Linux and macOS +have a larger buffer and do not reach it at these sizes. + +This is not new in 1.0.0 and it is not PowerShellBuild's own defect. It is a +deadlock in `BuildHelpers\Invoke-Git`, which redirects git's output streams +and then waits for the process to exit *before* reading them; when git writes +more than the pipe holds, neither side can proceed. `Get-BuildVariable` calls +it to populate `$env:BHCommitMessage`, so the payload is the whole commit +message body. It is listed here because `Initialize-PSBuild` calls +`Set-BuildEnvironment`, so any consumer building on Windows can hit it, and a +silent hang is a hard failure to diagnose without knowing the cause. + +**Workaround:** keep commit messages under a few kilobytes. If you squash-merge +pull requests, use a short squash body — the full description stays on the +pull request either way. Note that continuous integration will not warn you: +on a `pull_request` event the checked-out merge commit has a short message, so +the build is green, and the real message only becomes HEAD on the push to your +default branch. + +Tracked upstream as +[RamblingCookieMonster/BuildHelpers#86](https://github.com/RamblingCookieMonster/BuildHelpers/issues/86) +and here as +[#167](https://github.com/psake/PowerShellBuild/issues/167). The fix belongs in +BuildHelpers rather than in a workaround here, so that every consumer of +`Invoke-Git` gets it rather than only this module. + Everything below is the detail, one entry per issue. ### Changed From 2bcb78cc4c983f1c361def8417eedb698980ee23 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Fri, 28 Aug 2026 12:51:39 -0400 Subject: [PATCH 2/4] docs: Correct the known-issue note to cover the second failure mode Review of this pull request caught that the note was only half true. It described the hang as size-dependent, which tells a consumer that keeping commit messages short makes them safe. It does not. Closed PR #168 established a second face of the same defect: Invoke-Git deadlocks inside a PowerShell background job whatever the output size -- an 85-byte commit message and a five-byte rev-parse both hang. So calling Initialize-PSBuild or Set-BuildEnvironment from Start-Job hangs unconditionally, and no message-length discipline helps. A consumer following the note as written would conclude their pipeline was safe. Also adds recovery guidance, which the note lacked entirely: shortening the message releases an already-hung build, and nothing needs cleaning up because the build never started. Caught in review of #202. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01U1Jhu7fgTRJq7LK5MuKteE --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4678293..d2e17ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,17 @@ on a `pull_request` event the checked-out merge commit has a short message, so the build is green, and the real message only becomes HEAD on the push to your default branch. +**If a build is already hung**, shortening the message releases it — +`git commit --amend` locally, or fast-forward a checkout that is sitting on the +offending commit. There is nothing to clean up; the build never started. + +**Size is not the only trigger.** `Invoke-Git` also deadlocks inside a +PowerShell background job *whatever* the output size — an 85-byte commit +message and a five-byte `git rev-parse` both hang. So calling +`Initialize-PSBuild` or `Set-BuildEnvironment` from `Start-Job` hangs +unconditionally, short messages included, and no message-length discipline +helps. Run them in the foreground, or in a child process you can time out. + Tracked upstream as [RamblingCookieMonster/BuildHelpers#86](https://github.com/RamblingCookieMonster/BuildHelpers/issues/86) and here as From 3fd846cd2a43de0fe402dd30917ebf560b02f989 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Fri, 28 Aug 2026 13:10:22 -0400 Subject: [PATCH 3/4] docs: List LocalizedData.tests.ps1 in the repository instructions The test-file table in repository-specific.instructions.md was corrected in #188, which found it listing 5 of the 15 files that existed. #187 then added tests/LocalizedData.tests.ps1 without adding a row -- the same omission, one merge later. Folded into this documentation-only pull request rather than opened separately because it is a single row in a table two sibling pull requests are already amending, and leaving it would mean the table is wrong again the moment they land. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01U1Jhu7fgTRJq7LK5MuKteE --- instructions/repository-specific.instructions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/instructions/repository-specific.instructions.md b/instructions/repository-specific.instructions.md index 683a1d1..984f15c 100644 --- a/instructions/repository-specific.instructions.md +++ b/instructions/repository-specific.instructions.md @@ -263,6 +263,7 @@ own floor is **Pester 6.0.0** as of psake/PowerShellBuild#172, matching what CI | `IBTasks.tests.ps1` | Invoke-Build task definitions and the settings they reference | | `Initialize-PSBuild.tests.ps1` | Build environment initialization | | `Invoke-PSBuildModuleSigning.tests.ps1` | Authenticode signing of module files | +| `LocalizedData.tests.ps1` | How the module resolves its user-facing strings at import | | `Manifest.tests.ps1` | Module manifest validity | | `Meta.tests.ps1` | Text file formatting across the repository | | `New-PSBuildFileCatalog.tests.ps1` | Catalog (`.cat`) file creation | From b994a75602b0ec6b938936fb698f4556f3fa53b2 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Fri, 28 Aug 2026 14:08:37 -0400 Subject: [PATCH 4/4] docs: Move the known issue out of the changelog and into the README The changelog was the wrong home on three counts, and the review of this pull request said so before I argued past it. Keep a Changelog, which this file declares it follows, defines six change types: Added, Changed, Deprecated, Removed, Fixed, Security. The note was a seventh, sitting in the file's section list alongside the real ones. This repository's own rule says CHANGELOG.md documents user-facing *changes* to the shipped module. A known issue is not a change. And it is not new to this version. It is a BuildHelpers defect that affects 0.8.x identically, so a release-scoped entry has the wrong shape for a bug that spans every release including ones already shipped. The README is version-agnostic and is where someone whose build hangs with no output would look. Nothing is lost: the note keeps the cause, the threshold, the recovery step, the reason continuous integration stays green, and the background-job trigger that message length does not fix. For the record on how it got here: the reviewer flagged the changelog placement, and I suppressed the finding by citing the decision comment on #167 as mandating it. That comment was mine, written an hour earlier, so the justification was circular. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01U1Jhu7fgTRJq7LK5MuKteE --- CHANGELOG.md | 41 ----------------------------------------- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2e17ae..84b6dd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,47 +36,6 @@ code coverage percentages were truncated to zero so coverage gating could not be used at all, and under Invoke-Build the coverage report was written in a format the threshold gate could not read. -### Known issue: Windows builds can hang on a large commit message - -On Windows, a build can hang **with no output and no error** when the HEAD -commit message is large — roughly 5.7 KB in measurement, though the exact -threshold is a pipe-buffer size rather than a fixed number. Linux and macOS -have a larger buffer and do not reach it at these sizes. - -This is not new in 1.0.0 and it is not PowerShellBuild's own defect. It is a -deadlock in `BuildHelpers\Invoke-Git`, which redirects git's output streams -and then waits for the process to exit *before* reading them; when git writes -more than the pipe holds, neither side can proceed. `Get-BuildVariable` calls -it to populate `$env:BHCommitMessage`, so the payload is the whole commit -message body. It is listed here because `Initialize-PSBuild` calls -`Set-BuildEnvironment`, so any consumer building on Windows can hit it, and a -silent hang is a hard failure to diagnose without knowing the cause. - -**Workaround:** keep commit messages under a few kilobytes. If you squash-merge -pull requests, use a short squash body — the full description stays on the -pull request either way. Note that continuous integration will not warn you: -on a `pull_request` event the checked-out merge commit has a short message, so -the build is green, and the real message only becomes HEAD on the push to your -default branch. - -**If a build is already hung**, shortening the message releases it — -`git commit --amend` locally, or fast-forward a checkout that is sitting on the -offending commit. There is nothing to clean up; the build never started. - -**Size is not the only trigger.** `Invoke-Git` also deadlocks inside a -PowerShell background job *whatever* the output size — an 85-byte commit -message and a five-byte `git rev-parse` both hang. So calling -`Initialize-PSBuild` or `Set-BuildEnvironment` from `Start-Job` hangs -unconditionally, short messages included, and no message-length discipline -helps. Run them in the foreground, or in a child process you can time out. - -Tracked upstream as -[RamblingCookieMonster/BuildHelpers#86](https://github.com/RamblingCookieMonster/BuildHelpers/issues/86) -and here as -[#167](https://github.com/psake/PowerShellBuild/issues/167). The fix belongs in -BuildHelpers rather than in a workaround here, so that every consumer of -`Invoke-Git` gets it rather than only this module. - Everything below is the detail, one entry per issue. ### Changed diff --git a/README.md b/README.md index 3dfbf51..9e5e694 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,50 @@ $PSBPreference.Test.CodeCoverage.Enabled = $false ![Example](./media/ib_example.png) +## Known issues + +### Windows builds can hang on a large commit message + +On Windows a build can hang with **no output and no error** when the HEAD +commit message is large — roughly 5.7 KB in measurement, though the real +limit is a pipe-buffer size rather than a fixed number. Linux and macOS +have a larger buffer and do not reach it at these sizes. + +This is not a defect in PowerShellBuild and is not specific to any +version. It is a deadlock in `BuildHelpers\Invoke-Git`, which redirects +git's output streams and then waits for the process to exit *before* +reading them; when git writes more than the pipe holds, neither side can +proceed. `Get-BuildVariable` calls it to populate `$env:BHCommitMessage`, +so the payload is the whole commit message body. It reaches you because +`Initialize-PSBuild` calls `Set-BuildEnvironment`. + +**Keep commit messages under a few kilobytes.** If you squash-merge pull +requests, use a short squash body — the full description stays on the +pull request either way. + +**If a build is already hung**, shortening the message releases it: +`git commit --amend` locally, or fast-forward a checkout sitting on the +offending commit. Nothing needs cleaning up, because the build never +started. + +**Continuous integration will not warn you.** On a `pull_request` event +the checked-out merge commit has a short message, so the build is green; +the real message only becomes HEAD on the push to your default branch. + +**Size is not the only trigger.** `Invoke-Git` also deadlocks inside a +PowerShell background job *whatever* the output size — an 85-byte commit +message and a five-byte `git rev-parse` both hang. Calling +`Initialize-PSBuild` or `Set-BuildEnvironment` from `Start-Job` therefore +hangs unconditionally, and no message-length discipline helps. Run them in +the foreground, or in a child process you can time out. + +Tracked upstream as +[RamblingCookieMonster/BuildHelpers#86](https://github.com/RamblingCookieMonster/BuildHelpers/issues/86) +and here as +[#167](https://github.com/psake/PowerShellBuild/issues/167). The fix +belongs in BuildHelpers rather than in a workaround here, so that every +consumer of `Invoke-Git` gets it rather than only this module. + [github-actions-badge]: https://github.com/psake/PowerShellBuild/actions/workflows/test.yml/badge.svg [github-actions-badge-publish]: https://github.com/psake/PowerShellBuild/actions/workflows/publish.yaml/badge.svg?event=release [github-actions-build]: https://github.com/psake/PowerShellBuild/actions