用于自定义管道的 PowerShell 脚本

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

本文介绍如何超越编译和测试代码,以及如何使用 PowerShell 脚本将业务逻辑添加到管道。 Azure Pipelines PowerShell 任务 在管道中运行 PowerShell 脚本。 可以使用 PowerShell 访问 Azure DevOps REST API、使用 Azure DevOps 工作项和测试管理,或根据需要调用其他服务。

可以在 PowerShell 脚本中使用变量,包括 自己设置的用户定义变量 。 还可以使用 所有 Azure Pipelines 中可用的预定义变量 ,并设置 多作业输出变量 ,使变量可供将来的作业使用。 有关详细信息,请参阅定义变量

可以在 PowerShell 脚本中使用命名参数。 不支持其他类型的参数(如开关参数),如果尝试使用它们,则会导致错误。 有关详细信息,请参阅 如何声明 cmdlet 参数

将 PowerShell 脚本添加到管道

此生成使用代码的活动分支。 如果管道运行使用 main 分支,则脚本也可使用 main 分支。

可以在 Windows 生成代理上运行 Windows PowerShell,也可以在任何平台上运行 PowerShell Core。 包括 PowerShell Core 的语法与 Windows PowerShell 的语法略有不同。

将 PowerShell 脚本推送到存储库后,向管道添加或pwshpowershell步骤。 关键字 pwshpowershell 关键字都是运行 PowerShell 任务的快捷方式。

PowerShell Core 示例:

steps:
- pwsh: ./my-script.ps1

Windows PowerShell 示例:

steps:
- powershell: .\my-script.ps1

将版本应用于程序集的示例脚本

本节中的示例脚本将版本应用于程序集属性文件。 若要使脚本成功运行,定义的内部版本号格式必须有四个句点,例如 $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)

注意

内部版本号也称为运行编号。

使用 name 属性在 YAML 管道中自定义生成号。 该 name 属性必须位于管道的根级别。 有关详细信息,请参阅 配置运行或内部版本号

name: $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)

以下 PowerShell 示例脚本将版本应用于程序集。 例如,如果定义的生成号格式 $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r) 生成内部版本号 Build HelloWorld_2024.07.19.1,脚本会将版本 2024.07.19.1 应用于程序集。

# Enable -Verbose option
[CmdletBinding()]

# Regular expression pattern to find the version in the build number
$VersionRegex = "\d+\.\d+\.\d+\.\d+"

# If not running on a build server, remind user to set environment variables for debugging
if(-not ($Env:BUILD_SOURCESDIRECTORY -and $Env:BUILD_BUILDNUMBER))
{
    Write-Error "You must set the following environment variables"
    Write-Error "to test this script interactively."
    Write-Host '$Env:BUILD_SOURCESDIRECTORY - For example, enter something like:'
    Write-Host '$Env:BUILD_SOURCESDIRECTORY = "C:\code\Fabrikam\HelloWorld"'
    Write-Host '$Env:BUILD_BUILDNUMBER - For example, enter something like:'
    Write-Host '$Env:BUILD_BUILDNUMBER = "Build HelloWorld_0000.00.00.0"'
    exit 1
}

# Make sure path to source code directory is available
if (-not $Env:BUILD_SOURCESDIRECTORY)
{
    Write-Error ("BUILD_SOURCESDIRECTORY environment variable is missing.")
    exit 1
}
elseif (-not (Test-Path $Env:BUILD_SOURCESDIRECTORY))
{
    Write-Error "BUILD_SOURCESDIRECTORY does not exist: $Env:BUILD_SOURCESDIRECTORY"
    exit 1
}
Write-Verbose "BUILD_SOURCESDIRECTORY: $Env:BUILD_SOURCESDIRECTORY"
    
# Make sure there's a build number
if (-not $Env:BUILD_BUILDNUMBER)
{
    Write-Error ("BUILD_BUILDNUMBER environment variable is missing.")
    exit 1
}
Write-Verbose "BUILD_BUILDNUMBER: $Env:BUILD_BUILDNUMBER"
    
# Get and validate the version data
$VersionData = [regex]::matches($Env:BUILD_BUILDNUMBER,$VersionRegex)
switch($VersionData.Count)
{
   0        
      { 
         Write-Error "Couldn't find version number data in BUILD_BUILDNUMBER."
         exit 1
      }
   1 {}
   default 
      { 
         Write-Warning "Found more than one instance of version data in BUILD_BUILDNUMBER." 
         Write-Warning "Assuming first instance is version."
      }
}
$NewVersion = $VersionData[0]
Write-Verbose "Version: $NewVersion"
    
# Apply the version to the assembly property files
$files = gci $Env:BUILD_SOURCESDIRECTORY -recurse -include "*Properties*","My Project" | 
    ?{ $_.PSIsContainer } | 
    foreach { gci -Path $_.FullName -Recurse -include AssemblyInfo.* }
if($files)
{
    Write-Verbose "Applying $NewVersion to $($files.count) files."
    
    foreach ($file in $files) {
        $filecontent = Get-Content($file)
        attrib $file -r
        $filecontent -replace $VersionRegex, $NewVersion | Out-File $file
        Write-Verbose "$file.FullName - version applied"
    }
}
else
{
    Write-Warning "Found no files."
}

用于访问 REST API 的示例脚本

此示例使用 SYSTEM_ACCESSTOKEN 变量访问 Azure Pipelines REST API

可以在 $env:SYSTEM_ACCESSTOKEN YAML 管道中的内联脚本中使用来访问 OAuth 令牌。

YAML 管道中的以下内联 PowerShell 脚本使用 OAuth 令牌访问检索管道定义的 Azure Pipelines REST API。

- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$($env:SYSTEM_DEFINITIONID)?api-version=5.0"
              Write-Host "URL: $url"
              $pipeline = Invoke-RestMethod -Uri $url -Headers @{
                  Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
              }
              Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
  env:
     SYSTEM_ACCESSTOKEN: $(System.AccessToken)