From 83fb0eb028ee90d45a9e4e8881d348c90a00a92d Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Sat, 29 Aug 2026 20:39:29 +0200 Subject: [PATCH] chore(deps): centralize Standards updates --- .github/dependabot.yml | 2 + .github/workflows/ci.yml | 2 +- .github/workflows/continuous_release.yml | 2 +- .github/workflows/copilot-setup-steps.yml | 2 +- .github/workflows/integration_tests.yml | 4 +- .github/workflows/release_intent.yml | 2 +- JiraPS.build.ps1 | 6 +- Tests/Help.Tests.ps1 | 8 +- ...StandardsVersionConsistency.Unit.Tests.ps1 | 8 +- .../Update-DependenciesScript.Unit.Tests.ps1 | 491 ------------------ Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 | 1 + Tools/build.requirements.psd1 | 6 +- Tools/update.dependencies.ps1 | 100 ---- 13 files changed, 23 insertions(+), 611 deletions(-) delete mode 100644 Tests/Tools/Update-DependenciesScript.Unit.Tests.ps1 delete mode 100644 Tools/update.dependencies.ps1 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 03db77c56..c9481881f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,6 +6,8 @@ updates: directory: "/" schedule: interval: "weekly" + ignore: + - dependency-name: "AtlassianPS/AtlassianPS.Standards*" commit-message: prefix: "⬆️ " labels: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2004d93c3..7090e50ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ permissions: jobs: module-ci: - uses: AtlassianPS/AtlassianPS.Standards/.github/workflows/module_ci.yml@72a8008dcd2f840b373d22380a50bc5f1870211f # v0.3.3 + uses: AtlassianPS/AtlassianPS.Standards/.github/workflows/module_ci.yml@bd959dc3de7ee8426f89c31a62e0282e7140bd51 # v0.3.4 with: build-profile: jiraps smoke-profile: jira diff --git a/.github/workflows/continuous_release.yml b/.github/workflows/continuous_release.yml index b6f11465f..583724984 100644 --- a/.github/workflows/continuous_release.yml +++ b/.github/workflows/continuous_release.yml @@ -23,7 +23,7 @@ permissions: jobs: release: if: github.event_name == 'workflow_dispatch' || vars.JIRAPS_CD_ENABLED == 'true' - uses: AtlassianPS/AtlassianPS.Standards/.github/workflows/module_release.yml@72a8008dcd2f840b373d22380a50bc5f1870211f # v0.3.3 + uses: AtlassianPS/AtlassianPS.Standards/.github/workflows/module_release.yml@bd959dc3de7ee8426f89c31a62e0282e7140bd51 # v0.3.4 with: module-name: JiraPS release-impact: ${{ inputs.release_impact }} diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index ab428e1d0..02d804a71 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -13,4 +13,4 @@ jobs: steps: - uses: actions/checkout@v7 - - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/setup-powershell@72a8008dcd2f840b373d22380a50bc5f1870211f # v0.3.3 + - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/setup-powershell@bd959dc3de7ee8426f89c31a62e0282e7140bd51 # v0.3.4 diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 67deb89ae..6695d5cbf 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -56,7 +56,7 @@ jobs: JIRA_TEST_VERSION: ${{ vars.JIRA_TEST_VERSION }} steps: - uses: actions/checkout@v7 - - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/setup-powershell@72a8008dcd2f840b373d22380a50bc5f1870211f # v0.3.3 + - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/setup-powershell@bd959dc3de7ee8426f89c31a62e0282e7140bd51 # v0.3.4 - run: | Invoke-Build -Task TestIntegration -ThrottleLimit 6 -PesterVerbosity Detailed @@ -117,7 +117,7 @@ jobs: run: docker compose up -d shell: bash - - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/setup-powershell@72a8008dcd2f840b373d22380a50bc5f1870211f # v0.3.3 + - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/setup-powershell@bd959dc3de7ee8426f89c31a62e0282e7140bd51 # v0.3.4 - name: Wait for Jira to become reachable and provision the normal user run: pwsh ./Tools/Wait-JiraServer.ps1 -TimeoutSeconds 1200 diff --git a/.github/workflows/release_intent.yml b/.github/workflows/release_intent.yml index 9d96d9bc0..1c23e47d4 100644 --- a/.github/workflows/release_intent.yml +++ b/.github/workflows/release_intent.yml @@ -13,4 +13,4 @@ jobs: name: Release Intent runs-on: ubuntu-latest steps: - - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/validate-release-intent@72a8008dcd2f840b373d22380a50bc5f1870211f # v0.3.3 + - uses: AtlassianPS/AtlassianPS.Standards/.github/actions/validate-release-intent@bd959dc3de7ee8426f89c31a62e0282e7140bd51 # v0.3.4 diff --git a/JiraPS.build.ps1 b/JiraPS.build.ps1 index 3ffe06182..5c796f408 100644 --- a/JiraPS.build.ps1 +++ b/JiraPS.build.ps1 @@ -106,6 +106,8 @@ Task Clean { } Task Build Clean, { + Import-JiraPSStandard + if (-not (Test-Path "$env:BHBuildOutput/$env:BHProjectName")) { $null = New-Item -Path "$env:BHBuildOutput", "$env:BHBuildOutput/$env:BHProjectName" -ItemType Directory } @@ -220,8 +222,8 @@ Task Test { -Tag $Tag ` -ExcludeTag $ExcludeTag ` -DefaultExcludeTag @('Integration') ` - -MinimumPesterVersion ([Version]'5.7.0') ` - -MaximumPesterVersion ([Version]'5.7.999') ` + -MinimumPesterVersion ([Version]'5.9.0') ` + -MaximumPesterVersion ([Version]'5.9.999') ` -ResultOutputPath (Join-Path $env:BHProjectPath "Test-$resultName.xml") } } diff --git a/Tests/Help.Tests.ps1 b/Tests/Help.Tests.ps1 index ac51d9215..f7066f3bf 100644 --- a/Tests/Help.Tests.ps1 +++ b/Tests/Help.Tests.ps1 @@ -238,8 +238,12 @@ Describe "Help tests" -Tag "Documentation", "Build" { } } } - # To avoid calling Trim method on a null object. - $helpType = if ($parameterHelp.parameterValue) { $parameterHelp.parameterValue.Trim() } + $helpType = if ($parameterHelp.parameterValue) { + $parameterHelp.parameterValue.Trim() + } + elseif ($parameterHelp.type.name) { + $parameterHelp.type.name.Trim() + } if ($helpType -eq "PSCustomObject") { $helpType = "PSObject" } # PlatyPS 1.0 uses "Switch" instead of "SwitchParameter" if ($helpType -eq "Switch") { $helpType = "SwitchParameter" } diff --git a/Tests/Tools/StandardsVersionConsistency.Unit.Tests.ps1 b/Tests/Tools/StandardsVersionConsistency.Unit.Tests.ps1 index 9d5c9a3c4..9b10db4cd 100644 --- a/Tests/Tools/StandardsVersionConsistency.Unit.Tests.ps1 +++ b/Tests/Tools/StandardsVersionConsistency.Unit.Tests.ps1 @@ -31,7 +31,7 @@ Describe 'AtlassianPS.Standards version consistency' -Tag Unit { Where-Object { $_.ModuleName -eq 'AtlassianPS.Standards' } | Select-Object -First 1 $standardsVersion = [string] $standardsRequirement.RequiredVersion - $expectedStandardsSha = '72a8008dcd2f840b373d22380a50bc5f1870211f' + $expectedStandardsSha = 'bd959dc3de7ee8426f89c31a62e0282e7140bd51' $workflowPaths = Get-ChildItem -Path (Join-Path -Path $projectRoot -ChildPath '.github/workflows') -File -Filter '*.yml' | Select-Object -ExpandProperty FullName @@ -165,7 +165,6 @@ Describe 'AtlassianPS.Standards version consistency' -Tag Unit { } $setupScriptContent = Get-Content -LiteralPath (Join-Path -Path $projectRoot -ChildPath 'Tools/setup.ps1') -Raw - $updateScriptContent = Get-Content -LiteralPath (Join-Path -Path $projectRoot -ChildPath 'Tools/update.dependencies.ps1') -Raw $buildScriptContent = Get-Content -LiteralPath (Join-Path -Path $projectRoot -ChildPath 'JiraPS.build.ps1') -Raw $testToolsContent = Get-Content -LiteralPath (Join-Path -Path $projectRoot -ChildPath 'Tests/Helpers/TestTools.ps1') -Raw @@ -173,11 +172,6 @@ Describe 'AtlassianPS.Standards version consistency' -Tag Unit { $setupScriptContent | Should -Not -Match '\$standardsVersion\s*=\s*''' $setupScriptContent | Should -Match '-RequiredVersion\s+\$standardsVersion' - $updateScriptContent | Should -Match '\$buildRequirements\s*=\s*Import-PowerShellDataFile' - $updateScriptContent | Should -Not -Match '\$standardsVersion\s*=\s*''' - $updateScriptContent | Should -Match '-RequiredVersion\s+\$standardsVersion' - $updateScriptContent | Should -Match '\$PSCmdlet\.ShouldProcess\(' - $buildScriptContent | Should -Match '\$buildRequirements\s*=\s*Import-PowerShellDataFile' $buildScriptContent | Should -Match '-RequiredVersion\s+\$standardsRequirement\.RequiredVersion' $buildScriptContent | Should -Not -Match "AtlassianPS\.Standards.*RequiredVersion\s+'[0-9]+\.[0-9]+\.[0-9]+'" diff --git a/Tests/Tools/Update-DependenciesScript.Unit.Tests.ps1 b/Tests/Tools/Update-DependenciesScript.Unit.Tests.ps1 deleted file mode 100644 index f82c7b3dd..000000000 --- a/Tests/Tools/Update-DependenciesScript.Unit.Tests.ps1 +++ /dev/null @@ -1,491 +0,0 @@ -#requires -modules @{ ModuleName = "Pester"; ModuleVersion = "5.7"; MaximumVersion = "5.999" } - -Describe 'Tools/update.dependencies.ps1' -Tag Unit { - It 'delegates dependency updates to the shared standards updater with expected paths and switches' { - $projectRoot = if ( - $env:BHProjectPath -and - (Test-Path -LiteralPath (Join-Path -Path $env:BHProjectPath -ChildPath 'CODEOWNERS')) - ) { - (Resolve-Path -LiteralPath $env:BHProjectPath).ProviderPath - } - else { - $candidate = (Resolve-Path -LiteralPath $PSScriptRoot).ProviderPath - while ($candidate -and ($candidate -ne [System.IO.Path]::GetPathRoot($candidate))) { - if (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS')) { - break - } - - $candidate = Split-Path -Path $candidate -Parent - } - - if (-not $candidate -or -not (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS'))) { - throw "Could not resolve repository root from '$PSScriptRoot'." - } - - $candidate - } - - $sourceToolsPath = Join-Path -Path $projectRoot -ChildPath 'Tools' - $harnessRoot = Join-Path -Path $TestDrive -ChildPath ([Guid]::NewGuid().ToString()) - $toolsPath = Join-Path -Path $harnessRoot -ChildPath 'Tools' - $modulePath = Join-Path -Path $harnessRoot -ChildPath 'JiraPS' - $mockModulePath = Join-Path -Path $harnessRoot -ChildPath 'mockModules/AtlassianPS.Standards/0.1.10' - $scriptPath = Join-Path -Path $toolsPath -ChildPath 'update.dependencies.ps1' - $capturePath = Join-Path -Path $TestDrive -ChildPath 'update-deps.json' - $escapedCapturePath = $capturePath.Replace("'", "''") - - $null = New-Item -Path $toolsPath -ItemType Directory -Force - $null = New-Item -Path $modulePath -ItemType Directory -Force - $null = New-Item -Path $mockModulePath -ItemType Directory -Force - - Copy-Item -LiteralPath (Join-Path -Path $sourceToolsPath -ChildPath 'update.dependencies.ps1') -Destination $scriptPath - - Set-Content -LiteralPath (Join-Path -Path $toolsPath -ChildPath 'build.requirements.psd1') -Value @' -@( - @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "0.1.10" } - @{ ModuleName = "InvokeBuild"; RequiredVersion = "5.14.23" } -) -'@ - - Set-Content -LiteralPath (Join-Path -Path $modulePath -ChildPath 'JiraPS.psd1') -Value @' -@{ - RootModule = 'JiraPS.psm1' - ModuleVersion = '3.0' - RequiredModules = @() -} -'@ - - Set-Content -LiteralPath (Join-Path -Path $mockModulePath -ChildPath 'AtlassianPS.Standards.psm1') -Value @" -function Update-AtlassianPSDependencyReference { - [CmdletBinding()] - param( - [String]`$BuildRequirementsPath, - [String]`$ManifestPath, - [Switch]`$SkipBuildRequirement, - [Switch]`$SkipManifestRequirement - ) - - [PSCustomObject]@{ - BuildRequirementsPath = `$BuildRequirementsPath - ManifestPath = `$ManifestPath - SkipBuildRequirement = [Boolean]`$SkipBuildRequirement - SkipManifestRequirement = [Boolean]`$SkipManifestRequirement - } | ConvertTo-Json -Compress | Set-Content -LiteralPath '$escapedCapturePath' - - return [PSCustomObject]@{ - SkipBuildRequirement = [Boolean]`$SkipBuildRequirement - SkipManifestRequirement = [Boolean]`$SkipManifestRequirement - } -} - -Export-ModuleMember -Function Update-AtlassianPSDependencyReference -"@ - - Set-Content -LiteralPath (Join-Path -Path $mockModulePath -ChildPath 'AtlassianPS.Standards.psd1') -Value @' -@{ - RootModule = 'AtlassianPS.Standards.psm1' - ModuleVersion = '0.1.10' - GUID = 'c72f680f-a8f2-434e-8b70-80e0099f90d7' - FunctionsToExport = @('*') -} -'@ - - Mock -CommandName Get-PSRepository -MockWith { - [PSCustomObject]@{ - Name = 'PSGallery' - SourceLocation = 'https://www.powershellgallery.com/api/v2/' - InstallationPolicy = 'Trusted' - } - } - Mock -CommandName Register-PSRepository -MockWith {} - Mock -CommandName Get-PackageProvider -MockWith { [PSCustomObject]@{ Name = 'NuGet'; Version = [Version] '2.8.5.208' } } - Mock -CommandName Install-PackageProvider -MockWith {} - Mock -CommandName Set-PSRepository -MockWith {} - Mock -CommandName Install-Module -MockWith {} - - $moduleSearchPath = Join-Path -Path $harnessRoot -ChildPath 'mockModules' - $originalModulePath = $env:PSModulePath - $env:PSModulePath = "$moduleSearchPath$([System.IO.Path]::PathSeparator)$originalModulePath" - try { - $result = & $scriptPath -SkipBuildRequirement -SkipManifestRequirement - } - finally { - $env:PSModulePath = $originalModulePath - Remove-Module -Name 'AtlassianPS.Standards' -Force -ErrorAction SilentlyContinue - } - - $captured = Get-Content -LiteralPath $capturePath -Raw | ConvertFrom-Json - - $captured.BuildRequirementsPath | Should -Be (Join-Path -Path $harnessRoot -ChildPath 'Tools/build.requirements.psd1') - $captured.ManifestPath | Should -Be (Join-Path -Path $harnessRoot -ChildPath 'JiraPS/JiraPS.psd1') - $captured.SkipBuildRequirement | Should -BeTrue - $captured.SkipManifestRequirement | Should -BeTrue - $result.SkipBuildRequirement | Should -BeTrue - $result.SkipManifestRequirement | Should -BeTrue - } - - It 'installs the required standards version from build.requirements when not present locally' { - $projectRoot = if ( - $env:BHProjectPath -and - (Test-Path -LiteralPath (Join-Path -Path $env:BHProjectPath -ChildPath 'CODEOWNERS')) - ) { - (Resolve-Path -LiteralPath $env:BHProjectPath).ProviderPath - } - else { - $candidate = (Resolve-Path -LiteralPath $PSScriptRoot).ProviderPath - while ($candidate -and ($candidate -ne [System.IO.Path]::GetPathRoot($candidate))) { - if (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS')) { - break - } - - $candidate = Split-Path -Path $candidate -Parent - } - - if (-not $candidate -or -not (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS'))) { - throw "Could not resolve repository root from '$PSScriptRoot'." - } - - $candidate - } - - $sourceToolsPath = Join-Path -Path $projectRoot -ChildPath 'Tools' - $harnessRoot = Join-Path -Path $TestDrive -ChildPath ([Guid]::NewGuid().ToString()) - $toolsPath = Join-Path -Path $harnessRoot -ChildPath 'Tools' - $modulePath = Join-Path -Path $harnessRoot -ChildPath 'JiraPS' - $mockModulePath = Join-Path -Path $harnessRoot -ChildPath 'mockModules/AtlassianPS.Standards/9.9.9' - $scriptPath = Join-Path -Path $toolsPath -ChildPath 'update.dependencies.ps1' - - $null = New-Item -Path $toolsPath -ItemType Directory -Force - $null = New-Item -Path $modulePath -ItemType Directory -Force - $null = New-Item -Path $mockModulePath -ItemType Directory -Force - - Copy-Item -LiteralPath (Join-Path -Path $sourceToolsPath -ChildPath 'update.dependencies.ps1') -Destination $scriptPath - - Set-Content -LiteralPath (Join-Path -Path $toolsPath -ChildPath 'build.requirements.psd1') -Value @' -@( - @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "9.9.9" } -) -'@ - - Set-Content -LiteralPath (Join-Path -Path $modulePath -ChildPath 'JiraPS.psd1') -Value @' -@{ - RootModule = 'JiraPS.psm1' - ModuleVersion = '3.0' - RequiredModules = @() -} -'@ - - Set-Content -LiteralPath (Join-Path -Path $mockModulePath -ChildPath 'AtlassianPS.Standards.psm1') -Value @' -function Update-AtlassianPSDependencyReference { - [CmdletBinding()] - param( - [String]$BuildRequirementsPath, - [String]$ManifestPath, - [Switch]$SkipBuildRequirement, - [Switch]$SkipManifestRequirement - ) - - return [PSCustomObject]@{ - Installed = $true - BuildRequirementsPath = $BuildRequirementsPath - ManifestPath = $ManifestPath - SkipBuildRequirement = [Boolean]$SkipBuildRequirement - SkipManifestRequirement = [Boolean]$SkipManifestRequirement - } -} - -Export-ModuleMember -Function Update-AtlassianPSDependencyReference -'@ - - Set-Content -LiteralPath (Join-Path -Path $mockModulePath -ChildPath 'AtlassianPS.Standards.psd1') -Value @' -@{ - RootModule = 'AtlassianPS.Standards.psm1' - ModuleVersion = '9.9.9' - GUID = 'e61a3f95-a8d0-40ff-92cb-9e792ebd7d9f' - FunctionsToExport = @('*') -} -'@ - - Mock -CommandName Get-PSRepository -MockWith { - [PSCustomObject]@{ - Name = 'PSGallery' - SourceLocation = 'https://www.powershellgallery.com/api/v2/' - InstallationPolicy = 'Untrusted' - } - } - Mock -CommandName Register-PSRepository -MockWith {} - Mock -CommandName Get-PackageProvider -MockWith { [PSCustomObject]@{ Name = 'NuGet'; Version = [Version] '2.8.5.100' } } - Mock -CommandName Install-Module -MockWith {} - - $installPackageProviderCapturePath = Join-Path -Path $TestDrive -ChildPath 'update.installpackageprovider.called' - $setPSRepositoryCapturePath = Join-Path -Path $TestDrive -ChildPath 'update.setpsrepository.called' - $installPackageProviderCapturePathEscaped = $installPackageProviderCapturePath.Replace("'", "''") - $setPSRepositoryCapturePathEscaped = $setPSRepositoryCapturePath.Replace("'", "''") - Set-Item -Path Function:Global:Install-PackageProvider -Value ([scriptblock]::Create(@" -param([String]`$Name, [String]`$MinimumVersion, [String]`$Scope, [Switch]`$Force) -Set-Content -LiteralPath '$installPackageProviderCapturePathEscaped' -Value 'called' -"@)) - Set-Item -Path Function:Global:Set-PSRepository -Value ([scriptblock]::Create(@" -param([String]`$Name, [String]`$InstallationPolicy) -Set-Content -LiteralPath '$setPSRepositoryCapturePathEscaped' -Value 'called' -"@)) - - $moduleSearchPath = Join-Path -Path $harnessRoot -ChildPath 'mockModules' - $originalModulePath = $env:PSModulePath - $env:PSModulePath = "$moduleSearchPath$([System.IO.Path]::PathSeparator)$originalModulePath" - try { - $result = & $scriptPath -RuntimePSEdition Desktop -ForceDesktopBootstrapRemediation - } - finally { - $env:PSModulePath = $originalModulePath - Remove-Module -Name 'AtlassianPS.Standards' -Force -ErrorAction SilentlyContinue - if (Test-Path -LiteralPath Function:Global:Install-PackageProvider) { - Remove-Item -LiteralPath Function:Global:Install-PackageProvider - } - - if (Test-Path -LiteralPath Function:Global:Set-PSRepository) { - Remove-Item -LiteralPath Function:Global:Set-PSRepository - } - } - - Test-Path -LiteralPath $installPackageProviderCapturePath | Should -BeTrue - Test-Path -LiteralPath $setPSRepositoryCapturePath | Should -BeTrue - Should -Invoke -CommandName Install-Module -Exactly -Times 1 -ParameterFilter { - $Name -eq 'AtlassianPS.Standards' -and - $RequiredVersion -eq '9.9.9' -and - $Scope -eq 'CurrentUser' -and - $Repository -eq 'PSGallery' -and - [Boolean]$AllowClobber -and - [Boolean]$Force - } - $result.Installed | Should -BeTrue - } - - It 'honors -WhatIf and does not call the shared dependency updater' { - $projectRoot = if ( - $env:BHProjectPath -and - (Test-Path -LiteralPath (Join-Path -Path $env:BHProjectPath -ChildPath 'CODEOWNERS')) - ) { - (Resolve-Path -LiteralPath $env:BHProjectPath).ProviderPath - } - else { - $candidate = (Resolve-Path -LiteralPath $PSScriptRoot).ProviderPath - while ($candidate -and ($candidate -ne [System.IO.Path]::GetPathRoot($candidate))) { - if (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS')) { - break - } - - $candidate = Split-Path -Path $candidate -Parent - } - - if (-not $candidate -or -not (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS'))) { - throw "Could not resolve repository root from '$PSScriptRoot'." - } - - $candidate - } - - $sourceToolsPath = Join-Path -Path $projectRoot -ChildPath 'Tools' - $harnessRoot = Join-Path -Path $TestDrive -ChildPath ([Guid]::NewGuid().ToString()) - $toolsPath = Join-Path -Path $harnessRoot -ChildPath 'Tools' - $modulePath = Join-Path -Path $harnessRoot -ChildPath 'JiraPS' - $scriptPath = Join-Path -Path $toolsPath -ChildPath 'update.dependencies.ps1' - - $null = New-Item -Path $toolsPath -ItemType Directory -Force - $null = New-Item -Path $modulePath -ItemType Directory -Force - - Copy-Item -LiteralPath (Join-Path -Path $sourceToolsPath -ChildPath 'update.dependencies.ps1') -Destination $scriptPath - - Set-Content -LiteralPath (Join-Path -Path $toolsPath -ChildPath 'build.requirements.psd1') -Value @' -@( - @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "0.1.10" } -) -'@ - - Set-Content -LiteralPath (Join-Path -Path $modulePath -ChildPath 'JiraPS.psd1') -Value @' -@{ - RootModule = 'JiraPS.psm1' - ModuleVersion = '3.0' - RequiredModules = @() -} -'@ - - Mock -CommandName Get-PSRepository -MockWith { - [PSCustomObject]@{ - Name = 'PSGallery' - SourceLocation = 'https://www.powershellgallery.com/api/v2/' - InstallationPolicy = 'Trusted' - } - } - Mock -CommandName Register-PSRepository -MockWith {} - Mock -CommandName Install-Module -MockWith {} - Mock -CommandName Import-Module -MockWith {} - - $result = & $scriptPath -WhatIf - - Should -Invoke -CommandName Install-Module -Exactly -Times 0 - $result.Skipped | Should -BeTrue - } - - It 'fails with clear guidance when PSGallery is unavailable after registration attempt' { - $projectRoot = if ( - $env:BHProjectPath -and - (Test-Path -LiteralPath (Join-Path -Path $env:BHProjectPath -ChildPath 'CODEOWNERS')) - ) { - (Resolve-Path -LiteralPath $env:BHProjectPath).ProviderPath - } - else { - $candidate = (Resolve-Path -LiteralPath $PSScriptRoot).ProviderPath - while ($candidate -and ($candidate -ne [System.IO.Path]::GetPathRoot($candidate))) { - if (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS')) { - break - } - - $candidate = Split-Path -Path $candidate -Parent - } - - if (-not $candidate -or -not (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS'))) { - throw "Could not resolve repository root from '$PSScriptRoot'." - } - - $candidate - } - - $sourceToolsPath = Join-Path -Path $projectRoot -ChildPath 'Tools' - $harnessRoot = Join-Path -Path $TestDrive -ChildPath ([Guid]::NewGuid().ToString()) - $toolsPath = Join-Path -Path $harnessRoot -ChildPath 'Tools' - $modulePath = Join-Path -Path $harnessRoot -ChildPath 'JiraPS' - $scriptPath = Join-Path -Path $toolsPath -ChildPath 'update.dependencies.ps1' - - $null = New-Item -Path $toolsPath -ItemType Directory -Force - $null = New-Item -Path $modulePath -ItemType Directory -Force - - Copy-Item -LiteralPath (Join-Path -Path $sourceToolsPath -ChildPath 'update.dependencies.ps1') -Destination $scriptPath - - Set-Content -LiteralPath (Join-Path -Path $toolsPath -ChildPath 'build.requirements.psd1') -Value @' -@( - @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "0.1.10" } -) -'@ - - Set-Content -LiteralPath (Join-Path -Path $modulePath -ChildPath 'JiraPS.psd1') -Value @' -@{ - RootModule = 'JiraPS.psm1' - ModuleVersion = '3.0' - RequiredModules = @() -} -'@ - - Mock -CommandName Get-PSRepository -MockWith { $null } - Mock -CommandName Register-PSRepository -MockWith {} - Mock -CommandName Install-Module -MockWith {} - - { - & $scriptPath - } | Should -Throw -ExpectedMessage '*PSGallery repository is unavailable*' - } - - It 'fails fast when shared updater emits a non-terminating error' { - $projectRoot = if ( - $env:BHProjectPath -and - (Test-Path -LiteralPath (Join-Path -Path $env:BHProjectPath -ChildPath 'CODEOWNERS')) - ) { - (Resolve-Path -LiteralPath $env:BHProjectPath).ProviderPath - } - else { - $candidate = (Resolve-Path -LiteralPath $PSScriptRoot).ProviderPath - while ($candidate -and ($candidate -ne [System.IO.Path]::GetPathRoot($candidate))) { - if (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS')) { - break - } - - $candidate = Split-Path -Path $candidate -Parent - } - - if (-not $candidate -or -not (Test-Path -LiteralPath (Join-Path -Path $candidate -ChildPath 'CODEOWNERS'))) { - throw "Could not resolve repository root from '$PSScriptRoot'." - } - - $candidate - } - - $sourceToolsPath = Join-Path -Path $projectRoot -ChildPath 'Tools' - $harnessRoot = Join-Path -Path $TestDrive -ChildPath ([Guid]::NewGuid().ToString()) - $toolsPath = Join-Path -Path $harnessRoot -ChildPath 'Tools' - $modulePath = Join-Path -Path $harnessRoot -ChildPath 'JiraPS' - $mockModulePath = Join-Path -Path $harnessRoot -ChildPath 'mockModules/AtlassianPS.Standards/0.1.10' - $scriptPath = Join-Path -Path $toolsPath -ChildPath 'update.dependencies.ps1' - - $null = New-Item -Path $toolsPath -ItemType Directory -Force - $null = New-Item -Path $modulePath -ItemType Directory -Force - $null = New-Item -Path $mockModulePath -ItemType Directory -Force - - Copy-Item -LiteralPath (Join-Path -Path $sourceToolsPath -ChildPath 'update.dependencies.ps1') -Destination $scriptPath - - Set-Content -LiteralPath (Join-Path -Path $toolsPath -ChildPath 'build.requirements.psd1') -Value @' -@( - @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "0.1.10" } - @{ ModuleName = "InvokeBuild"; RequiredVersion = "5.14.23" } -) -'@ - - Set-Content -LiteralPath (Join-Path -Path $modulePath -ChildPath 'JiraPS.psd1') -Value @' -@{ - RootModule = 'JiraPS.psm1' - ModuleVersion = '3.0' - RequiredModules = @() -} -'@ - - Set-Content -LiteralPath (Join-Path -Path $mockModulePath -ChildPath 'AtlassianPS.Standards.psm1') -Value @' -function Update-AtlassianPSDependencyReference { - [CmdletBinding()] - param( - [String]$BuildRequirementsPath, - [String]$ManifestPath, - [Switch]$SkipBuildRequirement, - [Switch]$SkipManifestRequirement - ) - - Write-Error -Message "simulated updater failure" -} - -Export-ModuleMember -Function Update-AtlassianPSDependencyReference -'@ - - Set-Content -LiteralPath (Join-Path -Path $mockModulePath -ChildPath 'AtlassianPS.Standards.psd1') -Value @' -@{ - RootModule = 'AtlassianPS.Standards.psm1' - ModuleVersion = '0.1.10' - GUID = 'c72f680f-a8f2-434e-8b70-80e0099f90d7' - FunctionsToExport = @('*') -} -'@ - - Mock -CommandName Get-PSRepository -MockWith { - [PSCustomObject]@{ - Name = 'PSGallery' - SourceLocation = 'https://www.powershellgallery.com/api/v2/' - InstallationPolicy = 'Trusted' - } - } - Mock -CommandName Register-PSRepository -MockWith {} - Mock -CommandName Get-PackageProvider -MockWith { [PSCustomObject]@{ Name = 'NuGet'; Version = [Version] '2.8.5.208' } } - Mock -CommandName Install-PackageProvider -MockWith {} - Mock -CommandName Set-PSRepository -MockWith {} - Mock -CommandName Install-Module -MockWith {} - - $moduleSearchPath = Join-Path -Path $harnessRoot -ChildPath 'mockModules' - $originalModulePath = $env:PSModulePath - $env:PSModulePath = "$moduleSearchPath$([System.IO.Path]::PathSeparator)$originalModulePath" - try { - { - & $scriptPath -SkipBuildRequirement -SkipManifestRequirement | Out-Null - } | Should -Throw -ExpectedMessage '*simulated updater failure*' - } - finally { - $env:PSModulePath = $originalModulePath - Remove-Module -Name 'AtlassianPS.Standards' -Force -ErrorAction SilentlyContinue - } - } -} diff --git a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 index f8af0adca..131cee41a 100644 --- a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 +++ b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 @@ -24,5 +24,6 @@ Describe 'GitHub Actions workflow triggers' -Tag Unit { ([regex]::Matches($dependabot, 'package-ecosystem:\s*"(?:devcontainers|docker|docker-compose)"[\s\S]*?interval:\s*"?monthly"?')).Count | Should -Be 3 $dependabot | Should -Match 'package-ecosystem:\s*"github-actions"[\s\S]*?interval:\s*"?weekly"?' + $dependabot | Should -Match 'ignore:[\s\S]+dependency-name:\s*"AtlassianPS/AtlassianPS\.Standards\*"' } } diff --git a/Tools/build.requirements.psd1 b/Tools/build.requirements.psd1 index c8d51ad45..8e86baa04 100644 --- a/Tools/build.requirements.psd1 +++ b/Tools/build.requirements.psd1 @@ -1,9 +1,9 @@ @( - @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "0.3.3" } + @{ ModuleName = "AtlassianPS.Standards"; RequiredVersion = "0.3.4" } @{ ModuleName = "InvokeBuild"; RequiredVersion = "5.14.23" } @{ ModuleName = "Metadata"; RequiredVersion = "1.5.7" } - @{ ModuleName = "Pester"; RequiredVersion = "5.7.1" } - @{ ModuleName = "Microsoft.PowerShell.PlatyPS"; RequiredVersion = "1.0.1" } + @{ ModuleName = "Pester"; RequiredVersion = "5.9.1" } + @{ ModuleName = "Microsoft.PowerShell.PlatyPS"; RequiredVersion = "1.0.3" } @{ ModuleName = "PSScriptAnalyzer"; RequiredVersion = "1.25.0" } ) diff --git a/Tools/update.dependencies.ps1 b/Tools/update.dependencies.ps1 deleted file mode 100644 index 42399a932..000000000 --- a/Tools/update.dependencies.ps1 +++ /dev/null @@ -1,100 +0,0 @@ -#requires -Module PowerShellGet - -[CmdletBinding(SupportsShouldProcess = $true)] -param( - [Parameter()] - [Switch]$SkipBuildRequirement, - - [Parameter()] - [Switch]$SkipManifestRequirement, - - [Parameter(DontShow = $true)] - [ValidateSet('Desktop', 'Core')] - [String]$RuntimePSEdition = $PSVersionTable.PSEdition, - - [Parameter(DontShow = $true)] - [Switch]$ForceDesktopBootstrapRemediation -) - -$ErrorActionPreference = 'Stop' - -$projectRoot = (Resolve-Path -LiteralPath (Join-Path -Path $PSScriptRoot -ChildPath '..')).ProviderPath -$buildRequirementsPath = Join-Path -Path $projectRoot -ChildPath 'Tools/build.requirements.psd1' -$manifestPath = Join-Path -Path $projectRoot -ChildPath 'JiraPS/JiraPS.psd1' - -$buildRequirements = Import-PowerShellDataFile -Path $buildRequirementsPath -$standardsRequirement = $buildRequirements | - Where-Object { $_.ModuleName -eq 'AtlassianPS.Standards' } | - Select-Object -First 1 - -if (-not $standardsRequirement -or -not $standardsRequirement.RequiredVersion) { - throw "Could not resolve AtlassianPS.Standards required version from '$buildRequirementsPath'." -} - -$standardsVersion = [string] $standardsRequirement.RequiredVersion - -if (-not $PSCmdlet.ShouldProcess($manifestPath, 'Update AtlassianPS dependency references')) { - return [PSCustomObject]@{ - Skipped = $true - BuildRequirementsPath = $buildRequirementsPath - ManifestPath = $manifestPath - SkipBuildRequirement = [Boolean] $SkipBuildRequirement - SkipManifestRequirement = [Boolean] $SkipManifestRequirement - } -} - -$isWindowsPowerShell = $RuntimePSEdition -eq 'Desktop' -if ($isWindowsPowerShell) { - $nuGetProvider = Get-PackageProvider -Name 'NuGet' -ListAvailable -ErrorAction SilentlyContinue | - Sort-Object -Property Version -Descending | - Select-Object -First 1 - - $requiresNuGetBootstrap = ( - $ForceDesktopBootstrapRemediation -or - (-not $nuGetProvider -or $nuGetProvider.Version -lt [Version] '2.8.5.201') - ) - - if ($requiresNuGetBootstrap) { - Install-PackageProvider -Name 'NuGet' -MinimumVersion '2.8.5.201' -Scope CurrentUser -Force -ErrorAction Stop - } - -} - -$psGalleryRepository = Get-PSRepository -Name 'PSGallery' -ErrorAction SilentlyContinue -if (-not $psGalleryRepository) { - try { - Register-PSRepository -Default -ErrorAction Stop - } - catch { - throw "PSGallery repository is unavailable. Register PSGallery or configure repository access, then rerun '$($MyInvocation.MyCommand.Path)'." - } - - $psGalleryRepository = Get-PSRepository -Name 'PSGallery' -ErrorAction SilentlyContinue -} - -if (-not $psGalleryRepository) { - throw "PSGallery repository is unavailable. Register PSGallery or configure repository access, then rerun '$($MyInvocation.MyCommand.Path)'." -} - -if ($isWindowsPowerShell -and ($ForceDesktopBootstrapRemediation -or $psGalleryRepository.InstallationPolicy -ne 'Trusted')) { - Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted -ErrorAction Stop -} - -Install-Module -Name 'AtlassianPS.Standards' ` - -RequiredVersion $standardsVersion ` - -Scope CurrentUser ` - -Repository 'PSGallery' ` - -AllowClobber ` - -Force ` - -ErrorAction Stop - -Import-Module -Name 'AtlassianPS.Standards' -RequiredVersion $standardsVersion -Force -ErrorAction Stop - -$result = Update-AtlassianPSDependencyReference ` - -BuildRequirementsPath $buildRequirementsPath ` - -ManifestPath $manifestPath ` - -SkipBuildRequirement:$SkipBuildRequirement ` - -SkipManifestRequirement:$SkipManifestRequirement ` - -ErrorAction Stop - -$result