From b8c184ef6ba821307094ac445ad9fd6109231f1d Mon Sep 17 00:00:00 2001 From: James Brundage Date: Mon, 12 Jul 2021 12:09:08 -0700 Subject: [PATCH 1/4] Adding Register-ADOArtifactFeed --- Register-ADOArtifactFeed.ps1 | 112 +++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Register-ADOArtifactFeed.ps1 diff --git a/Register-ADOArtifactFeed.ps1 b/Register-ADOArtifactFeed.ps1 new file mode 100644 index 00000000..0f833905 --- /dev/null +++ b/Register-ADOArtifactFeed.ps1 @@ -0,0 +1,112 @@ +function Register-ADOArtifactFeed +{ + <# + .Synopsis + Registers an Azure DevOps artifact feed. + .Description + Registers an Azure DevOps artifact feed as a PowerShell Repository. + thThis allows Install-Module, Publish-Module, and Save-Module to work against an Azure DevOps artifact feed. + .Link + https://docs.microsoft.com/en-us/azure/devops/artifacts/tutorials/private-powershell-library?view=azure-devops + .Link + Get-ADOArtifactFeed + .Link + Unregister-ADOArtifactFeed + .Link + Get-PSRepository + .Link + Register-PSRepository + .Link + Unregister-PSRepository + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", + Justification="Abstracting Credential Structure is part of the point")] + param( + # The name of the organization. + [Parameter(Mandatory,ValueFromPipelineByPropertyName)] + [string] + $Organization, + + # The Project + [Parameter(Mandatory,ValueFromPipelineByPropertyName)] + [string] + $Project, + + # The name or ID of the feed. + [Parameter(Mandatory,ValueFromPipelineByPropertyName)] + [Alias('fullyQualifiedId')] + [string] + $FeedID, + + # The personal access token used to connect to the feed. + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('PAT')] + [string] + $PersonalAccessToken, + + # The email address used to connect + [Parameter(ValueFromPipelineByPropertyName)] + [string] + $EmailAddress, + + # If provided, will create a repository source using a given name. + # By default, the RepositoryName will be $Organization-$Project-$FeedID + [Parameter(ValueFromPipelineByPropertyName)] + [string] + $RepositoryName, + + # If provided, will create a repository using a given URL. + # By default, the RepositoryURL is predicted using -Organization, -Project, and -FeedID + [Parameter(ValueFromPipelineByPropertyName)] + [string] + $RepositoryUrl, + + # If set, will remove the connection to an existing feed and then create a new one. + [switch] + $Force + ) + + + begin { + $psRepos = Get-PSRepository + } + process { + #region Check if Repository Already Exists + $targetName = if ($RepositoryName) { $RepositoryName } + else { "${Organization}-${Project}-${FeedID}" } + $targetSource = if ($RepositoryUrl) { $RepositoryUrl } + else { "https://pkgs.dev.azure.com/$Organization/$Project/_packaging/$FeedID/nuget/v2" } + $psRepoExists = $psRepos | + Where-Object { + $_.Name -eq $targetName -or + $_.SourceLocation -eq $targetSource + } + + if ($psRepoExists -and $Force) { + $psRepoExists | Unregister-PSRepository + } elseif ($psRepoExists) { + Write-Verbose "Repository already exists: $($psRepoExists.Name)" + return $psRepoExists + } + #endregion Check if Repository Already Exists + + #region Create Credential and Register-PSRepository + if (-not $PersonalAccessToken -and $env:SYSTEM_ACCESSTOKEN) { + $PersonalAccessToken = $env:SYSTEM_ACCESSTOKEN + } + + if (-not $EmailAddress -and $PersonalAccessToken) { + $EmailAddress = $PersonalAccessToken + } + + if (-not $EmailAddress -and -not $PersonalAccessToken) { + Write-Error "Must provide a -PersonalAccessToken. Should provide an -EmailAddress" + return + } + + $repoCred = [Management.Automation.PSCredential]::new($EmailAddress, (ConvertTo-SecureString -AsPlainText -Force $PersonalAccessToken)) + + Register-PSRepository -Name $targetName -SourceLocation $targetSource -PublishLocation $targetSource -InstallationPolicy Trusted -Credential $repoCred + #endregion Create Credential and Register-PSRepository + } +} From 5b55cd7103b5e54c485a693f11f9394f88f4452b Mon Sep 17 00:00:00 2001 From: James Brundage Date: Tue, 13 Jul 2021 01:55:17 -0700 Subject: [PATCH 2/4] Register-ADOArtifactFeed: Making -Project optional. --- Register-ADOArtifactFeed.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Register-ADOArtifactFeed.ps1 b/Register-ADOArtifactFeed.ps1 index 0f833905..55de7932 100644 --- a/Register-ADOArtifactFeed.ps1 +++ b/Register-ADOArtifactFeed.ps1 @@ -28,7 +28,7 @@ $Organization, # The Project - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] + [Parameter(ValueFromPipelineByPropertyName)] [string] $Project, @@ -73,9 +73,11 @@ process { #region Check if Repository Already Exists $targetName = if ($RepositoryName) { $RepositoryName } - else { "${Organization}-${Project}-${FeedID}" } + elseif ($Project) { "${Organization}-${Project}-${FeedID}" } + else { "${Organization}-${FeedID}" } $targetSource = if ($RepositoryUrl) { $RepositoryUrl } - else { "https://pkgs.dev.azure.com/$Organization/$Project/_packaging/$FeedID/nuget/v2" } + elseif ($Project) { "https://pkgs.dev.azure.com/$Organization/$Project/_packaging/$FeedID/nuget/v2" } + else { "https://pkgs.dev.azure.com/$Organization/_packaging/$FeedID/nuget/v2" } $psRepoExists = $psRepos | Where-Object { $_.Name -eq $targetName -or From ad831166a74959f24b5ae6f8dbf44750dc904cee Mon Sep 17 00:00:00 2001 From: James Brundage Date: Tue, 13 Jul 2021 02:18:33 -0700 Subject: [PATCH 3/4] Register-ADOArtifactFeed: Making -FeedID -Name. Adding examples. Static Analysis cleanup. --- Register-ADOArtifactFeed.ps1 | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Register-ADOArtifactFeed.ps1 b/Register-ADOArtifactFeed.ps1 index 55de7932..24a1f28c 100644 --- a/Register-ADOArtifactFeed.ps1 +++ b/Register-ADOArtifactFeed.ps1 @@ -6,6 +6,8 @@ .Description Registers an Azure DevOps artifact feed as a PowerShell Repository. thThis allows Install-Module, Publish-Module, and Save-Module to work against an Azure DevOps artifact feed. + .Example + Register-ADOArtifactFeed -Organization MyOrg -Project MyProject -Name MyFeed -PersonalAccessToken $myPat .Link https://docs.microsoft.com/en-us/azure/devops/artifacts/tutorials/private-powershell-library?view=azure-devops .Link @@ -21,6 +23,7 @@ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification="Abstracting Credential Structure is part of the point")] + [OutputType('Microsoft.PowerShell.Commands.PSRepository')] param( # The name of the organization. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] @@ -33,10 +36,9 @@ $Project, # The name or ID of the feed. - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] - [Alias('fullyQualifiedId')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] - $FeedID, + $Name, # The personal access token used to connect to the feed. [Parameter(ValueFromPipelineByPropertyName)] @@ -50,13 +52,13 @@ $EmailAddress, # If provided, will create a repository source using a given name. - # By default, the RepositoryName will be $Organization-$Project-$FeedID + # By default, the RepositoryName will be $Organization-$Project-$Name [Parameter(ValueFromPipelineByPropertyName)] [string] $RepositoryName, # If provided, will create a repository using a given URL. - # By default, the RepositoryURL is predicted using -Organization, -Project, and -FeedID + # By default, the RepositoryURL is predicted using -Organization, -Project, and -Name [Parameter(ValueFromPipelineByPropertyName)] [string] $RepositoryUrl, @@ -73,11 +75,11 @@ process { #region Check if Repository Already Exists $targetName = if ($RepositoryName) { $RepositoryName } - elseif ($Project) { "${Organization}-${Project}-${FeedID}" } - else { "${Organization}-${FeedID}" } + elseif ($Project) { "${Organization}-${Project}-${Name}" } + else { "${Organization}-${Name}" } $targetSource = if ($RepositoryUrl) { $RepositoryUrl } - elseif ($Project) { "https://pkgs.dev.azure.com/$Organization/$Project/_packaging/$FeedID/nuget/v2" } - else { "https://pkgs.dev.azure.com/$Organization/_packaging/$FeedID/nuget/v2" } + elseif ($Project) { "https://pkgs.dev.azure.com/$Organization/$Project/_packaging/$Name/nuget/v2" } + else { "https://pkgs.dev.azure.com/$Organization/_packaging/$Name/nuget/v2" } $psRepoExists = $psRepos | Where-Object { $_.Name -eq $targetName -or @@ -109,6 +111,9 @@ $repoCred = [Management.Automation.PSCredential]::new($EmailAddress, (ConvertTo-SecureString -AsPlainText -Force $PersonalAccessToken)) Register-PSRepository -Name $targetName -SourceLocation $targetSource -PublishLocation $targetSource -InstallationPolicy Trusted -Credential $repoCred + if ($?) { + Get-PSRepository -Name $targetName + } #endregion Create Credential and Register-PSRepository } } From 870a2be3dca130d63ebe56b55198bfec0ecd2f80 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Tue, 13 Jul 2021 10:24:12 -0700 Subject: [PATCH 4/4] Updating module version and release notes --- PSDevOps.psd1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PSDevOps.psd1 b/PSDevOps.psd1 index 0e19afd6..c10a28a3 100644 --- a/PSDevOps.psd1 +++ b/PSDevOps.psd1 @@ -1,5 +1,5 @@ @{ - ModuleVersion = '0.5.4.1' + ModuleVersion = '0.5.4.2' RootModule = 'PSDevOps.psm1' Description = 'PowerShell Tools for DevOps' Guid = 'e6b56c5f-41ac-4ba4-8b88-2c063f683176' @@ -9,6 +9,10 @@ ProjectURI = 'https://github.com/StartAutomating/PSDevOps' LicenseURI = 'https://github.com/StartAutomating/PSDevOps/blob/master/LICENSE' ReleaseNotes = @' +0.5.4.2: +--- +* Adding Register-ADOArtifactFeed (Fixes #118) + 0.5.4.1: --- * Fixing Invoke-ADORestApi issues: #111,#114,#115