<# .SYNOPSIS Azure RTOS ThreadX CI/CD script .DESCRIPTION Entry point for automated building, cleaning, testing, verification, ... .EXAMPLE .\azrtos_cicd.ps1 -clean This cleans all examples in the default database. .\azrtos_cicd.ps1 -MatchName 'Modules' -build This builds all ThreadX Modules examples. .\azrtos_cicd.ps1 -MatchName 'Modules','IAR' -build This builds all examples in the default database that have names matching the string 'Modules' and 'IAR'. .\azrtos_cicd.ps1 -MatchName 'Cortex M4','ARM compiler v6' -StartCLI This opens CLI with set environments for all examples in the default database that have names matching the 'Cortex M4' and 'ARM compiler v6'. .LINK https://azure.com/rtos .NOTES Author: Andres Mlinar Date: 2021 #> [CmdletBinding(PositionalBinding=$false)] Param( [string[]] #One or more CSV files with the list of examples to process $CsvFile = "azrtos_cicd.csv", [string[]] #One or more regular expression strings to match names for $MatchName, [string[]] #One or more regular expression strings to match keywords for $MatchKeywords, [string[]] #One or more regular expression strings to match paths for $MatchPath, [string] #The source root directory, if not specified it defaults to the current repo $SrcDir = $( Join-Path $PSScriptRoot "..\.." ), [string] #The script root directory, if not specified it defaults to this script's directory $ScriptDir = $PSScriptRoot, [string] #The output log directory $LogDir = $( Join-Path $PSScriptRoot "log" ), [switch] #Start a CLI with a set environment for the specified examples $StartCLI = $false, [switch] #Check compliance for the specified examples $CheckCompliance = $false, [switch] #Clean all files not in the repository for the specified examples $RealClean = $false, [switch] #Clean the specified examples $Clean = $false, [switch] #Build the specified examples $Build = $false, [switch] #Test the specified examples $Test = $false ) If ($PSVersionTable.PSVersion.Major -lt 7) { Write-Host "ERROR: PowerShell version 7 or higher is required!" Exit -2 } Write-Verbose ("CSV files: " + $CsvFile) Write-Verbose ("MatchName: " + $MatchName.Count + "[" + $MatchName + "]") Write-Verbose ("MatchKeywords: " + $MatchKeywords.Count + "[" + $MatchKeywords + "]") Write-Verbose ("MatchPath: " + $MatchPath.Count + "[" + $MatchPath + "]") Write-Verbose ("SrcDir: " + $SrcDir) Write-Verbose ("ScriptDir: " + $ScriptDir) Write-Verbose ("LogDir: " + $LogDir) Write-Verbose ("StartCLI? " + $StartCLI) Write-Verbose ("CheckCompliance? " + $CheckCompliance) Write-Verbose ("RealClean? " + $RealClean) Write-Verbose ("Clean? " + $Clean) Write-Verbose ("Build? " + $Build) Write-Verbose ("Test? " + $Test) $Stats = [PSCustomObject]@{ Total = 0 CurrentCsv = 0 CleanScriptOK = 0 CleanScriptERROR = 0 BuildScriptOK = 0 BuildScriptERROR = 0 TestScriptOK = 0 TestScriptERROR = 0 } function Invoke-CustomScript { Param ( [string] #A string describing the script type $Type, [string] #The sample name $Name, [string] #The environment setup script full path $EnvScript, [string] #The script full path $Script ) Write-Verbose ("Type: " + $Type) Write-Verbose ("SampleDir: " + $SampleDir) Write-Verbose ("EnvScript: " + $EnvScript) Write-Verbose ("Script: " + $Script) If (-not (Test-Path -Path $EnvScript -PathType leaf)) { Write-Host "ERROR: the environment setup script doesn't exist:" $Script -ForegroundColor red return -1 } If (-not (Test-Path -Path $Script -PathType leaf)) { Write-Host "ERROR: the script doesn't exist:" $Script -ForegroundColor red return -1 } Write-Host ("`n`r") Write-Host (Get-Date -Format FileDateTimeUniversal) "INFO:" $Type "starting" "->" $Name -ForegroundColor green $ScriptOutput = & CMD /C "$EnvScript && $Script 2>&1" $ExitCode = $LASTEXITCODE Write-Verbose ("ExitCode: " + $ExitCode) Write-Verbose ("ScriptOutput: " + $ScriptOutput) $LogFileName = (Get-Date -Format FileDateTimeUniversal) + '.' + ($Name -replace ' ', '_' -replace '/', '_' -replace '\\', '_') + "." + $Type + "." + (($ExitCode -eq 0) ? "OK" : "ERROR") + ".log" $LogFileFullPath = Join-Path $LogDir $LogFileName Write-Verbose ("LogFileNmae: " + $LogFileName) Write-Verbose ("LogFileFullPath: " + $LogFileFullPath) $ScriptOutput | Out-File -FilePath $LogFileFullPath If ($ExitCode -ne 0) { Write-Host (Get-Date -Format FileDateTimeUniversal) "ERROR:" $Type "failed!" "->" $Name -ForegroundColor red } else { Write-Host (Get-Date -Format FileDateTimeUniversal) "INFO:" $Type "success!" "->" $Name -ForegroundColor green } return $ExitCode } # Create the log directory if it doesn't already exists If (-Not (Test-Path -Path $LogDir -PathType Container)) { New-Item -Path $LogDir -ItemType Directory } ForEach ($f in $CsvFile) { Write-Host $(Get-Date -Format FileDateTimeUniversal) "INFO:" $f -ForegroundColor green Write-Verbose ("CSV file: " + $f) try { $t = Import-Csv -Path $f } catch { Write-Output "ERROR: failed to open CSV file:" $f -ForegroundColor red Continue } Write-Verbose ("Table rows: " + $t.Count) $Stats.CurrentCsv = 0 ForEach ($i in $t) { $Stats.Total++ $Stats.CurrentCsv++ Write-Verbose ("`n`r") Write-Verbose ("Name: " + $i.Name) Write-Verbose ("Keywords: " + $i.Keywords) Write-Verbose ("Path: " + $i.Path) Write-Verbose ("HostPlatform: " + $i.HostPlatform) If ($i.HostPlatform -ne $PSVersionTable.Platform) { Write-Verbose ("HostPlatform mismatch, skipping...") Continue } $match = $true If ($MatchName.Count -ne 0) { Write-Verbose ("Matching name...") ForEach ($m in $MatchName) { Write-Verbose ("Matching " + $m) If (-not ($i.Name -match $m)) { Write-Verbose ("Name mismatch: " + $m) $match = $false; } } } If ($MatchKeywords.Count -ne 0) { Write-Verbose ("Matching keywords...") ForEach ($m in $MatchKeywords) { Write-Verbose ("Matching " + $m) If (-not ($i.Keywords -match $m)) { Write-Verbose ("Keywords mismatch: " + $m) $match = $false } } } If ($MatchPath.Count -ne 0) { Write-Verbose ("Matching path...") ForEach ($m in $MatchPath) { Write-Verbose ("Matching " + $m) If (-not ($i.Path -match $m)) { Write-Verbose ("Path mismatch: " + $m) $match = $false } } } If (-not $match) { Write-Verbose ("No match, skipping...") Continue } $FullPath = Join-Path $SrcDir $i.Path Write-Verbose ("FullPath: " + $FullPath) If (-Not $( Test-Path $FullPath -PathType Container )) { Write-Host "ERROR: path doesn't exist:" $FullPath -ForegroundColor red Continue } If ($StartCLI) { If ($PSVersionTable.Platform -eq "Win32NT") { Start-Process ` -FilePath "cmd.exe" ` -WorkingDirectory $FullPath ` -ArgumentList ( "/k " ` + ("set PATH=" + $PSScriptRoot + ";%PATH% & ") ` + ("DOSKEY realclean=" + "git clean -d -f -X " + $FullPath + " & ") ` + ("DOSKEY clean=" + (Join-Path $ScriptDir $i.CleanEnvScript) + '$T$T' + (Join-Path $ScriptDir $i.CleanScript) + " & ") ` + ("DOSKEY build=" + (Join-Path $ScriptDir $i.BuildEnvScript) + '$T$T' + (Join-Path $ScriptDir $i.BuildScript) + " & ") ` + ("DOSKEY test=" + (Join-Path $ScriptDir $i.TestEnvScript) + '$T$T' + (Join-Path $ScriptDir $i.TestScript)) ) } } Push-Location $FullPath If ($RealClean ) { & ("git clean -d -f -X " + $FullPath) } If ($Clean -and ($i.CleanScript -ne "")) { Write-Progress -Activity $f -Status ($Stats.CurrentCsv.ToString() + "/" + $t.Count.ToString()) -CurrentOperation $i.Name -PercentComplete (1.0 * $Stats.CurrentCsv / $t.Count * 100) $result = Invoke-CustomScript "Clean" $i.Name (Join-Path $ScriptDir $i.CleanEnvScript) (Join-Path $ScriptDir $i.CleanScript) if ($result -ne 0) { $Stats.CleanScriptERROR++ } else { $Stats.CleanScriptOK++ } } If ($Build -and ($i.BuildScript -ne "")) { Write-Progress -Activity $f -Status ($Stats.CurrentCsv.ToString() + "/" + $t.Count.ToString()) -CurrentOperation $i.Name -PercentComplete (1.0 * $Stats.CurrentCsv / $t.Count * 100) $result = Invoke-CustomScript "Build" $i.Name (Join-Path $ScriptDir $i.BuildEnvScript) (Join-Path $ScriptDir $i.BuildScript) if ($result -ne 0) { $Stats.BuildScriptERROR++ } else { $Stats.BuildScriptOK++ } } If ($Test -and ($i.TestScript -ne "")) { Write-Progress -Activity $f -Status ($Stats.CurrentCsv.ToString() + "/" + $t.Count.ToString()) -CurrentOperation $i.Name -PercentComplete (1.0 * $Stats.CurrentCsv / $t.Count * 100) $result = Invoke-CustomScript "Test" $i.Name (Join-Path $ScriptDir $i.TestEnvScript) (Join-Path $ScriptDir $i.TestScript) if ($result -ne 0) { $Stats.TestScriptERROR++ } else { $Stats.TestScriptOK++ } } Pop-Location } } "Total: " + $Stats.Total If ($Clean) { "Clean: " + $Stats.CleanScriptOK + " OK, " + $Stats.CleanScriptERROR + " failed" } If ($Build) { "Build: " + $Stats.BuildScriptOK + " OK, " + $Stats.BuildScriptERROR + " failed" } If ($Test) { "Test: " + $Stats.TestScriptOK + " OK, " + $Stats.TestScriptERROR + " failed" } Exit $Stats.CleanScriptERROR+$Stats.BuildScriptERROR+$Stats.TestScriptERROR