Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions .azure-pipelines/sln-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# .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.
# 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
# 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.

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 10) {
Write-Error "Too many new .sln files ($($slnList.Count)). Refusing to proceed — maximum is 10."
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'
48 changes: 48 additions & 0 deletions .github/workflows/check-for-modules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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:
paths:
- 'src/**/*.sln'
types:
- opened
- edited
jobs:
compare-branches:
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 "Module Onboard"
.github/workflows/script/PrLabeled.ps1 -LabelName "Module Onboard" -PrUrl $env:PR
} else {
Write-Host "No new module detected"
}
7 changes: 7 additions & 0 deletions .github/workflows/script/PrLabeled.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ 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" = @"
To the current spint master,
This pull request introduces a **new module** which requires onboarding into the MAR Manifest before merge.

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**.

"@
"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.
Expand Down