Skip to content

Commit

Permalink
Merge pull request #93 from aldrichtr/fix/project-directories
Browse files Browse the repository at this point in the history
Find the project directories based on file type
  • Loading branch information
aldrichtr authored Jan 3, 2024
2 parents b7db471 + 0ac3e45 commit 61184be
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 164 deletions.
71 changes: 35 additions & 36 deletions source/stitch/private/SourceInfo/Get-TestItemInfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,52 @@ function Get-TestItemInfo {
# The root directory to use for test properties
[Parameter(
)]
[string]$Root,

# Optionally run the testes
[Parameter(
)]
[switch]$RunTest

[string]$Root
)
begin {
Write-Debug "`n$('-' * 80)`n-- Begin $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
process {
foreach ($p in $Path) {
Write-Debug "Processing $p"
#-------------------------------------------------------------------------------
#region File selection
#-------------------------------------------------------------------------------
#region File selection

$fileItem = Get-Item $p -ErrorAction Stop
#TODO: Are there other extensions we should look for ?
if ($fileItem.Extension -notlike '.ps1') {
Write-Verbose "Not adding $($fileItem.Name) because it is not a .ps1 file"
continue
} else {
Write-Debug "$($fileItem.Name) is a test item"
}
#endregion File selection
#-------------------------------------------------------------------------------
$fileItem = Get-Item $p -ErrorAction Stop

#-------------------------------------------------------------------------------
#region Object creation
Write-Debug " Creating item $($fileItem.BaseName) from $($fileItem.FullName)"
$pesterConfig = New-PesterConfiguration
$pesterConfig.Run.PassThru = $true
$pesterConfig.Run.SkipRun = (-not ($RunTest))
try {
$pesterContainer = New-PesterContainer -Path:$p
$pesterConfig.Run.Container = $pesterContainer
$testResult = Invoke-Pester -Configuration $pesterConfig
Write-Debug "Root is $Root"
} catch {
throw "Could not load test item $Path`n$_ "
}
if ($fileItem.Extension -notlike '.ps1') {
Write-Verbose "Not adding $($fileItem.Name) because it is not a .ps1 file"
continue
} else {
Write-Debug "$($fileItem.Name) is a test item"
}
#endregion File selection
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
#region Object creation
$pesterConfig = New-PesterConfiguration
$pesterConfig.Run.Path = $p.FullName
$pesterConfig.Run.SkipRun = $true
$pesterConfig.Run.PassThru = $true
$pesterConfig.Output.Verbosity = 'None' # Quiet
try {
$testResult = Invoke-Pester -Configuration $pesterConfig
Write-Debug "Root is $Root"
} catch {
throw "Could not load test item $Path`n$_ "
}
end {
$testResult
Write-Debug "`n$('-' * 80)`n-- End $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
$testInfo = @{
PSTypeName = 'Stitch.TestItemInfo'
Tests = $testResult.Tests
Path = $p.FullName
}

[PSCustomObject]$testInfo | Write-Output
}
}
end {
Write-Debug "`n$('-' * 80)`n-- End $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}

}
50 changes: 50 additions & 0 deletions source/stitch/public/Path/Find-ModuleManifest.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

function Find-ModuleManifest {
<#
.SYNOPSIS
Find all module manifests in the given directory.
#>
[CmdletBinding()]
param(
# Specifies a path to one or more locations.
[Parameter(
Position = 0,
ValueFromPipeline,
ValueFromPipelineByPropertyName
)]
[Alias('PSPath')]
[string[]]$Path
)
begin {
Write-Debug "`n$('-' * 80)`n-- Begin $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
process {
$possibleManifests = Get-ChildItem @PSBoundParameters -Recurse -Filter "*.psd1"

foreach ($possibleManifest in $possibleManifests) {
try {
$module = $possibleManifest | Import-Psd -Unsafe
} catch {
Write-Debug "$possibleManifest could not be imported"
continue
}
if ($null -ne $module) {
Write-Debug "Checking if $($possibleManifest.Name) is a manifest"
if (
($module.Keys -contains 'ModuleVersion') -and
($module.Keys -contains 'GUID') -and
($module.Keys -contains 'PrivateData')
) {
$possibleManifest | Write-Output
} else {
Write-Debug "- Not a module manifest file"
}
} else {
continue
}
}
}
end {
Write-Debug "`n$('-' * 80)`n-- End $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
}
53 changes: 53 additions & 0 deletions source/stitch/public/Path/Find-SourceDirectory.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

function Find-SourceDirectory {
<#
.SYNOPSIS
Find the directory that contains the project's source files
#>
[CmdletBinding()]
param(
)
begin {
Write-Debug "`n$('-' * 80)`n-- Begin $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
$ignoredDirectories = @('.build', '.stitch')
$maximumNestedLevel = 4
}
process {
$root = Resolve-ProjectRoot
Write-Debug "Looking for source directory in $root"

$manifests = Find-ModuleManifest $root

if ($manifests.Count -gt 0) {
:manifest foreach ($manifest in $manifests) {
$relativePath = [System.IO.Path]::GetRelativePath($root, $manifest.FullName)
$parts = $relativePath -split [regex]::Escape([System.IO.Path]::DirectorySeparatorChar)
Write-Debug "$($manifest.FullName) is $($parts.Count) levels below root"
:parts switch ($parts.Count) {
0 {
throw "The path to $($manifest.FullName) is invalid"
}
default {
if ($parts[0] -notin $ignoredDirectories) {

if ($parts.Count -lt $maximumNestedLevel ) {
Get-Item (Join-Path $root $parts[0] ) | Write-Output
} else {
Write-Debug "$($manifest.Name) is nested below maximum levels: $($parts.Count)"
}
} else {
Write-Debug "$($parts[0]) is ignored"
}
continue manifest
}
}
}
} else {
throw "No manifests found in project '$root'"
}

}
end {
Write-Debug "`n$('-' * 80)`n-- End $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
}
48 changes: 48 additions & 0 deletions source/stitch/public/Path/Find-TestDirectory.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

function Find-TestDirectory {
<#
.SYNOPSIS
Find the directory where tests are stored
#>
[CmdletBinding()]
param(
# Test file pattern
[Parameter(
)]
[string]$TestsPattern = '*.Tests.ps1'
)
begin {
Write-Debug "`n$('-' * 80)`n-- Begin $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
process {
$root = Resolve-ProjectRoot
Write-Debug "Looking for test directory in $root"

$testFiles = Find-TestFile $root -TestsPattern $TestsPattern
$foundDirectories = [System.Collections.ArrayList]::new()

if ($testFiles.Count -gt 0) {
:testfile foreach ($testFile in $testFiles) {
$relativePath = [System.IO.Path]::GetRelativePath($root, $testFile.FullName)
$parts = $relativePath -split [regex]::Escape([System.IO.Path]::DirectorySeparatorChar)
Write-Debug "$($testFile.FullName) is $($parts.Count) levels below root"
:parts switch ($parts.Count) {
0 {
throw "The path to $($testFile.FullName) is invalid"
}
default {
$possibleTestPath = (Join-Path $root $parts[0])
if ($possibleTestPath -notin $foundDirectories) {
[void]$foundDirectories.Add($possibleTestPath)
continue testfile
}
}
}
}
}
}
end {
$foundDirectories | Foreach-Object { Get-Item $_ | Write-Output }
Write-Debug "`n$('-' * 80)`n-- End $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
}
42 changes: 42 additions & 0 deletions source/stitch/public/Path/Find-TestFile.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

function Find-TestFile {
<#
.SYNOPSIS
Find files that contain tests
#>
[CmdletBinding()]
param(
# Specifies a path to one or more locations.
[Parameter(
Position = 0,
ValueFromPipeline,
ValueFromPipelineByPropertyName
)]
[Alias('PSPath')]
[string[]]$Path,

# Test file pattern
[Parameter(
)]
[string]$TestsPattern = '*.Tests.ps1'
)
begin {
Write-Debug "`n$('-' * 80)`n-- Begin $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
process {
$possibleTestFiles = Get-ChildItem -Path $Path -Recurse -File -Filter $TestsPattern

foreach ($possibleTestFile in $possibleTestFiles) {
Write-Debug "Checking $possibleTestFile for Pester tests"
if ($possibleTestFile | Select-String '\s*Describe') {
Write-Debug "- Has the 'Describe' keyword"
$possibleTestFile | Write-Output
} else {
continue
}
}
}
end {
Write-Debug "`n$('-' * 80)`n-- End $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
}
}
51 changes: 11 additions & 40 deletions source/stitch/public/Path/Resolve-ProjectRoot.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,7 @@ function Resolve-ProjectRoot {

# Optionally limit the number of levels to seach
[Parameter()]
[int]$Depth = 8,

# Powershell Data File with defaults
[Parameter(
)]
[string]$Defaults,

# Default Source directory
[Parameter(
)]
[string]$Source = '.\source',

# Default Tests directory
[Parameter(
)]
[string]$Tests = '.\tests',

# Default Staging directory
[Parameter(
)]
[string]$Staging = '.\stage',

# Default Artifact directory
[Parameter(
)]
[string]$Artifact = '.\out',

# Default Docs directory
[Parameter(
)]
[string]$Docs = '.\docs'
[int]$Depth = 8
)
begin {
Write-Debug "`n$('-' * 80)`n-- Begin $($MyInvocation.MyCommand.Name)`n$('-' * 80)"
Expand All @@ -68,34 +38,35 @@ function Resolve-ProjectRoot {
process {
$rootReached = $false
if ($null -ne $BuildRoot) {
Write-Debug "BuildRoot is set, using that"
Write-Debug 'BuildRoot is set, using that'
$BuildRoot | Write-Output
break
}
#TODO: Here we could look for .build.ps1 as the root, or perhaps tie it to a repository by looking for .git/

:location do {
if ($null -ne $currentLocation) {
$null = $PSBoundParameters.Remove('Path')
if (Test-ProjectRoot @PSBoundParameters -Path $currentLocation.FullName) {
Write-Debug "Level $level : Testing directory $($currentLocation.FullName)"
if ($currentLocation.FullName | Test-ProjectRoot) {
$rootReached = $true
Write-Debug "Project Root found : $($currentLocation.FullName)"
Write-Debug "- Project Root found : $($currentLocation.FullName)"
$currentLocation.FullName | Write-Output
break location
} elseif ($level -eq $Depth) {
$rootReached = $true
throw "Could not find project root in $Depth levels"
throw "- Could not find project root in $Depth levels"
break location
} elseif ($currentLocation -like $driveRoot) {
$rootReached = $true
throw "$driveRoot reached looking for project root"
throw "- $driveRoot reached looking for project root"
break location
} else {
Write-Debug " Level: $level - $($currentLocation.Name) is not the project root"
Write-Debug "- $($currentLocation.Name) is not the project root"
}
} else {
Write-Debug "- Reached the root of the drive"
$rootReached = $true
}
Write-Debug "Setting current location to Parent"
Write-Debug 'Setting current location to Parent'
$currentLocation = $currentLocation.Parent
$level++
} until ($rootReached)
Expand Down
Loading

0 comments on commit 61184be

Please sign in to comment.