microsoft/typespec

Public

mirrored from https://github.com/microsoft/typespecAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
63dce6b8a5ec2b25b203f52f4fe376f352ea51f4

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

eng/common/scripts/Analyze-Changes.ps1

176lines · modecode

1#Requires -Version 7.0
2
3param(
4 [string] $TargetBranch
5)
6
7# Represents an isolated package which has its own stages in typespec - ci pipeline
8class IsolatedPackage {
9 [string[]] $Paths
10 [string] $RunVariable
11 [bool] $RunValue
12
13 IsolatedPackage([string[]]$paths, [string]$runVariable, [bool]$runValue) {
14 $this.Paths = $paths
15 $this.RunVariable = $runVariable
16 $this.RunValue = $runValue
17 }
18}
19
20# Emitter packages in the repo
21$isolatedPackages = @{
22 "http-client-csharp" = [IsolatedPackage]::new(@("packages/http-client-csharp", ".editorconfig"), "RunCSharp", $false)
23 "http-client-java" = [IsolatedPackage]::new(@("packages/http-client-java"), "RunJava", $false)
24 "http-client-typescript" = [IsolatedPackage]::new(@("packages/http-client-typescript"), "RunTypeScript", $false)
25 "http-client-python" = [IsolatedPackage]::new(@("packages/http-client-python"), "RunPython", $false)
26}
27
28# A tree representation of a set of files
29# Each node represents a directory and contains a list of child nodes.
30class TreeNode {
31 [string] $Name
32 [System.Collections.Generic.List[TreeNode]] $Children
33
34 TreeNode([string]$name) {
35 $this.Name = $name
36 $this.Children = @()
37 }
38
39 # Add a file to the tree
40 [void] Add([string]$filePath) {
41 $parts = $filePath -split '/'
42
43 $currentNode = $this
44 foreach ($part in $parts) {
45 $childNode = $currentNode.Children | Where-Object { $_.Name -eq $part }
46 if (-not $childNode) {
47 $childNode = [TreeNode]::new($part)
48 $currentNode.Children.Add($childNode)
49 }
50 $currentNode = $childNode
51 }
52 }
53
54 # Check if a file exists in the tree
55 [bool] PathExists([string]$filePath) {
56 $parts = $filePath -split '/'
57
58 $currentNode = $this
59 foreach ($part in $parts) {
60 $childNode = $currentNode.Children | Where-Object { $_.Name -eq $part }
61 if (-not $childNode) {
62 return $false
63 }
64 $currentNode = $childNode
65 }
66 return $true
67 }
68
69 # Check if anything outside of emitter packages exists
70 [bool] AnythingOutsideIsolatedPackagesExists($isolatedPackages) {
71 if ($this.Children.Count -eq 0) {
72 return $false
73 }
74
75 # if anything in first level is not 'packages', return true
76 foreach ($child in $this.Children) {
77 if ($child.Name -ne 'packages') {
78 return $true
79 }
80 }
81
82 $packagesNode = $this.Children | Where-Object { $_.Name -eq "packages" }
83 if (-not $packagesNode) {
84 return $false
85 }
86
87 # if anything in second level is not an emitter package, return true
88 foreach ($child in $packagesNode.Children) {
89 if ($child.Name -notin $isolatedPackages.Keys) {
90 return $true
91 }
92 }
93
94 return $false
95 }
96
97 [string] ToString() {
98 return $this.Name
99 }
100}
101
102function Get-ActiveVariables($changes) {
103 # initialize tree
104 $root = [TreeNode]::new('Root')
105 $variables = @()
106
107 $changes | ForEach-Object {
108 $root.Add($_)
109 }
110
111 # exit early if no changes detected
112 if ($root.Children.Count -eq 0) {
113 Write-Host "##[error] No changes detected"
114 exit 1
115 }
116
117 # set global flag to run all if common files are changed
118 $runAll = $root.PathExists('eng/common')
119
120 # set global isolated package flag to run if any eng/emiters files changed
121 $runIsolated = $root.PathExists('eng/emitters')
122
123 # no need to check individual packages if runAll is true
124 if (-not $runAll) {
125 if (-not $runIsolated) {
126 # set each isolated package flag
127 foreach ($package in $isolatedPackages.Values) {
128 foreach ($path in $package.Paths) {
129 $package.RunValue = $package.RunValue -or $root.PathExists($path)
130 if ($package.RunValue) {
131 break
132 }
133 }
134 }
135 }
136
137 # set runCore to true if none of the
138 $runCore = $root.AnythingOutsideIsolatedPackagesExists($isolatedPackages)
139 }
140
141 # set log commands
142 if ($runAll -or $runCore) {
143 $variables += "RunCore"
144 }
145
146 # foreach isolated package, set log commands if the RunValue is true
147 foreach ($package in $isolatedPackages.Values) {
148 if ($runAll -or $runIsolated -or $package.RunValue) {
149 $variables += $package.RunVariable
150 }
151 }
152
153 return $variables
154}
155
156
157# add all changed files to the tree
158Write-Host "Checking for changes in current branch compared to $TargetBranch"
159$changes = git diff --name-only origin/$TargetBranch...
160
161Write-Host "##[group]Files changed in this pr"
162$changes | ForEach-Object {
163 Write-Host " - $_"
164}
165Write-Host "##[endgroup]"
166
167if ($LASTEXITCODE -ne 0) {
168 Write-Host "##[error] 'git diff --name-only origin/$TargetBranch...' failed, exiting..."
169 exit 1 # Exit with a non-zero exit code to indicate failure
170}
171
172$variables = Get-ActiveVariables $changes
173foreach ($variable in $variables) {
174 Write-Host "Setting $variable to true"
175 Write-Host "##vso[task.setvariable variable=$variable;isOutput=true]true"
176}
177