将 Azure DevOps Build Pipeline 运行时变量值传递到 powershell GUI 中?

问题描述 投票:0回答:1

我已经设置了一个 powershell 脚本,该脚本旨在使用 REST API 触发 Azure DevOps 构建管道,并允许我传入控制其中运行哪些任务所需的运行时变量。请参阅下面的脚本(删除了敏感细节)。

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/json")
$headers.Add("Authorization", "Basic [Redacted PAT]")
$headers.Add("Cookie", "VstsSession=%7B%22PersistentSessionId%22%3A%22404b5f44-9de5-4f0c-9f5d-0bd588e89d68%22%2C%22PendingAuthenticationSessionId%22%3A%2200000000-0000-0000-0000-000000000000%22%2C%22CurrentAuthenticationSessionId%22%3A%2200000000-0000-0000-0000-000000000000%22%2C%22SignInState%22%3A%7B%7D%7D")

$body = @{
    stagesToSkip = @{}
    resources = @{
        repositories = @{
            "self" = "@{
                refName = 'refs/heads/master'}"
            }
        }
        
    templateParameters = @{}
    variables = @{
        'variable1' = @{
            value = ''
        }
    'variable2' = @{
            value = ''
        }
        'variable3' = @{
            value = ''
        }
    'variable4' = @{
            value = ''
        }
    'variable5' = @{
            value = ''
        }
    'variable6'= @{
            value = ''
        }
    'variable7'= @{
            value = ''
        }
    'variable8'= @{
            value = ''
        }
    'variable9'= @{
            value = ''
        }
    'variable10'= @{
            value = ''
        }
    'variable11'= @{
            value = ''
        }
    'variable12'= @{
            value = ''
        }
    'variable13'= @{
            value = ''
        }
    }
} | ConvertTo-Json

$response = Invoke-RestMethod 'https://dev.azure.com/[myorganisation]/[myproject]/_apis/pipelines/[pipelineID]/runs?api-version=7.0' -Method 'POST' -Headers $headers -Body $body
$response | ConvertTo-Json`

这工作正常,我可以为所需变量指定一个值,并在脚本运行时传递它们。

但是我想对此进行扩展,使其可以从简单的 GUI 运行。我一直在尝试使用 System.Windows.Forms 程序集来实现此目的,虽然我在技术上可以使用它运行构建管道,但我无法找到传递运行时变量值的方法。

我尝试在 GUI 中设置文本框,链接回特定变量,但管道运行时不会传入值。

这是我使用过的脚本,鉴于我在这方面缺乏经验,我承认它是从我们半可靠的人工智能朋友 chat-gpt 那里获取的:

Add-Type -AssemblyName System.Windows.Forms

# Define the form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Azure DevOps Build Trigger"
$form.Width = 400
$form.Height = 500

# Define the variables
$variables = @{
    'variable1' = ''
    'variable2' = ''
    'variable3' = ''
    'variable4' = ''
    'variable5' = ''
    'variable6' = ''
    'variable7' = ''
    'variable8' = ''
    'variable9' = ''
    'variable10' = ''
    'variable11' = ''
    'variable12' = ''
    'variable13' = ''
}

# Function to create a label and text box for a variable
function CreateVariableControl($labelText, $top) {
    $label = New-Object System.Windows.Forms.Label
    $label.Text = $labelText
    $label.Location = New-Object System.Drawing.Point(10, $top)
    $label.AutoSize = $true

    $textBox = New-Object System.Windows.Forms.TextBox
    $textBox.Location = New-Object System.Drawing.Point(150, $top)
    $textBox.Size = New-Object System.Drawing.Size(200, 20)

    $form.Controls.Add($label)
    $form.Controls.Add($textBox)

    # Add an event handler to update the variable value when the text box changes
    $script:variableName = $labelText
    $textBox.Add_TextChanged({
        $variables[$script:variableName] = $textBox.Text
    })
}

# Add controls for each variable
$top = 30
CreateVariableControl 'variable1' $top
$top += 30
CreateVariableControl 'variable2' $top
$top += 30
CreateVariableControl 'variable3' $top
$top += 30
CreateVariableControl 'variable4' $top
$top += 30
CreateVariableControl 'variable5' $top
$top += 30
CreateVariableControl 'variable6' $top
$top += 30
CreateVariableControl 'variable7' $top
$top += 30
CreateVariableControl 'variable8' $top
$top += 30
CreateVariableControl 'variable9' $top
$top += 30
CreateVariableControl 'variable10' $top
$top += 30
CreateVariableControl 'variable11' $top
$top += 30
CreateVariableControl 'variable12' $top
$top += 30
CreateVariableControl 'variable13' $top

$buttonRun = New-Object System.Windows.Forms.Button
$buttonRun.Text = "Run"
$buttonRun.Location = New-Object System.Drawing.Point(150, $top + 30)
$buttonRun.Add_Click({
    # Read the content of the TriggerBuild.ps1 script with error handling
    $triggerBuildScriptPath = "BuildPipelinePowershellScript.ps1"
    try {
        $triggerBuildScriptContent = Get-Content $triggerBuildScriptPath -Raw -ErrorAction Stop
    } catch {
        Write-Host "Error reading TriggerBuild.ps1 script: $_"
        return
    }

    # Concatenate the TriggerBuild script content with the entered variables
    $scriptWithVariables = $triggerBuildScriptContent
    foreach ($variableName in $variables.Keys) {
        $scriptWithVariables = $scriptWithVariables -replace "\$$variableName", "`$$variableName = '$($variables[$variableName])'"
    }

    # Execute the TriggerBuild script with the concatenated content
    Invoke-Expression $scriptWithVariables
})

$form.Controls.Add($buttonRun)
$form.ShowDialog()

这只是设计为一个非常简单的 GUI,带有文本框,可以在其中输入变量值,然后点击“运行”按钮来触发构建管道。

我尝试以多种不同的方式格式化此 GUI 脚本,包括将构建管道脚本包含在同一脚本中,但每次都会出现相同的行为(即构建运行但未传入运行时变量值) .

我的期望是,从该脚本创建的 GUI 中,我可以输入所需变量的值,当我点击运行时,构建管道将运行,并传入相应运行时变量的指定值。

举个例子:

这将导致构建管道按照此处的示例运行:

相反,在当前配置中,所有变量都显示“未定义”。

powershell variables azure-devops azure-pipelines azure-devops-rest-api
1个回答
0
投票

先决条件:

如果您想使用 Rest API 触发使用变量运行的管道,请确认您在

Project Settings -> Pipelines -> Settings
docs Link 中取消选择变量限制。

如果不修改上述设置,即使你的所有 powershell UI 都工作正常,你也可能会收到错误。

Invoke-RestMethod : {"$id":"1","innerException":null,"message":"参见 https://aka.ms/AzPipelines/SettingVariablesAtQueueTime - 您无法设置 以下变量(变量2、变量0、变量1)。如果你想 能够设置这些变量

1.我给你的示例代码:

表格.ps1
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,120)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
##
$cnt = 2
$textBoxArray = @()
foreach($item in @(0..$cnt)){

    $labelPositionY = ($item - 1)*25 + 30
    $textBoxPositionY = ($item - 1)*25 + 30

    $label = New-Object System.Windows.Forms.Label
    $label.Location = New-Object System.Drawing.Point(10,$labelPositionY)
    $label.Size = New-Object System.Drawing.Size(60,20)
    $label.Text = 'Variable{0}: ' -f $item
    $form.Controls.Add($label)

    $textBox = New-Object System.Windows.Forms.TextBox
    $textBox.Location = New-Object System.Drawing.Point(75,$textBoxPositionY)
    $textBox.Size = New-Object System.Drawing.Size(180,20)
    $form.Controls.Add($textBox)

    $textBoxArray += $textBox
}

$form.Topmost = $true

# $form.Add_Shown({$textBox[0].Select()})
$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    foreach($item in $textBoxArray){
        $var = $item.Text
        Write-Host $var
    }
    . .\runPipelineWithVariables.ps1 -Variable0 $textBoxArray[0].Text -Variable1 $textBoxArray[1].Text -Variable2 $textBoxArray[2].Text
}
runPipelineWithVariables.ps1
[CmdletBinding()]
param (
    [Parameter()]
    [string]$Variable0,
    [Parameter()]
    [string]$Variable1,
    [Parameter()]
    [string]$Variable2
)
##
$userName = "xxx"
$personalAccessToken = "xxx"
#
$organizationName = "xxx"
$projectName = "xxx"
$pipelineId = 111
#
$basicAuth = ("{0}:{1}" -f $userName, $personalAccessToken)
$basicAuth = [System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth = [System.Convert]::ToBase64String($basicAuth)
$headers = @{Authorization = ("Basic {0}" -f $basicAuth) }
##
$headers = Get-AzureDevOpsHeaders -UserName $userName -PersonalAccessToken $personalAccessToken

$uri = "https://dev.azure.com/{0}/{1}/_apis/pipelines/{2}/runs?api-version=7.1-preview.1" -f $organizationName, $projectName, $pipelineId

$body = @{
    resources = @{
        repositories = @{
            'self' = @{
                refName = 'refs/heads/master'
                }
            }
        }
    variables = @{
        'variable0' = @{
            isSecret = $false
            value = $Variable0
        }
        'variable1' = @{
            isSecret = $false
            value = $Variable1
        }
        'variable2' = @{
            isSecret = $false
            value = $Variable2
        }
    }
} | ConvertTo-Json -Depth 10

Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType 'application/json' -Headers $headers -Body $body

替换

runPipelineWithVariables.ps1
中未给出的参数并运行
form.ps1
,它会要求输入
variable0, variables1, variables2.

2.您可能需要这样的 yaml 来调试变量:
pool:
  vmImage: ubuntu-latest

steps:
- script: echo "variable0 is, $(variable0)"
- script: echo "variable1 is, $(variable1)"
- script: echo "variable2 is, $(variable2)"
3.我的测试结果:

© www.soinside.com 2019 - 2024. All rights reserved.