Skip to content

(Scheduled) M365 Endpoints includes automation #370

(Scheduled) M365 Endpoints includes automation

(Scheduled) M365 Endpoints includes automation #370

Workflow file for this run

name: (Scheduled) M365 Endpoints includes automation
permissions:
contents: write
pull-requests: write
actions: read
on:
schedule:
- cron: "0 */6 * * *"
workflow_dispatch:
jobs:
get-previous-run:
if: github.repository_visibility == 'private'
name: Get previous run ID
runs-on: ubuntu-latest
continue-on-error: true
outputs:
PreviousRun: ${{ steps.previous_run.outputs.previous_run_id }}
steps:
- name: Get previous run ID
id: previous_run
uses: actions/github-script@v7
with:
script: |
const response = await github.rest.actions.listWorkflowRuns({
owner: "MicrosoftDocs",
repo: "microsoft-365-docs-pr",
workflow_id: 117238499,
branch: "main",
status: "success",
per_page: 2,
});
// Find the previous run by looking at the second run in the list
const previousRun = response.data.workflow_runs.find(run => run.id !== context.runId);
core.setOutput("previous_run_id", previousRun.id);
- name: Output previous run ID
run: |
echo "Previous run ID: ${{ steps.previous_run.outputs.previous_run_id }}"
update-includes:
if: github.repository_visibility == 'private'
needs: get-previous-run
name: Update includes
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
name: Download previous run data artifact
continue-on-error: true
with:
name: RunData
path: "${{ github.workspace }}/run-data/"
run-id: ${{ needs.get-previous-run.outputs.PreviousRun}}
github-token: ${{ github.token }}
- name: Process endpoint data
shell: pwsh
env:
AccessToken: ${{ secrets.MARVEL_REPO_ACCESS_TOKEN }}
TargetOrganization: "MicrosoftDocs"
TargetRepository: "microsoft-365-docs-pr"
TargetPath: "microsoft-365/includes"
EndpointsContentOwner: "kelleyvice-msft"
run: |
# GetServiceInstanceEndpoints
# Original script created 4-December-2018 by Peter Worley v-peworl@microsoft.com
# Script updated for Azure Torus 2-September-2020 by David Strome dstrome@microsoft.com
# Script updated for GitHub workflows 10-September-2024 by David Strome dstrome@microsoft.com
<#
This script retreives Office 365 endpoint sets for each service instance
from the endpoints web service, converts the endpoint sets into tables,
saves the tables in a markdown file for each service instance,
then uploads each markdown file to a GitHub repository for automated
publishing.
#>
# Set default encoding for file output to ASCII
$PSDefaultParameterValues['*:Encoding'] = 'ASCII'
function Set-ScriptOptions {
<#
.SYNOPSIS
Set up script variables
.DESCRIPTION
Define variables, directories, service instances, and service areas,
as well as GitHub user, authentication, & repository information.
Environment specific changes to the script can be done here.
#>
# Web Service Address Setup
# Web Service root URL
$script:ws = "https://endpoints.office.com"
Write-Host "Setting script options"
# Script Environment Setup
# Paths & files for storing client ID, service instance versions, and script output files
$script:dataPath = "$env:GITHUB_WORKSPACE/run-data/" # path to store data files
$clientIDFile = $dataPath + "endpoints-clientid.txt" # file to store client request id
$script:siVersionFile = $dataPath + "endpoints-service-instance-versions.json" # file to store service instance versions
write-host "Storage path: $dataPath"
# Output File Setup
# HTML commented-out automation notice to display at top of output files
$script:scriptContact = "the Office 365 Endpoints team" # who should be contacted for script questions/changes/etc.
$script:fileNotice = "<!--THIS FILE IS AUTOMATICALLY GENERATED. MANUAL CHANGES WILL BE OVERWRITTEN.-->`n<!--Please contact " + $scriptContact + " with any questions.-->"
# Naming convention for output file (appended after the service instance name)
$script:outFileSuffix = " Endpoints.md"
# Create output directory
If (!$(Test-Path $dataPath)) { mkdir $dataPath }
# Client ID Setup
# Fetch the local client request ID if data file exists; otherwise generate a new one
if (Test-Path $clientIDFile) {
Write-Host "Getting client request ID"
$script:clientRequestId = Get-Content -Path $clientIDFile
}
else {
Write-Host "Creating client request ID"
$script:clientRequestId = [GUID]::NewGuid().Guid
@($clientRequestId) | Out-File -FilePath $clientIDFile
}
# Service Instance Setup
# Create a lookup hash of service instances from the WS and their corresponding display names
# This name determines the output file header, as well as the file name
# (The file name is the official name + output file suffix, converted to lowercase and replacing spaces with dashes)
$script:siHash = @{}
$siHash.China = "Office 365 operated by 21Vianet"
$siHash.Germany = "Office 365 Germany"
$siHash.USGovDoD = "Office 365 U.S. Government DoD"
$siHash.USGovGCCHigh = "Office 365 U.S. Government GCC High"
$siHash.Worldwide = "Office 365 Worldwide"
# Service Area Setup
# Create a list of service areas from the WS
# This could be automated, but we want to sort manually
$script:allServiceAreas = @("Exchange", "SharePoint", "Skype", "Common")
# GitHub Setup
# Create github HTTP authentication header
$script:OfficedocsprToken = $env:AccessToken
$script:GitHubHeaders = @{}
$script:GitHubHeaders.Add("Authorization","token $($OfficedocsprToken)")
$script:GitHubHeaders.Add("User-Agent", "OfficeDocs")
# GitHub user and repo values to use
$script:Organization = $env:TargetOrganization # The GitHub user that owns the repository
$script:Repository = $env:TargetRepository # The remote repository to upload to
$script:TargetBranch = "M365-Endpoints"
$script:DefaultBranch = Get-RepoDefaultBranch -Headers $script:GitHubHeaders -Org $script:Organization -Repo $script:Repository # The remote branch
$script:RepoDir = $env:TargetPath # The target directory in the remote repository
$script:EndpointsContentOwner = $env:EndpointsContentOwner
$script:PrDescription = "@MicrosoftDocs/marveldocs-pubops`n`nThis is an automated pull request to update M365 Endpoints include files in **$RepoDir**. Before merging this PR, confirm the following:`n`n- There are no more than **$($siHash.count)** files in the PR`n- The only files in the pull request end with **$($OutFileSuffix.Trim())**`n- There are no obvious formatting issues with the content`n- The pull request is from **$TargetBranch** to **$DefaultBranch**`n`nIf issues are found with the PR, remove the **Sign off** label and add the **Back to submitter** label, assign the PR to **$EndpointsContentOwner**, and @-mention **$EndpointsContentOwner** with instructions on how to resolve the issue.`n`nAcrolinx issues can be ignored per exception: https://office.visualstudio.com/MAX/_workitems/edit/9352479`n`nIf no issues are found, merge the PR. If you have questions, email marveldocs-admins."
} # end Set-ScriptOptions function
function Get-RepoDefaultBranch {
param(
$Headers,
$Org,
$Repo
)
<#
.SYNOPSIS
Retrieve the default branch for the repo from GitHub
.DESCRIPTION
This function retrieves the repo's default branch dynamically in the event that
it's modified. A call retrieves the repo config data and the default_branch property
retrieved from that data.
#>
$DefaultBranch = $Null
$script:SetDefaultBranchSuccess = $False
# Get the default branch for Github
Try {
Write-Host "Getting default branch for $Repo. URL: https://api.github.com/repos/$Org/$Repo"
$DefaultBranch = (Invoke-RestMethod -Headers $Headers -Uri https://api.github.com/repos/$Org/$Repo -ErrorAction Stop -ErrorVariable GitHubDefaultBranchError).default_branch
# $DefaultBranch = "dstrome-test"
Write-Host "Default for $Repo is `"$DefaultBranch`""
$script:SetDefaultBranchSuccess = $True
} Catch {
Write-Host "***Failure retrieving default branch for $Repository. <p>Error: $($GitHubDefaultBranchError.ErrorRecord)"
}
Return $DefaultBranch
} # end Get-RepoDefaultBranch function
function Get-UpdateList {
<#
.SYNOPSIS
Create a list of service instances that need to be updated
.DESCRIPTION
This function calls the web service to get the current versions
for each service instance, checks the versions against a local file
containing the versions from the last time the script was run, then
builds a list of service instances that need updates.
.PARAMETER siList
A list of service instances
.PARAMETER versionFile
A path to a file which stores service instance versions
#>
param ($siList, $versionFile)
# Fetch the previous service instance versions from the local
# version file if it exists, otherwise create a new version file
if (Test-Path $versionFile) {
$previousVersions = Get-Content -Path $versionFile | ConvertFrom-Json
}
else {
$previousVersions = ""
}
Write-Host "Create list of service instances that need updates"
# Update the local version file with the current service instance versions
$siList | ConvertTo-Json | Out-File -FilePath $versionFile
# Build a hash with previous service instance versions for comparison
$siPreviousVersionHash = @{}
foreach ($item in $previousVersions) {
$instance = $item.instance;
$latest = $item.latest;
$siPreviousVersionHash.$instance = $latest;
}
# Compare the previous service instance versions with the current versions;
# Build a list of service instances that need updates
$newSiList = @()
foreach ($item in $siList) {
$instance = $item.instance;
$latest = $item.latest;
if ($siPreviousVersionHash.$instance -lt $latest) {
$newSiList += $instance
}
}
return $newSiList
} # end Get-UpdateList function
function Get-RemoteDirectoryListing {
<#
.SYNOPSIS
Create the directory listing of a remote repository
.DESCRIPTION
This function configures TLS, connects to GitHub, then gets the SHA
values of the files in the remote repository so they can be updated.
#>
# Fix TLS version so we can connect to GitHub
[net.servicepointmanager]::securityprotocol = [net.securityprotocoltype]::Tls12
Write-Host "Get file list from GitHub"
# Try to get $TargetBranch. If it exists, get the file list from $TargetBranch. If not, get it from $DefaultBranch.
Try {
Invoke-RestMethod -uri "https://api.github.com/repos/$Organization/$Repository/git/ref/heads/$TargetBranch" -headers $GitHubHeaders -Method Get | Out-Null
Write-Host "Branch $TargetBranch exists. Getting file list from $TargetBranch."
# We need the SHA of the existing files on GitHub in order to update (i.e. replace) them.
# To do that we get the repository directory listing.
$repoList = Invoke-RestMethod -Headers $GitHubHeaders -Uri https://api.github.com/repos/$Organization/$Repository/contents/$($RepoDir)?ref=$($TargetBranch)
} Catch {
Write-Host "Branch $TargetBranch does not exist. Getting file list from $DefaultBranch."
# We need the SHA of the existing files on GitHub in order to update (i.e. replace) them.
# To do that we get the repository directory listing.
$repoList = Invoke-RestMethod -Headers $GitHubHeaders -Uri https://api.github.com/repos/$Organization/$Repository/contents/$($RepoDir)?ref=$($DefaultBranch)
}
# Create a hash table with the name and SHA of each file in the remote repository
# This will be used when uploading the output files
$shaHash = @{}
foreach ($item in $repoList) {
$sname = $item.name
$ssha = $item.sha
$shaHash.$sname = $ssha
}
return $shaHash
} # end Get-RemoteDirectoryListing function
function ConvertTo-Markdown {
<#
.SYNOPSIS
Converts a PowerShell object to a Markdown table.
.DESCRIPTION
This function converts a PowerShell object (endpoint data) to a markdown table
Original function: https://gist.github.com/mac2000/86150ab43cfffc5d0eef
.EXAMPLE
$data | ConvertTo-Markdown
.EXAMPLE
ConvertTo-Markdown($data)
#>
[CmdletBinding()]
[OutputType([string])]
Param (
[Parameter(
Mandatory = $true,
Position = 0,
ValueFromPipeline = $true
)]
[PSObject[]]$collection
)
Begin {
$items = @()
$columns = [ordered]@{}
Write-Host "Convert data to markdown"
}
Process {
ForEach($item in $collection) {
$items += $item
$item.PSObject.Properties | ForEach-Object {
if(-not $columns.Contains($_.Name) -or $columns[$_.Name] -lt $_.Value.ToString().Length) {
$columns[$_.Name] = $_.Value.ToString().Length
}
}
}
}
End {
ForEach($key in $($columns.Keys)) {
$columns[$key] = [Math]::Max($columns[$key], $key.Length)
}
$header = @()
ForEach($key in $columns.Keys) {
$header += $key
}
$header -join ' | '
$separator = @()
ForEach($key in $columns.Keys) {
$separator += '-' * $columns[$key]
}
$separator -join ' | '
ForEach($item in $items) {
$values = @()
ForEach($key in $columns.Keys) {
$values += $item.($key)
}
$values -join ' | '
}
}
} # end ConvertTo-Markdown function
function Format-Ports {
<#
.SYNOPSIS
Sorts and formats a list of ports
.DESCRIPTION
Splits a string of ports into a list of ports, then separates
the individual ports from the port ranges and sorts them
.PARAMETER portList
A string containing a comma-delimited list of ports
#>
param ($portList)
# The port entry from the web service is a string; we need to convert it into an array
$splitPorts = @()
$splitPorts = $portList.Split(",")
# Separate the individual ports from port ranges and sort them
# If it has a "-" then it's a port range, otherwise it's a port
$tempPorts = $splitPorts | Where-Object {$_ -notlike '*-*'} | Sort-Object
$tempRanges = $splitPorts | Where-Object {$_ -like '*-*'} | Sort-Object
# Combine the two lists into a single object so we can specify a delimiter later
$ports = @()
$ports += $tempPorts
$ports += $tempRanges
# Return the formatted arrays of ports and ranges
return $ports
} # end function Format-Ports
function Add-OutputFile {
<#
.SYNOPSIS
Creates an output file for a service instance
.DESCRIPTION
Creates an output file for a service instance at a given path,
then places a descriptive header at the top of the file.
The output file will be referenced and added to throughout the script.
.PARAMETER siList
A list of service instances with versions
.PARAMETER si
A service instance
.PARAMETER path
A path for the output file
#>
param($siList, $si, $path)
Write-Host "Create output file for $si"
# Generate the file name, converted to lowercase and replacing spaces with dashes for compatibility
$script:siFile = (($siHash.$si + $outFileSuffix) -replace (" ", "-")).ToLower()
Out-File -FilePath ($path + $siFile) -Force # overwrite previous output file if it exists
$fileNotice | Out-File -Append -FilePath ($path + $siFile)
"<!--" + $si + " endpoints version " + ($siList | Where-Object {$_.instance -eq $si} | ForEach-Object {$_.latest}) + "-->" | Out-File -Append -FilePath ($path + $siFile)
"<!--File generated " + (Get-Date -Format yyyy-MM-dd` HH:mm:ss.ffff) + "-->" | Out-File -Append -FilePath ($path + $siFile)
# Commenting out H1 header as it's currently not needed in the include file
# "`n# " + $siHash.$si + " Endpoints`n" | Out-File -Append -FilePath ($path + $siFile)
} # end Add-OutputFile function
function Write-ServiceAreaHeader {
param($saName, $path, $file)
Write-Host "Write service header for $saName"
# Add a header with the service area name to the output file
"`n## " + $saName + "`n" | Out-File -Append -FilePath ($path + $file)
} # end function Write-ServiceAreaHeader
function ConvertTo-EndpointObject {
<#
.SYNOPSIS
Builds an endpoint set object for a service area
.DESCRIPTION
Builds a custom PS object from a list of formatted endpoint sets for the
specified service area. The resulting object will have normalized fields
corresponding to the desired fields in the final output file.
.PARAMETER eps
A list of formatted endpoint sets
.PARAMETER sa
A service area name
.NOTES
The PSCustomObject attributes will correspond to the column headers
when converted to a markdown table.
#>
param ($eps, $sa)
Write-Host "Create endpoint set for $sa"
# Loop through the endpoint sets in the service instance and build
# an object out of the endpoint sets in the current service area
$eps | ForEach-Object {
if ($_.serviceArea -eq $sa) {
$endpointSet = $_
# Join the URLs/IPs/ports into strings for output. Define the "-join" separator
# (generally "<BR>" or "," or ", ") between each URL, each IP address, and each port.
# Use <BR> if you want each IP/URL address/port to appear on a separate line
$urls = ($(if ($endpointSet.urls.Count -gt 0) {"``" + (($endpointSet.urls | Where-Object { $_ -ne $null }) -join ", ") + "``"} else { @() }))
$ips = ($(if ($endpointSet.ips.Count -gt 0) {"``" + (($endpointSet.ips | Where-Object { $_ -ne $null }) -join ", ") + "``"} else { @() }))
$tcpPorts = ($(if ($endpointSet.tcpPorts) {"**TCP:** " + ((Format-Ports $endpointSet.tcpPorts) -join ", ")}) | Where-Object { $_ -ne $null }) -join ", "
$udpPorts = ($(if ($endpointSet.udpPorts) {"**UDP:** " + ((Format-Ports $endpointSet.udpPorts) -join ", ")}) | Where-Object { $_ -ne $null }) -join ", "
# Set up the category field to also display required or optional, as well as notes
if ($endpointSet.required) {
$category = $endpointSet.category + "<BR>Required"
}
else {
$category = $endpointSet.category + "<BR>Optional<BR>" + "**Notes:** " + $endpointSet.notes
}
# Create a PowerShell object from the normalized endpoint data
# This object will be converted into a markdown table
# The attributes of this object determine the columns in the table
# The order of the object attributes determine the order of the table columns
[PSCustomObject] @{
ID = $endpointSet.id;
Category = $category;
ER = $(if($endpointSet.expressRoute) {"Yes"} else {"No"}); # Use "Yes/No" instead of "True/False"
Addresses = ($(if($urls){$urls}), $(if($ips){$ips}) | Where-Object { $_ -ne $null }) -join "<BR>";
Ports = ($(if($tcpPorts){$tcpPorts}), $(if($udpPorts){$udpPorts}) | Where-Object { $_ -ne $null }) -join "<BR>";
}
} # end if (test for service area)
} # end of $endpointSet object loop
} # end function ConvertTo-EndpointObject
function Update-TenantURLs {
# This function exists so we can put "<tenant>" in tenant wildcard URLs
param ($epsList, $placeholderString, $replaceString)
Write-Host "Update tenant URLs"
$epsList | Where-Object {$_.urls -like "*$placeHolderString*"} | ForEach-Object {
$_.urls = ($_.urls -replace $placeholderString, $replaceString)
}
return $epsList
} # end function Update-TenantURLs
function Send-ToGitHub {
<#
.SYNOPSIS
Uploads a file to a GitHub repository using the GitHub API
.DESCRIPTION
The function uses the GitHub variables declared earlier in the script
(Organization, Repository, RepoDir, Branch, GitHubHeaders) to upload a file
to a repository.
.PARAMETER path
A path where the directory where theupload file can be found
.PARAMETER file
The name of the file to be uploaded
#>
param($path, $file)
# Get the sha of the file from the repository list,
# based on the matching local file name (previously created)
Write-Host "Upload $file to GitHub"
$sha = $shaHash.$file
# Convert the local file to be uploaded to Base64 (as required by GitHub)
$Base64Content = [System.Convert]::ToBase64String([IO.File]::ReadAllBytes($path + $file))
# Build the body of the message with the file info.
$Body = @{
message = "Uploaded file: " + ($file) + " - " + (Get-Date -Format yyyy-MM-dd` HH:mm:ss.ffff)
content = $Base64Content
sha = $sha
branch = $TargetBranch
} | ConvertTo-Json
# Check if $TargetBranch exists and, if not, create it from $DefaultBranch
Try {
Invoke-RestMethod -uri "https://api.github.com/repos/$Organization/$Repository/git/ref/heads/$TargetBranch" -headers $GitHubHeaders -Method Get | Out-Null
} Catch {
Write-Host "Branch $TargetBranch does not exist. Creating branch $TargetBranch from $DefaultBranch."
$DefaultBranchData = Invoke-RestMethod -uri "https://api.github.com/repos/$Organization/$Repository/git/ref/heads/$DefaultBranch" -Headers $GitHubHeaders -Method Get
$BranchBody = @{
ref = "refs/heads/$TargetBranch"
sha = $DefaultBranchData.object.sha
} | ConvertTo-Json
Invoke-RestMethod -uri "https://api.github.com/repos/$Organization/$Repository/git/refs" -headers $GitHubHeaders -Method POST -Body $BranchBody
}
Write-Host $Body
Write-Host "https://api.github.com/repos/$Organization/$Repository/contents/$($RepoDir)/$($File)?ref=$TargetBranch"
# Upload the file
Invoke-RestMethod -Headers $GitHubHeaders -Uri https://api.github.com/repos/$Organization/$Repository/contents/$($RepoDir)/$($File)?ref=$TargetBranch -Method PUT -Body $Body
} # end Send-ToGitHub function
Function New-PullRequest {
$BranchResponse = $Null
Write-Host "Checking if $TargetBranch exists"
Try {
$BranchResponse = Invoke-RestMethod -uri "https://api.github.com/repos/$Organization/$Repository/git/ref/heads/$TargetBranch" -headers $GitHubHeaders -Method Get -ErrorAction Stop
} Catch {
Write-Host "Branch doesn't exist."
}
If ($BranchResponse) {
Write-Host "Checking if $TargetBranch is ahead of $DefaultBranch"
Try {
$CompareResponse = Invoke-RestMethod -Uri "https://api.github.com/repos/$Organization/$Repository/compare/$DefaultBranch...$TargetBranch" -Method GET -Headers $GitHubHeaders
} Catch {
Throw "Failed to check if $TargetBranch is ahead of $DefaultBranch. Error: $($Error[0])"
}
If ($CompareResponse.ahead_by -gt 0) {
Write-Host "$TargetBranch has changes ahead of $DefaultBranch"
Write-Host "Checking if a pull request exists between $TargetBranch and $DefaultBranch"
Try {
$PrsResponse = Invoke-RestMethod -Uri "https://api.github.com/repos/$Organization/$Repository/pulls?head=$($Organization):$TargetBranch&base=$DefaultBranch&state=open" -Method GET -Headers $GitHubHeaders
} Catch {
Throw "Failed to check if pull request exists between $TargetBranch and $DefaultBranch. Error: $($Error[0])"
}
If (($PrsResponse | Measure-Object).Count -le 0) {
Write-Host "No existing pull request. Creating a new PR from $TargetBranch to $DefaultBranch"
$PrBody = @{
title = "Merge $TargetBranch into $DefaultBranch"
head = $TargetBranch
base = "$DefaultBranch"
body = "$PrDescription"
} | ConvertTo-Json
Try {
$PrResponse = Invoke-RestMethod -Uri "https://api.github.com/repos/$Organization/$Repository/pulls" -Method POST -Headers $GitHubHeaders -Body $PrBody
Write-Host "Created pull request $($PrResponse.html_url)"
$LabelBody = @{
labels = @("Sign off")
} | ConvertTo-Json
Invoke-RestMethod -Uri "https://api.github.com/repos/$Organization/$Repository/issues/$($PrResponse.number)/labels" -Method POST -Headers $GitHubHeaders -Body $LabelBody
} Catch {
Throw "Failed to create pull request. Error: $($Error[0])"
}
} Else {
Write-Host "Pull request exists. "
}
}
}
}
### END FUNCTION BLOCK ###
### BEGIN EXECUTION BLOCK ###
Write-Host "Starting endpoints update script"
# Set up the script variables
Set-ScriptOptions
If ($SetDefaultBranchSuccess) {
# Get the current list of service instances and versions from the web service
$allServiceInstances = Invoke-RestMethod -Uri ($ws + "/version?clientrequestid=" + $clientRequestId)
# Check the service instances for new versions, then if necessary
# create a list of service instances needing updates
$serviceInstances = Get-UpdateList $allServiceInstances $siVersionFile
# If any service instances need to be updated, we need the SHA of the
# existing files on GitHub in order to replace them with updated files
if ($serviceInstances.Count -gt 0) {
$shaHash = Get-RemoteDirectoryListing $serviceInstances
} Else {
Write-Host "No service instances need updates"
}
# Loop through the list of service instances to get updated endpoint sets, format
# the endpoint data, convert to markdown, save an output file, and upload to GitHub.
$serviceInstances | ForEach-Object {
$currentServiceInstance = $_
Write-Host "Processing $currentServiceInstance"
# Create the initial output file for the service instance ($siFile). We will
# write to this file as we build the markdown table for each service area.
Add-OutputFile $allServiceInstances $currentServiceInstance $dataPath
# DEALING WITH TENANT WILDCARD URLS
# We need to display <tenant> in tenant wildcard URLs, but we can't
# actually pass that value to the web service anymore.
# The following workaround uses placeholder text for tenant URLs,
# then replaces the placeholder text with the text we need displayed.
$tenantPlaceHolderText = "AnyUniqueString"
$tenantTextToDisplay = "<tenant>"
$endpointSets = ""
Write-Host "Retrieving endpoint set for $currentServiceInstance from M365 web service"
# Call the web service to get the endpoint sets for the current service instance
$endpointSets = Invoke-RestMethod -Uri ($ws + "/endpoints/"+ $currentServiceInstance + "?tenantname=" + $tenantPlaceHolderText + "&clientRequestId=" + $clientRequestId)
# Only continue if we have valid endpoint set data
if ($endpointSets -ne "") {
Write-Host "Retrieved endpoint sets"
# Replace the tenant placeholder text with the text we need to display
$endpointSets = Update-TenantURLs $endpointSets $tenantPlaceHolderText $tenantTextToDisplay
# Group the endpoint sets by service area and convert to markdown, then append to the output file
$allServiceAreas | ForEach-Object {
$currentServiceArea = $_
Write-Host "Processing $currentServiceArea"
# Create a custom object from the list of normalized endpoint sets
$saEndpointSetsObject = ConvertTo-EndpointObject $endpointSets $currentServiceArea
# Get the official display name for the service area
$saDisplayName = $endpointSets | Where-Object -Property serviceArea -EQ $currentServiceArea | ForEach-Object {$_.serviceAreaDisplayName} | Select-Object -Unique
# Put a header at the top of each service area section in the markdown
Write-ServiceAreaHeader $saDisplayName $dataPath $siFile
# Convert the endpoint sets object to markdown and append to the output file for the current service instance
($saEndpointSetsObject) | Select-Object * | ConvertTo-Markdown | Out-File -Append -FilePath ($dataPath + $siFile)
} # end allServiceAreas loop
# Upload the final output file to GitHub
Send-ToGitHub $dataPath $siFile
} Else {
Write-Host "Didn't receive any endpoint sets from webservice for $currentServiceInstance"
}
} # end serviceInstances loop
# Create a new pull request. New-PullRequest will only create a new PR if one is needed.
New-PullRequest
} # set default branch check
ls -alr $dataPath
Write-Host "Finished endpoints update script"
- uses: actions/upload-artifact@v4
name: Upload run data artifact
with:
name: RunData
path: "${{ github.workspace }}/run-data/endpoints*"