1 <#
2 .SYNOPSIS
3 Azure RTOS ThreadX CI/CD script
4
5 .DESCRIPTION
6 Entry point for automated building, cleaning, testing, verification, ...
7
8 .EXAMPLE
9 .\azrtos_cicd.ps1 -clean
10 This cleans all examples in the default database.
11
12 .\azrtos_cicd.ps1 -MatchName 'Modules' -build
13 This builds all ThreadX Modules examples.
14
15 .\azrtos_cicd.ps1 -MatchName 'Modules','IAR' -build
16 This builds all examples in the default database that have names matching the string 'Modules' and 'IAR'.
17
18 .\azrtos_cicd.ps1 -MatchName 'Cortex M4','ARM compiler v6' -StartCLI
19 This opens CLI with set environments for all examples in the default database that have names matching the 'Cortex M4' and 'ARM compiler v6'.
20
21 .LINK
22 https://azure.com/rtos
23
24 .NOTES
25 Author: Andres Mlinar
26 Date: 2021
27 #>
28
29 [CmdletBinding(PositionalBinding=$false)] Param(
30
31 [string[]]
32 #One or more CSV files with the list of examples to process
33 $CsvFile = "azrtos_cicd.csv",
34
35 [string[]]
36 #One or more regular expression strings to match names for
37 $MatchName,
38
39 [string[]]
40 #One or more regular expression strings to match keywords for
41 $MatchKeywords,
42
43 [string[]]
44 #One or more regular expression strings to match paths for
45 $MatchPath,
46
47 [string]
48 #The source root directory, if not specified it defaults to the current repo
49 $SrcDir = $( Join-Path $PSScriptRoot "..\.." ),
50
51 [string]
52 #The script root directory, if not specified it defaults to this script's directory
53 $ScriptDir = $PSScriptRoot,
54
55 [string]
56 #The output log directory
57 $LogDir = $( Join-Path $PSScriptRoot "log" ),
58
59 [switch]
60 #Start a CLI with a set environment for the specified examples
61 $StartCLI = $false,
62
63 [switch]
64 #Check compliance for the specified examples
65 $CheckCompliance = $false,
66
67 [switch]
68 #Clean all files not in the repository for the specified examples
69 $RealClean = $false,
70
71 [switch]
72 #Clean the specified examples
73 $Clean = $false,
74
75 [switch]
76 #Build the specified examples
77 $Build = $false,
78
79 [switch]
80 #Test the specified examples
81 $Test = $false
82
83 )
84
85 If ($PSVersionTable.PSVersion.Major -lt 7) {
86 Write-Host "ERROR: PowerShell version 7 or higher is required!"
87 Exit -2
88 }
89
90 Write-Verbose ("CSV files: " + $CsvFile)
91 Write-Verbose ("MatchName: " + $MatchName.Count + "[" + $MatchName + "]")
92 Write-Verbose ("MatchKeywords: " + $MatchKeywords.Count + "[" + $MatchKeywords + "]")
93 Write-Verbose ("MatchPath: " + $MatchPath.Count + "[" + $MatchPath + "]")
94 Write-Verbose ("SrcDir: " + $SrcDir)
95 Write-Verbose ("ScriptDir: " + $ScriptDir)
96 Write-Verbose ("LogDir: " + $LogDir)
97 Write-Verbose ("StartCLI? " + $StartCLI)
98 Write-Verbose ("CheckCompliance? " + $CheckCompliance)
99 Write-Verbose ("RealClean? " + $RealClean)
100 Write-Verbose ("Clean? " + $Clean)
101 Write-Verbose ("Build? " + $Build)
102 Write-Verbose ("Test? " + $Test)
103
104 $Stats = [PSCustomObject]@{
105 Total = 0
106 CurrentCsv = 0
107 CleanScriptOK = 0
108 CleanScriptERROR = 0
109 BuildScriptOK = 0
110 BuildScriptERROR = 0
111 TestScriptOK = 0
112 TestScriptERROR = 0
113 }
114
Invoke-CustomScriptnull115 function Invoke-CustomScript {
116
117 Param (
118
119 [string]
120 #A string describing the script type
121 $Type,
122
123 [string]
124 #The sample name
125 $Name,
126
127 [string]
128 #The environment setup script full path
129 $EnvScript,
130
131 [string]
132 #The script full path
133 $Script
134 )
135
136 Write-Verbose ("Type: " + $Type)
137 Write-Verbose ("SampleDir: " + $SampleDir)
138 Write-Verbose ("EnvScript: " + $EnvScript)
139 Write-Verbose ("Script: " + $Script)
140
141 If (-not (Test-Path -Path $EnvScript -PathType leaf)) {
142 Write-Host "ERROR: the environment setup script doesn't exist:" $Script -ForegroundColor red
143 return -1
144 }
145
146 If (-not (Test-Path -Path $Script -PathType leaf)) {
147 Write-Host "ERROR: the script doesn't exist:" $Script -ForegroundColor red
148 return -1
149 }
150
151 Write-Host ("`n`r")
152 Write-Host (Get-Date -Format FileDateTimeUniversal) "INFO:" $Type "starting" "->" $Name -ForegroundColor green
153
154 $ScriptOutput = & CMD /C "$EnvScript && $Script 2>&1"
155 $ExitCode = $LASTEXITCODE
156 Write-Verbose ("ExitCode: " + $ExitCode)
157 Write-Verbose ("ScriptOutput: " + $ScriptOutput)
158
159 $LogFileName = (Get-Date -Format FileDateTimeUniversal) + '.' + ($Name -replace ' ', '_' -replace '/', '_' -replace '\\', '_') + "." + $Type + "." + (($ExitCode -eq 0) ? "OK" : "ERROR") + ".log"
160 $LogFileFullPath = Join-Path $LogDir $LogFileName
161 Write-Verbose ("LogFileNmae: " + $LogFileName)
162 Write-Verbose ("LogFileFullPath: " + $LogFileFullPath)
163
164 $ScriptOutput | Out-File -FilePath $LogFileFullPath
165
166 If ($ExitCode -ne 0) {
167 Write-Host (Get-Date -Format FileDateTimeUniversal) "ERROR:" $Type "failed!" "->" $Name -ForegroundColor red
168 } else {
169 Write-Host (Get-Date -Format FileDateTimeUniversal) "INFO:" $Type "success!" "->" $Name -ForegroundColor green
170 }
171
172 return $ExitCode
173 }
174
175 # Create the log directory if it doesn't already exists
176 If (-Not (Test-Path -Path $LogDir -PathType Container)) {
177 New-Item -Path $LogDir -ItemType Directory
178 }
179
180 ForEach ($f in $CsvFile) {
181
182 Write-Host $(Get-Date -Format FileDateTimeUniversal) "INFO:" $f -ForegroundColor green
183
184 Write-Verbose ("CSV file: " + $f)
185
186 try {
187 $t = Import-Csv -Path $f
188 } catch {
189 Write-Output "ERROR: failed to open CSV file:" $f -ForegroundColor red
190 Continue
191 }
192
193 Write-Verbose ("Table rows: " + $t.Count)
194
195 $Stats.CurrentCsv = 0
196
197 ForEach ($i in $t) {
198
199 $Stats.Total++
200 $Stats.CurrentCsv++
201
202 Write-Verbose ("`n`r")
203 Write-Verbose ("Name: " + $i.Name)
204 Write-Verbose ("Keywords: " + $i.Keywords)
205 Write-Verbose ("Path: " + $i.Path)
206 Write-Verbose ("HostPlatform: " + $i.HostPlatform)
207
208 If ($i.HostPlatform -ne $PSVersionTable.Platform) {
209 Write-Verbose ("HostPlatform mismatch, skipping...")
210 Continue
211 }
212
213 $match = $true
214
215 If ($MatchName.Count -ne 0) {
216 Write-Verbose ("Matching name...")
217 ForEach ($m in $MatchName) {
218 Write-Verbose ("Matching " + $m)
219 If (-not ($i.Name -match $m)) {
220 Write-Verbose ("Name mismatch: " + $m)
221 $match = $false;
222 }
223 }
224 }
225
226 If ($MatchKeywords.Count -ne 0) {
227 Write-Verbose ("Matching keywords...")
228 ForEach ($m in $MatchKeywords) {
229 Write-Verbose ("Matching " + $m)
230 If (-not ($i.Keywords -match $m)) {
231 Write-Verbose ("Keywords mismatch: " + $m)
232 $match = $false
233 }
234 }
235 }
236
237 If ($MatchPath.Count -ne 0) {
238 Write-Verbose ("Matching path...")
239 ForEach ($m in $MatchPath) {
240 Write-Verbose ("Matching " + $m)
241 If (-not ($i.Path -match $m)) {
242 Write-Verbose ("Path mismatch: " + $m)
243 $match = $false
244 }
245 }
246 }
247
248 If (-not $match) {
249 Write-Verbose ("No match, skipping...")
250 Continue
251 }
252
253 $FullPath = Join-Path $SrcDir $i.Path
254 Write-Verbose ("FullPath: " + $FullPath)
255
256 If (-Not $( Test-Path $FullPath -PathType Container )) {
257 Write-Host "ERROR: path doesn't exist:" $FullPath -ForegroundColor red
258 Continue
259 }
260
261 If ($StartCLI) {
262 If ($PSVersionTable.Platform -eq "Win32NT") {
263 Start-Process `
264 -FilePath "cmd.exe" `
265 -WorkingDirectory $FullPath `
266 -ArgumentList (
267 "/k " `
268 + ("set PATH=" + $PSScriptRoot + ";%PATH% & ") `
269 + ("DOSKEY realclean=" + "git clean -d -f -X " + $FullPath + " & ") `
270 + ("DOSKEY clean=" + (Join-Path $ScriptDir $i.CleanEnvScript) + '$T$T' + (Join-Path $ScriptDir $i.CleanScript) + " & ") `
271 + ("DOSKEY build=" + (Join-Path $ScriptDir $i.BuildEnvScript) + '$T$T' + (Join-Path $ScriptDir $i.BuildScript) + " & ") `
272 + ("DOSKEY test=" + (Join-Path $ScriptDir $i.TestEnvScript) + '$T$T' + (Join-Path $ScriptDir $i.TestScript))
273 )
274 }
275 }
276
277 Push-Location $FullPath
278
279 If ($RealClean ) {
280 & ("git clean -d -f -X " + $FullPath)
281 }
282
283 If ($Clean -and ($i.CleanScript -ne "")) {
284 Write-Progress -Activity $f -Status ($Stats.CurrentCsv.ToString() + "/" + $t.Count.ToString()) -CurrentOperation $i.Name -PercentComplete (1.0 * $Stats.CurrentCsv / $t.Count * 100)
285 $result = Invoke-CustomScript "Clean" $i.Name (Join-Path $ScriptDir $i.CleanEnvScript) (Join-Path $ScriptDir $i.CleanScript)
286 if ($result -ne 0) {
287 $Stats.CleanScriptERROR++
288 } else {
289 $Stats.CleanScriptOK++
290 }
291 }
292
293 If ($Build -and ($i.BuildScript -ne "")) {
294 Write-Progress -Activity $f -Status ($Stats.CurrentCsv.ToString() + "/" + $t.Count.ToString()) -CurrentOperation $i.Name -PercentComplete (1.0 * $Stats.CurrentCsv / $t.Count * 100)
295 $result = Invoke-CustomScript "Build" $i.Name (Join-Path $ScriptDir $i.BuildEnvScript) (Join-Path $ScriptDir $i.BuildScript)
296 if ($result -ne 0) {
297 $Stats.BuildScriptERROR++
298 } else {
299 $Stats.BuildScriptOK++
300 }
301 }
302
303 If ($Test -and ($i.TestScript -ne "")) {
304 Write-Progress -Activity $f -Status ($Stats.CurrentCsv.ToString() + "/" + $t.Count.ToString()) -CurrentOperation $i.Name -PercentComplete (1.0 * $Stats.CurrentCsv / $t.Count * 100)
305 $result = Invoke-CustomScript "Test" $i.Name (Join-Path $ScriptDir $i.TestEnvScript) (Join-Path $ScriptDir $i.TestScript)
306 if ($result -ne 0) {
307 $Stats.TestScriptERROR++
308 } else {
309 $Stats.TestScriptOK++
310 }
311 }
312
313 Pop-Location
314 }
315 }
316
317 "Total: " + $Stats.Total
318 If ($Clean) {
319 "Clean: " + $Stats.CleanScriptOK + " OK, " + $Stats.CleanScriptERROR + " failed"
320 }
321 If ($Build) {
322 "Build: " + $Stats.BuildScriptOK + " OK, " + $Stats.BuildScriptERROR + " failed"
323 }
324 If ($Test) {
325 "Test: " + $Stats.TestScriptOK + " OK, " + $Stats.TestScriptERROR + " failed"
326 }
327
328 Exit $Stats.CleanScriptERROR+$Stats.BuildScriptERROR+$Stats.TestScriptERROR
329