Publishing Powershell Modules to VSTS Package Management

I am currently building a deployment framework made up of Powershell modules. I wanted these to be stored in a central but private feed, where my builds can download modules they require to include as part of the artefact for deployment. On the surface of it, this is a fairly simple setup process, however I came across some stumbling blocks, so hopefully this will make your life easier if you try to use VSTS Package Management as a private powershell module feed!

For my steps, I am using WMF5.1 and PowerShellGet 1.1.2. My scripts are semi-idempotent – they are run on a CI build server, so my requirement is not complete idempotency, just enough so they are re-runnable. I've also already created my feed on VSTS - there is plently of documentation from MSFT on this so I won't go into Package Management or security using PAT tokens.

Registering the Repository

This first step registers the repository as a PSRepository for PowerShell. You also have to register the feed with nuget, otherwise you will get an error similar to this:

Publish-PSArtifactUtility : Failed to publish module 'Framework.Logging': 'Publishing to a ******** package management feed 'https://xxx.pkgs.visualstudio.com/_packaging/PowershellModules/nuget/v2' requires it to be registered as a NuGet package source. Retry after adding this source


'https://xxx.pkgs.visualstudio.com/_packaging/PowershellModules/nuget/v2' as NuGet package source by following the instructions specified at 'https://go.microsoft.com/fwlink/?LinkID=698608''. At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.1.2.0\PSModule.psm1:1227 char:17 + Publish-PSArtifactUtility -PSModuleInfo $moduleInfo ` + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : FailedToPublishTheModule,Publish-PSArtifactUtility

 

Import-Module PowerShellGet -RequiredVersion 1.1.2.0

$repo = Get-PSRepository -Name $RepositoryName -ErrorAction SilentlyContinue

if($repo -eq $null)
{
    .\Nuget  sources add -name $RepositoryName -source $RepositorySourceUri -username $RepositoryUsername `
    -password $RepositoryPassword -storePasswordInClearText  -verbosity detailed

    $securePass = ConvertTo-SecureString -String $RepositoryPassword -AsPlainText -Force
    $cred = New-Object System.Management.Automation.PSCredential ($RepositoryUsername, $securePass)

    Write-Debug "Adding the Repository $RepositoryName"
    Register-PSRepository -Name $RepositoryName -SourceLocation $RepositorySourceUri `
                         -PublishLocation $RepositoryPublishUri -Credential $cred `
                         -PackageManagementProvider Nuget -InstallationPolicy Trusted
}
else
{
    Write-Debug "The repository $RepositoryName is already registered on this node. Skipped registration."
}

 

You can verify that the repository is registered in Powershell by running

Get-PSRepository

and in Nuget by

.\nuget source list

Publishing the Module

This step is simple. This example of calling Publish-Module passes the minimum detail:

Import-Module PowerShellGet -RequiredVersion 1.1.2.0

$PublishParams = @{
    Path = $ModuleFolderPath
    ProjectUri = $ProjectUri
    Tags = $ModuleTags
    Repository = $RepositoryName
    NugetApiKey = $NugetApiKey
}

Publish-Module @PublishParams -Force -Verbose

 

If you didn’t register the feed with nuget, this is where you will get the error stating the repository has to be a Nuget package source. VSTS Package Management will return an HTTP 409 status if the version of the package you are trying to publish already exists. This happens even if you have deleted the package from the feed as VSTS Package Management keeps a record of it.

 

Cleaning Up

This step isn’t necessary, but I am running this on my CI agent, so I want to undo any changes that may affect other builds in the future. This code will unregister the repository in Powershell, and remove the feed as a Nuget source.

Import-Module PowerShellGet -MinimumVersion 1.1.2.0

$repo = Get-PSRepository -Name $RepositoryName -ErrorAction SilentlyContinue

if($repo -ne $null)
{
    .\Nuget sources remove -name $RepositoryName -verbosity detailed
    Write-Debug "Removing the Repository $RepositoryName"
    Unregister-PSRepository -Name $RepositoryName
}
else
{
    Write-Debug "The repository $RepositoryName does not exist. Skipped removal."
}

 

Using your feed

To use your feed to download modules, simply register is as a PSRepository, and go! (You don’t have to register it again if it is already registered from the first step).

$securePass = ConvertTo-SecureString -String $RepositoryPassword -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($RepositoryUsername, $securePass)

Register-PSRepository -Name $RepositoryName -SourceLocation $RepositorySourceUri `
                        -PublishLocation $RepositoryPublishUri -Credential $cred `
                        -PackageManagementProvider Nuget -InstallationPolicy Trusted

Find-Module CMCS.POSHDeploy.Framework.Logging -Credential $cred

Install-Module -Name CMCS.POSHDeploy.Framework.Logging -RequiredVersion 1.0.296 -Credential $cred


Tagged: Powershell,
Categorised: PowerShell,
By:
On: