将 Azure Artifacts 源用作专用 PowerShell 存储库

Azure DevOps Services

Azure Artifacts 提供了一个方便的解决方案,用于共享 PowerShell 脚本。 通过使用 Azure Artifacts 源,可以从命令行无缝发布 PowerShell 模块,并通过源设置控制对这些模块的访问。 本文将指导你设置 Azure Artifacts 源作为专用 PowerShell 存储库来存储和共享 PowerShell 模块。

本文将指导如何进行以下操作:

  • 创建个人访问令牌
  • 创建 PowerShell 模块
  • 创建 SecretStore 保管库并注册存储库
  • 从源发布和使用包

先决条件

注意

PSResourceGet 不支持 Azure Artifacts 凭据提供程序。

创建个人访问令牌

个人访问令牌充当数字标识,充当使用 Azure DevOps 进行身份验证的替代密码。

  1. 导航到 Azure DevOps 组织 https://dev.azure.com/<ORGANIZATION_NAME>/

  2. 选择用户设置图标,选择 “个人访问令牌”,然后选择“ 新建令牌”。

  3. 输入 PAT 的名称,设置到期日期,选择“自定义”,然后选择“打包>读取”、“写入和管理”。

  4. 完成后选择“创建,并确保将 PAT 复制并存储在安全的位置。

    显示如何设置新的个人访问令牌的屏幕截图。

创建 PowerShell 模块

如果没有自己的模块,请按照本节中的说明创建示例 PowerShell 模块。 否则,请跳到下一步:

  1. 创建新的文件夹 PowerShell-Demo。 导航到文件夹并创建新文件 PowerShell-Demo.psm1

  2. 将以下脚本粘贴到 PowerShell-Demo.psm1 文件中:

    Function PowerShell-Demo{
        Write-Host "Hello World!"
    }
    
  3. 通过在 PowerShell-Demo 目录中运行以下命令生成模块清单:

    New-ModuleManifest -Path .\PowerShell-Demo.psd1
    
  4. 打开 PowerShell-Demo.psd1 文件并找到变量RootModule。 此设置指定导入模块时 PowerShell 加载的主脚本文件。 将空字符串替换为 PowerShell-Demo.psm1 文件的路径

    RootModule = 'PowerShell-Demo.psm1'
    
  5. FunctionsToExport 部分指定导入模块时用户可以访问哪些函数。 包括 PowerShell-Demo 函数:

    FunctionsToExport = @('PowerShell-Demo')
    
  6. 找到该 FileList 部分,其中列出了打包模块时包含的文件。 使用模块添加要打包的文件:

    FileList = @('./PowerShell-Demo.psm1')
    

注册存储库

  1. 运行以下命令以创建凭据对象。 将占位符替换为正确的信息。

    $username = "<USER_NAME>"
    $patToken = "<PERSONAL_ACCESS_TOKEN>" | ConvertTo-SecureString -AsPlainText -Force
    
    $credentials = New-Object System.Management.Automation.PSCredential($username, $patToken)
    
  2. 确保 已安装 SecretManagementSecretStore ,然后运行以下命令来创建保管库并添加机密:

    Register-SecretVault -Name "MySecretVault" -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
    
    Set-Secret -Name "MyCredential" -Secret $credentials -Vault "MySecretVault"
    
    $CredentialInfo = [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo]::new('MySecretVault', 'MyCredential')
    
  3. 若要验证保管库和机密是否已成功创建,请运行以下命令列出所有机密:

    PS > Get-SecretInfo
    
    Name            Type         VaultName
    ----            ----         ---------
    MyCredential    PSCredential MySecretVault
    
    
  4. 运行以下命令来注册 PowerShell 存储库。 可以通过导航到项目>连接到源>NuGet.exe,在“项目设置”部分>源 URL 下找到SourceLocation链接。

    • 项目作用域的源:

      Register-PSResourceRepository -Name "PowershellPSResourceRepository" `
          -Uri "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v3/index.json" `
          -Trusted `
          -CredentialInfo $CredentialInfo
      
    • 组织作用域的源:

      Register-PSResourceRepository -Name "PowershellPSResourceRepository" `
          -Uri "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/nuget/v3/index.json" `
          -Trusted `
          -CredentialInfo $CredentialInfo
      

    提示

    某些版本的 PowerShell 可能需要在运行 Register-PSResourceRepository cmdlet 后启动新会话,以防止遇到 无法解析包源 警告。

  5. 若要验证存储库是否已成功注册,请运行以下命令以检索当前用户的所有已注册存储库:

    Get-PSResourceRepository
    

注意

如果遇到错误:响应状态代码未指示成功: 404(找不到)。请确保源 URL 指向 nuget/v3/index.json 而不是 nuget/v2

发布包

运行以下命令,将包发布到源:

Publish-PSResource -Path <PACKAGE_PATH> -Repository <REPOSITORY_NAME> -ApiKey (Get-Secret <SECRET_NAME>) 

示例:

PS C:\AzureDevOps\Demos\PowerShellDemo> Publish-PSResource -Path .\scripts\ -Repository FabrikamFiberFeed -ApiKey (Get-Secret MyNewCredential) -verbose
VERBOSE: Performing the operation "Publish-PSResource" on target "Publish resource
'C:\AzureDevOps\Demos\PowerShellDemo\scripts\' from the machine".
VERBOSE: The newly created nuspec is:
C:\Users\xxxx\AppData\Local\Temp\xxxxxxxxx\PowerShell-Demo.nuspec
VERBOSE: credential successfully read from vault and set for repository: FabrikamFiberFeed
VERBOSE: Successfully packed the resource into a .nupkg
VERBOSE: Successfully published the resource to
'https://pkgs.dev.azure.com/ramiMSFTDevOps/DemoProject/_packaging/FabrikamFiberFeed/nuget/v3/index.json'
VERBOSE: Deleting temporary directory 'C:\Users\xxxx\AppData\Local\Temp\xxxxxxx'

显示发布到源的 PowerShell 演示包的屏幕截图。

安装包

  1. 若要确认模块是否在存储库中可用,请使用以下命令搜索它:

    Find-PSResource -Name <RESOURCE_NAME> -Repository <REPOSITORY_NAME> -verbose
    
  2. 运行以下命令以安装模块的最新稳定版本:

    Install-PSResource <MODULE_NAME>
    

提示

如果遇到错误: 调用“WriteObject”的异常,请启动新的 PowerShell 窗口并运行 Get-SecretInfo。 在运行 Find-PSResource 和 Install-PSResource 之前输入保管库密码,因为 SecretStore 超时期限可能会过期。 默认 PasswordTimeout 为 900 秒,但可以根据需要修改此值。 有关更多详细信息,请参阅 自动化 中的 SecretStore。

本文将指导如何进行以下操作:

  • 创建个人访问令牌
  • 创建、打包和发布 PowerShell 模块
  • 以 PowerShell 存储库的形式连接到源
  • 使用 Azure Pipelines 注册并安装 PowerShell 模块

先决条件

创建个人访问令牌

个人访问令牌充当数字标识,充当使用 Azure DevOps 进行身份验证的替代密码。

  1. 导航到 Azure DevOps 组织 https://dev.azure.com/<ORGANIZATION_NAME>/

  2. 选择用户设置图标,选择 “个人访问令牌”,然后选择“ 新建令牌”。

  3. 输入 PAT 的名称,设置到期日期,选择“自定义”,然后选择“打包>读取”、“写入和管理”。

  4. 完成后选择“创建,并确保将 PAT 复制并存储在安全的位置。

    显示如何设置新的个人访问令牌的屏幕截图。

创建 PowerShell 模块

如果没有自己的模块,请按照本节中的说明创建示例 PowerShell 模块。 否则,请跳到下一步:

  1. 创建新文件夹 Get-Hello。 导航到文件夹并创建新文件 Get-Hello.psm1

  2. 将以下脚本粘贴到 Get-Hello.psm1 文件中:

    Function Get-Hello{
        Write-Host "Hello Azure DevOps!"
    }
    
  3. 通过在 Get-Hello 目录中运行以下命令来生成模块清单:

    New-ModuleManifest -Path .\Get-Hello.psd1
    
  4. 打开 Get-Hello.psd1 文件并找到变量RootModule。 此设置指定导入模块时 PowerShell 加载的主脚本文件。 将空字符串替换为 Get-Hello.psm1 文件的路径

    RootModule = 'Get-Hello.psm1'
    
  5. FunctionsToExport 部分指定导入模块时用户可以访问哪些函数。 包括 Get-Hello 函数:

    FunctionsToExport = @('Get-Hello')
    
  6. 查找节 FileList ,该节指定打包模块时包含的文件。 使用模块添加要打包的文件:

    FileList = @('./Get-Hello.psm1')
    

打包和发布模块

  1. 为模块生成 nuspec 文件。 此命令创建一个 Get-Hello.nuspec 文件,其中包含打包模块所需的元数据:

    nuget spec Get-Hello
    
  2. 运行以下命令来打包模块:

    nuget pack Get-Hello.nuspec
    
  3. 运行以下命令以添加源源 URL。 请确保在源 URL 中使用 V2,因为不支持 NuGet V3。

    • 组织作用域的源:

      nuget sources Add -Name "<FEED_NAME>" -Source "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/nuget/v2" -username "<USER_NAME>" -password "<PERSONAL_ACCESS_TOKEN>"
      
    • 项目作用域的源:

      nuget sources Add -Name "<FEED_NAME>" -Source "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v2" -username "<USER_NAME>" -password "<PERSONAL_ACCESS_TOKEN>"
      
  4. 将包发布到源:

    nuget push -Source "<FEED_NAME>" -ApiKey "<ANY_STRING>" "<PACKAGE_PATH>"
    

重要

模块清单(.psd1)中的版本号必须与 .nuspec 文件中的版本号相同。

以 PowerShell 存储库的形式连接到源

本部分将指导你使用源作为 PowerShell 存储库进行身份验证,并使用源中托管的模块:

  1. 在 PowerShell 提示窗口中,运行以下命令来设置凭据。 将占位符替换为相应的信息。

    $patToken = "<PERSONAL_ACCESS_TOKEN>" | ConvertTo-SecureString -AsPlainText -Force
    
    $credsAzureDevopsServices = New-Object System.Management.Automation.PSCredential("<USER_NAME>", $patToken)
    
  2. 注册 PowerShell 存储库。 可以通过导航到项目>连接到源>NuGet.exe,在“项目设置”部分>源 URL 下找到SourceLocation链接。

    • 项目作用域的源:

      Register-PSRepository -Name <REPOSITORY_NAME> -SourceLocation "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v2" -PublishLocation "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v2" -InstallationPolicy Trusted -Credential $credsAzureDevopsServices
      
    • 组织作用域的源:

      Register-PSRepository -Name <REPOSITORY_NAME> -SourceLocation "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/nuget/v2" -PublishLocation "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/nuget/v2" -InstallationPolicy Trusted -Credential $credsAzureDevopsServices
      

    提示

    某些版本的 PowerShell 可能需要在运行 Register-PSRepository cmdlet 后启动新会话,以防止遇到 无法解析包源 警告。

  3. 注册包源:

    • 项目作用域的源:

      Register-PackageSource -Name <REPOSITORY_NAME> -Location "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v2" -ProviderName NuGet -Trusted -SkipValidate -Credential $credsAzureDevopsServices
      
    • 组织作用域的源:

      Register-PackageSource -Name <REPOSITORY_NAME> -Location "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/nuget/v2" -ProviderName NuGet -Trusted -SkipValidate -Credential $credsAzureDevopsServices 
      

    注意

    • Register-PSRepository:用于注册 PowerShell 存储库以查找和安装模块。
    • Register-PackageSource:用于注册包源以查找和发布包。
  4. 若要验证存储库是否已成功注册,请运行以下命令以检索当前用户的所有已注册存储库:

    Get-PSRepository
    
  5. 运行以下命令以安装 Get-Hello 模块。

    Install-Module -Name <PACKAGE_NAME> -Repository <REPOSITORY_NAME>
    

注意

如果组织使用防火墙或代理服务器,请确保允许访问 Azure Artifacts 域 URL 和 IP 地址

从管道安装包

此示例逐步讲解如何使用 Azure Artifacts 源进行身份验证,并从管道安装 PowerShell 模块。 若要使用个人访问令牌,请将其添加为管道变量,如下所示:

  1. 登录到 Azure DevOps 组织,并导航到你的项目。

  2. 选择 管道,选择管道定义,然后选择“ 编辑” 以修改管道。

  3. 选择 右上角的“变量 ”,然后选择“ 新建变量”。

  4. 输入变量的名称,然后将个人访问令牌粘贴到“值”文本框中。

  5. 请确保选中“ 保留此值机密 ”复选框。 完成后,选择“ 确定 ”。

  6. userName 添加第二个变量。 输入变量的名称,然后在“值文本框中输入 userName

  7. 完成时选择“保存”。

trigger:
- main

pool:
  vmImage: 'Windows-latest'

variables:
  PackageFeedEndpoint: 'https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v2' ## For organization scoped feeds use'https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/nuget/v2'

steps:
- powershell: |
    $pat = ConvertTo-SecureString ${env:pat_token} -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential("${env:userName}", $pat)
    Register-PSRepository -Name <REPOSITORY_NAME> -SourceLocation "$(PackageFeedEndpoint)" -InstallationPolicy Trusted -Credential $credential
  displayName: 'Register PSRepository'
  env:
    pat_token: $patToken
    userName: $userName

- powershell: |
    nuget install <PACKAGE_NAME> -Source "https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v3/index.json"
  displayName: 'Install module'