Skip to content

Rewrite central package versions and version properties in .props files in fallout-migrate - #694

Open
ANcpLua wants to merge 3 commits into
Fallout-build:developfrom
ANcpLua:bugfix/migrate-central-package-versions
Open

ANcpLua wants to merge 3 commits into
Fallout-build:developfrom
ANcpLua:bugfix/migrate-central-package-versions

Conversation

@ANcpLua

@ANcpLua ANcpLua commented Oct 3, 2026 •

Copy link
Copy Markdown

Fixes #492 (central package management: Directory.Packages.props and VersionOverride are not rewritten, so restore fails with NU1010), including the 10.4.0 comment where the version is a property in an imported Version.props.

RewriteCsprojsStep now covers *.props files as well as *.csproj, and classifies version variables over all files before rewriting any of them. It builds on the variable handling from #478 (bump or decouple version variables) instead of replacing it.

What changed

  • Package items (PackageReference, PackageVersion, PackageDownload) are handled per element: a Nuke.X item becomes Fallout.X, and a literal Version or VersionOverride on it is pinned to the current Fallout version, whatever the attribute order. PackageDownload keeps its [exact] brackets. An item that is already Fallout.X keeps its pin.
  • A version variable used by a Nuke.* PackageVersion in one file and defined in another is bumped where it is defined. <NukeVersion> in an imported file is renamed to <FalloutVersion> and bumped.
  • A variable shared with an unrelated package across files is decoupled to $(FalloutVersion) as before. The property is only inserted when no file defines it yet.
  • An unreadable file contributes nothing to the classification; ApplyRewrite reports it as before.
  • The System.Security.Cryptography.Xml pin is still removed from *.csproj files only. A pin in a *.props file, such as a root Directory.Build.props, applies to every project in the repository, so it is kept.
  • The migration step skill and docs/Migration/from-nuke.md now mention *.props and central package versions.

Tests
Nine specs in RewriteCsprojsStepSpecs: central versions, the imported Version.props property, a variable defined in another file, a shared variable across files, VersionOverride, Version before Include, PackageDownload, an already-migrated pin that stays, and a Cryptography.Xml pin in a .props file that stays.

@avidenic is assigned to #492. If you have a change in progress, say so and I will close this one.

🤖 Generated with Claude Code

ANcpLua and others added 2 commits October 3, 2026 22:06
…es in fallout-migrate

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rate

Now that RewriteCsprojsStep also rewrites *.props files, a
System.Security.Cryptography.Xml reference in a root Directory.Build.props
was removed too. That reference applies to every project in the repository,
not only the build project, so it is kept.

Also mention *.props and central package versions in the migration step
skill and in docs/Migration/from-nuke.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ANcpLua
ANcpLua marked this pull request as ready for review October 6, 2026 21:56
@ANcpLua
ANcpLua requested a review from a team as a code owner October 6, 2026 21:56
Copilot AI balanced review requested due to automatic review settings October 6, 2026 21:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ChrisonSimtian ChrisonSimtian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blocking issue, the rest are optional.

Blocking: <FalloutVersion> is added to unrelated .csproj/.props files when any variable is ambiguous (reproduced, see the inline comment on line 206).

The design is sound: classifying version variables over all files first is the right fix for the imported Version.props case in #492. The specs are well chosen and follow the repo conventions.


content = EnsureFalloutVersionPropertyExists(content, ambiguousVariables, falloutVersionVariable, falloutVersion,
ref edits);
if (!variables.DefinesFalloutVersion)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproduced on c346a4a. <FalloutVersion> is inserted into every .csproj and .props file, not only the file that needs it.

Setup:

  • Directory.Packages.props: Nuke.Common and Serilog both use $(ToolsVersion) (ambiguous).
  • Version.props: defines ToolsVersion.
  • src/Lib.csproj: unrelated, uses no version variable.

Result: Lib.csproj gets <FalloutVersion>11.0.0</FalloutVersion> added to its first <PropertyGroup>. Version.props is affected too.

Cause: variables.Ambiguous is the same set for every file, and EnsureFalloutVersionPropertyExists only skips a file that already has <FalloutVersion>. Before this PR the classification was per file, so only the file with the ambiguity changed.

Suggestion: insert the property only into a file that contains a redirected $(FalloutVersion) reference. A spec asserting that unrelated files are unchanged would catch this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b54279c. <FalloutVersion> is now added only to a file where a reference was redirected to $(FalloutVersion). Added the spec you suggested: with your setup, Version.props and src/Lib.csproj stay unchanged.


// The literal value of a Version or VersionOverride attribute. PackageDownload needs an exact
// range (`[10.1.0]`), so the brackets stay outside the match.
private static readonly Regex literalVersionPattern = new(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A version range can be broken here.

For Version="[10.1.0,)" the match is 10.1.0,). The leading [ is consumed by the lookbehind. The result is Version="[11.0.0", which is an invalid range.

Ranges are rare on Nuke packages. Either skip values that contain ,, ( or ), or add a spec that shows the intended result.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b54279c. A value that contains ,, ( or ) is no longer matched, so a range is kept as written. The package name is still renamed. A spec covers [10.1.0,) and (10.1.0,11.0.0).

{
return path.ReadAllText();
}
catch (IOException)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReadOrEmpty catches only IOException. An UnauthorizedAccessException now crashes the run in this pre-pass. Before, ApplyRewrite would have reported it as a warning.

Suggestion: catch UnauthorizedAccessException too. Every file is also read twice (here and in ApplyRewrite). That is fine for repo-sized inputs, but worth knowing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b54279c. ReadOrEmpty now also catches UnauthorizedAccessException. ApplyRewrite in MigrationFileOperations caught only IOException too, so it also crashed before this PR. It now catches both and reports the file as a warning. No spec, because permission tests are not reliable on CI (for example when the runner is root).

@@ -204,7 +268,7 @@ private static (string content, int edits) RedirectAmbiguousVariablesToFalloutVe
// everything up to and including the opening `Version="` so it can be re-emitted
// unchanged while just swapping the variable reference.
var redirectPattern = new Regex(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern still needs Include before Version. Pass 1 now accepts either order, so <PackageVersion Version="$(X)" Include="Nuke.Common" /> is classified as ambiguous but never redirected to $(FalloutVersion).

Same gap before this PR, but it is now easier to hit with .props files. Optional: match the Version attribute separately from the Include attribute.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b54279c. Classification and redirect now use one pattern that reads the Include and Version attributes separately, in either order. A spec covers <PackageVersion Version="$(X)" Include="Nuke.Common" />.

// A variable also shared with a non-Fallout package is ambiguous: bumping it directly would
// change that unrelated package's version too, so it's decoupled instead — the Fallout
// reference is redirected to a dedicated $(FalloutVersion) property.
public static VersionVariables Collect(IEnumerable<string> contents)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ambiguity is now decided by variable name across all files. If $(Foo) is a per-project property, used by Fallout in project A and by an unrelated package in project B, then A is decoupled even though A's own definition is not shared.

The result is safe, only noisier. A short comment here would document the trade-off.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment on Collect in b54279c that documents this trade-off.

@"(?<=\bVersion(?:Override)?=""\[?)(?!\$\()[^""\[\]]+(?=\]?"")",
RegexOptions.Compiled);

// ProjectReference / Remove `Include="Nuke.X"` → `Include="Fallout.X"` — namespace only.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment drift: this says "ProjectReference / Remove", but the pattern still matches Include|Update|Remove. It also overlaps nukeIncludePattern. Please fix the comment, or merge the two patterns.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b54279c. Merged the two patterns into one nukeItemNamePattern (Include, Update or Remove). Pass 1 and pass 2 both use it, and the comment now matches.

…ut-migrate

Review feedback on the central package versions change:

- Add the FalloutVersion property only to a file where a reference was
  redirected to $(FalloutVersion). Before, every .csproj and .props file
  got the property when any version variable was shared with another package.
- Keep a version range such as [10.1.0,) as written. Before, only the lower
  bound was replaced, which left an invalid range.
- Report a file that can't be read because of missing permissions as a
  warning instead of stopping the run.
- Find a version variable when the Version attribute comes before Include.
- Merge the two Nuke. prefix patterns into one and document that ambiguity
  is decided by variable name over all files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ANcpLua

ANcpLua commented Oct 8, 2026 •

Copy link
Copy Markdown
Author

@ChrisonSimtian All 5 points are addressed in b54279c, with a reply on each thread. Ready for another review. (I can't re-request review myself, because I don't have triage permission on this repo.)

CI for b54279c is waiting for approval from a maintainer. Could you approve the two build runs? https://github.com/Fallout-build/Fallout/actions/runs/37745892640 and https://github.com/Fallout-build/Fallout/actions/runs/37745892575

@ChrisonSimtian
ChrisonSimtian self-requested a review October 8, 2026 09:21

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fallout-migrate: CPM repos fail to restore after migration (NU1010); Directory.Packages.props & VersionOverride not rewritten

3 participants