使用内置系统变量创建 Powershell 环境变量

Create Powershell env variables using built in System variables

我有一个 Powershell 脚本,它会向 SonarQube 的 REST API 发出 GET 请求,以检查 Quality Gate 是否通过。如果质量门失败,管道将失败。我可以在只查看 master 分支时完成这项工作,但是,我正在尝试查看所有分支和拉取请求。

我的管道 Powershell 脚本:

  - job:
  
    pool:
      name: 'POEM-GBT-Agent'

    variables:
    - group: SonarQube

    displayName: 'SonarQube API'
    
    steps:
    - checkout: none
    - powershell: |
        $token = [System.Text.Encoding]::UTF8.GetBytes("$(SONARQUBE_API_TOKEN)" + ":")
        $base64 = [System.Convert]::ToBase64String($token)
        
        $basicAuth = [string]::Format("Basic {0}", $base64)
        $headers = @{ Authorization = $basicAuth }

        if ($(System.PullRequest.PullRequestId)) {
           $param = "pullRequest=$(System.PullRequest.PullRequestId)"
        }
        else {
          $param = "branch=$env:$BRANCH_NAME"
        }
        
        $result = Invoke-RestMethod -Method Get -Uri https://sonarqube.tjx.com/api/qualitygates/project_status?projectKey=$(sonarProjectKey)"&"$param -Headers $headers
        $result | ConvertTo-Json | Write-Host
        
        if ($result.projectStatus.status -ne "OK") {
          Write-Host "##vso[task.logissue type=error]Quality Gate Failed"
          Write-Host "##vso[task.complete result=Failed]"
        }

        env:
          BRANCH_NAME: replace('$(Build.SourceBranch)', 'refs/heads/', '')

这会导致错误提示:

+   $param = "branch=$env:$BRANCH_NAME"
+                    ~~~~~
Variable reference is not valid. ':' was not followed by a valid variable name 
character. Consider using ${} to delimit the name.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : InvalidVariableReferenceWithDrive

收到此错误后,我将条件语句更改为:

        if ($(System.PullRequest.PullRequestId)) {
           $param = "pullRequest=$(System.PullRequest.PullRequestId)"
        }
        else {
          $param = "branch=${env}:$BRANCH_NAME"
        }

更改条件后出现此错误:

System.PullRequest.PullRequestId : The term 'System.PullRequest.PullRequestId' 
is not recognized as the name of a cmdlet, function, script file, or operable 
program. Check the spelling of the name, or if a path was included, verify 
that the path is correct and try again.
At D:\GBT\agent\Workspace\_temp[=13=]a756446-474a-4d58-94ff-ad25e38c3c7a.ps1:9 
char:7
+ if ($(System.PullRequest.PullRequestId)) {
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (System.PullRequest.PullRequestI 
   d:String) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : CommandNotFoundException

如果 Git PR 受到影响,我正在尝试将 $param 设置为 pullRequest=1234,否则,我想将 $param 设置为 branch=feature/my-branch-name.

你这里有两个问题。我将在下面深入探讨。


无法识别术语 'System.PullRequest.PullRequestId'

在你的工作step下,定义一些环境变量。我对 Azure DevOps 的经验有限(从这里开始将作为 ADO 引用),但您需要在 powershell 环境变量定义下使用两个(您已经有 BRANCH_NAME 但我将在下面包含它):

- job:
  steps:
  - powershell: |
      YOUR
      CODE
      HERE

    env:
      BRANCH_NAME: replace('$(Build.SourceBranch)', 'refs/heads/', '')
      PULL_REQUEST_ID: $(System.PullRequest.PullRequestId)

您需要将 PULL_REQUEST_ID 定义为环境变量,因为您呈现的 PowerShell 脚本不会将 $() 呈现为来自 ADO 的插入值。这可能是设计使然,因为 $() 是其他编程语言 including PowerShell 中使用的语法。这是您的问题的症结所在,无法找到 System.PullRequest.PullRequestId 作为命令; PowerShell 从字面上试图将其用作它找不到的程序名称。

在您的脚本中,您可以通过以下方式引用拉取请求 ID:

$env:PULL_REQUEST_ID

变量引用无效。 “:”后面没有跟一个有效的变量名字符

该问题与上述问题不同,但解决方法相同。只需将环境变量引用为:

$env:BRANCH_NAME

您不需要额外的 $,因为这只会混淆解析器。

现在,你不是在要求这个,但如果你需要一个条件环境变量名称(例如,环境变量的名称来自其他一些 ADO 变量),你需要使用不同的语法来访问环境变量,因为 $ 在通过 $env: 语法访问时会混淆解析器。 如果您对此感到好奇,请继续阅读


如果您确实需要访问名称为条件的环境变量

PowerShell 不允许在未将变量名称指定为字符串的情况下在变量名称中使用特殊字符。值得注意的例外是 _(没有特殊含义)和 :,后者用作 PSDrive 中定义的 变量的分隔符.环境变量可通过 Environment 提供程序访问,可在 Env PSDrive 下访问。你可以通过运行 Get-PSDrive看到这个,在Env驱动器下暴露了一个Environment提供者。

您可以通过几种方式引用PSProvider变量,最常见的方式是$drive:path(变量名在技术上被认为是提供者下的路径节点)。因此要引用 UserProfile 变量,您可以使用:

$env:UserProfile # ====> Returns the path to your user profile directory

您的代码存在以下问题:

$env:$VariableName

在这种情况下,目的是获取一个环境变量值,其名称基于另一个变量的值,但这会使解析器对该语法感到困惑,因为 $ 现在被翻译为变量名,无效。通常你会使用 ${} 语法来避免这种情况......但你不能在这里,因为混淆的部分应该作为同一个变量的一部分呈现。在这种情况下,您需要使用替代方法来访问环境变量,直接通过提供程序。

再次以UserProfile为例:

$envVarName = 'UserProfile'
$envVarValue = (Get-ChildItem Env:/$envVarName).Value

这是从 PSProvider 获取值的另一种方法;将其内容作为驱动器遍历。这有点像文件系统,尽管 Get-ChildItem 将 return 不同的提供者类型的不同属性而不是 FileInfoDirectoryInfo 您可能习惯于来自 [=45= 的对象] 供应商。这有点麻烦,但幸运的是,这不是人们经常需要考虑的情况。