From 568c6f00b951071172770dddddd2b52e9584ea10 Mon Sep 17 00:00:00 2001 From: Microsoft Graph DevX Tooling Date: Wed, 15 Jul 2026 14:39:51 -0700 Subject: [PATCH 1/3] Split doc generation pipeline into parallel v1.0 and beta stages Adds a -GraphProfileFilter parameter (v1.0/beta/both, default both) to the generation scripts so each profile can be generated independently, and splits powershell-docs.yml into two parallel stages (GenerateV1, GenerateBeta) via a new reusable generate-docs-steps.yml template. Each stage generates a single profile, commits to its own branch, and opens its own PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 672bde33-f50e-49f9-a53c-623f7445b1e9 --- .../common-templates/generate-docs-steps.yml | 173 ++++++++++++++++++ azure-pipelines/powershell-docs.yml | 171 +++-------------- scripts/CorrectRelatedLinks-AllFiles.ps1 | 1 + scripts/EscapeDisallowedHtmlTags.ps1 | 7 +- scripts/GenerateAliasedDocs.ps1 | 9 +- scripts/GenerateMarkDown.ps1 | 10 +- scripts/GeneratePermissionsTable.ps1 | 5 +- scripts/MsSubserviceUpdate.ps1 | 5 +- scripts/RemoveBoilerPlateCode.ps1 | 25 ++- scripts/RemoveInvalidFullStops.ps1 | 7 +- .../RepairExamplesDescriptionsAndTitle.ps1 | 5 +- scripts/UpdateLinks.ps1 | 13 +- 12 files changed, 263 insertions(+), 168 deletions(-) create mode 100644 azure-pipelines/common-templates/generate-docs-steps.yml diff --git a/azure-pipelines/common-templates/generate-docs-steps.yml b/azure-pipelines/common-templates/generate-docs-steps.yml new file mode 100644 index 0000000000000..13a891ff08784 --- /dev/null +++ b/azure-pipelines/common-templates/generate-docs-steps.yml @@ -0,0 +1,173 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# +# Reusable steps that generate the Microsoft Graph PowerShell reference docs for a +# single SDK profile (v1.0 or beta), commit the result to a dedicated branch and +# open a pull request for that profile. Consumed by the parallel stages in +# powershell-docs.yml so that v1.0 and beta each produce an independent PR. + +parameters: + - name: GraphProfileFilter + type: string + values: + - v1.0 + - beta + - name: BranchPrefix + type: string + - name: PrTitle + type: string + - name: PrBody + type: string + default: "This pull request was automatically created by Azure Pipelines. **Important** Check for unexpected deletions or changes in this PR." + +steps: + - template: ../update-template.yml + - task: PowerShell@2 + name: "ComputeBranch" + displayName: 'Compute Branch Name' + inputs: + targetType: 'inline' + script: | + git submodule update --init --recursive + $branch = "{0}_{1}" -f "${{ parameters.BranchPrefix }}", (Get-Date -Format yyyyMMddHHmm) + Write-Host "Compute branch: $branch" + Write-Host "##vso[task.setvariable variable=WeeklyReferenceDocsBranch;isOutput=true]$branch" + - task: Bash@3 + displayName: "Create weekly refresh branch" + inputs: + targetType: inline + script: | + git status + git branch $(ComputeBranch.WeeklyReferenceDocsBranch) + git checkout $(ComputeBranch.WeeklyReferenceDocsBranch) + git status + - task: PowerShell@2 + displayName: 'Create missing external docs folder' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/CreateExternalDocsFolder.ps1 + - task: PowerShell@2 + displayName: 'Generate markdown files from PowerShell help files' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/GenerateMarkDown.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Escape disallowed html tags' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/EscapeDisallowedHtmlTags.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Update metadata header' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/MsSubserviceUpdate.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Generate permissions table' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/GeneratePermissionsTable.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Update Links' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/UpdateLinks.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + errorActionPreference: 'stop' + - task: PowerShell@2 + displayName: 'Repair Examples and Descriptions and Title' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/RepairExamplesDescriptionsAndTitle.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Remove boiler plate code' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/RemoveBoilerPlateCode.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Remove invalid fullstops' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/RemoveInvalidFullStops.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Generate missing docs for aliased cmdlets' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/GenerateAliasedDocs.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Correct related links section' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/CorrectRelatedLinks-AllFiles.ps1 + arguments: -GraphProfileFilter '${{ parameters.GraphProfileFilter }}' + - task: PowerShell@2 + displayName: 'Stabilize ms.date values' + continueOnError: false + inputs: + targetType: 'filePath' + pwsh: true + filePath: scripts/StabilizeMsDate.ps1 + errorActionPreference: 'stop' + - task: AzureKeyVault@2 + displayName: "Azure Key Vault: Get GitHub App secrets" + inputs: + azureSubscription: "Federated AKV Managed Identity Connection" + KeyVaultName: akv-prod-eastus + SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey" + - task: PowerShell@2 + displayName: Pushing to github + env: + GhAppId: $(microsoft-graph-devx-bot-appid) + GhAppKey: $(microsoft-graph-devx-bot-privatekey) + inputs: + targetType: inline + pwsh: true + script: | + git config --global user.email "GraphTooling@service.microsoft.com" + git config --global user.name "Microsoft Graph DevX Tooling" + git config --system core.longpaths true + # The microsoft-graph-devx-bot GitHub App must have contents:write on this repo. + $token = & "$(Build.SourcesDirectory)/scripts/Generate-Github-Token.ps1" -AppClientId $env:GhAppId -AppPrivateKeyContents $env:GhAppKey -Repository "MicrosoftDocs/microsoftgraph-docs-powershell" + if ([string]::IsNullOrWhiteSpace($token)) { throw "Failed to generate GitHub App installation token." } + # Mask the token so it is never surfaced in pipeline logs. + Write-Host "##vso[task.setsecret]$token" + git status + git add . + git commit -m "Updating reference docs" + git push --set-upstream "******github.com/MicrosoftDocs/microsoftgraph-docs-powershell.git" $(ComputeBranch.WeeklyReferenceDocsBranch) + git status + - template: create-pr.yml + parameters: + BaseBranch: "main" + TargetBranch: $(ComputeBranch.WeeklyReferenceDocsBranch) + Title: "${{ parameters.PrTitle }}" + Body: "${{ parameters.PrBody }}" diff --git a/azure-pipelines/powershell-docs.yml b/azure-pipelines/powershell-docs.yml index c0304ad79ada1..04d1c72ec610d 100644 --- a/azure-pipelines/powershell-docs.yml +++ b/azure-pipelines/powershell-docs.yml @@ -47,156 +47,41 @@ extends: customBuildTags: - ES365AIMigrationTooling stages: - - stage: stage + - stage: GenerateV1 + displayName: 'Generate v1.0 reference docs' + dependsOn: [] jobs: - - job: PowerShellDocsUpdate + - job: PowerShellDocsUpdateV1 timeoutInMinutes: ${{ parameters.PipelineTimeout }} templateContext: outputs: - output: pipelineArtifact displayName: 'Publish Examples to be reviewed as artifact' targetPath: missingexternaldocsurl - artifactName: 'MissingExternalDocs' + artifactName: 'MissingExternalDocs-v1.0' publishLocation: 'Container' steps: - - template: azure-pipelines/update-template.yml@self - - task : PowerShell@2 - name: "ComputeBranch" - displayName: 'Compute Branch Name' - inputs: - targetType: 'inline' - script: | - git submodule update --init --recursive - $branch = "{0}_{1}" -f "WeeklyReferenceDocsUpdate", (Get-Date -Format yyyyMMddHHmm) - Write-Host "Compute branch: $branch" - Write-Host "##vso[task.setvariable variable=WeeklyReferenceDocsBranch;isOutput=true]$branch" - - task: Bash@3 - displayName: "Create weekly refresh branch" - inputs: - targetType: inline - script: | - git status - git branch $(ComputeBranch.WeeklyReferenceDocsBranch) - git checkout $(ComputeBranch.WeeklyReferenceDocsBranch) - git status - - task: PowerShell@2 - displayName: 'Create missing external docs folder' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/CreateExternalDocsFolder.ps1 - - - task: PowerShell@2 - displayName: 'Generate markdown files from PowerShell help files' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/GenerateMarkDown.ps1 - - task: PowerShell@2 - displayName: 'Escape disallowed html tags' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/EscapeDisallowedHtmlTags.ps1 - - task: PowerShell@2 - displayName: 'Update metadata header' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/MsSubserviceUpdate.ps1 - - task: PowerShell@2 - displayName: 'Generate permissions table' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/GeneratePermissionsTable.ps1 - - task: PowerShell@2 - displayName: 'Update Links' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/UpdateLinks.ps1 - errorActionPreference: 'stop' - - task: PowerShell@2 - displayName: 'Repair Examples and Descriptions and Title' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/RepairExamplesDescriptionsAndTitle.ps1 - - task: PowerShell@2 - displayName: 'Remove boiler plate code' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/RemoveBoilerPlateCode.ps1 - - task: PowerShell@2 - displayName: 'Remove invalid fullstops' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/RemoveInvalidFullStops.ps1 - - task: PowerShell@2 - displayName: 'Generate missing docs for aliased cmdlets' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/GenerateAliasedDocs.ps1 - - task: PowerShell@2 - displayName: 'Correct related links section' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/CorrectRelatedLinks-AllFiles.ps1 - - task: PowerShell@2 - displayName: 'Stabilize ms.date values' - continueOnError: false - inputs: - targetType: 'filePath' - pwsh: true - filePath: scripts/StabilizeMsDate.ps1 - errorActionPreference: 'stop' - - task: AzureKeyVault@2 - displayName: "Azure Key Vault: Get GitHub App secrets" - inputs: - azureSubscription: "Federated AKV Managed Identity Connection" - KeyVaultName: akv-prod-eastus - SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey" - - task: PowerShell@2 - displayName: Pushing to github - env: - GhAppId: $(microsoft-graph-devx-bot-appid) - GhAppKey: $(microsoft-graph-devx-bot-privatekey) - inputs: - targetType: inline - pwsh: true - script: | - git config --global user.email "GraphTooling@service.microsoft.com" - git config --global user.name "Microsoft Graph DevX Tooling" - git config --system core.longpaths true - # The microsoft-graph-devx-bot GitHub App must have contents:write on this repo. - $token = & "$(Build.SourcesDirectory)/scripts/Generate-Github-Token.ps1" -AppClientId $env:GhAppId -AppPrivateKeyContents $env:GhAppKey -Repository "MicrosoftDocs/microsoftgraph-docs-powershell" - if ([string]::IsNullOrWhiteSpace($token)) { throw "Failed to generate GitHub App installation token." } - # Mask the token so it is never surfaced in pipeline logs. - Write-Host "##vso[task.setsecret]$token" - git status - git add . - git commit -m "Updating reference docs" - git push --set-upstream "https://x-access-token:$token@github.com/MicrosoftDocs/microsoftgraph-docs-powershell.git" $(ComputeBranch.WeeklyReferenceDocsBranch) - git status - - template: azure-pipelines/common-templates/create-pr.yml@self + - template: azure-pipelines/common-templates/generate-docs-steps.yml@self parameters: - BaseBranch: "main" - TargetBranch: $(ComputeBranch.WeeklyReferenceDocsBranch) - Title: "Weekly PowerShell Microsoft Graph Reference Docs Refresh" - Body: "This pull request was automatically created by Azure Pipelines. **Important** Check for unexpected deletions or changes in this PR." \ No newline at end of file + GraphProfileFilter: 'v1.0' + BranchPrefix: 'WeeklyReferenceDocsUpdate-v1' + PrTitle: 'Weekly PowerShell Microsoft Graph v1.0 Reference Docs Refresh' + - stage: GenerateBeta + displayName: 'Generate beta reference docs' + dependsOn: [] + jobs: + - job: PowerShellDocsUpdateBeta + timeoutInMinutes: ${{ parameters.PipelineTimeout }} + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish Examples to be reviewed as artifact' + targetPath: missingexternaldocsurl + artifactName: 'MissingExternalDocs-beta' + publishLocation: 'Container' + steps: + - template: azure-pipelines/common-templates/generate-docs-steps.yml@self + parameters: + GraphProfileFilter: 'beta' + BranchPrefix: 'WeeklyReferenceDocsUpdate-beta' + PrTitle: 'Weekly PowerShell Microsoft Graph beta Reference Docs Refresh' diff --git a/scripts/CorrectRelatedLinks-AllFiles.ps1 b/scripts/CorrectRelatedLinks-AllFiles.ps1 index 3f6a71383b9e6..4fb92908cac64 100644 --- a/scripts/CorrectRelatedLinks-AllFiles.ps1 +++ b/scripts/CorrectRelatedLinks-AllFiles.ps1 @@ -19,6 +19,7 @@ param( [Parameter(Mandatory = $false)] [ValidateSet("v1.0", "beta", "both")] + [Alias("GraphProfileFilter")] [string]$GraphProfile = "both" ) diff --git a/scripts/EscapeDisallowedHtmlTags.ps1 b/scripts/EscapeDisallowedHtmlTags.ps1 index 7f2d4079ff9da..a390324b1a3bc 100644 --- a/scripts/EscapeDisallowedHtmlTags.ps1 +++ b/scripts/EscapeDisallowedHtmlTags.ps1 @@ -2,7 +2,9 @@ # Licensed under the MIT License. Param( $ModulesToGenerate = @(), - [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config/ModulesMapping.jsonc") + [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config/ModulesMapping.jsonc"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Get-GraphMapping { $graphMapping = @{} @@ -18,7 +20,8 @@ function EscapeDisallowedHtmlTags { $ModulePrefix = "Microsoft.Graph" $GraphMapping = Get-GraphMapping - $GraphMapping.Keys | ForEach-Object { + $profilesToProcess = if ($GraphProfileFilter -eq 'both') { $GraphMapping.Keys } else { @($GraphProfileFilter) } + $profilesToProcess | ForEach-Object { $graphProfile = $_ Get-FilesByProfile -GraphProfile $graphProfile -GraphProfilePath $GraphMapping[$graphProfile] -ModulePrefix $ModulePrefix -ModulesToGenerate $ModulesToGenerate } diff --git a/scripts/GenerateAliasedDocs.ps1 b/scripts/GenerateAliasedDocs.ps1 index 97eba9685354d..23052eb40eff2 100644 --- a/scripts/GenerateAliasedDocs.ps1 +++ b/scripts/GenerateAliasedDocs.ps1 @@ -6,12 +6,17 @@ See related PR for more information. #> +param( + [ValidateSet("v1.0", "beta", "both")] + [string]$GraphProfileFilter = "both" +) + function Start-GenerateAliasedDocs { $BreakingChangeReportV1Report = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/docs/PowerShellBreakingChanges-V1.0.csv") $BreakingChangeReportBetaReport = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/docs/PowerShellBreakingChanges-beta.csv") $Reports = @() - $Reports += $BreakingChangeReportV1Report - $Reports += $BreakingChangeReportBetaReport + if ($GraphProfileFilter -ne 'beta') { $Reports += $BreakingChangeReportV1Report } + if ($GraphProfileFilter -ne 'v1.0') { $Reports += $BreakingChangeReportBetaReport } foreach ($BreakingChangeReport in $Reports) { Import-Csv $BreakingChangeReport | ForEach-Object { $Command = $_."NewCmdlet" diff --git a/scripts/GenerateMarkDown.ps1 b/scripts/GenerateMarkDown.ps1 index 52498f065e01d..e653f1bc308b8 100644 --- a/scripts/GenerateMarkDown.ps1 +++ b/scripts/GenerateMarkDown.ps1 @@ -5,7 +5,9 @@ Param( $ModulesToGenerate = @(), [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config\ModulesMapping.jsonc"), [string] $WorkLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph"), - [string] $CmdletMetadataPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src/Authentication/Authentication/custom/common/MgCommandMetadata.json") + [string] $CmdletMetadataPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src/Authentication/Authentication/custom/common/MgCommandMetadata.json"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Get-GraphMapping { $graphMapping = @{} @@ -91,13 +93,16 @@ function Start-GraphHelp { $GraphMapping = Get-GraphMapping $TempAuthDir = Join-Path ([System.IO.Path]::GetTempPath()) "GraphDocsTempAuth_$([guid]::NewGuid().ToString('N'))" New-Item -Path $TempAuthDir -ItemType Directory -Force | Out-Null - $GraphMapping.Keys | ForEach-Object { + $profilesToProcess = if ($GraphProfileFilter -eq 'both') { $GraphMapping.Keys } else { @($GraphProfileFilter) } + $profilesToProcess | ForEach-Object { $graphProfile = $_ $profilePath = "graph-powershell-1.0" if ($graphProfile -eq "beta") { $profilePath = "graph-powershell-beta" } + # Authentication docs live only under graph-powershell-1.0, so generate them for the v1.0 profile only. + if ($graphProfile -eq "v1.0") { # Generate all auth module docs to temp directory using module-level generation Set-Help -ModuleDocsPath $TempAuthDir -Command "Connect-MgGraph" -Module "Microsoft.Graph.Authentication" @@ -122,6 +127,7 @@ function Start-GraphHelp { Write-Host "Added auth doc: $($_.BaseName)" } } + } } Get-FolderByProfile -GraphProfile $graphProfile -GraphProfilePath $profilePath -ModulePrefix $ModulePrefix -ModulesToGenerate $ModulesToGenerate } diff --git a/scripts/GeneratePermissionsTable.ps1 b/scripts/GeneratePermissionsTable.ps1 index aeca973f7f228..8c0a5eda4485b 100644 --- a/scripts/GeneratePermissionsTable.ps1 +++ b/scripts/GeneratePermissionsTable.ps1 @@ -1,6 +1,8 @@ param( [string]$MgCommandMetadatJsonFile = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src/Authentication/Authentication/custom/common/MgCommandMetadata.json"), - [string[]]$CmdList = @() + [string[]]$CmdList = @(), + [ValidateSet("v1.0", "beta", "both")] + [string]$GraphProfileFilter = "both" ) function Start-Generator { @@ -11,6 +13,7 @@ function Start-Generator { $CommandName = $_.Command; $ApiVersion = $_.ApiVersion $Module = $_.Module; + if ($GraphProfileFilter -ne 'both' -and $ApiVersion -ne $GraphProfileFilter) { return } #Array for DelegatedWork Permissions $DelegatedWorkPermissions = @(); #Array for Application Permissions diff --git a/scripts/MsSubserviceUpdate.ps1 b/scripts/MsSubserviceUpdate.ps1 index d9bbd826afe67..85cdacda82fbe 100644 --- a/scripts/MsSubserviceUpdate.ps1 +++ b/scripts/MsSubserviceUpdate.ps1 @@ -5,7 +5,9 @@ Param( [string] $SDKDocsPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src"), [string] $SDKOpenApiPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell"), [string] $WorkLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph"), - [string] $MissingMsSubserviceHeaderPath = (Join-Path $PSScriptRoot "../missingexternaldocsurl") + [string] $MissingMsSubserviceHeaderPath = (Join-Path $PSScriptRoot "../missingexternaldocsurl"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Start-Generator { if (Test-Path $CommandMetadataPath) { @@ -14,6 +16,7 @@ function Start-Generator { $ModuleName = $_.Module $GraphProfile = $_.ApiVersion $Command = $_.Command + if ($GraphProfileFilter -ne 'both' -and $GraphProfile -ne $GraphProfileFilter) { return } $ExternalDocUrl = $_.ApiReferenceLink $GraphProfilePath = "graph-powershell-1.0" $ModulePrefix = "Microsoft.Graph" diff --git a/scripts/RemoveBoilerPlateCode.ps1 b/scripts/RemoveBoilerPlateCode.ps1 index 246e79ba3febe..14e5aadca8c4c 100644 --- a/scripts/RemoveBoilerPlateCode.ps1 +++ b/scripts/RemoveBoilerPlateCode.ps1 @@ -4,7 +4,9 @@ Param( $ModulesToGenerate = @(), [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config/ModulesMapping.jsonc"), [string] $WorkLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph"), - [string] $AuthLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph/graph-powershell-1.0/Microsoft.Graph.Authentication") + [string] $AuthLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph/graph-powershell-1.0/Microsoft.Graph.Authentication"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Get-GraphMapping { $graphMapping = @{} @@ -19,18 +21,21 @@ function Start-Repair { $ModulesToGenerate = @() ) - #Cleanup Authentication Module first - $files = Get-ChildItem -Path $AuthLoadDocsPath -Filter *.md -Recurse - foreach ($file in $files) { - $content = Get-Content -Path $file.FullName - # Remove lines that contain '{{ Fill in the Description }}' or '### This' or '### *' or '### have' or '### certain' or '### the' - $cleanedContent = $content | Where-Object { $_ -notmatch '^\s*{{ Fill in the Description }}|^\s*### This|^\s*### \*|^\s*### have|^\s*### certain|^\s*### the' } - # Write the cleaned content back to the file - $cleanedContent | Set-Content -Path $file.FullName + #Cleanup Authentication Module first (Authentication docs live under the v1.0 folder) + if ($GraphProfileFilter -ne 'beta') { + $files = Get-ChildItem -Path $AuthLoadDocsPath -Filter *.md -Recurse + foreach ($file in $files) { + $content = Get-Content -Path $file.FullName + # Remove lines that contain '{{ Fill in the Description }}' or '### This' or '### *' or '### have' or '### certain' or '### the' + $cleanedContent = $content | Where-Object { $_ -notmatch '^\s*{{ Fill in the Description }}|^\s*### This|^\s*### \*|^\s*### have|^\s*### certain|^\s*### the' } + # Write the cleaned content back to the file + $cleanedContent | Set-Content -Path $file.FullName + } } $ModulePrefix = "Microsoft.Graph" $GraphMapping = Get-GraphMapping - $GraphMapping.Keys | ForEach-Object { + $profilesToProcess = if ($GraphProfileFilter -eq 'both') { $GraphMapping.Keys } else { @($GraphProfileFilter) } + $profilesToProcess | ForEach-Object { $graphProfile = $_ $profilePath = "graph-powershell-1.0" if ($graphProfile -eq "beta") { diff --git a/scripts/RemoveInvalidFullStops.ps1 b/scripts/RemoveInvalidFullStops.ps1 index 37be47e7c73df..a4a5a41b2d9c7 100644 --- a/scripts/RemoveInvalidFullStops.ps1 +++ b/scripts/RemoveInvalidFullStops.ps1 @@ -2,7 +2,9 @@ # Licensed under the MIT License. Param( $ModulesToGenerate = @(), - [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config/ModulesMapping.jsonc") + [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config/ModulesMapping.jsonc"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Get-GraphMapping { $graphMapping = @{} @@ -18,7 +20,8 @@ function Remove-InvalidFullStops { $ModulePrefix = "Microsoft.Graph" $GraphMapping = Get-GraphMapping - $GraphMapping.Keys | ForEach-Object { + $profilesToProcess = if ($GraphProfileFilter -eq 'both') { $GraphMapping.Keys } else { @($GraphProfileFilter) } + $profilesToProcess | ForEach-Object { $graphProfile = $_ Get-FilesByProfile -GraphProfile $graphProfile -GraphProfilePath $GraphMapping[$graphProfile] -ModulePrefix $ModulePrefix -ModulesToGenerate $ModulesToGenerate } diff --git a/scripts/RepairExamplesDescriptionsAndTitle.ps1 b/scripts/RepairExamplesDescriptionsAndTitle.ps1 index c8e3c74074799..f104cb92d2595 100644 --- a/scripts/RepairExamplesDescriptionsAndTitle.ps1 +++ b/scripts/RepairExamplesDescriptionsAndTitle.ps1 @@ -4,7 +4,9 @@ Param( $ModulesToGenerate = @(), [string] $SDKDocsPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src"), [string] $WorkLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph"), - [string] $CommandMetadataPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src/Authentication/Authentication/custom/common/MgCommandMetadata.json") + [string] $CommandMetadataPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src/Authentication/Authentication/custom/common/MgCommandMetadata.json"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Start-Copy { @@ -15,6 +17,7 @@ function Start-Copy { $ModuleName = $_.Module $GraphProfile = $_.ApiVersion $Command = $_.Command + if ($GraphProfileFilter -ne 'both' -and $GraphProfile -ne $GraphProfileFilter) { return } $GraphProfilePath = "graph-powershell-1.0" $ModulePrefix = "Microsoft.Graph" if ($GraphProfile -eq "beta") { diff --git a/scripts/UpdateLinks.ps1 b/scripts/UpdateLinks.ps1 index f7edf3e93bcd6..918ac4537ba00 100644 --- a/scripts/UpdateLinks.ps1 +++ b/scripts/UpdateLinks.ps1 @@ -4,7 +4,9 @@ Param( $ModulesToGenerate = @(), [string] $ModuleMappingConfigPath = (Join-Path $PSScriptRoot "../microsoftgraph/config/ModulesMapping.jsonc"), [string] $SDKDocsPath = (Join-Path $PSScriptRoot "../msgraph-sdk-powershell/src"), - [string] $WorkLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph") + [string] $WorkLoadDocsPath = (Join-Path $PSScriptRoot "../microsoftgraph"), + [ValidateSet("v1.0", "beta", "both")] + [string] $GraphProfileFilter = "both" ) function Get-GraphMapping { $graphMapping = @{} @@ -20,7 +22,8 @@ function Start-Update { $ModulePrefix = "Microsoft.Graph" $GraphMapping = Get-GraphMapping - $GraphMapping.Keys | ForEach-Object { + $profilesToProcess = if ($GraphProfileFilter -eq 'both') { $GraphMapping.Keys } else { @($GraphProfileFilter) } + $profilesToProcess | ForEach-Object { $GraphProfile = $_ $profilePath = "graph-powershell-1.0" if ($GraphProfile -eq "beta") { @@ -116,7 +119,8 @@ function Construct-Path { $BetaFilePath = Join-Path $WorkLoadDocsPath "graph-powershell-beta" "Microsoft.Graph.Beta.$Module" "$Command.md" $V1FilePath = Join-Path $WorkLoadDocsPath "graph-powershell-1.0" "Microsoft.Graph.$Module" "$Command.md" - if (Test-Path $BetaFilePath) { + # Adds the cross-profile note into the beta doc (skip when generating v1.0 only). + if ((Test-Path $BetaFilePath) -and ($GraphProfileFilter -ne 'v1.0')) { $V1Command = $Command.Replace("-MgBeta", "-Mg") $ConfirmV1Path = Join-Path $WorkLoadDocsPath "graph-powershell-1.0" "Microsoft.Graph.$Module" "$V1Command.md" if (Test-Path $ConfirmV1Path) { @@ -124,7 +128,8 @@ function Construct-Path { } } - if (Test-Path $V1FilePath) { + # Adds the cross-profile note into the v1.0 doc (skip when generating beta only). + if ((Test-Path $V1FilePath) -and ($GraphProfileFilter -ne 'beta')) { $BetaCommand = $Command.Replace("-Mg", "-MgBeta") $ConfirmBetaPath = Join-Path $WorkLoadDocsPath "graph-powershell-beta" "Microsoft.Graph.Beta.$Module" "$BetaCommand.md" if (Test-Path $ConfirmBetaPath) { From c3b9b42b54f3fcbc1464599a41a0a20b72b339de Mon Sep 17 00:00:00 2001 From: Microsoft Graph DevX Tooling Date: Thu, 16 Jul 2026 14:39:18 -0700 Subject: [PATCH 2/3] fix: repair GitHub push URL and make weekly docs pipeline fail loudly The push URL in the weekly docs pipeline had been corrupted to a literal '******github.com/...' (a masked log value pasted into source) since #802, so 'git push' failed silently while the step still reported success because 'git status' ran last. The branch never reached GitHub, so 'gh pr create' failed with 'No commits between main and '. - generate-docs-steps.yml: fix push URL to https://x-access-token:$token@github.com/..., throw on non-zero 'git push' exit code, and detect real changes by comparing the branch tip to the recorded base commit (the generation scripts pre-commit their output, so the working tree is clean at push time). - create-pr.yml: add a Condition parameter so PR creation is skipped cleanly when there are no changes instead of erroring. - GenerateMarkDown.ps1: track generated file count and fail if generation produces zero files, so a silent generation failure surfaces immediately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f3873c6c-209b-4bd2-b1a7-e96a27d4834a --- .../common-templates/create-pr.yml | 4 ++ .../common-templates/generate-docs-steps.yml | 35 ++++++++++++++--- scripts/GenerateMarkDown.ps1 | 38 +++++++++++++++++-- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/azure-pipelines/common-templates/create-pr.yml b/azure-pipelines/common-templates/create-pr.yml index ed1a64e51f499..5c585ab594e7e 100644 --- a/azure-pipelines/common-templates/create-pr.yml +++ b/azure-pipelines/common-templates/create-pr.yml @@ -14,10 +14,14 @@ parameters: - name: Body type: string default: "" + - name: Condition + type: string + default: "succeeded()" steps: - task: PowerShell@2 displayName: Create Pull Request for generated build + condition: ${{ parameters.Condition }} env: GhAppId: $(microsoft-graph-devx-bot-appid) GhAppKey: $(microsoft-graph-devx-bot-privatekey) diff --git a/azure-pipelines/common-templates/generate-docs-steps.yml b/azure-pipelines/common-templates/generate-docs-steps.yml index 13a891ff08784..1b3a44f80c476 100644 --- a/azure-pipelines/common-templates/generate-docs-steps.yml +++ b/azure-pipelines/common-templates/generate-docs-steps.yml @@ -33,6 +33,7 @@ steps: Write-Host "Compute branch: $branch" Write-Host "##vso[task.setvariable variable=WeeklyReferenceDocsBranch;isOutput=true]$branch" - task: Bash@3 + name: "CreateBranch" displayName: "Create weekly refresh branch" inputs: targetType: inline @@ -40,6 +41,12 @@ steps: git status git branch $(ComputeBranch.WeeklyReferenceDocsBranch) git checkout $(ComputeBranch.WeeklyReferenceDocsBranch) + # Record the commit the branch was created from so the push step can tell + # whether generation actually advanced the branch (the generation scripts + # commit their own output, so the working tree is clean by push time). + BASE_COMMIT=$(git rev-parse HEAD) + echo "Base commit: $BASE_COMMIT" + echo "##vso[task.setvariable variable=BaseCommit;isOutput=true]$BASE_COMMIT" git status - task: PowerShell@2 displayName: 'Create missing external docs folder' @@ -144,6 +151,7 @@ steps: KeyVaultName: akv-prod-eastus SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey" - task: PowerShell@2 + name: "PushChanges" displayName: Pushing to github env: GhAppId: $(microsoft-graph-devx-bot-appid) @@ -155,19 +163,36 @@ steps: git config --global user.email "GraphTooling@service.microsoft.com" git config --global user.name "Microsoft Graph DevX Tooling" git config --system core.longpaths true + # Commit anything the formatting steps left behind. The generation scripts + # already commit their own output, so this may legitimately be a no-op. + git add . + if (-not [string]::IsNullOrWhiteSpace((git status --porcelain))) { + git commit -m "Updating reference docs" + } + # Detect real changes by comparing the branch tip to the commit it was created + # from. Checking the working tree is not enough because earlier steps already + # committed their output, leaving the tree clean but the branch ahead of base. + $baseCommit = "$(CreateBranch.BaseCommit)" + $headCommit = (git rev-parse HEAD).Trim() + if ($headCommit -eq $baseCommit) { + Write-Host "No documentation changes detected (branch is at its base commit); skipping push and pull request." + Write-Host "##vso[task.setvariable variable=HasChanges;isOutput=true]false" + return + } # The microsoft-graph-devx-bot GitHub App must have contents:write on this repo. $token = & "$(Build.SourcesDirectory)/scripts/Generate-Github-Token.ps1" -AppClientId $env:GhAppId -AppPrivateKeyContents $env:GhAppKey -Repository "MicrosoftDocs/microsoftgraph-docs-powershell" if ([string]::IsNullOrWhiteSpace($token)) { throw "Failed to generate GitHub App installation token." } # Mask the token so it is never surfaced in pipeline logs. Write-Host "##vso[task.setsecret]$token" - git status - git add . - git commit -m "Updating reference docs" - git push --set-upstream "******github.com/MicrosoftDocs/microsoftgraph-docs-powershell.git" $(ComputeBranch.WeeklyReferenceDocsBranch) - git status + # A GitHub App installation token authenticates over HTTPS as user "x-access-token". + $pushUrl = "https://x-access-token:$token@github.com/MicrosoftDocs/microsoftgraph-docs-powershell.git" + git push --set-upstream $pushUrl $(ComputeBranch.WeeklyReferenceDocsBranch) + if ($LASTEXITCODE -ne 0) { throw "git push failed with exit code $LASTEXITCODE." } + Write-Host "##vso[task.setvariable variable=HasChanges;isOutput=true]true" - template: create-pr.yml parameters: BaseBranch: "main" TargetBranch: $(ComputeBranch.WeeklyReferenceDocsBranch) Title: "${{ parameters.PrTitle }}" Body: "${{ parameters.PrBody }}" + Condition: "and(succeeded(), eq(variables['PushChanges.HasChanges'], 'true'))" diff --git a/scripts/GenerateMarkDown.ps1 b/scripts/GenerateMarkDown.ps1 index e653f1bc308b8..df0764b3362d2 100644 --- a/scripts/GenerateMarkDown.ps1 +++ b/scripts/GenerateMarkDown.ps1 @@ -83,7 +83,15 @@ function Start-GraphHelp { Param( $ModulesToGenerate = @() ) - + + # Track how much PlatyPS actually produced. New-MarkdownCommandHelp writes a temp + # file on every run (even when the content matches the committed docs), so a total + # of zero generated files means generation itself failed rather than the docs being + # up to date. This lets the pipeline tell a silent generation failure apart from a + # legitimate no-op (see the hard check at the end of this script). + $script:GeneratedFileCount = 0 + $script:GenerationFailures = [System.Collections.Generic.List[string]]::new() + #Generate for auth module first $ModulePrefix = "Microsoft.Graph" $AuthPath = "$ModulePrefix.Authentication" @@ -108,11 +116,17 @@ function Start-GraphHelp { # Compare and copy all generated auth files $TempAuthModuleDir = Join-Path $TempAuthDir $AuthPath - if (Test-Path $TempAuthModuleDir) { + $authFiles = if (Test-Path $TempAuthModuleDir) { @(Get-ChildItem -Path $TempAuthModuleDir -Filter "*.md" -File) } else { @() } + if ($authFiles.Count -eq 0) { + $script:GenerationFailures.Add("Microsoft.Graph.Authentication (module page)") + Write-Warning "Auth module generation produced no markdown files." + } + if ($TempAuthModuleDir -and (Test-Path $TempAuthModuleDir)) { if (-not (Test-Path $AuthDestination)) { New-Item -Path $AuthDestination -ItemType Directory -Force | Out-Null } - Get-ChildItem -Path $TempAuthModuleDir -Filter "*.md" -File | ForEach-Object { + $authFiles | ForEach-Object { + $script:GeneratedFileCount++ $tempFile = $_.FullName $existingFile = Join-Path $AuthDestination $_.Name if (Test-Path $existingFile) { @@ -208,6 +222,7 @@ function Get-FolderByProfile { Set-Help -ModuleDocsPath $TempOutputDir -Command $Command -Module $Path $TempFilePath = Join-Path $TempOutputDir $Path "$Command.md" if (Test-Path $TempFilePath) { + $script:GeneratedFileCount++ if (Test-Path $CmdletDocsPath) { $existingContent = Get-NormalizedContent -FilePath $CmdletDocsPath $newContent = Get-NormalizedContent -FilePath $TempFilePath @@ -219,6 +234,11 @@ function Get-FolderByProfile { Copy-Item -Path $TempFilePath -Destination $CmdletDocsPath -Force Write-Host "Added: $Command" } + } else { + # The command is available but PlatyPS produced no file: a real + # generation failure (its error was swallowed inside Set-Help). + $script:GenerationFailures.Add($Command) + Write-Warning "Generation produced no output for available command: $Command" } } elseif (-not (Test-Path $CmdletDocsPath)) { Write-Warning "Cmdlet $Command is not available." @@ -286,4 +306,16 @@ if ($ModulesToGenerate.Count -eq 0) { } Write-Host -ForegroundColor Green "-------------finished checking out to today's branch-------------" Start-GraphHelp -ModulesToGenerate $ModulesToGenerate + +# Fail loudly when generation produced nothing. Without this guard a broken generation +# (e.g. a PlatyPS/module error swallowed by Set-Help) looks exactly like an up-to-date +# no-op: the working tree stays clean, an empty branch is pushed and the PR step fails +# with a confusing "No commits between main and " error. +if ($script:GeneratedFileCount -eq 0) { + throw "Doc generation produced no markdown files for profile '$GraphProfileFilter'. This indicates a generation failure (PlatyPS/module error), not up-to-date docs. Failing the build so the empty result is not silently published." +} +if ($script:GenerationFailures.Count -gt 0) { + Write-Warning "Generation produced no output for $($script:GenerationFailures.Count) available command(s): $($script:GenerationFailures -join ', ')" +} +Write-Host "Generation summary for profile '$GraphProfileFilter': $($script:GeneratedFileCount) file(s) generated, $($script:GenerationFailures.Count) failure(s)." Write-Host -ForegroundColor Green "-------------Done-------------" \ No newline at end of file From 4db65f26866c8e455c74097b85c21ccb31483375 Mon Sep 17 00:00:00 2001 From: Microsoft Graph DevX Tooling Date: Mon, 20 Jul 2026 18:17:28 -0700 Subject: [PATCH 3/3] Guard against empty commits in doc post-processing scripts The weekly docs pipeline failed at the 'Remove invalid fullstops' step because RemoveInvalidFullStops.ps1 ends in 'git commit', which exits 1 when there is nothing to commit ('nothing to commit, working tree clean'). As the last command in the script, that exit code failed the step even though nothing was wrong. Apply the same 'commit only if staged changes exist' guard already used in CorrectRelatedLinks-AllFiles.ps1, UpdateLinks.ps1 and MsSubserviceUpdate.ps1 to the remaining unguarded scripts so a no-op pass no longer fails the build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f3873c6c-209b-4bd2-b1a7-e96a27d4834a --- scripts/EscapeDisallowedHtmlTags.ps1 | 13 ++++++++++++- scripts/GenerateMarkDown.ps1 | 13 ++++++++++++- scripts/GeneratePermissionsTable.ps1 | 13 ++++++++++++- scripts/RemoveBoilerPlateCode.ps1 | 13 ++++++++++++- scripts/RemoveInvalidFullStops.ps1 | 13 ++++++++++++- scripts/RepairExamplesDescriptionsAndTitle.ps1 | 13 ++++++++++++- 6 files changed, 72 insertions(+), 6 deletions(-) diff --git a/scripts/EscapeDisallowedHtmlTags.ps1 b/scripts/EscapeDisallowedHtmlTags.ps1 index a390324b1a3bc..4c98cb950a337 100644 --- a/scripts/EscapeDisallowedHtmlTags.ps1 +++ b/scripts/EscapeDisallowedHtmlTags.ps1 @@ -29,7 +29,18 @@ function EscapeDisallowedHtmlTags { git config --global user.email "timwamalwa@gmail.com" git config --global user.name "Timothy Wamalwa" git add . - git commit -m "Escaped disallowed html tags" + + # Check for staged changes; commit only if any exist + $pending = git status --porcelain + if (-not [string]::IsNullOrWhiteSpace($pending)) { + git commit -m "Escaped disallowed html tags" + Write-Host "Committed escaping of disallowed html tags." + } + else { + Write-Host "Nothing to commit; skipping commit step." + # Ensure a clean exit code even if earlier native commands returned 1 + $global:LASTEXITCODE = 0 + } } function Get-FilesByProfile { Param( diff --git a/scripts/GenerateMarkDown.ps1 b/scripts/GenerateMarkDown.ps1 index df0764b3362d2..77fa2a8080f75 100644 --- a/scripts/GenerateMarkDown.ps1 +++ b/scripts/GenerateMarkDown.ps1 @@ -149,7 +149,18 @@ function Start-GraphHelp { git config --global user.email "GraphTooling@service.microsoft.com" git config --global user.name "Microsoft Graph DevX Tooling" git add . - git commit -m "Updated markdown help" + + # Check for staged changes; commit only if any exist + $pending = git status --porcelain + if (-not [string]::IsNullOrWhiteSpace($pending)) { + git commit -m "Updated markdown help" + Write-Host "Committed updated markdown help." + } + else { + Write-Host "Nothing to commit; skipping commit step." + # Ensure a clean exit code even if earlier native commands returned 1 + $global:LASTEXITCODE = 0 + } } function Get-FolderByProfile { diff --git a/scripts/GeneratePermissionsTable.ps1 b/scripts/GeneratePermissionsTable.ps1 index 8c0a5eda4485b..27815e137e4d2 100644 --- a/scripts/GeneratePermissionsTable.ps1 +++ b/scripts/GeneratePermissionsTable.ps1 @@ -73,7 +73,18 @@ function Start-Generator { git config --global user.email "GraphTooling@service.microsoft.com" git config --global user.name "Microsoft Graph DevX Tooling" git add . - git commit -m "Inserted permissions Table" + + # Check for staged changes; commit only if any exist + $pending = git status --porcelain + if (-not [string]::IsNullOrWhiteSpace($pending)) { + git commit -m "Inserted permissions Table" + Write-Host "Committed permissions table." + } + else { + Write-Host "Nothing to commit; skipping commit step." + # Ensure a clean exit code even if earlier native commands returned 1 + $global:LASTEXITCODE = 0 + } } catch { Write-Host "Error in $_"; diff --git a/scripts/RemoveBoilerPlateCode.ps1 b/scripts/RemoveBoilerPlateCode.ps1 index 14e5aadca8c4c..a677f75f07dd2 100644 --- a/scripts/RemoveBoilerPlateCode.ps1 +++ b/scripts/RemoveBoilerPlateCode.ps1 @@ -46,7 +46,18 @@ function Start-Repair { git config --global user.email "GraphTooling@service.microsoft.com" git config --global user.name "Microsoft Graph DevX Tooling" git add . - git commit -m "Remove boiler plate code injected by Autorest" + + # Check for staged changes; commit only if any exist + $pending = git status --porcelain + if (-not [string]::IsNullOrWhiteSpace($pending)) { + git commit -m "Remove boiler plate code injected by Autorest" + Write-Host "Committed removal of boiler plate code." + } + else { + Write-Host "Nothing to commit; skipping commit step." + # Ensure a clean exit code even if earlier native commands returned 1 + $global:LASTEXITCODE = 0 + } } function Get-FilesByProfile { Param( diff --git a/scripts/RemoveInvalidFullStops.ps1 b/scripts/RemoveInvalidFullStops.ps1 index a4a5a41b2d9c7..c3aa6191e7f83 100644 --- a/scripts/RemoveInvalidFullStops.ps1 +++ b/scripts/RemoveInvalidFullStops.ps1 @@ -29,7 +29,18 @@ function Remove-InvalidFullStops { git config --global user.email "timwamalwa@gmail.com" git config --global user.name "Timothy Wamalwa" git add . - git commit -m "Removed invalid full stops from the beginning of lines" + + # Check for staged changes; commit only if any exist + $pending = git status --porcelain + if (-not [string]::IsNullOrWhiteSpace($pending)) { + git commit -m "Removed invalid full stops from the beginning of lines" + Write-Host "Committed removal of invalid full stops." + } + else { + Write-Host "Nothing to commit; skipping commit step." + # Ensure a clean exit code even if earlier native commands returned 1 + $global:LASTEXITCODE = 0 + } } function Get-FilesByProfile { Param( diff --git a/scripts/RepairExamplesDescriptionsAndTitle.ps1 b/scripts/RepairExamplesDescriptionsAndTitle.ps1 index f104cb92d2595..06eba0fcbbe2e 100644 --- a/scripts/RepairExamplesDescriptionsAndTitle.ps1 +++ b/scripts/RepairExamplesDescriptionsAndTitle.ps1 @@ -41,7 +41,18 @@ function Start-Copy { git config --global user.email "GraphTooling@service.microsoft.com" git config --global user.name "Microsoft Graph DevX Tooling" git add . - git commit -m "Repaired examples and descriptions" + + # Check for staged changes; commit only if any exist + $pending = git status --porcelain + if (-not [string]::IsNullOrWhiteSpace($pending)) { + git commit -m "Repaired examples and descriptions" + Write-Host "Committed repaired examples and descriptions." + } + else { + Write-Host "Nothing to commit; skipping commit step." + # Ensure a clean exit code even if earlier native commands returned 1 + $global:LASTEXITCODE = 0 + } }