I have for the first time made something I want to share on NuGet, but I am not sure how this "release preparation" is done.
At the moment my following steps are:
MyAssembly
) in AssemblyInfo.cs
from 1.0.0.0
to 1.1.0.0
nuget pack -prop configuration=release
== MyAssembly.1.1.0.0.nupkg
)nuget push MyAssembly.1.1.0.0.nupkg
)MyAssembly
(e.g. MyAssembly.Web.Mvc
gets its MyAssembly
updated from v1.0.0.0
-> v1.1.0.0
using the NuGet Package Manager) defined in packages.configAssemblyInfo.cs
of MyAssembly.Web.Mvc
to 1.1.0.0
, build release, NuGet pack and publishThis is some steps that are a PITA, and I will some day make an error and break the release.
This got me think, am I missing a crucial point, am I doing all this wrong?
UPDATE
Based on the knowledge @ialekseev provided, I have now created this:
Build.ps1
Param(
[Parameter(Mandatory=$true)]
[string]$version,
[string]$configuration = "Release",
[boolean]$tests = $false,
[boolean]$publish = $false,
[boolean]$pack = $false,
[string]$outputFolder = "build\packages"
)
# Include build functions
. "./BuildFunctions.ps1"
# The solution we are building
$solution = "NerveFramework.sln"
$assemblies = "NerveFramework", "NerveFramework.Web", "NerveFramework.Web.Mvc", "NerveFramework.Web.WebApi"
# Start by changing the assembly version
Write-Host "Changing the assembly versions to '$version'..."
$assemblyInfos = Get-ChildItem $assemblies -Filter "AssemblyInfo.cs" -Recurse | Resolve-Path -Relative
foreach ($assemblyInfo in $assemblyInfos) {
ChangeAssemblyVersion $assemblyInfo $version
}
# Build the entire solution
Write-Host "Cleaning and building $solution (Configuration: $configuration)"
BuildSolution $solution $configuration
# Change dependency version on all depending assemblies
Write-Host "Changing the NerveFramework(s) NuGet Spec version dependencies to '$version'..."
$nuspecs = Get-ChildItem $assemblies -Filter "NerveFramework*.nuspec" -Recurse | Resolve-Path -Relative
foreach ($nuspec in $nuspecs) {
ChangeNugetSpecDependencyVersion $nuspec "NerveFramework" $version
}
# Pack the assemblies and move to output folder
if ($pack) {
Write-Host "Packaging projects..."
$projects = Get-ChildItem $assemblies -Filter "NerveFramework*.csproj" -Recurse | Resolve-Path -Relative
foreach ($project in $projects) {
PackProject $project $configuration $outputFolder
}
}
# Publish the assemblies
if ($publish) {
Write-Host "Publishing packages..."
$packages = Get-ChildItem $outputFolder -Filter "*$version.nupkg" -Recurse | Resolve-Path -Relative
foreach ($package in $packages) {
PublishPackage $package
}
}
BuildFunctions.ps1
Function BuildSolution() {
Param(
[Parameter(Mandatory=$true)]
[string]$solution,
[Parameter(Mandatory=$true)]
[string]$configuration
)
# Set the path to the .NET folder in order to use "msbuild.exe"
$env:PATH = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
Invoke-Expression "msbuild.exe $solution /nologo /v:m /p:Configuration=$configuration /t:Clean"
Invoke-Expression "msbuild.exe $solution /nologo /v:m /p:Configuration=$configuration /clp:ErrorsOnly"
}
Function ChangeAssemblyVersion() {
Param(
[Parameter(Mandatory=$true)]
[string]$filePath,
[Parameter(Mandatory=$true)]
[string]$publishVersion
)
Write-Host "-- Updating '$filePath' to version '$publishVersion'"
$assemblyVersionPattern = 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
$assemblyVersion = 'AssemblyVersion("' + $publishVersion + '")';
$assemblyFileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
$assemblyFileVersion = 'AssemblyFileVersion("' + $publishVersion + '")';
(Get-Content $filePath -Encoding utf8) | ForEach-Object {
% { $_ -Replace $assemblyVersionPattern, $assemblyVersion } |
% { $_ -Replace $assemblyFileVersionPattern, $assemblyFileVersion }
} | Set-Content $filePath
}
Function ChangeNugetSpecDependencyVersion() {
Param(
[Parameter(Mandatory=$true)]
[string]$filePath,
[Parameter(Mandatory=$true)]
[string]$packageId,
[Parameter(Mandatory=$true)]
[string]$publishVersion
)
[xml] $toFile = (Get-Content $filePath)
$nodes = $toFile.SelectNodes("//package/metadata/dependencies/dependency[starts-with(@id, $packageId)]")
if ($nodes) {
foreach ($node in $nodes) {
$nodeId = $node.id
Write-Host "-- Updating '$nodeId' in '$filePath' to version '$publishVersion'"
$node.version = "[" + $publishVersion +"]"
$toFile.Save($filePath)
}
}
}
Function PackProject() {
Param(
[Parameter(Mandatory=$true)]
[string]$project,
[Parameter(Mandatory=$true)]
[string]$configuration,
[Parameter(Mandatory=$true)]
[string]$outputFolder
)
if (!(Test-Path -Path $outputFolder)) {
New-Item $outputFolder -Type Directory
}
Write-Host "-- Packaging '$project'"
Invoke-Expression ".nuget\NuGet.exe pack $project -OutputDirectory '$outputFolder' -Prop Configuration=$configuration"
}
Function PublishPackage() {
Param(
[Parameter(Mandatory=$true)]
[string]$package
)
Write-Host "-- Publishing '$package'"
Invoke-Expression ".nuget\NuGet.exe push $package"
}
Run like .\Build -version 1.2.0.0 -pack $true
You need to automate you procedure, because, yes, doing it manually is very error-prone process.
I usually write powershell/cmd scripts that could perform the following steps:
Then you could just run it locally to go through all these steps automatically. Also you could delegate some tasks to your Build-server (if you have one). E.g. Teamcity could take responsibility for building, running tests, and even publishing packages to NuGet. Anyway, I like to have all these scripts in my source control to be able to run them locally whenever I want to. If you are interested, you could review scripts I wrote for one of my projects on GitHub. Scripts are in build folder and publish_local.cmd is an entry point. Project has multiple NuGet dependencies, so, I believe it's similar to what you are trying to accomplish.
I know it's better to provide examples directly in the answer, but there are too many scripts to include here. If you have any questions, please be my guest.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With