NuGet is a free, open source package management system for
.NET platform, which helps in easy dependency management. Using NuGet very easy
for project owners to build and define package dependencies which will be
included in the package during the packaging process and later publish this to
the repository for usage by external users.
Users can later install the package by searching in the
NuGet source repository which will automatically download and install the
dependencies as well. You can use the NuGet command line utility to create
packages from a specification file and later publish them to the repository
whenever needed. If you want to automate the process of package creation and
publishing from a TFS build process, you can make use of custom PowerShell
scripts that can be invoked as part of the build process. The Team Foundation Build
template (TfvcTemplate.12.xaml) provides the capability to extend the build
process by using PowerShell scripts at stages like Pre build and Post build.
You can use the default template to run PowerShell and batch
(.bat) scripts before and after you compile your code, and before and after
your run your tests. During the script execution you can make use of the Team
foundation build environment variables to get key bits of data that you need
for your build process logic.
I've created a PowerShell module that contains the functions
that I need to build and publish a nuget package.
$ErrorActionPreference = "Stop"
Function Publish-NugetPackage
{
param
(
[Parameter(Mandatory =
$true,
Position = 0)]
[ValidateNotNullOrEmpty()]
[string] $Project
)
# Read the
product version from the assembly
$version
= Get-ChildItem
-Filter "$($Project).dll"
`
-Recurse `
-Path (Join-Path $env:TF_BUILD_BUILDDIRECTORY bin) `
-File | select -First 1 | select -expand VersionInfo |
select -expand ProductVersion
# Read the
contents of the nuspec file
$nuspecFile
= Get-ChildItem
-Filter "$($Project).nuspec"
`
-Recurse `
-Path $env:TF_BUILD_SOURCESDIRECTORY
-File | select -First 1
$nuspecContents
= Get-Content
$nuspecFile.FullName
# Replace the
version of the nuspec file with the assembly version
Set-Content
-Path $nuspecFile.FullName `
-Value
($nuspecContents -replace
"[0-9]+(\.([0-9]+|\*)){1,3} ", " $($version)
")
`
-Force
# Create the
nuget package
New-NugetPackage
$nuspecFile.FullName
# Fetch the
newly created nuget package
$nugetPackage
= Get-ChildItem
-Filter "*.nupkg"
`
-Recurse `
-Path $env:TF_BUILD_SOURCESDIRECTORY
-File | select -First 1
# Publish the
nuget package to nuget repository
Push-NugetPackage
$nugetPackage.FullName
}
Function New-NugetPackage
{
param
(
[Parameter(Mandatory =
$true,
Position = 0)]
[ValidateNotNull()]
[ValidateScript({Test-Path
$_})]
[String] $NuspecFile,
[Parameter(Position=
1)]
[ValidateScript({Test-Path
$_ -PathType
Leaf -Include
"nuget.exe"})]
[String] $NugetLocation =
(Join-Path $PSScriptRoot
"nuget.exe")
)
$command
= $NugetLocation
+ " pack $($NuspecFile)"
Invoke-Expression
$command
}
Function Push-NugetPackage
{
param
(
[Parameter(Position=
3)]
[string] $Source = "http://prajeeshnuget.azurewebsites.net/nuget",
[Parameter(Mandatory =
$true,
Position = 0)]
[ValidateNotNull()]
[ValidateScript({Test-Path
$_})]
[string] $PackagePath,
[Parameter(Position=
2)]
[string] $APIKey = "MY_NUGET_APIKEY",
[Parameter(Position=
1)]
[ValidateScript({Test-Path
$_ -PathType
Leaf -Include
"nuget.exe"})]
[String] $NugetLocation =
(Join-Path $PSScriptRoot
"nuget.exe")
)
$command
= $NugetLocation
+ " push $($PackagePath) $($APIKey)"
if(-not ([String]::IsNullOrEmpty($Source)))
{
$command
+= " -s
" +
$Source
}
Invoke-Expression
$command |
Out-Null
}
Export-ModuleMember -Function Publish*
The module contains logic to update the NuSpec file with the
latest product version from the assembly that is build. Once updated this file
will be used to create a nuget package and then published to the repository. As
you can see, I’ve used the TF_BUILD_SOURCESDIRECTORY and
TF_BUILD_BUILDDIRECTORY to get the source location and build location
respectively in the module. To read more about TF_BUILD variables, refer to the
link https://msdn.microsoft.com/en-us/library/hh850448.aspx.
I’ve created a script that I use to invoke the functions in
this module
param
(
[string]$Project
)
$exitCode = 0
trap
{
$Host.UI.WriteErrorLine($error[0].Exception.Message)
$Host.UI.WriteErrorLine($error[0].Exception.StackTrace)
if ($exitCode -eq
0)
{
$exitCode
= 1
}
}
Import-Module .\TFSNugetExtensions.psm1
Publish-NugetPackage $Project
exit $exitCode
The next step is to publish these scripts along with the
Nuget.exe file to the source control, so that I can refer these files as part
of my build definition. I’ve added these files into the BuildExtensions folder
in my team project
Now we can go ahead and create the build definition for our
project. While creating the build definition it’s important to create the
source settings mapping for the scripts folder so that they are also available
as part of the build process.
In the process tab, you can now call the script which we
have created as part of the post build execution phase.
That’s it, next time you queue a build, you can see that the
build creates and uploads a nuget package to the repository automatically.
2 comments:
Brother, you seem to be very highly knowledgeable.
I need to Create new packages for Chrome, Firefox, FlashPlayer, Java whenever the new updates are available.
The work consists of creating Nuget packages (with tools ChocolateyInstall.ps1 & chocolateyUninstall.ps1 in Nuget Package Explorer) and uploading it to the NugetServer for further consumption. I need to build that on Powershell and not finding anything relevant resources for this.
Helpful
Post a Comment