Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
34 changes: 34 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,40 @@ jobs:
shell: pwsh
run: Invoke-Pester tests/powershell/ -Output Detailed

powershell51-tests:
name: PowerShell 5.1 tests (Pester)
needs: detect-changes
# Advisory only: not registered in the ruleset's required-check set
# yet, so a failure here does not block merges (#166). Promotion to
# required is a later decision once this leg proves stable.
# always() overrides the default "skip if a need failed" behavior
# so a failed/cancelled detect-changes fails open to running the
# real job, rather than silently skipping it (which would satisfy
# the required-status-check gate without ever having run).
if: |
always() &&
(needs.detect-changes.result != 'success' || needs.detect-changes.outputs.requires_full_ci == 'true')
runs-on: windows-latest
steps:
- uses: actions/checkout@v7
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Confirm Windows PowerShell 5.1
shell: powershell
run: |
$PSVersionTable.PSVersion
if ($PSVersionTable.PSVersion.Major -ne 5) {
throw "Expected Windows PowerShell 5.1 (major version 5), got $($PSVersionTable.PSVersion)"
}
- name: Install Pester if needed
shell: powershell
run: |
if (-not (Get-Module -ListAvailable Pester |
Where-Object { $_.Version -ge [version]'5.0' })) {
Install-Module Pester -MinimumVersion 5.0 -Force -SkipPublisherCheck -Scope CurrentUser
}
Comment thread
kurone-kito marked this conversation as resolved.
Comment thread
kurone-kito marked this conversation as resolved.
- name: Run Pester tests
shell: powershell
run: Invoke-Pester tests/powershell/ -Output Detailed
Comment thread
kurone-kito marked this conversation as resolved.
Outdated

lua-syntax:
name: Lua syntax check
needs: detect-changes
Expand Down
2 changes: 1 addition & 1 deletion home/dot_local/bin/executable_secret-deploy-state.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function Invoke-Record {

$tmp = "$statePath.tmp.$([System.Guid]::NewGuid().ToString('N'))"
try {
Set-Content -LiteralPath $tmp -Value $merged -Encoding utf8NoBOM -NoNewline
[System.IO.File]::WriteAllText($tmp, $merged, [System.Text.UTF8Encoding]::new($false))
Set-RestrictedAcl -Path $tmp
Move-Item -LiteralPath $tmp -Destination $statePath -Force
} catch {
Expand Down
2 changes: 1 addition & 1 deletion tests/powershell/02-cargo.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ BeforeAll {
) '02-cargo.ps1'
}

Describe '02-cargo (Unix pwsh)' -Skip:($IsWindows -eq $true) {
Describe '02-cargo (Unix pwsh)' -Skip:($IsWindows -ne $false) {

BeforeEach {
$script:OriginalHome = $HOME
Expand Down
8 changes: 4 additions & 4 deletions tests/powershell/25-deploy-secret-files.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BeforeAll {
$script:Fixture = Join-Path $PSScriptRoot 'fixtures' '25-deploy-secret-files.ps1'
$script:Template = Join-Path $PSScriptRoot '..' '..' 'home' `
$script:Fixture = Join-Path (Join-Path $PSScriptRoot 'fixtures') '25-deploy-secret-files.ps1'
$script:Template = Join-Path (Join-Path (Join-Path (Join-Path $PSScriptRoot '..') '..') 'home') `
'run_onchange_after_25-deploy-secret-files.ps1.tmpl'
$script:TemplateContent = Get-Content -Raw $script:Template
}
Expand Down Expand Up @@ -48,15 +48,15 @@

It 'deploys .aws/credentials with correct content' {
& $script:Fixture
$path = Join-Path $env:DOTFILES_TEST_HOME '.aws' 'credentials'
$path = Join-Path (Join-Path $env:DOTFILES_TEST_HOME '.aws') 'credentials'
$path | Should -Exist
$content = Get-Content -Raw $path
$content | Should -Match 'aws_access_key_id = AKIAEXAMPLE'

Check warning on line 54 in tests/powershell/25-deploy-secret-files.Tests.ps1

View workflow job for this annotation

GitHub Actions / lint

Unknown word (AKIAEXAMPLE)

Check warning on line 54 in tests/powershell/25-deploy-secret-files.Tests.ps1

View workflow job for this annotation

GitHub Actions / lint

Unknown word (AKIAEXAMPLE)
}

It 'deploys .docker/config.json with correct content' {
& $script:Fixture
$path = Join-Path $env:DOTFILES_TEST_HOME '.docker' 'config.json'
$path = Join-Path (Join-Path $env:DOTFILES_TEST_HOME '.docker') 'config.json'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
$path | Should -Exist
$content = Get-Content -Raw $path
$content | Should -Match '"auths"'
Expand Down
6 changes: 5 additions & 1 deletion tests/powershell/fixtures/generate-authorized-keys.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ $homeDir = if ($env:AUTHORIZED_KEYS_HOME) {

$sshDir = Join-Path $homeDir '.ssh'
$authorized = Join-Path $sshDir 'authorized_keys'
# [System.IO.File] does not understand PS provider paths (e.g. TestDrive:\...),
# so resolve to a real filesystem path before using it with .NET I/O below.
$authorized = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($authorized)
$beginMarker = '# >>> chezmoi managed keys >>>'
$endMarker = '# <<< chezmoi managed keys <<<'

Expand Down Expand Up @@ -72,7 +75,8 @@ if ($hasValidBlock) {
$outLines += $endMarker
}

($outLines -join "`n") + "`n" | Set-Content -Path $authorized -Encoding utf8NoBOM -NoNewline
$authorizedContent = ($outLines -join "`n") + "`n"
[System.IO.File]::WriteAllText($authorized, $authorizedContent, [System.Text.UTF8Encoding]::new($false))

icacls $authorized /inheritance:r `
/grant:r "${env:USERNAME}:(F)" `
Expand Down
16 changes: 12 additions & 4 deletions tests/powershell/fixtures/generate-git-profiles.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,22 @@ else {
}
New-Item -ItemType Directory -Path $profilesDir -Force | Out-Null

# [System.IO.File] does not understand PS provider paths (e.g. TestDrive:\...),
# so resolve to a real filesystem path before using it with .NET I/O below.
$profilesDir = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($profilesDir)

$utf8NoBom = [System.Text.UTF8Encoding]::new($false)

$profilePath = Join-Path $profilesDir 'personal'
@'
$personalProfile = @'
[user]
email = "personal@example.com"
name = "Personal User"
'@ | Set-Content -Path $profilePath -Encoding utf8NoBOM
'@
[System.IO.File]::WriteAllText($profilePath, $personalProfile, $utf8NoBom)

$profilePath = Join-Path $profilesDir 'work'
@'
$workProfile = @'
[user]
email = "work@example.com"
name = "Work User"
Expand All @@ -43,7 +50,8 @@ $profilePath = Join-Path $profilesDir 'work'
[tag]
forceSignAnnotated = true
gpgsign = true
'@ | Set-Content -Path $profilePath -Encoding utf8NoBOM
'@
[System.IO.File]::WriteAllText($profilePath, $workProfile, $utf8NoBom)

$validProfiles = @(
'personal'
Expand Down
59 changes: 37 additions & 22 deletions tests/powershell/generate-authorized-keys.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ BeforeAll {
$script:Fixture = Join-Path $PSScriptRoot 'fixtures/generate-authorized-keys.ps1'
$script:BeginMarker = '# >>> chezmoi managed keys >>>'
$script:EndMarker = '# <<< chezmoi managed keys <<<'

# PS5.1 does not recognize the utf8NoBOM encoding literal accepted by
# Set-Content on PS6+, so write test fixtures via .NET directly.
function script:Set-TestFileUtf8NoBom {
param(
[Parameter(Mandatory, ValueFromPipeline)][AllowEmptyString()][string[]]$Value,
[Parameter(Mandatory)][string]$Path
)
begin { $lines = @() }
process { $lines += $Value }
end {
$content = ($lines -join "`n") + "`n"
[System.IO.File]::WriteAllText($Path, $content, [System.Text.UTF8Encoding]::new($false))
}
}
}

Describe 'generate-authorized-keys' {
Expand Down Expand Up @@ -41,9 +56,9 @@ Describe 'generate-authorized-keys' {

It 'creates a managed block from the available public keys' {
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')
'ssh-ed25519 BBBB secondary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'secondary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'secondary.pub')

& $script:Fixture

Expand All @@ -58,7 +73,7 @@ Describe 'generate-authorized-keys' {

It 'skips missing public keys and keeps the remaining file content' {
'ssh-ed25519 BBBB secondary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'secondary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'secondary.pub')

& $script:Fixture

Expand All @@ -77,9 +92,9 @@ Describe 'generate-authorized-keys' {
}

It 'preserves a foreign line that predates the managed block' {
'ssh-rsa FOREIGN from-cloud-provider' | Set-Content -Path $script:Authorized -Encoding utf8NoBOM
'ssh-rsa FOREIGN from-cloud-provider' | Set-TestFileUtf8NoBom -Path $script:Authorized
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

& $script:Fixture

Expand All @@ -90,9 +105,9 @@ Describe 'generate-authorized-keys' {

It 'does not duplicate a legacy key already present in an unmarked file' {
@('ssh-ed25519 AAAA primary@test', 'ssh-rsa FOREIGN other-machine') |
Set-Content -Path $script:Authorized -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path $script:Authorized
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

& $script:Fixture

Expand All @@ -103,15 +118,15 @@ Describe 'generate-authorized-keys' {

It 'preserves foreign lines on both sides of an existing managed block' {
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')
& $script:Fixture

$existing = Get-Content $script:Authorized
@('ssh-rsa FOREIGN-BEFORE ssh-copy-id') + $existing + @('ssh-rsa FOREIGN-AFTER manually-added') |
Set-Content -Path $script:Authorized -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path $script:Authorized

'ssh-ed25519 BBBB secondary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'secondary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'secondary.pub')
& $script:Fixture

$content = Get-Content $script:Authorized
Expand All @@ -123,9 +138,9 @@ Describe 'generate-authorized-keys' {

It 'removes a key from the managed block when it disappears from config' {
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')
'ssh-ed25519 BBBB secondary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'secondary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'secondary.pub')
& $script:Fixture

Remove-Item (Join-Path $script:SshDir.FullName 'primary.pub')
Expand All @@ -138,7 +153,7 @@ Describe 'generate-authorized-keys' {

It 'produces no diff when re-run with unchanged keys' {
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')
& $script:Fixture
$before = Get-Content $script:Authorized -Raw

Expand All @@ -150,9 +165,9 @@ Describe 'generate-authorized-keys' {

It 'falls back to append instead of dropping content when the end marker is missing' {
@('ssh-rsa FOREIGN untouched', $script:BeginMarker, 'ssh-rsa STALE stale-key') |
Set-Content -Path $script:Authorized -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path $script:Authorized
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

$warnings = & $script:Fixture 3>&1 | Where-Object { $_ -is [System.Management.Automation.WarningRecord] }

Expand All @@ -168,9 +183,9 @@ Describe 'generate-authorized-keys' {
$script:BeginMarker, 'ssh-rsa OLD1 old', $script:EndMarker,
'ssh-rsa FOREIGN between-blocks',
$script:BeginMarker, 'ssh-rsa OLD2 old', $script:EndMarker
) | Set-Content -Path $script:Authorized -Encoding utf8NoBOM
) | Set-TestFileUtf8NoBom -Path $script:Authorized
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

$warnings = & $script:Fixture 3>&1 | Where-Object { $_ -is [System.Management.Automation.WarningRecord] }

Expand All @@ -182,7 +197,7 @@ Describe 'generate-authorized-keys' {

It 'does not warn about malformed markers on a normal run' {
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

$warnings = & $script:Fixture 3>&1 | Where-Object { $_ -is [System.Management.Automation.WarningRecord] }

Expand All @@ -191,9 +206,9 @@ Describe 'generate-authorized-keys' {

It 'converges on the same block count after repeated runs when the end marker was missing' {
@('ssh-rsa FOREIGN untouched', $script:BeginMarker, 'ssh-rsa STALE stale-key') |
Set-Content -Path $script:Authorized -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path $script:Authorized
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

& $script:Fixture | Out-Null
$countAfterRun1 = (Get-Content $script:Authorized | Where-Object { $_ -eq $script:BeginMarker }).Count
Expand All @@ -220,9 +235,9 @@ Describe 'generate-authorized-keys' {
$script:BeginMarker, 'ssh-rsa OLD1 old', $script:EndMarker,
'ssh-rsa FOREIGN between-blocks',
$script:BeginMarker, 'ssh-rsa OLD2 old', $script:EndMarker
) | Set-Content -Path $script:Authorized -Encoding utf8NoBOM
) | Set-TestFileUtf8NoBom -Path $script:Authorized
'ssh-ed25519 AAAA primary@test' |
Set-Content -Path (Join-Path $script:SshDir.FullName 'primary.pub') -Encoding utf8NoBOM
Set-TestFileUtf8NoBom -Path (Join-Path $script:SshDir.FullName 'primary.pub')

& $script:Fixture | Out-Null
& $script:Fixture | Out-Null
Expand Down
2 changes: 1 addition & 1 deletion tests/powershell/secret-deploy-state.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Tests for the secret-deploy-state pwsh helper.

BeforeAll {
$script:ScriptPath = Join-Path $PSScriptRoot '..' '..' 'home' 'dot_local' 'bin' 'executable_secret-deploy-state.ps1'
$script:ScriptPath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $PSScriptRoot '..') '..') 'home') 'dot_local') 'bin') 'executable_secret-deploy-state.ps1'

# A real-world path can contain an apostrophe (e.g. a Windows
# username like O'Connor), which would otherwise break the
Expand Down
12 changes: 6 additions & 6 deletions tests/powershell/secret-status.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# manifest, which works on any host.

BeforeAll {
$script:ScriptPath = Join-Path $PSScriptRoot '..' '..' 'home' 'dot_local' 'bin' 'executable_secret-status.ps1'
$script:ScriptPath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $PSScriptRoot '..') '..') 'home') 'dot_local') 'bin') 'executable_secret-status.ps1'
$script:TmpRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("secret-status-" + [Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Force -Path $TmpRoot | Out-Null
$script:HomeDir = Join-Path $TmpRoot 'home'
Expand Down Expand Up @@ -92,7 +92,7 @@ Describe 'secret-status.ps1' {
@($obj.rows | Where-Object status -eq 'MISSING').Count | Should -BeGreaterThan 0
}

It 'secret file present with correct mode is OK' -Skip:($IsWindows -eq $true) {
It 'secret file present with correct mode is OK' -Skip:($IsWindows -ne $false) {
$f = Join-Path $HomeDir 'secret.txt'
Set-Content -LiteralPath $f -Value 'secret'
& chmod 600 $f
Expand All @@ -107,7 +107,7 @@ Describe 'secret-status.ps1' {
$r.Output | Should -Match 'OK'
}

It 'secret file with wrong mode is WARN' -Skip:($IsWindows -eq $true) {
It 'secret file with wrong mode is WARN' -Skip:($IsWindows -ne $false) {
$f = Join-Path $HomeDir 'secret-bad.txt'
Set-Content -LiteralPath $f -Value 'secret'
& chmod 644 $f
Expand Down Expand Up @@ -156,7 +156,7 @@ Describe 'secret-status.ps1' {
$r.Output | Should -Match 'ghq root unresolved'
}

It 'env file warns when filename not in .gitignore' -Skip:($IsWindows -eq $true) {
It 'env file warns when filename not in .gitignore' -Skip:($IsWindows -ne $false) {
$repo = Join-Path $HomeDir 'repo-warn'
New-Item -ItemType Directory -Force -Path (Join-Path $repo '.git') | Out-Null
$envPath = Join-Path $repo '.env'
Expand All @@ -175,7 +175,7 @@ Describe 'secret-status.ps1' {
$r.Output | Should -Match 'not in .gitignore'
}

It 'env file OK when gitignore lists filename' -Skip:($IsWindows -eq $true) {
It 'env file OK when gitignore lists filename' -Skip:($IsWindows -ne $false) {
$repo = Join-Path $HomeDir 'repo-ok'
New-Item -ItemType Directory -Force -Path (Join-Path $repo '.git') | Out-Null
$envPath = Join-Path $repo '.env'
Expand Down Expand Up @@ -210,7 +210,7 @@ Describe 'secret-status.ps1' {
}
}

Describe 'secret-status.ps1 DRIFT detection' -Skip:($IsWindows -eq $true) {
Describe 'secret-status.ps1 DRIFT detection' -Skip:($IsWindows -ne $false) {
BeforeAll {
$script:StatePath = Join-Path $HomeDir '.config/chezmoi/secret-deploy-state.json'
$script:OrigHome = $env:HOME
Expand Down
8 changes: 4 additions & 4 deletions tests/powershell/signing-resolve.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ BeforeDiscovery {
}

BeforeAll {
$script:RepoHome = Join-Path $PSScriptRoot '..' '..' 'home' | Resolve-Path
$script:ConfigTmpl = Join-Path $script:RepoHome 'dot_config' 'git' 'config.tmpl'
$script:RepoHome = Join-Path (Join-Path (Join-Path $PSScriptRoot '..') '..') 'home' | Resolve-Path
$script:ConfigTmpl = Join-Path (Join-Path $script:RepoHome 'dot_config') (Join-Path 'git' 'config.tmpl')
$script:ProfilesTmpl = Join-Path $script:RepoHome 'run_onchange_after_generate-git-profiles.ps1.tmpl'

function Invoke-Render {
Expand All @@ -19,7 +19,7 @@ BeforeAll {
$cfg = Join-Path ([IO.Path]::GetTempPath()) ("signing-{0}.json" -f [guid]::NewGuid())
$dest = Join-Path ([IO.Path]::GetTempPath()) ("signing-{0}-dest" -f [guid]::NewGuid())
New-Item -ItemType Directory -Path $dest -Force | Out-Null
Set-Content -Path $cfg -Value $ConfigJson -Encoding utf8NoBOM
[System.IO.File]::WriteAllText($cfg, $ConfigJson, [System.Text.UTF8Encoding]::new($false))
try {
$output = & chezmoi execute-template --file $TemplatePath `
--config $cfg --config-format json `
Expand Down Expand Up @@ -135,7 +135,7 @@ Describe 'signing-resolve' -Skip:(-not $script:HasChezmoi) {
throw 'Could not locate the profile here-string in rendered output'
}
$renderedProfile = Join-Path ([IO.Path]::GetTempPath()) ("signing-{0}-profile" -f [guid]::NewGuid())
Set-Content -Path $renderedProfile -Value $Matches[1] -Encoding utf8NoBOM
[System.IO.File]::WriteAllText($renderedProfile, $Matches[1], [System.Text.UTF8Encoding]::new($false))
Comment thread
kurone-kito marked this conversation as resolved.
Outdated

$scratch = Join-Path ([IO.Path]::GetTempPath()) ("signing-{0}-scratch" -f [guid]::NewGuid())
New-Item -ItemType Directory -Path $scratch -Force | Out-Null
Expand Down
Loading