Validation pipeline migration to 1ES (#129183)

* This PR migrates the WinGetSVC validation pipeline to 1ES, including changes to the following files:

validation-pipeline.yaml

The winget-pkgs repo was updated with the changes from the winget-pkgs-preprod repo, which had been merged from the pipeline staging process through PR. This manual copying was necessary because the automatic deployment failed for the production pipeline.

[How Validated:]

The changes have been validated against the preprod environment by manually triggering the pipeline and ensuring successful runs.

[Important Note:]

During our last deployment, we discovered that the validation process encountered a failure in the SDL Source, caused by a permission issue with a task automatically injected by the 1ES pipeline. This issue occurred when the pipeline ran on PR commits from fork branches created by community contributors external to Microsoft. We have reported the issue to the 1ES team and are actively engaging with them to find a resolution. Until then, this PR will be kept in a draft state.

* Apply SkipBuildTagsForGitHubPullRequests workaround fix to resolve Tag build and log custom issues (1ES PT) with Access denied error

1ES PT uses ADO access token to add tags to pipeline runs. For forked GitHub repo pipelines, access token lacks Edit build quality permission, preventing tag addition. Use SkipBuildTagsForGitHubPullRequests option to unblock
This commit is contained in:
Madhusudhan-MSFT
2023-12-14 11:21:35 -08:00
committed by GitHub
parent edabcf93aa
commit aa22e6f63a
+302 -284
View File
@@ -12,304 +12,322 @@ pr:
include:
- manifests
jobs:
resources:
repositories:
- repository: 1ESPipelineTemplates
type: git
name: 1ESPipelineTemplates/1ESPipelineTemplates
ref: refs/tags/release
extends:
template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
parameters:
pool:
name: Azure-Pipelines-1ESPT-ExDShared
image: windows-2022
os: windows
customBuildTags:
- ES365AIMigrationTooling
settings:
skipBuildTagsForGitHubPullRequests: true
stages:
- stage: WinGetSvc_Validation
jobs:
# Agent phase. Process pull request changes and validate manifests.
- job: 'FileValidation'
displayName: 'Pull Request Validation'
pool:
vmImage: 'windows-latest'
variables:
skipComponentGovernanceDetection: ${{ true }}
runCodesignValidationInjection: ${{ false }}
timeoutInMinutes: 0
steps:
# Agent phase. Process pull request changes and validate manifests.
- job: 'FileValidation'
displayName: 'Pull Request Validation'
variables:
skipComponentGovernanceDetection: ${{ true }}
runCodesignValidationInjection: ${{ false }}
timeoutInMinutes: 0
steps:
# Downloads all the setup files and its dependencies.
- task: AzureCLI@1
displayName: 'Azure Setup'
inputs:
azureSubscription: '$(WinGet.Subscription)'
scriptLocation: inlineScript
inlineScript: 'az storage blob download-batch -d . --pattern * -s servicewrapper --output none'
env:
AZURE_STORAGE_CONNECTION_STRING: $(ValidationStorageAccountConnectionString)
# Downloads all the setup files and its dependencies.
- task: AzureCLI@1
displayName: 'Azure Setup'
inputs:
azureSubscription: '$(WinGet.Subscription)'
scriptLocation: inlineScript
inlineScript: 'az storage blob download-batch -d . --pattern * -s servicewrapper --output none'
env:
AZURE_STORAGE_CONNECTION_STRING: $(ValidationStorageAccountConnectionString)
# WinGet setup
- script: 'winget_validation_setup.cmd'
name: 'wingetsetup'
displayName: 'WinGet Setup'
workingDirectory: scripts
env:
HOST_KEY: $(AzureFunctionHostKey)
SMART_SCREEN_ENDPOINT: $(AzFuncSmartScreenEndpoint)
DOMAIN_URLS_VALIDATION_ENDPOINT: $(AzFuncDomainUrlValEndpoint)
MANIFEST_POLICY_ENDPOINT: $(AzFuncManifestPolicyEndpoint)
SCAN_ENDPOINT: $(AzFuncScanEndpoint)
INSTALLATION_ENDPOINT: $(AzFuncInstallationVerificationEndpoint)
LABEL_ENDPOINT: $(AzFuncSetLabelOnPullRequestEndpoint)
CLEANUP_ENDPOINT: $(AzFuncCleanupEndpoint)
LABEL_KEY: $(AzureFunctionLabelKey)
CATALOG_CONTENT_VERIFICATION_ENDPOINT: $(AzFuncCatalogContentVerificationEndpoint)
- task: CmdLine@2
name: 'wingetsetup'
displayName: 'WinGet Setup'
env:
HOST_KEY: $(AzureFunctionHostKey)
SMART_SCREEN_ENDPOINT: $(AzFuncSmartScreenEndpoint)
DOMAIN_URLS_VALIDATION_ENDPOINT: $(AzFuncDomainUrlValEndpoint)
MANIFEST_POLICY_ENDPOINT: $(AzFuncManifestPolicyEndpoint)
SCAN_ENDPOINT: $(AzFuncScanEndpoint)
INSTALLATION_ENDPOINT: $(AzFuncInstallationVerificationEndpoint)
LABEL_ENDPOINT: $(AzFuncSetLabelOnPullRequestEndpoint)
CLEANUP_ENDPOINT: $(AzFuncCleanupEndpoint)
LABEL_KEY: $(AzureFunctionLabelKey)
CATALOG_CONTENT_VERIFICATION_ENDPOINT: $(AzFuncCatalogContentVerificationEndpoint)
inputs:
script: 'winget_validation_setup.cmd'
workingDirectory: scripts
# Validates integrity of pull request.
- task: CmdLine@2
displayName: 'Validate Pull Request'
inputs:
script: 'WinGetSvcWrapper.exe process-pr --operationId %BUILD_BUILDNUMBER%'
failOnStderr: true
condition: succeeded()
env:
ValidationConnectionString: $(ValidationStorageAccountConnectionString)
GithubRepository: $(GithubRepository)
GithubServiceAccountToken: $(GithubServiceAccountToken)
ExecutionEnvironment: $(ExecutionEnvironment)
DIApplicationInsightKey: $(DIApplicationInsightKey)
WinGet:AppConfig:Primary: $(AppConfigPrimary)
WinGet:AppConfig:Secondary: $(AppConfigSecondary)
# Validates integrity of pull request.
- task: CmdLine@2
displayName: 'Validate Pull Request'
inputs:
script: 'WinGetSvcWrapper.exe process-pr --operationId %BUILD_BUILDNUMBER%'
failOnStderr: true
condition: succeeded()
env:
ValidationConnectionString: $(ValidationStorageAccountConnectionString)
GithubRepository: $(GithubRepository)
GithubServiceAccountToken: $(GithubServiceAccountToken)
ExecutionEnvironment: $(ExecutionEnvironment)
DIApplicationInsightKey: $(DIApplicationInsightKey)
WinGet:AppConfig:Primary: $(AppConfigPrimary)
WinGet:AppConfig:Secondary: $(AppConfigSecondary)
# Validates manifest integrity.
- task: CmdLine@2
displayName: 'Validate Manifest'
inputs:
script: 'WinGetSvcWrapper.exe validate-manifests --operationId %BUILD_BUILDNUMBER%'
failOnStderr: true
condition: succeeded()
env:
ValidationConnectionString: $(ValidationStorageAccountConnectionString)
CacheConnectionString: $(CacheStorageAccountConnectionString)
DIApplicationInsightKey: $(DIApplicationInsightKey)
WinGet:AppConfig:Primary: $(AppConfigPrimary)
WinGet:AppConfig:Secondary: $(AppConfigSecondary)
# Validates manifest integrity.
- task: CmdLine@2
displayName: 'Validate Manifest'
inputs:
script: 'WinGetSvcWrapper.exe validate-manifests --operationId %BUILD_BUILDNUMBER%'
failOnStderr: true
condition: succeeded()
env:
ValidationConnectionString: $(ValidationStorageAccountConnectionString)
CacheConnectionString: $(CacheStorageAccountConnectionString)
DIApplicationInsightKey: $(DIApplicationInsightKey)
WinGet:AppConfig:Primary: $(AppConfigPrimary)
WinGet:AppConfig:Secondary: $(AppConfigSecondary)
# Agentless phase. Depends on previous job.
- job: 'ContentValidation'
pool: server
displayName: 'Manifest Content Validation'
timeoutInMinutes: 1500
dependsOn:
- 'FileValidation'
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
SmartScreenEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.smartScreenEndpoint']]
DomainUrlValidationEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.domainUrlValidationEndpoint']]
ManiestPolicyEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.manifestPolicyEndpoint']]
steps:
# Agentless phase. Depends on previous job.
- job: 'ContentValidation'
pool: server
displayName: 'Manifest Content Validation'
timeoutInMinutes: 1500
dependsOn:
- 'FileValidation'
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
SmartScreenEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.smartScreenEndpoint']]
DomainUrlValidationEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.domainUrlValidationEndpoint']]
ManiestPolicyEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.manifestPolicyEndpoint']]
steps:
# Scans all the urls from manifest contents.
- task: AzureFunction@1
displayName: 'URLs Validation'
inputs:
function: '$(SmartScreenEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Scans all the urls from manifest contents.
- task: AzureFunction@1
displayName: 'URLs Validation'
inputs:
function: '$(SmartScreenEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Domain url validations.
- task: AzureFunction@1
displayName: 'URL Domain validation'
inputs:
function: '$(DomainUrlValidationEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Domain url validations.
- task: AzureFunction@1
displayName: 'URL Domain validation'
inputs:
function: '$(DomainUrlValidationEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Manifest policy checks.
- task: AzureFunction@1
displayName: 'Manifest Policy Validation'
inputs:
function: '$(ManiestPolicyEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Manifest policy checks.
- task: AzureFunction@1
displayName: 'Manifest Policy Validation'
inputs:
function: '$(ManiestPolicyEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Agentless phase. Depends on previous job.
- job: 'InstallerValidation'
pool: server
displayName: 'Installer Validation'
timeoutInMinutes: 1500
dependsOn:
- 'FileValidation'
- 'ContentValidation'
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
ScanEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.scanEndpoint']]
InstallationEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.installationEndpoint']]
steps:
# Agentless phase. Depends on previous job.
- job: 'InstallerValidation'
pool: server
displayName: 'Installer Validation'
timeoutInMinutes: 1500
dependsOn:
- 'FileValidation'
- 'ContentValidation'
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
ScanEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.scanEndpoint']]
InstallationEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.installationEndpoint']]
steps:
# Scan installers in manifests.
- task: AzureFunction@1
displayName: 'Installers Scan'
inputs:
function: '$(ScanEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Scan installers in manifests.
- task: AzureFunction@1
displayName: 'Installers Scan'
inputs:
function: '$(ScanEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Validates installation.
- task: AzureFunction@1
displayName: 'Installation Validation'
inputs:
function: '$(InstallationEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Validates installation.
- task: AzureFunction@1
displayName: 'Installation Validation'
inputs:
function: '$(InstallationEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Agentless phase. Depends on previous job.
- job: 'CatalogContentVerification'
pool: server
displayName: 'Catalog Content Verification'
timeoutInMinutes: 1500
dependsOn:
- 'FileValidation'
- 'ContentValidation'
- 'InstallerValidation'
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
CatalogContentVerificationEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.catalogContentVerificationEndpoint']]
steps:
# Agentless phase. Depends on previous job.
- job: 'CatalogContentVerification'
pool: server
displayName: 'Catalog Content Verification'
timeoutInMinutes: 1500
dependsOn:
- 'FileValidation'
- 'ContentValidation'
- 'InstallerValidation'
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
CatalogContentVerificationEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.catalogContentVerificationEndpoint']]
steps:
# Catalog content verification
- task: AzureFunction@1
displayName: 'Catalog Content Verification'
inputs:
function: '$(CatalogContentVerificationEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Catalog content verification
- task: AzureFunction@1
displayName: 'Catalog Content Verification'
inputs:
function: '$(CatalogContentVerificationEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"BuildId": "$(Build.BuildId)",
"PlanUrl": "$(system.CollectionUri)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Agentless phase. Runs even if previous jobs failed.
- job: 'postvalidation'
pool: server
displayName: 'Post Validation'
dependsOn:
- 'FileValidation'
- 'ContentValidation'
- 'InstallerValidation'
- 'CatalogContentVerification'
condition: succeededOrFailed()
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
LabelKeySecret : $[ dependencies.FileValidation.outputs['wingetsetup.labelkey']]
LabelEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.labelEndpoint']]
RepositoryId: $[ dependencies.FileValidation.outputs['wingetsetup.repoId']]
CleanupEndpointSecret: $[ dependencies.filevalidation.outputs['wingetsetup.cleanupEndpoint']]
steps:
# Agentless phase. Runs even if previous jobs failed.
- job: 'postvalidation'
pool: server
displayName: 'Post Validation'
dependsOn:
- 'FileValidation'
- 'ContentValidation'
- 'InstallerValidation'
- 'CatalogContentVerification'
condition: succeededOrFailed()
variables:
HostKeySecret: $[ dependencies.FileValidation.outputs['wingetsetup.hostkey']]
LabelKeySecret : $[ dependencies.FileValidation.outputs['wingetsetup.labelkey']]
LabelEndpointSecret: $[ dependencies.FileValidation.outputs['wingetsetup.labelEndpoint']]
RepositoryId: $[ dependencies.FileValidation.outputs['wingetsetup.repoId']]
CleanupEndpointSecret: $[ dependencies.filevalidation.outputs['wingetsetup.cleanupEndpoint']]
steps:
# Set label in GitHub PullRequest.
- task: AzureFunction@1
displayName: 'Set Label'
condition: eq(variables['WinGet.RepositoryType'], 'GitHub')
inputs:
function: '$(LabelEndpointSecret)'
key: '$(LabelKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"PlanUrl": "$(system.CollectionUri)",
"BuildId": "$(Build.BuildId)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)",
"BuildRepositoryId": "$(RepositoryId)",
"PullRequestNumber": "$(System.PullRequest.PullRequestNumber)",
}
waitForCompletion: "true"
# Set label in GitHub PullRequest.
- task: AzureFunction@1
displayName: 'Set Label'
condition: eq(variables['WinGet.RepositoryType'], 'GitHub')
inputs:
function: '$(LabelEndpointSecret)'
key: '$(LabelKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"PlanUrl": "$(system.CollectionUri)",
"BuildId": "$(Build.BuildId)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)",
"BuildRepositoryId": "$(RepositoryId)",
"PullRequestNumber": "$(System.PullRequest.PullRequestNumber)",
}
waitForCompletion: "true"
# Cleanup resources.
- task: AzureFunction@1
displayName: 'Validation cleanup'
inputs:
function: '$(CleanupEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"PlanUrl": "$(system.CollectionUri)",
"BuildId": "$(Build.BuildId)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"
# Cleanup resources.
- task: AzureFunction@1
displayName: 'Validation cleanup'
inputs:
function: '$(CleanupEndpointSecret)'
key: '$(HostKeySecret)'
body: |
{
"operationId": "$(Build.BuildNumber)",
"PlanUrl": "$(system.CollectionUri)",
"BuildId": "$(Build.BuildId)",
"HubName": "$(system.HostType)",
"ProjectId": "$(system.TeamProjectId)",
"PlanId": "$(system.PlanId)",
"JobId": "$(system.JobId)",
"TimelineId": "$(system.TimelineId)",
"TaskInstanceId": "$(system.TaskInstanceId)",
"AuthToken": "$(system.AccessToken)"
}
waitForCompletion: "true"