Repository navigation
Metadata commits authored as "Github Actions" count as meaningful after #179, so a split release can publish a different version than VERSION.md #185
Description
What's wrong
#179 (the fix for #157) moved bot detection into BotCommitFilter. It now matches "[bot]" and "github-actions" against the commit author only (KtsuBuild/Git/BotCommitFilter.cs:19, :31-35). The only subject patterns left are ProjectDirector and SyncFileContents.
KtsuBuild's own metadata commit matches neither author pattern:
- The subject is
[bot][skip ci] Update Metadata(KtsuBuild/Metadata/MetadataUpdateOptions.cs:26). - The fallback identity is
"Github Actions" <[email protected]>(KtsuBuild/Metadata/MetadataService.cs:116).KtsuBuild/Publishing/GitHubService.cs:30uses the same identity. actions/checkoutsets no identity, so this fallback is the identity that actually lands on the commit. EveryUpdate Metadatacommit in this repo's history is authoredGithub Actions.
"Github Actions" contains neither [bot] nor github-actions, because the pattern has a hyphen and the name has a space. Before #179, the patterns were also matched against the subject, so the [bot] prefix filtered these commits out.
The tests missed this because they model the metadata commit as Author = "github-actions[bot]", an identity KtsuBuild never commits with (KtsuBuild.Tests/Git/CommitAnalyzerTests.cs:161, KtsuBuild.Tests/Metadata/ChangelogGeneratorTests.cs:385).
CommitAnalyzer.HasMeaningfulCommits (KtsuBuild/Git/CommitAnalyzer.cs:71, :108-111) therefore treats the metadata commit as a meaningful human change.
Failure scenario (the split pipeline in this repo's own dotnet.yml)
The workflow runs ci --no-test --no-release, then ktsubuild release. Suppose the last tag is v1.2.3 and the only changes since are a dependabot bump plus its "Merge pull request …" commit.
cianalysesv1.2.3..GITHUB_SHA.- The dependabot commit is a bot commit and the merge matches the PR patterns, so the result is Prerelease.
VERSION.mdbecomes1.2.4-pre.1and is committed as[bot][skip ci] Update MetadatabyGithub Actions.- The packages are built at
1.2.4-pre.1.
releaseresolvesautooverv1.2.3..HEAD(KtsuBuild.Tool/Commands/ReleaseCommand.cs:79-88). That range now includes the metadata commit.- The metadata commit counts as meaningful and the .cs diff is empty, so the result is Patch, version
1.2.4.
- The metadata commit counts as meaningful and the .cs diff is empty, so the result is Patch, version
- The tag, GitHub release and zips come out as a non-prerelease
v1.2.4. The nupkgs, packed with--no-buildfrom VERSION.md, are1.2.4-pre.1.
This was reproduced with a scratch MSTest against CommitAnalyzer:
- The dependabot bump plus merge alone returns
Prerelease. - Adding
{Subject = "[bot][skip ci] Update Metadata", Author = "Github Actions"}returnsPatch.
A secondary effect hits single-job ci too. A metadata commit that never got tagged stays in the next run's range and forces at least a Patch where a Prerelease was due. That happens when a release is held by a gate, fails, or is skipped after metadata was committed.
Suggested fix
- Make
BotCommitFilterrecognise the identity and/or subject KtsuBuild itself commits with. Share one constant betweenMetadataService,GitHubServiceandBotCommitFilterso they cannot drift. - Matching the metadata commit subject is the most robust option. Switching the fallback identity to
github-actions[bot]alone would not cover historical commits or runners with a pre-set identity. - Update the tests to use the identity KtsuBuild really commits with.
Acceptance criteria
CommitAnalyzer.AnalyzeAsyncreturns the same increment whether or not a[bot][skip ci] Update Metadatacommit authored byGithub Actionsis in the range.- A standalone
releaseafterci --no-releaseresolves the same version thatciwrote to VERSION.md, when the range holds only bot and merge commits. - A human commit that mentions GitHub (A commit whose message mentions "GitHub" is treated as a bot commit: it gets a prerelease instead of a patch and is dropped from the changelog #157) is still treated as meaningful.
Activity
matt-edmondson commentedon Sep 28, 2026
Triage
ci --no-release/releaseflow, a range that holds only bot and merge commits can produce a non-prerelease tag and GitHub release (v1.2.4) whose nupkgs are1.2.4-pre.1. Nothing fails, so the mismatch reaches nuget.org and the releases page silently. A metadata commit that was never tagged also forces a Patch on the next single-jobcirun.KtsuBuild/Git(BotCommitFilter,CommitAnalyzer) plus the committer identity inMetadataService/GitHubService. Whoever landed Match bot patterns against the author, so human commits mentioning GitHub still count [patch] #179.Suggested next step: match the metadata commit's subject (
[bot][skip ci] Update Metadata) through one shared constant, and change the test fixtures to authorGithub Actions, which is the identity the tool actually commits as. Then check whether any release published since #179 already shipped with mismatched versions.Generated by Claude Code