Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/run-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Run PSScriptAnalyzer Tests
on:
pull_request:
branches:
- develop
- main
workflow_dispatch:

jobs:
psscriptanalyzer:
name: PSScriptAnalyzer
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
checks: write
pull-requests: write
security-events: write
steps:
- uses: actions/checkout@v4
- name: Lint with PSScriptAnalyzer
shell: pwsh
run: |
.\runSecurity.ps1

- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
token: ${{ secrets.GITHUB_TOKEN }}
80 changes: 80 additions & 0 deletions .github/workflows/run-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Run Pester Tests
on:
pull_request:
branches:
- develop
- main
workflow_dispatch:

jobs:
pester-test-linux:
name: Pester test (On Linux)
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: read
issues: read
checks: write
pull-requests: write
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Execute runTests.ps1
shell: pwsh
run: |
.\runTests.ps1
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action/linux@v2
if: (!cancelled())
with:
check_name: Pester test (On Linux) Results
files: testResults.xml

pester-test-windows:
name: Pester test (On Windows)
runs-on: windows-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: read
issues: read
checks: write
pull-requests: write
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Execute runTests.ps1
shell: pwsh
run: |
.\runTests.ps1
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action/windows@v2
if: (!cancelled())
with:
check_name: Pester test (On Windows) Results
files: testResults.xml

pester-test-macos:
name: Pester test (On macOS)
runs-on: macos-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: read
issues: read
checks: write
pull-requests: write
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Execute runTests.ps1
shell: pwsh
run: |
.\runTests.ps1
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action/macos@v2
if: (!cancelled())
with:
check_name: Pester test (On macOS) Results
files: testResults.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ BeforeAll {
. $PSScriptRoot\ConvertFrom-3rdPartyInstall.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\3rdParty\VisualStudio\ConvertFrom-VisualStudioInstall.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\3rdParty\VisualStudioCode\ConvertFrom-VisualStudioCodeInstall.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\Utils\Test-OperatingSystem.ps1
Mock Write-Host { }
Mock Write-Warning { }
Mock ConvertFrom-VisualStudioInstall { $true }
Mock ConvertFrom-VisualStudioCodeInstall { $true }
Mock Test-OperatingSystem { $true }
}

Describe "ConvertFrom-3rdPartyInstall" {
Expand Down
20 changes: 11 additions & 9 deletions DevSetup/Private/3rdParty/ConvertFrom-3rdPartyInstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
[string]$Config
)

# Convert from Visual Studio installations
Write-Host "`nScanning Visual Studio installations..." -ForegroundColor Cyan
if (-not (ConvertFrom-VisualStudioInstall -Config $Config)) {
Write-Warning "Failed to convert Visual Studio installations, but continuing..."
}
if((Test-OperatingSystem -Windows)) {
# Convert from Visual Studio installations
Write-Host "`nScanning Visual Studio installations..." -ForegroundColor Cyan
if (-not (ConvertFrom-VisualStudioInstall -Config $Config)) {
Write-Warning "Failed to convert Visual Studio installations, but continuing..."
}

# Convert from Visual Studio Code installations
Write-Host "`nScanning Visual Studio Code installation..." -ForegroundColor Cyan
if (-not (ConvertFrom-VisualStudioCodeInstall -Config $Config)) {
Write-Warning "Failed to convert Visual Studio Code installation, but continuing..."
# Convert from Visual Studio Code installations
Write-Host "`nScanning Visual Studio Code installation..." -ForegroundColor Cyan
if (-not (ConvertFrom-VisualStudioCodeInstall -Config $Config)) {
Write-Warning "Failed to convert Visual Studio Code installation, but continuing..."
}
}
}
94 changes: 73 additions & 21 deletions DevSetup/Private/Commands/Export-DevSetupEnv.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,50 +1,102 @@
BeforeAll {
. $PSScriptRoot\Export-DevSetupEnv.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\Utils\Get-DevSetupEnvPath.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\Utils\Get-DevSetupLocalEnvPath.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\Utils\Get-DevSetupCommunityEnvPath.ps1
. $PSScriptRoot\..\..\..\DevSetup\Private\Utils\Write-NewConfig.ps1
Mock Get-DevSetupEnvPath { "TestDrive:\DevSetupEnvs" }
Mock Get-DevSetupLocalEnvPath { "TestDrive:\DevSetupEnvs\local"}
Mock Get-DevSetupCommunityEnvPath { "TestDrive:\DevSetupEnvs\community"}
. (Join-Path $PSScriptRoot "Export-DevSetupEnv.ps1")
. (Join-Path $PSScriptRoot "..\..\..\DevSetup\Private\Utils\Get-DevSetupEnvPath.ps1")
. (Join-Path $PSScriptRoot "..\..\..\DevSetup\Private\Utils\Get-DevSetupLocalEnvPath.ps1")
. (Join-Path $PSScriptRoot "..\..\..\DevSetup\Private\Utils\Get-DevSetupCommunityEnvPath.ps1")
. (Join-Path $PSScriptRoot "..\..\..\DevSetup\Private\Utils\Write-NewConfig.ps1")
. (Join-Path $PSScriptRoot "..\..\..\DevSetup\Private\Utils\Write-StatusMessage.ps1")
if ($PSVersionTable.PSVersion.Major -eq 5) {
Mock Get-DevSetupEnvPath { "$TestDrive\DevSetup\DevSetupEnvs" }
Mock Get-DevSetupLocalEnvPath { "$TestDrive\DevSetup\DevSetupEnvs\local" }
Mock Get-DevSetupCommunityEnvPath { "$TestDrive\DevSetup\DevSetupEnvs\community" }
} elseif ($PSVersionTable.PSVersion.Major -ge 6) {
if ($IsWindows) {
Mock Get-DevSetupEnvPath { "$TestDrive\DevSetup\DevSetupEnvs" }
Mock Get-DevSetupLocalEnvPath { "$TestDrive\DevSetup\DevSetupEnvs\local" }
Mock Get-DevSetupCommunityEnvPath { "$TestDrive\DevSetup\DevSetupEnvs\community" }
}
if ($IsLinux) {
Mock Get-DevSetupEnvPath { "$TestDrive/home/testuser/DevSetup/DevSetupEnvs" }
Mock Get-DevSetupLocalEnvPath { "$TestDrive/home/testuser/DevSetup/DevSetupEnvs/local" }
Mock Get-DevSetupCommunityEnvPath { "$TestDrive/home/testuser/DevSetup/DevSetupEnvs/community" }
}
if ($IsMacOS) {
Mock Get-DevSetupEnvPath { "$TestDrive/Users/TestUser/DevSetup/DevSetupEnvs" }
Mock Get-DevSetupLocalEnvPath { "$TestDrive/Users/TestUser/DevSetup/DevSetupEnvs/local" }
Mock Get-DevSetupCommunityEnvPath { "$TestDrive/Users/TestUser/DevSetup/DevSetupEnvs/community" }
}
}
Mock Write-NewConfig { param($OutFile) $OutFile }
Mock Write-Host { }
Mock Write-Error { }
Mock Write-StatusMessage { }
}

Describe "Export-DevSetupEnv" {

Context "When called with a valid name" {
It "Should create the config file and return its path" {
$result = Export-DevSetupEnv -Name "MyEnv"
$result | Should -Be "TestDrive:\DevSetupEnvs\local\MyEnv.devsetup"
Assert-MockCalled Write-NewConfig -Exactly 1 -Scope It -ParameterFilter { $OutFile -eq "TestDrive:\DevSetupEnvs\local\MyEnv.devsetup" }
Assert-MockCalled Write-Host -Scope It -ParameterFilter { $Object -match "exported to" -and $ForegroundColor -eq "Green" }
if ($PSVersionTable.PSVersion.Major -eq 5 -or ($PSVersionTable.PSVersion.Major -ge 6 -and $IsWindows)) {
$expectedPath = "$TestDrive\DevSetup\DevSetupEnvs\local\MyEnv.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsLinux) {
$expectedPath = "$TestDrive/home/testuser/DevSetup/DevSetupEnvs/local/MyEnv.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsMacOS) {
$expectedPath = "$TestDrive/Users/TestUser/DevSetup/DevSetupEnvs/local/MyEnv.devsetup"
}
$result | Should -Be $expectedPath
Assert-MockCalled Write-NewConfig -Exactly 1 -Scope It -ParameterFilter { $OutFile -eq $expectedPath }
Assert-MockCalled Write-StatusMessage -Scope It -ParameterFilter { $Message -match "exported to" -and $ForegroundColor -eq "Green" }
}
}

Context "When called with a valid path" {
It "Should create the config file and return its path" {
$result = Export-DevSetupEnv -Path "TestDrive:\MyCustomPath\MyEnv.devsetup"
$result | Should -Be "TestDrive:\MyCustomPath\MyEnv.devsetup"
Assert-MockCalled Write-NewConfig -Exactly 1 -Scope It -ParameterFilter { $OutFile -eq "TestDrive:\MyCustomPath\MyEnv.devsetup" }
Assert-MockCalled Write-Host -Scope It -ParameterFilter { $Object -match "exported to" -and $ForegroundColor -eq "Green" }
if ($PSVersionTable.PSVersion.Major -eq 5 -or ($PSVersionTable.PSVersion.Major -ge 6 -and $IsWindows)) {
$result = Export-DevSetupEnv -Path "$TestDrive\MyCustomPath\MyEnv.devsetup"
$expectedPath = "$TestDrive\MyCustomPath\MyEnv.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsLinux) {
$result = Export-DevSetupEnv -Path "$TestDrive/MyCustomPath/MyEnv.devsetup"
$expectedPath = "$TestDrive/MyCustomPath/MyEnv.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsMacOS) {
$result = Export-DevSetupEnv -Path "$TestDrive/MyCustomPath/MyEnv.devsetup"
$expectedPath = "$TestDrive/MyCustomPath/MyEnv.devsetup"
}
$result | Should -Be $expectedPath
Assert-MockCalled Write-NewConfig -Exactly 1 -Scope It -ParameterFilter { $OutFile -eq $expectedPath }
Assert-MockCalled Write-StatusMessage -Scope It -ParameterFilter { $Message -match "exported to" -and $ForegroundColor -eq "Green" }
}
}

Context "When called with a name that needs sanitization" {
It "Should sanitize the name and warn" {
$result = Export-DevSetupEnv -Name "Data Science Environment!"
$result | Should -Be "TestDrive:\DevSetupEnvs\local\DataScienceEnvironment.devsetup"
Assert-MockCalled Write-Host -Scope It -ParameterFilter { $Object -match "sanitized" -and $ForegroundColor -eq "Yellow" }
if ($PSVersionTable.PSVersion.Major -eq 5 -or ($PSVersionTable.PSVersion.Major -ge 6 -and $IsWindows)) {
$expectedPath = "$TestDrive\DevSetup\DevSetupEnvs\local\DataScienceEnvironment.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsLinux) {
$expectedPath = "$TestDrive/home/testuser/DevSetup/DevSetupEnvs/local/DataScienceEnvironment.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsMacOS) {
$expectedPath = "$TestDrive/Users/TestUser/DevSetup/DevSetupEnvs/local/DataScienceEnvironment.devsetup"
}
$result | Should -Be $expectedPath
Assert-MockCalled Write-StatusMessage -Scope It -ParameterFilter { $Message -match "sanitized" -and $ForegroundColor -eq "Yellow" }
}
}

Context "When called with a path that needs sanitization" {
It "Should sanitize the path and warn" {
$result = Export-DevSetupEnv -Path "TestDrive:\MyCustomPath\MyEnv!.devsetup"
$result | Should -Be "TestDrive:\MyCustomPath\MyEnv.devsetup"
Assert-MockCalled Write-Host -Scope It -ParameterFilter { $Object -match "sanitized" -and $ForegroundColor -eq "Yellow" }
if ($PSVersionTable.PSVersion.Major -eq 5 -or ($PSVersionTable.PSVersion.Major -ge 6 -and $IsWindows)) {
$result = Export-DevSetupEnv -Path "$TestDrive\MyCustomPath\MyEnv!.devsetup"
$expectedPath = "$TestDrive\MyCustomPath\MyEnv.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsLinux) {
$result = Export-DevSetupEnv -Path "$TestDrive/MyCustomPath/MyEnv!.devsetup"
$expectedPath = "$TestDrive/MyCustomPath/MyEnv.devsetup"
} elseif ($PSVersionTable.PSVersion.Major -ge 6 -and $IsMacOS) {
$result = Export-DevSetupEnv -Path "$TestDrive/MyCustomPath/MyEnv!.devsetup"
$expectedPath = "$TestDrive/MyCustomPath/MyEnv.devsetup"
}
$result | Should -Be $expectedPath
Assert-MockCalled Write-StatusMessage -Scope It -ParameterFilter { $Message -match "sanitized" -and $ForegroundColor -eq "Yellow" }
}
}

Expand All @@ -53,7 +105,7 @@ Describe "Export-DevSetupEnv" {
Mock Write-NewConfig { param($OutFile) $null }
$result = Export-DevSetupEnv -Name "FailEnv"
$result | Should -Be $null
Assert-MockCalled Write-Error -Exactly 1 -Scope It -ParameterFilter { $Message -match "Failed to create configuration file" }
Assert-MockCalled Write-StatusMessage -Exactly 1 -Scope It -ParameterFilter { $Message -match "Failed to create configuration file" -and $Verbosity -eq "Error" }
}
}
}
28 changes: 15 additions & 13 deletions DevSetup/Private/Commands/Export-DevSetupEnv.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

.EXAMPLE
Export-DevSetupEnv -Name "MyCurrentSetup"

Exports the current system state to a configuration file named "MyCurrentSetup.yaml".

.EXAMPLE
Expand All @@ -31,12 +31,12 @@
} else {
Write-Host "Export failed"
}

Demonstrates capturing the return value to verify export success.

.EXAMPLE
Export-DevSetupEnv -Name "Data Science Environment!"

The exclamation mark will be removed, resulting in "DataScienceEnvironment.yaml".
A warning message will indicate the sanitization that occurred.

Expand Down Expand Up @@ -65,7 +65,9 @@ Function Export-DevSetupEnv {
[Parameter(Mandatory=$true, ParameterSetName="Export")]
[string]$Name,
[Parameter(Mandatory=$true, ParameterSetName="ExportPath")]
[string]$Path
[string]$Path,
[Parameter(Mandatory=$false)]
[switch]$DryRun
)
$OutFile = $null
if($PSBoundParameters.ContainsKey('Name')) {
Expand All @@ -78,7 +80,7 @@ Function Export-DevSetupEnv {
}
$SanitizedEnvName = $Name -replace '[^a-zA-Z0-9\-\.]', ''
if ($SanitizedEnvName -ne $Name) {
Write-Host "EnvName sanitized from '$Name' to '$SanitizedEnvName' (removed non-alphanumeric characters)" -ForegroundColor Yellow
Write-StatusMessage "EnvName sanitized from '$Name' to '$SanitizedEnvName' (removed non-alphanumeric characters)" -ForegroundColor Yellow
}

$BasePath = Join-Path -Path (Get-DevSetupEnvPath) -ChildPath $Provider
Expand All @@ -96,25 +98,25 @@ Function Export-DevSetupEnv {
if($Name -notlike "*.devsetup") {
$Name = "$Name.devsetup"
}

$SanitizedEnvName = $Name -replace '[^a-zA-Z0-9\-\.]', ''

if ($SanitizedEnvName -ne $Name) {
Write-Host "EnvName sanitized from '$Name' to '$SanitizedEnvName' (removed non-alphanumeric characters)" -ForegroundColor Yellow
Write-StatusMessage "EnvName sanitized from '$Name' to '$SanitizedEnvName' (removed non-alphanumeric characters)" -ForegroundColor Yellow
}
$OutFile = Join-Path -Path $BasePath -ChildPath $SanitizedEnvName
}

if(-not $OutFile) {
Write-Error "Failed to determine output file path"
Write-StatusMessage "Failed to determine output file path" -Verbosity Error
return $null
}

$config = Write-NewConfig -OutFile $OutFile
$config = Write-NewConfig -OutFile $OutFile -DryRun:$DryRun
if (-not $config) {
Write-Error "Failed to create configuration file"
Write-StatusMessage "Failed to create configuration file" -Verbosity Error
return $null
}
Write-Host "Configuration file exported to: $OutFile" -ForegroundColor Green
return $OutFile
}
Write-StatusMessage "Configuration file exported to: $OutFile" -ForegroundColor Green
return $OutFile
}
Loading
Loading