Skip to content

Move template AssemblyInfo generation from FAKE files to MSBuild pack-time metadata#320

Draft
Copilot wants to merge 8 commits intomasterfrom
copilot/use-msbuild-assemblyinfo-generation
Draft

Move template AssemblyInfo generation from FAKE files to MSBuild pack-time metadata#320
Copilot wants to merge 8 commits intomasterfrom
copilot/use-msbuild-assemblyinfo-generation

Conversation

Copy link
Contributor

Copilot AI commented Mar 7, 2026

  • Inspect recent CI workflow runs and collect failing job logs
  • Reproduce the failure locally with targeted tests
  • Apply minimal fix for build/test flakiness
  • Re-run targeted validation and repository build
  • Run code review and CodeQL checks
  • Reply to the PR comment with the addressing commit hash
Original prompt

This section details on the original issue you should resolve

<issue_title>Use MsBuild assemblyInfo generation</issue_title>
<issue_description>Is your feature request related to a problem? Please describe.

We generate assemblyinfo in FAKE with

let generateAssemblyInfo _ =
, however it would be nice to generate all this through MsBuild.

Describe the solution you'd like

  • Find how to translate what we're putting into AssemblyInfo using msbuild primitives directly
  • We only want to generate most of this info during package time, since it could disrupt Incremental Builds
  • This should apply to all projects under src, so it would be ideal to update/add Directory.Build.props/Directory.Build.targets under the src folder.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.
</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits March 7, 2026 16:43
Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement assemblyInfo generation using MsBuild Move Library template AssemblyInfo generation from FAKE files to MSBuild pack-time metadata Mar 7, 2026
@TheAngryByrd
Copy link
Owner

@copilot add a test that verifies the assemblyinfo values are set in the dll after a dotnetpack

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the library template’s assembly metadata generation away from FAKE-generated AssemblyInfo.fs files and toward MSBuild-driven assembly info/metadata at pack time, with an added integration assertion to validate the resulting DLL metadata.

Changes:

  • Add integration assertions to ensure AssemblyInfo.fs is not generated and that key assembly attributes/metadata are present after DotnetPack.
  • Remove AssemblyInfo.fs from the library template project and introduce MSBuild Directory.Build.props/targets to generate assembly info + pack-time AssemblyMetadata.
  • Update the library template FAKE build script to pass MSBuild properties during packing (and remove git staging of generated AssemblyInfo files).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/MiniScaffold.Tests/Tests.fs Wires new asserts into the library template integration scenario.
tests/MiniScaffold.Tests/Asserts.fs Adds assertions for missing AssemblyInfo.fs and for assembly attribute/metadata values.
Content/Library/src/MyLib.1/MyLib.1.fsproj Stops compiling the template’s AssemblyInfo.fs.
Content/Library/src/MyLib.1/AssemblyInfo.fs Removes FAKE-generated assembly info source file from the template.
Content/Library/src/Directory.Build.props Enables MSBuild assembly info generation and sets Product.
Content/Library/src/Directory.Build.targets Adds pack-time AssemblyMetadata items gated by IsPacking.
Content/Library/build/build.fs Passes MSBuild version/metadata properties and no-ops the old assembly-info generation logic.

@TheAngryByrd
Copy link
Owner

@copilot address comments

Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
<AssemblyMetadata Include="ReleaseChannel" Value="$(AssemblyMetadataReleaseChannel)" Condition="'$(AssemblyMetadataReleaseChannel)' != ''" />
<AssemblyMetadata Include="GitHash" Value="$(AssemblyMetadataGitHash)" Condition="'$(AssemblyMetadataGitHash)' != ''" />
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="'$(AssemblyMetadataReleaseDate)' != ''">
Copy link
Owner

Choose a reason for hiding this comment

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

@copilot Are these needed if we’re setting them via FAKE?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes—these are still needed. FAKE is passing the values as MSBuild properties during pack, but MSBuild still needs the AssemblyAttribute items here to materialize those values into assembly metadata attributes in the compiled DLL. No UI changes in this PR.

Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot add a test that verifies the assemblyinfo values are set in the dll after a dotnetpack

Implemented in 1364acb. I added a targeted integration assertion that reads the packed DLL from the generated .nupkg after DotnetPack and verifies assembly/version metadata values. No UI changes in this PR.

@copilot address comments

Addressed in 1364acb. The review comments were applied: per-project Product metadata, pack-time-only stamping behavior in build flow, and a robust post-pack DLL metadata assertion with safe unload/cleanup. No UI changes in this PR.

Comment on lines +536 to +540
let generateAssemblyInfo _ =
let isNoop = true

let (|Fsproj|Csproj|Vbproj|) (projFileName: string) =
match projFileName with
| f when f.EndsWith("fsproj") -> Fsproj
| f when f.EndsWith("csproj") -> Csproj
| f when f.EndsWith("vbproj") -> Vbproj
| _ ->
failwith (sprintf "Project file %s not supported. Unknown project type." projFileName)

let releaseChannel =
match latestEntry.SemVer.PreRelease with
| Some pr -> pr.Name
| _ -> "release"

let getAssemblyInfoAttributes projectName = [
AssemblyInfo.Title(projectName)
AssemblyInfo.Product productName
AssemblyInfo.Version latestEntry.AssemblyVersion
AssemblyInfo.Metadata("ReleaseDate", latestEntry.Date.Value.ToString("o"))
AssemblyInfo.FileVersion latestEntry.AssemblyVersion
AssemblyInfo.InformationalVersion latestEntry.AssemblyVersion
AssemblyInfo.Metadata("ReleaseChannel", releaseChannel)
AssemblyInfo.Metadata("GitHash", Git.Information.getCurrentSHA1 (null))
]

let getProjectDetails (projectPath: string) =
let projectName = IO.Path.GetFileNameWithoutExtension(projectPath)

(projectPath,
projectName,
IO.Path.GetDirectoryName(projectPath),
(getAssemblyInfoAttributes projectName))

!!srcGlob
|> Seq.map getProjectDetails
|> Seq.iter (fun (projFileName, _, folderName, attributes) ->
match projFileName with
| Fsproj ->
AssemblyInfoFile.createFSharp
(folderName
</> "AssemblyInfo.fs")
attributes
| Csproj ->
AssemblyInfoFile.createCSharp
((folderName
</> "Properties")
</> "AssemblyInfo.cs")
attributes
| Vbproj ->
AssemblyInfoFile.createVisualBasic
((folderName
</> "My Project")
</> "AssemblyInfo.vb")
attributes
)
if isNoop then
()
Copy link
Owner

Choose a reason for hiding this comment

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

@copilot This should just be deleted. What are you even doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in c6c3c1a. I deleted the no-op GenerateAssemblyInfo target and removed its dependency wiring from Content/Library/build/build.fs, plus removed the stale GenerateAssemblyInfo target entry from Content/Library/README.md. No UI changes in this PR.

…graph

Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
@TheAngryByrd
Copy link
Owner

@copilot

  • apply these kinds of changes to Content/Console
  • Remove AssemblyInfo from the ProjLib, ProjConsole and ProjTest

Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot

  • apply these kinds of changes to Content/Console
  • Remove AssemblyInfo from the ProjLib, ProjConsole and ProjTest

Done in a37a01c.

Applied the AssemblyInfo migration pattern to Content/Console, removed FAKE AssemblyInfo generation there, and removed AssemblyInfo.fs from ProjLib and ProjConsole templates (ProjTest already had no AssemblyInfo file to remove). I also updated integration tests to assert these generated project templates do not produce AssemblyInfo.fs and switched the failure-injection hook off the removed function.

No UI changes in this PR (screenshot not applicable).

Copilot AI changed the title Move Library template AssemblyInfo generation from FAKE files to MSBuild pack-time metadata Move template AssemblyInfo generation from FAKE files to MSBuild pack-time metadata Mar 8, 2026
@TheAngryByrd TheAngryByrd requested a review from Copilot March 8, 2026 03:04
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

Comment on lines +233 to +240
finally
assemblyContext.Unload()

extractedDllDir
|> Option.iter (fun path ->
if Directory.Exists path then
Directory.Delete(path, true)
)
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

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

AssemblyLoadContext.Unload() does not guarantee immediate release of file handles; on Windows the extracted DLL can remain locked briefly, making Directory.Delete(path, true) flaky in CI. Consider loading the assembly from a stream (e.g., read bytes + LoadFromStream) or forcing unload completion (GC.Collect/WaitForPendingFinalizers loop) and/or retrying the directory delete to avoid intermittent failures.

Copilot uses AI. Check for mistakes.
@TheAngryByrd
Copy link
Owner

@copilot address build failures

Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use MsBuild assemblyInfo generation

3 participants