From 9bbf28dbe2539c5e7feea5e33e5f3434ecef3937 Mon Sep 17 00:00:00 2001 From: Missy Messa Date: Wed, 16 Sep 2026 10:02:47 -0700 Subject: [PATCH] Use GitHub App for promotion validation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9d4901ab-a32c-4ce3-8cf2-b6f4c1a6e8b5 --- .vault-config/product-builds-engkeyvault.yaml | 7 +++++++ azure-pipelines.yml | 1 + eng/build.yml | 15 +++++++++------ eng/validate-promotion.yml | 9 +++++++++ eng/validation/validate-promotion.ps1 | 7 ++++--- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/.vault-config/product-builds-engkeyvault.yaml b/.vault-config/product-builds-engkeyvault.yaml index 6026b0e587c..d713c4d5808 100644 --- a/.vault-config/product-builds-engkeyvault.yaml +++ b/.vault-config/product-builds-engkeyvault.yaml @@ -51,6 +51,13 @@ secrets: hasWebhookSecret: false hasOAuthSecret: false + arcade-promotion-validation-app: + type: github-app-secret + parameters: + hasPrivateKey: true + hasWebhookSecret: false + hasOAuthSecret: false + BotAccount-dotnet-maestro-bot: type: github-account parameters: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 530b3f0f180..23304f7f5af 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -69,3 +69,4 @@ extends: oneLocEnabled: true microbuildUseESRP: true runValidateSdk: ${{ parameters.runValidateSdk }} + runPromotionValidation: true diff --git a/eng/build.yml b/eng/build.yml index bf4a303274f..50eb1c4c3a7 100644 --- a/eng/build.yml +++ b/eng/build.yml @@ -5,14 +5,16 @@ parameters: - name: microbuildUseESRP default: false type: boolean -# When true (default), run the Validate Arcade SDK stage: three parallel validations of the newly -# produced SDK - signing validation, self-build (self-bootstrap), and promotion to a test channel -# with the new Arcade. Set to false as a bootstrap-breakage escape hatch to ship a new Arcade when -# the current one cannot self-validate; the promotion to '.NET Eng - Latest' still runs on build -# success. +# When true (default), run the Validate Arcade SDK stage for the newly produced SDK. Set to false as +# a bootstrap-breakage escape hatch to ship a new Arcade when the current one cannot self-validate; +# the promotion to '.NET Eng - Latest' still runs on build success. - name: runValidateSdk default: true type: boolean +# Promotion validation requires credentials restricted to the internal official pipeline. +- name: runPromotionValidation + default: false + type: boolean # The channel successful builds are promoted to, and the source branch the promotion gate runs on. # Defined once here so they aren't duplicated throughout the promotion stage below. - name: promotionChannel @@ -83,7 +85,8 @@ stages: parameters: microbuildUseESRP: ${{ parameters.microbuildUseESRP }} # Validate that build promotion works when driven by the newly built Arcade. - - template: /eng/validate-promotion.yml@self + - ${{ if eq(parameters.runPromotionValidation, true) }}: + - template: /eng/validate-promotion.yml@self - template: /eng/common/templates-official/post-build/post-build.yml@self parameters: diff --git a/eng/validate-promotion.yml b/eng/validate-promotion.yml index 504d2bcdb6c..21f015fa492 100644 --- a/eng/validate-promotion.yml +++ b/eng/validate-promotion.yml @@ -44,6 +44,14 @@ jobs: $azdoToken = az account get-access-token --resource "499b84ac-1321-427f-aa17-267ca6975798" --query accessToken -o tsv if ($LASTEXITCODE -ne 0) { Write-Error "Failed to get AzDO token"; exit 1 } Write-Host "##vso[task.setvariable variable=WifAzDoToken;issecret=true]$azdoToken" + - template: /eng/common/templates-official/steps/get-github-app-token.yml@self + parameters: + azureSubscription: "dnceng-arcade-promotion-githubapp" + keyVaultName: EngKeyVault + appIdSecretName: arcade-promotion-validation-app-app-id + appPrivateKeySecretName: arcade-promotion-validation-app-app-private-key + installationOwner: dotnet + outputVariableName: GitHubAppInstallationToken - task: AzureCLI@2 displayName: Validate promotion with the newly built Arcade inputs: @@ -55,3 +63,4 @@ jobs: -BuildId $(BARBuildId) -Commit $(Build.SourceVersion) -AzdoToken $(WifAzDoToken) + -GitHubToken $(GitHubAppInstallationToken) diff --git a/eng/validation/validate-promotion.ps1 b/eng/validation/validate-promotion.ps1 index e7049af4da8..74a4a74e081 100644 --- a/eng/validation/validate-promotion.ps1 +++ b/eng/validation/validate-promotion.ps1 @@ -20,6 +20,7 @@ Param( [Parameter(Mandatory=$true)][int] $BuildId, # BAR build id of the build being validated. [Parameter(Mandatory=$true)][string] $Commit, # The commit that produced this build (Build.SourceVersion). [Parameter(Mandatory=$true)][string] $AzdoToken, # AzDO OAuth/AAD access token (WIF), not a PAT; needs code read/write on the mirror. + [Parameter(Mandatory=$true)][string] $GitHubToken, # Short-lived GitHub App installation token for dependency metadata and common scripts. [string] $AzdoOrg = 'dnceng', [string] $AzdoProject = 'internal', [string] $AzdoRepoName = 'dotnet-arcade', @@ -92,9 +93,9 @@ try { & git checkout -b $targetBranch $Commit if ($LASTEXITCODE -ne 0) { throw "git checkout of $Commit failed." } - # Do not supply a GitHub credential. This validates whether the current dependency graph can be - # updated using its public metadata and the AzDO credential used for the internal mirror. - & $darc update-dependencies --id $BuildId --azdev-pat $AzdoToken --ci + # The --id form retrieves dependency metadata and common scripts from GitHub while applying + # updates, so it requires a GitHub credential even when there are no coherent dependencies. + & $darc update-dependencies --id $BuildId --azdev-pat $AzdoToken --github-pat $GitHubToken --ci if ($LASTEXITCODE -ne 0) { throw "darc update-dependencies failed." } # A no-op update means darc produced the same versions already pinned, which is unexpected for a