function Invoke-CategorizeAllProjects { <# .SYNOPSIS Categorize each and every solution in the Alkami repository infrastructure for package componentization structure. Recurses the current path or specified location for all *.sln .PARAMETER Path The location to start recursing from .PARAMETER OutputPath The location to write the final values to #> <# foreach sln foreach csproj if (has manifest) isX/Y/Z break if (inherits X,Y,Z) isX/Y/Z break if (package contains X,Y,Z) isX/Y/Z break #> <# Providers - Look for packages.config Alkami.Common and ProcessorBase or ConnectorBase Web Target - Look for MVC ref in packages.config Widgets - Look for SiteText xml Widgets - Look for AreaRegistration WebExtensions - Look for IAlkamiWebExtension or IAlkamiModule WebApplications - Look for global.asax Services are already taken care of but I still need a way to deref walk the tree for providers and services to get their provider_type and provider_assembly_info and provider_name #> [CmdletBinding()] [OutputType([string[]])] param( [Parameter(Mandatory = $false)] [string]$Path = (Get-RepoCheckpointPath), [Parameter(Mandatory = $false)] [string]$OutputPath ) $psStopWatch = [System.Diagnostics.Stopwatch]::StartNew() $logLead = (Get-LogLeadName) if (!(Test-Path -Path $Path)) { $Path = (Get-Location) } $outputPathSpecified = ![string]::IsNullOrWhiteSpace($OutputPath) $solutions = @() $allSlns = (Get-ChildItem -Path (Join-Path -Path $Path -ChildPath '*.sln') -Recurse).FullName $solutions = Invoke-JobRunner -JobInputs $allSlns -ReturnObjects -ScriptBlock { param ($solutionPath) $obsoleteRegex = "^(zz|deprecated|archive|obsolete|xxx)" if ($solutionPath.IndexOf('[') -gt -1) { Write-Host "$logLead : Not even trying to touch [$solutionPath] due to bad name format" } try { $pathSplits = ($solutionPath -split '\\') $solutionRepo = $pathSplits[2] $solutionFolderPath = (Split-Path -Path $solutionPath -Parent) $solutionName = (Split-Path -Path $solutionFolderPath -Leaf) $solutionProject = (Split-Path -Path (Split-Path -Path $solutionFolderPath -Parent) -Leaf) $solutionFileObject = (ConvertFrom-SlnFile -Path $solutionPath) $files = (Get-ChildItem -Path $solutionFolderPath) $semVerPath = ($files.Where({ $_.Name -eq "sem.ver" }).FullName) $solutionHasSemVer = $null $solutionHasPackagesConfig = $null $semverValueRaw = $null $semverValueVersion = $null if (![string]::IsNullOrWhiteSpace($semVerPath)) { $solutionHasSemVer = $true try { $semverValueRaw = (ConvertFrom-Json (Get-Content -Path $semVerPath -Raw)) if (($null -ne $semverValueRaw) -and ($null -ne $semverValueRaw.Version)) { $semverValueVersion = "$($semverValueRaw.Version.Major).$($semverValueRaw.Version.Minor).$($semverValueRaw.Version.Patch)" } } catch { Write-Warning "$logLead : Could not capture the semver from [$semverPath]" } } $packagesConfigPath = ($files.Where({ $_.Name -eq "packages.config" }).FullName) $packagesConfig = $null if (![string]::IsNullOrWhiteSpace($packagesConfigPath)) { $solutionHasPackagesConfig = $true $packagesConfig = (([xml](Get-Content $packagesConfigPath)).packages.package | Select-Object -Property id, version, targetFramework) } $nuspecPath = @($files.Where({ $_.Name.EndsWith(".nuspec") }).FullName)[0] $nuspecContent = $null $nuspecIsChocolatey = $null $solutionHasNuspec = $null $solutionNuspecId = $null if (![string]::IsNullOrWhiteSpace($nuspecPath)) { $solutionHasNuspec = $true $nuspecContent = [xml](Get-Content $nuspecPath) $solutionNuspecId = $nuspecContent.package.metadata.id $nuspecIsChocolatey = ($nuspecContent.package.files.file.src.EndsWith('chocolateyInstall.ps1').Where({ $_ }).Count -gt 0) } $solutionHasTools = ($null -ne (Get-Item -Path (Join-Path -Path $solutionFolderPath -ChildPath 'Tools') -ErrorAction Ignore)) $solutionToolsHasChocoFiles = $null if ($solutionHasTools) { $solutionToolsHasChocoFiles = ($null -ne (Get-ChildItem -Path (Join-Path -Path (Join-Path -Path $solutionFolderPath -ChildPath 'Tools') -ChildPath "choco*.ps1"))) } $solution = @{ Name = $solutionName Project = $solutionProject Repo = $solutionRepo Path = $solutionPath SolutionFile = $solutionFileObject SolutionHasTools = $solutionHasTools SolutionToolsHasChocoFiles = $solutionToolsHasChocoFiles SolutionHasPackagesConfig = $solutionHasPackagesConfig PackagesConfig = $packagesConfig SolutionHasSemVer = $solutionHasSemVer SemVerValueVersion = $semverValueVersion SolutionHasNuspec = $solutionHasNuspec SolutionNuspecIsChocolatey = $nuspecIsChocolatey SolutionNuspecId = $solutionNuspecId SolutionIsService = $null SolutionIsDatabaseService = $null IsLikelyDeprecated = $solutionName -match $obsoleteRegex -or $solutionProject -match $obsoleteRegex Projects = @() } if (Any $solutionFileObject.Projects) { if (Any $solutionFileObject.Projects.Where({ ![string]::IsNullOrWhiteSpace($_.Path) })) { foreach ($project in $solutionFileObject.Projects.Where({ ![string]::IsNullOrWhiteSpace($_.Path) })) { try { $solution.Projects += Invoke-CategorizeCSProj -Project $project } catch { Write-Host "$logLead : could not process project [$($project.Path)], exception was [$($_.Exception.Message)]" } } } } $solution.SolutionIsDatabaseService = ($solution.Projects.Where({ $null -ne $_.FluentMigrator.Version }).where({ $_ }).Count -gt 0) $solution.SolutionIsService = ($solution.Projects.Where({ $_.ServiceInstaller.Legacy -eq $true }).where({ $_ }).Count -gt 0) $solution.SolutionIsService = $solution.SolutionIsService -or $project.AlkamiManifest.ComponentType -eq "Service" return $solution } catch { Write-Host "$logLead : Could not process solution [$solutionPath], exception was [$($_.Exception.Message)]" } } if ($outputPathSpecified) { $categorizeJsonFilename = "categorize.$PID.json" $categorizePath = Join-Path -Path $OutputPath -ChildPath $categorizeJsonFilename Set-Content -Path $categorizePath -Value (ConvertTo-Json -InputObject $solutions -Depth 50) -Force Write-Host "File is located at $categorizePath" } $rows = @() foreach ($solution in $solutions) { foreach ($project in $solution.Projects) { if ($null -eq $project) { continue } if ($project.AlkamiManifest.ComponentType -eq 'Unknown') { $project.AlkamiManifest.ComponentType = $null } $rows += @( $solution.Repo $solution.Project $solution.Name $solution.SemVerValueVersion $solution.SolutionHasNuspec $solution.SolutionNuspecIsChocolatey $solution.SolutionNuspecId $solution.SolutionIsService $solution.SolutionIsDatabaseService $project.Name $null -ne $project.ServiceInstaller.Name $project.Nuspec.IsChocolatey $project.Nuspec.PackageId $project.AlkamiManifest.ComponentType $project.AlkamiManifest.IsLegacyInstaller $project.AlkamiManifest.IsUnkownInstaller $project.SemVer.Version $project.HasTestReferences $project.HasProgramMain $project.AlkamiManifest.HasAlkamiManifest $project.IsLikelyDeprecated -or $solution.IsLikelyDeprecated $project.ChocoFiles.InstallFileSize $project.ChocoFiles.UninstallFileSize @($project.NewRelicAgentApi.Version)[0] $project.FluentMigrator.Version @($project.TopShelf.Version)[0] $project.MicroservicesCore.Version $project.ShouldHaveAManifestedInstaller ($project.AlkamiManifest.HasAlkamiManifest -and $project.ChocoFiles.HasChocoFiles -and -not $project.ChocoFiles.InstallFileNew) $project.TargetFramework $project.TargetFrameworkValue # $project.ServicePointManagerLines ) -join ',' } } if (Test-IsInteractiveSession) { $rows | Set-Clipboard } if ($outputPathSpecified) { $resultsFilename = "results.$PID.csv" $resultsPath = Join-Path -Path $OutputPath -ChildPath $resultsFilename Set-Content -Path $resultsPath -Value $rows } $psStopWatch.Stop() Write-Host "$logLead : Finished in $($psStopWatch.Elapsed) Seconds" return $solutions }