Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ See https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-director
<Nullable>enable</Nullable>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
<PackageVersion Include="Fake.Core.Process" Version="6.2.0" />
<PackageVersion Include="Fake.Core.ReleaseNotes" Version="6.2.0" />
<PackageVersion Include="Fake.Core.Target" Version="6.2.0" />
<PackageVersion Include="Fake.DotNet.AssemblyInfoFile" Version="6.2.0" />
<PackageVersion Include="Fake.DotNet.Cli" Version="6.2.0" />
<PackageVersion Include="Fake.DotNet.Paket" Version="6.2.0" />
<PackageVersion Include="Fake.IO.FileSystem" Version="6.2.0" />
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ or
- `GenerateCoverageReport` - Code coverage is run during `DotnetTest` and this generates a report via [ReportGenerator](https://github.com/danielpalme/ReportGenerator).
- `ShowCoverageReport` - Shows the report generated in `GenerateCoverageReport`.
- `WatchTests` - Runs [dotnet watch](https://docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-3.0) with the test projects. Useful for rapid feedback loops.
- `GenerateAssemblyInfo` - Generates [AssemblyInfo](https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.applicationservices.assemblyinfo?view=netframework-4.8) for libraries.
- `GenerateAssemblyInfo` - Writes the version, the release date, the release channel and the git hash of the latest changelog entry into `src/AssemblyInfo.Build.props`, which `src/Directory.Build.props` imports, so that the SDK generates the assembly attributes of the libraries from it.
- `DotnetPack` - Runs [dotnet pack](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-pack). This includes running [Source Link](https://github.com/dotnet/sourcelink).
- `SourceLinkTest` - Runs a Source Link test tool to verify Source Links were properly generated.
- `PublishToNuGet` - Publishes the NuGet packages generated in `DotnetPack` to NuGet via [dotnet nuget push](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-nuget-push). Runs only from `Github Actions`.
Expand Down
106 changes: 77 additions & 29 deletions build/build.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
open System
open System.Xml.Linq
open Fake.Core
open Fake.DotNet
open Fake.Tools
Expand Down Expand Up @@ -28,6 +29,9 @@ let rootDirectory = __SOURCE_DIRECTORY__ </> ".."

let productName = "FSharp.Collections.Immutable"

/// The assembly information of the release. `src/Directory.Build.props` imports it, so that the SDK generates the attributes.
let assemblyInfoPropsPath = rootDirectory </> "src" </> "AssemblyInfo.Build.props"

let sln = rootDirectory </> "FSharp.Collections.Immutable.slnf"

let srcCodeGlob =
Expand Down Expand Up @@ -432,47 +436,90 @@ let watchTests _ =

cancelEvent.Cancel <- true

/// Writes the assembly information of the latest changelog entry in two places. `src/AssemblyInfo.Build.props` holds
/// the properties and the `AssemblyMetadata` items from which the SDK generates the assembly attributes, and
/// `src/Directory.Build.props` imports it, so a project sets only what is specific to it in its own project file.
/// `AssemblyInfo.fs` of each F# project in `src` holds the literals of `AssemblyVersionInformation`, which the code can
/// use at compile time. It has no attributes, because the SDK generates them.
let generateAssemblyInfo _ =

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
| _ -> failwithf "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
// The date is optional in a changelog entry
match latestEntry.Date with
| Some releaseDate -> AssemblyInfo.Metadata ("ReleaseDate", releaseDate.ToString ("o"))
// The date is optional in a changelog entry
let releaseDate = latestEntry.Date |> Option.map _.ToString("o")
let gitHash = Git.Information.getCurrentSHA1 (null)

let metadata = [
match releaseDate with
| Some date -> "ReleaseDate", date
| None -> ()
AssemblyInfo.FileVersion latestEntry.AssemblyVersion
AssemblyInfo.InformationalVersion latestEntry.AssemblyVersion
AssemblyInfo.Metadata ("ReleaseChannel", releaseChannel)
AssemblyInfo.Metadata ("GitHash", Git.Information.getCurrentSHA1 (null))
"ReleaseChannel", releaseChannel
"GitHash", gitHash
]

let getProjectDetails (projectPath : string) =
let projectName = IO.Path.GetFileNameWithoutExtension (projectPath)
let properties =
XElement (
"PropertyGroup",
XElement ("Product", productName),
XElement ("AssemblyVersion", latestEntry.AssemblyVersion),
XElement ("FileVersion", latestEntry.AssemblyVersion),
XElement ("InformationalVersion", latestEntry.AssemblyVersion),
// The git hash is in the metadata, so the SDK must not append the source revision to the informational version
XElement ("IncludeSourceRevisionInInformationalVersion", "false")
)

(projectPath, projectName, IO.Path.GetDirectoryName (projectPath), (getAssemblyInfoAttributes projectName))
let items =
XElement (
"ItemGroup",
metadata
|> List.map (fun (key, value) ->
XElement ("AssemblyMetadata", XAttribute ("Include", key), XAttribute ("Value", value))
)
)

!!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
)
let props =
XDocument (XComment " Auto-Generated by FAKE; do not edit ", XElement ("Project", properties, items))

// XDocument breaks lines as the operating system does, and the other generated file has "\n" everywhere
let propsText = props.ToString().ReplaceLineEndings "\n"

File.writeString false assemblyInfoPropsPath $"%s{propsText}\n"

let versionInformation projectName =
let literals = [
"AssemblyTitle", projectName
"AssemblyProduct", productName
"AssemblyVersion", latestEntry.AssemblyVersion
match releaseDate with
| Some date -> "AssemblyMetadata_ReleaseDate", date
| None -> ()
"AssemblyFileVersion", latestEntry.AssemblyVersion
"AssemblyInformationalVersion", latestEntry.AssemblyVersion
"AssemblyMetadata_ReleaseChannel", releaseChannel
"AssemblyMetadata_GitHash", gitHash
]

[
"// Auto-Generated by FAKE; do not edit"
"namespace System"
""
"module internal AssemblyVersionInformation ="
yield!
literals
|> List.map (fun (name, value) -> $" let [<Literal>] %s{name} = \"%s{value}\"")
]
|> String.concat "\n"

let writeVersionInformation (projectPath : string) =
// The project path is not null, so neither is the name
let projectName = IO.Path.GetFileNameWithoutExtension projectPath |> nonNull
File.writeString false (Path.getDirectory projectPath </> "AssemblyInfo.fs") $"%s{versionInformation projectName}\n"

!!(rootDirectory </> "src/**/*.fsproj")
|> Seq.iter writeVersionInformation

let dotnetPack ctx =
// Get release notes with properly-linked version number
Expand Down Expand Up @@ -534,6 +581,7 @@ let gitRelease _ =

!!(rootDirectory </> "src/**/AssemblyInfo.fs")
++ (rootDirectory </> "tests/**/AssemblyInfo.fs")
++ assemblyInfoPropsPath
|> Seq.iter (Git.Staging.stageFile "" >> ignore)

let msg = $"release: bump version to `%s{latestEntry.NuGetVersion}`\n\n%s{releaseNotesGitCommitFormat}"
Expand Down
1 change: 0 additions & 1 deletion build/build.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
<PackageReference Include="Fake.Core.Process" />
<PackageReference Include="Fake.Core.ReleaseNotes" />
<PackageReference Include="Fake.Core.Target" />
<PackageReference Include="Fake.DotNet.AssemblyInfoFile" />
<PackageReference Include="Fake.DotNet.Cli" />
<PackageReference Include="Fake.DotNet.Paket" />
<PackageReference Include="Fake.IO.FileSystem" />
Expand Down
15 changes: 15 additions & 0 deletions src/AssemblyInfo.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Auto-Generated by FAKE; do not edit -->
<Project>
<PropertyGroup>
<Product>FSharp.Collections.Immutable</Product>
<AssemblyVersion>1.0.0</AssemblyVersion>
<FileVersion>1.0.0</FileVersion>
<InformationalVersion>1.0.0</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>
<ItemGroup>
<AssemblyMetadata Include="ReleaseDate" Value="2020-02-23T00:00:00.0000000" />
<AssemblyMetadata Include="ReleaseChannel" Value="release" />
<AssemblyMetadata Include="GitHash" Value="59d59515d1f3a3ecee1bb208b9bc1378035e4694" />
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<Project>
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
<!-- The build script (FAKE) writes the assembly information of the release into this file, and the SDK generates the assembly attributes from it -->
<Import Project="AssemblyInfo.Build.props" Condition="Exists('$(MSBuildThisFileDirectory)AssemblyInfo.Build.props')" />
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPackable>true</IsPackable>
Expand Down
11 changes: 0 additions & 11 deletions src/FSharp.Collections.Immutable/AssemblyInfo.fs
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
// Auto-Generated by FAKE; do not edit
namespace System
open System.Reflection

[<assembly: AssemblyTitleAttribute("FSharp.Collections.Immutable")>]
[<assembly: AssemblyProductAttribute("FSharp.Collections.Immutable")>]
[<assembly: AssemblyVersionAttribute("1.0.0")>]
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-02-23T00:00:00.0000000")>]
[<assembly: AssemblyFileVersionAttribute("1.0.0")>]
[<assembly: AssemblyInformationalVersionAttribute("1.0.0")>]
[<assembly: AssemblyMetadataAttribute("ReleaseChannel","release")>]
[<assembly: AssemblyMetadataAttribute("GitHash","59d59515d1f3a3ecee1bb208b9bc1378035e4694")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Collections.Immutable"
Expand Down
Loading