将 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 存储库。 可以通过导航到 Artifacts>连接到源>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

发布包

运行以下命令,以将包发布到源。 将占位符替换为包路径、存储库名称、前面创建的凭据对象,并为 ApiKey 提供任何字符串。

Publish-PSResource -Path <PACKAGE_PATH> -Repository <REPOSITORY_NAME> -Credential $credentials -ApiKey <ANY_STRING>

示例

PS C:\AzureDevOps\Demos\PowerShellDemo> Publish-PSResource -Path .\scripts\ -Repository FabrikamFiberFeed -Credential $credentials -ApiKey az -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-PSResourceInstall-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 存储库。 可以通过导航到 Artifacts>连接到源>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'