From 80f29cfb20b1f2aa6324030ad903345ef102face Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Thu, 2 Apr 2026 16:01:53 +1030 Subject: [PATCH 01/11] Created Github action that detects any new .sln files in a PR and adds a new module label if there is --- .github/workflows/check-for-modules.yml | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/check-for-modules.yml diff --git a/.github/workflows/check-for-modules.yml b/.github/workflows/check-for-modules.yml new file mode 100644 index 000000000000..c24811797f1e --- /dev/null +++ b/.github/workflows/check-for-modules.yml @@ -0,0 +1,45 @@ +name: pr-new-modules +run-name: Triggered by pr +env: + GH_TOKEN: ${{ github.token }} + PR: ${{ github.event.pull_request.html_url }} +on: + pull_request_target: + types: + - opened + - edited +jobs: + process_labels: + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: read + steps: + - uses: actions/checkout@v6 + with: + sparse-checkout: | + .github + + - name: Fetch PR Head + run: git fetch origin refs/pull/${{ github.event.pull_request.number }}/head:pr-head + + - name: Fetch comparison branch + run: git fetch origin ${{ github.base_ref }} + + - name: check for new modules + shell: pwsh + env: + BASE_REF: ${{ github.base_ref }} + run: | + $files = @(git diff ` + origin/$env:BASE_REF..pr-head ` + --diff-filter=A ` + --name-only ` + -- '**/*.sln') + + if ($files.Count -gt 0) { + Write-Host "Detected a new module" + gh pr edit "$env:PR" --add-label "new module" + } else { + Write-Host "No new module detected" + } From a07b9b2130027bf9166871d37f33ddde11506398 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 14:27:20 +0930 Subject: [PATCH 02/11] Add path filter for solution files in workflow --- .github/workflows/check-for-modules.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/check-for-modules.yml b/.github/workflows/check-for-modules.yml index c24811797f1e..0a72015182e9 100644 --- a/.github/workflows/check-for-modules.yml +++ b/.github/workflows/check-for-modules.yml @@ -5,6 +5,8 @@ env: PR: ${{ github.event.pull_request.html_url }} on: pull_request_target: + paths: + - 'src/**/*.sln' types: - opened - edited From 6baf1edd351c72bb214727060403ccdae92f9fb0 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 14:28:28 +0930 Subject: [PATCH 03/11] Fix YAML syntax for pull_request_target paths --- .github/workflows/check-for-modules.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-for-modules.yml b/.github/workflows/check-for-modules.yml index 0a72015182e9..a6bd1770320c 100644 --- a/.github/workflows/check-for-modules.yml +++ b/.github/workflows/check-for-modules.yml @@ -5,7 +5,7 @@ env: PR: ${{ github.event.pull_request.html_url }} on: pull_request_target: - paths: + paths: - 'src/**/*.sln' types: - opened From 66aabeeb9f6d94d21ec2bdf76c88b0bec87a34f6 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 15:59:59 +0930 Subject: [PATCH 04/11] Enhance PR template with new module onboarding info Add onboarding instructions for new module in PR template. --- .github/workflows/script/PrLabeled.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/script/PrLabeled.ps1 b/.github/workflows/script/PrLabeled.ps1 index 9dc749c84dbb..667e7b1edd54 100644 --- a/.github/workflows/script/PrLabeled.ps1 +++ b/.github/workflows/script/PrLabeled.ps1 @@ -29,6 +29,14 @@ Please resolve all open review comments and make sure all CI checks are green. R "codegen-survey" = @" Thanks for using autorest.powershell to develop your PowerShell module! Would you like to take [a 5-minute survey](https://forms.office.com/r/j6rQuFUqUf?origin=lprLink) to help us improve the tool? Much appreciated :) "@ + "Module Onboard" = @" +This pull request introduces a **new module** which requires onboarding into the MAR Manifest. + +Please ensure this module is added to the **MAR manifest** for first release. + +Follow the **First Release onboarding guide** here: +https://eng.ms/docs/cloud-ai-platform/azure-core/azure-experiences-and-ecosystems/azure-portal-and-client-tools-ruhim/azure-cli-tools-azure-cli-powershell-and-terraform/azure-cli-tools/onboarding/azurepowershell/release#Firstrelease +" "Legacy" = @" To improve dev experience and reduce maintenance efforts, we are deprecating branch: generation now. Azure-PowerShell modules generated by autorest.powershell no longer target branch generation, and will be targeting directly to main instead. From d0e2536c728d73e6663ab4271fa03e0ff8cdfc54 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 16:00:55 +0930 Subject: [PATCH 05/11] Rename job from process_labels to compare-branches --- .github/workflows/check-for-modules.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-for-modules.yml b/.github/workflows/check-for-modules.yml index a6bd1770320c..268473c634a0 100644 --- a/.github/workflows/check-for-modules.yml +++ b/.github/workflows/check-for-modules.yml @@ -11,7 +11,7 @@ on: - opened - edited jobs: - process_labels: + compare-branches: runs-on: ubuntu-latest permissions: pull-requests: write @@ -41,7 +41,7 @@ jobs: if ($files.Count -gt 0) { Write-Host "Detected a new module" - gh pr edit "$env:PR" --add-label "new module" + gh pr edit "$env:PR" --add-label "Module Onboard" } else { Write-Host "No new module detected" } From 044abf63eada29f10ca1f18eb13d15fdf5a674de Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 16:09:05 +0930 Subject: [PATCH 06/11] Deprecate branch generation in PrLabeled.ps1 Deprecate branch generation for Azure-PowerShell modules and update documentation. --- .github/workflows/script/PrLabeled.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/script/PrLabeled.ps1 b/.github/workflows/script/PrLabeled.ps1 index 667e7b1edd54..e1efc9deda45 100644 --- a/.github/workflows/script/PrLabeled.ps1 +++ b/.github/workflows/script/PrLabeled.ps1 @@ -36,7 +36,7 @@ Please ensure this module is added to the **MAR manifest** for first release. Follow the **First Release onboarding guide** here: https://eng.ms/docs/cloud-ai-platform/azure-core/azure-experiences-and-ecosystems/azure-portal-and-client-tools-ruhim/azure-cli-tools-azure-cli-powershell-and-terraform/azure-cli-tools/onboarding/azurepowershell/release#Firstrelease -" +"@ "Legacy" = @" To improve dev experience and reduce maintenance efforts, we are deprecating branch: generation now. Azure-PowerShell modules generated by autorest.powershell no longer target branch generation, and will be targeting directly to main instead. From f33ffd6c4f0efc36d311e9a5d44d895dbc3d320a Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 16:10:55 +0930 Subject: [PATCH 07/11] Fix PowerShell script to handle new module detection --- .github/workflows/check-for-modules.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-for-modules.yml b/.github/workflows/check-for-modules.yml index 268473c634a0..26bfc7fea807 100644 --- a/.github/workflows/check-for-modules.yml +++ b/.github/workflows/check-for-modules.yml @@ -42,6 +42,7 @@ jobs: if ($files.Count -gt 0) { Write-Host "Detected a new module" gh pr edit "$env:PR" --add-label "Module Onboard" + .github/workflows/script/PrLabeled.ps1 -LabelName "Module Onboard" -PrUrl $env:PR } else { Write-Host "No new module detected" } From ecbf478bfaccf7238d6edf21277f258e05232c56 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Mon, 13 Apr 2026 16:23:29 +0930 Subject: [PATCH 08/11] Update onboarding instructions in PrLabeled.ps1 Clarify onboarding instructions for new module in PR template. --- .github/workflows/script/PrLabeled.ps1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/script/PrLabeled.ps1 b/.github/workflows/script/PrLabeled.ps1 index e1efc9deda45..da6d6f051b21 100644 --- a/.github/workflows/script/PrLabeled.ps1 +++ b/.github/workflows/script/PrLabeled.ps1 @@ -30,12 +30,11 @@ Please resolve all open review comments and make sure all CI checks are green. R Thanks for using autorest.powershell to develop your PowerShell module! Would you like to take [a 5-minute survey](https://forms.office.com/r/j6rQuFUqUf?origin=lprLink) to help us improve the tool? Much appreciated :) "@ "Module Onboard" = @" -This pull request introduces a **new module** which requires onboarding into the MAR Manifest. +To the current spint master, +This pull request introduces a **new module** which requires onboarding into the MAR Manifest before merge. -Please ensure this module is added to the **MAR manifest** for first release. +Follow the **[First Release](https://eng.ms/docs/cloud-ai-platform/azure-core/azure-experiences-and-ecosystems/azure-portal-and-client-tools-ruhim/azure-cli-tools-azure-cli-powershell-and-terraform/azure-cli-tools/onboarding/azurepowershell/release#Firstrelease) onboarding guide**. -Follow the **First Release onboarding guide** here: -https://eng.ms/docs/cloud-ai-platform/azure-core/azure-experiences-and-ecosystems/azure-portal-and-client-tools-ruhim/azure-cli-tools-azure-cli-powershell-and-terraform/azure-cli-tools/onboarding/azurepowershell/release#Firstrelease "@ "Legacy" = @" To improve dev experience and reduce maintenance efforts, we are deprecating branch: generation now. Azure-PowerShell modules generated by autorest.powershell no longer target branch generation, and will be targeting directly to main instead. From fc94ec7aecd61978c03d63eb5c3b305d2713b4a2 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Fri, 8 May 2026 14:17:50 +0930 Subject: [PATCH 09/11] Added a check for sln pipeline --- .azure-pipelines/sln-check.yml | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .azure-pipelines/sln-check.yml diff --git a/.azure-pipelines/sln-check.yml b/.azure-pipelines/sln-check.yml new file mode 100644 index 000000000000..3f46381833b4 --- /dev/null +++ b/.azure-pipelines/sln-check.yml @@ -0,0 +1,97 @@ +# .pipelines/sln-check.yml +# PUBLIC pipeline — detects new .sln files in PRs. +# Contains NO secrets. Safe to run with PR-sourced YAML. +# +# When new .sln files are found, this pipeline publishes an artifact +# consumed by an internal pipeline (sln-trigger-internal) that: +# 1. Posts a "pending" GitHub status check ('module-onboarding') to the PR +# 2. Triggers internal pipeline 678 for each new module +# 3. Waits for pipeline 678 to complete +# 4. Posts "success" or "failure" to the same GitHub status check +# +# Configure GitHub branch protection to require the 'module-onboarding' +# status check so the PR cannot merge until the internal work finishes. + +trigger: none + +pr: + branches: + include: + - main + +pool: + vmImage: 'ubuntu-latest' + +steps: + - checkout: self + fetchDepth: 0 + submodules: false + persistCredentials: false + lfs: false + + - pwsh: | + Set-StrictMode -Version 2.0 + $ErrorActionPreference = 'Stop' + + # Validate and normalize the target branch + $targetBranch = "$(System.PullRequest.TargetBranch)" -replace '^refs/heads/', '' + if ($targetBranch -notmatch '^[a-zA-Z0-9._/-]+$') { + Write-Error "Invalid target branch name: $targetBranch" + exit 1 + } + + Write-Host "Fetching target branch: $targetBranch" + git fetch origin "+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}" + + # Find new .sln files added in this PR (three-dot = merge-base comparison) + $newSlnFiles = git diff --name-only --diff-filter=A "origin/${targetBranch}...HEAD" -- '*.sln' + + if (-not $newSlnFiles) { + Write-Host "##[section]No new .sln files found. Nothing to do." + Write-Host "##vso[task.setvariable variable=hasNewSln]false" + return + } + + $slnList = @($newSlnFiles -split "`n" | Where-Object { $_.Trim() -ne '' }) + + if ($slnList.Count -gt 5) { + Write-Error "Too many new .sln files ($($slnList.Count)). Refusing to proceed — maximum is 5." + exit 1 + } + + Write-Host "##[section]New .sln files detected ($($slnList.Count)):" + + $moduleNames = @() + foreach ($slnPath in $slnList) { + $slnPath = $slnPath.Trim() + $moduleName = [System.IO.Path]::GetFileNameWithoutExtension($slnPath) + + # Validate module name: alphanumeric start, safe characters, max 100 chars + if ($moduleName -notmatch '^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,99}$') { + Write-Error "Invalid module name derived from '$slnPath': '$moduleName'" + exit 1 + } + + Write-Host " $slnPath -> ModuleName: $moduleName" + $moduleNames += $moduleName + } + + # Write module names and PR metadata to artifact for the internal pipeline + $artifactDir = Join-Path "$(Build.ArtifactStagingDirectory)" 'sln-check' + New-Item -ItemType Directory -Path $artifactDir -Force | Out-Null + $moduleNames | Set-Content -Path (Join-Path $artifactDir 'new-modules.txt') -Encoding utf8 + + # Include the PR commit SHA so the internal pipeline can post status checks + $prSha = "$(Build.SourceVersion)" + $prSha | Set-Content -Path (Join-Path $artifactDir 'pr-commit-sha.txt') -Encoding utf8 + + Write-Host "PR commit SHA: $prSha" + Write-Host "##vso[task.setvariable variable=hasNewSln]true" + displayName: 'Detect new SLN files' + + - task: PublishPipelineArtifact@1 + displayName: 'Publish new module names' + condition: eq(variables['hasNewSln'], 'true') + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)/sln-check' + artifactName: 'sln-check' From 265c5aee147f33ece7341259ea1669bdc3cb1540 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Wed, 13 May 2026 15:15:15 +0930 Subject: [PATCH 10/11] Added a trigger for internal validate pipeline --- .azure-pipelines/sln-check.yml | 54 +++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/.azure-pipelines/sln-check.yml b/.azure-pipelines/sln-check.yml index 3f46381833b4..482c82d146c7 100644 --- a/.azure-pipelines/sln-check.yml +++ b/.azure-pipelines/sln-check.yml @@ -1,16 +1,24 @@ -# .pipelines/sln-check.yml +# .azure-pipelines/sln-check.yml # PUBLIC pipeline — detects new .sln files in PRs. # Contains NO secrets. Safe to run with PR-sourced YAML. # -# When new .sln files are found, this pipeline publishes an artifact -# consumed by an internal pipeline (sln-trigger-internal) that: +# When new .sln files are found, this pipeline: +# 1. Publishes module names + PR commit SHA as an artifact +# 2. Triggers the internal sln-trigger-internal pipeline via REST API +# (using System.AccessToken — no secrets stored in this pipeline) +# +# The internal pipeline then: # 1. Posts a "pending" GitHub status check ('module-onboarding') to the PR -# 2. Triggers internal pipeline 678 for each new module -# 3. Waits for pipeline 678 to complete +# 2. Creates a PR in MCR with the new module manifest entries +# 3. Waits for the MCR PR to be merged # 4. Posts "success" or "failure" to the same GitHub status check # # Configure GitHub branch protection to require the 'module-onboarding' # status check so the PR cannot merge until the internal work finishes. +# +# PERMISSIONS: +# The public project's build service identity needs 'Queue builds' +# permission on pipeline 1201 in the internal project. trigger: none @@ -54,8 +62,8 @@ steps: $slnList = @($newSlnFiles -split "`n" | Where-Object { $_.Trim() -ne '' }) - if ($slnList.Count -gt 5) { - Write-Error "Too many new .sln files ($($slnList.Count)). Refusing to proceed — maximum is 5." + if ($slnList.Count -gt 10) { + Write-Error "Too many new .sln files ($($slnList.Count)). Refusing to proceed — maximum is 10." exit 1 } @@ -95,3 +103,35 @@ steps: inputs: targetPath: '$(Build.ArtifactStagingDirectory)/sln-check' artifactName: 'sln-check' + + - pwsh: | + $ErrorActionPreference = 'Stop' + + $orgUrl = "$(System.CollectionUri)".TrimEnd('/') + $token = "$(System.AccessToken)" | ConvertTo-SecureString -AsPlainText + + # Trigger sln-trigger-internal (pipeline 1201) in the internal project + $uri = "$orgUrl/internal/_apis/pipelines/1201/runs?api-version=7.1-preview.1" + + $body = @{ + resources = @{ + pipelines = @{ + 'sln-check' = @{ + version = "$(Build.BuildId)" + } + } + } + } | ConvertTo-Json -Depth 10 + + Write-Host "Triggering sln-trigger-internal..." + Write-Host "POST $uri" + + $response = Invoke-RestMethod -Uri $uri -Method Post ` + -ContentType 'application/json' ` + -Authentication Bearer -Token $token ` + -Body $body + + Write-Host "Triggered run ID: $($response.id)" + Write-Host "URL: $($response._links.web.href)" + displayName: 'Trigger internal pipeline' + condition: eq(variables['hasNewSln'], 'true') From 0beae3816e6fce32663a63dd9f8c1ca44fadd5c1 Mon Sep 17 00:00:00 2001 From: Thomas Temby Date: Wed, 13 May 2026 16:18:03 +0930 Subject: [PATCH 11/11] removed Invoke to call pipeline --- .azure-pipelines/sln-check.yml | 44 ++++------------------------------ 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/.azure-pipelines/sln-check.yml b/.azure-pipelines/sln-check.yml index 482c82d146c7..f8b2c50a4c23 100644 --- a/.azure-pipelines/sln-check.yml +++ b/.azure-pipelines/sln-check.yml @@ -2,10 +2,10 @@ # PUBLIC pipeline — detects new .sln files in PRs. # Contains NO secrets. Safe to run with PR-sourced YAML. # -# When new .sln files are found, this pipeline: -# 1. Publishes module names + PR commit SHA as an artifact -# 2. Triggers the internal sln-trigger-internal pipeline via REST API -# (using System.AccessToken — no secrets stored in this pipeline) +# When new .sln files are found, this pipeline publishes an artifact. +# An Azure DevOps Service Hook (configured in the public project UI) +# detects the build completion and triggers sln-trigger-internal in +# the internal project via an Incoming Webhook service connection. # # The internal pipeline then: # 1. Posts a "pending" GitHub status check ('module-onboarding') to the PR @@ -15,10 +15,6 @@ # # Configure GitHub branch protection to require the 'module-onboarding' # status check so the PR cannot merge until the internal work finishes. -# -# PERMISSIONS: -# The public project's build service identity needs 'Queue builds' -# permission on pipeline 1201 in the internal project. trigger: none @@ -103,35 +99,3 @@ steps: inputs: targetPath: '$(Build.ArtifactStagingDirectory)/sln-check' artifactName: 'sln-check' - - - pwsh: | - $ErrorActionPreference = 'Stop' - - $orgUrl = "$(System.CollectionUri)".TrimEnd('/') - $token = "$(System.AccessToken)" | ConvertTo-SecureString -AsPlainText - - # Trigger sln-trigger-internal (pipeline 1201) in the internal project - $uri = "$orgUrl/internal/_apis/pipelines/1201/runs?api-version=7.1-preview.1" - - $body = @{ - resources = @{ - pipelines = @{ - 'sln-check' = @{ - version = "$(Build.BuildId)" - } - } - } - } | ConvertTo-Json -Depth 10 - - Write-Host "Triggering sln-trigger-internal..." - Write-Host "POST $uri" - - $response = Invoke-RestMethod -Uri $uri -Method Post ` - -ContentType 'application/json' ` - -Authentication Bearer -Token $token ` - -Body $body - - Write-Host "Triggered run ID: $($response.id)" - Write-Host "URL: $($response._links.web.href)" - displayName: 'Trigger internal pipeline' - condition: eq(variables['hasNewSln'], 'true')