Skip to content

Commit 951ad82

Browse files
committed
[2026-05-22] Add package version selection and refresh pins
Add command-aware package version selection, previousByVersion, inventory-backed version replacement, and refreshed shipped package releases while preserving previous authored versions.
1 parent 1ba6730 commit 951ad82

20 files changed

Lines changed: 1133 additions & 127 deletions

src/prj/Eigenverft.Manifested.Sandbox.Test/Eigenverft.Manifested.Sandbox.Package.AcquisitionAndOwnership.Tests.ps1

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,228 @@ Invoke-TestPackageDescribe -Name 'Eigenverft.Manifested.Sandbox Package - acquis
604604
$result.InstallOrigin | Should -Be 'PackageReused'
605605
}
606606

607+
It 'discovers an older OpenCode package-owned install from inventory and replaces it for a new selected version' {
608+
$rootPath = Join-Path $TestDrive 'opencode-inventory-update'
609+
$preferredInstallRoot = Join-Path $rootPath 'installs'
610+
$oldInstallRoot = Join-Path $preferredInstallRoot 'opencode-runtime\stable\1.14.46\win32-x64'
611+
$packageStateIndexPath = Join-Path $rootPath 'PackageAssignmentInventory.json'
612+
$null = New-Item -ItemType Directory -Path (Join-Path $oldInstallRoot 'bin') -Force
613+
Write-TestTextFile -Path (Join-Path $oldInstallRoot 'Code.exe') -Content 'fake'
614+
Write-TestTextFile -Path (Join-Path $oldInstallRoot 'bin\code.cmd') -Content "@echo off`r`necho 1.14.46`r`n"
615+
Write-TestJsonDocument -Path $packageStateIndexPath -Document @{
616+
records = @(
617+
@{
618+
installSlotId = 'OpenCodeCli:stable:win32-x64'
619+
definitionId = 'OpenCodeCli'
620+
releaseTrack = 'stable'
621+
artifactDistributionVariant = 'win32-x64'
622+
currentReleaseId = 'opencode-runtime-win32-x64-stable'
623+
currentVersion = '1.14.46'
624+
installDirectory = $oldInstallRoot
625+
ownershipKind = 'PackageInstalled'
626+
updatedAtUtc = [DateTime]::UtcNow.ToString('o')
627+
}
628+
)
629+
}
630+
631+
$sharedInstall = @{
632+
install = @{
633+
kind = 'expandArchive'
634+
installDirectory = 'opencode-runtime/{releaseTrack}/{version}/{artifactDistributionVariant}'
635+
expandedRoot = 'auto'
636+
}
637+
versionUpdatePolicy = @{
638+
whenAssigned = 'trackSelectedVersion'
639+
onSameSelectedVersion = 'reuseOrRepair'
640+
onNewSelectedVersion = 'replacePackageOwnedInstall'
641+
}
642+
}
643+
$readiness = New-TestReadiness -Version '1.15.7' -Directories @()
644+
$release = New-TestPackageRelease -Id 'opencode-runtime-win32-x64-stable' -Version '1.15.7' -Architecture 'x64' -ArtifactDistributionVariant 'win32-x64' -FileName 'opencode-1.15.7.zip' -Readiness $readiness
645+
$documents = Write-TestPackageDocuments -RootPath $rootPath -GlobalDocument (New-TestPackageGlobalDocument -PreferredTargetInstallDirectory $preferredInstallRoot -PackageAssignmentInventoryFilePath $packageStateIndexPath) -DefinitionDocument (New-TestVSCodeDefinitionDocument -DefinitionId 'OpenCodeCli' -Releases @($release) -SharedInstall $sharedInstall -SharedReadiness $readiness -SharedExistingInstallDiscovery (New-TestExistingInstallDiscovery -Enabled $false))
646+
647+
[Environment]::SetEnvironmentVariable($script:SourceInventoryEnvVarName, (Join-Path $TestDrive 'missing-inventory.json'), 'Process')
648+
Mock Get-PackageConfigPath { $documents.GlobalConfigPath }
649+
Mock Get-PackageDefinitionPath { param($DefinitionId) $documents.DefinitionPath }
650+
651+
$config = Get-PackageConfig -DefinitionId 'OpenCodeCli'
652+
$result = New-PackageResult -PackageConfig $config
653+
$result = Resolve-PackagePackage -PackageResult $result
654+
$result = Resolve-PackagePaths -PackageResult $result
655+
$newInstallRoot = $result.InstallDirectory
656+
Test-Path -LiteralPath $newInstallRoot -PathType Container | Should -BeFalse
657+
$result = Find-PackageExistingPackage -PackageResult $result
658+
$result = Set-PackageExistingPackage -PackageResult $result
659+
$result = Resolve-PackageExistingPackageDecision -PackageResult $result
660+
661+
$result.ExistingPackage.SearchKind | Should -Be 'packageInventoryInstallSlot'
662+
$result.ExistingPackage.InstallDirectory | Should -Be ([System.IO.Path]::GetFullPath($oldInstallRoot))
663+
$result.ExistingPackage.Decision | Should -Be 'ReplacePackageOwnedInstall'
664+
$result.InstallDirectory | Should -Be $newInstallRoot
665+
$result.Readiness | Should -BeNullOrEmpty
666+
}
667+
668+
It 'uses an exact PackageVersion selector to downgrade a package-owned install when replacement is allowed' {
669+
$rootPath = Join-Path $TestDrive 'opencode-inventory-downgrade'
670+
$preferredInstallRoot = Join-Path $rootPath 'installs'
671+
$newerInstallRoot = Join-Path $preferredInstallRoot 'opencode-runtime\stable\1.15.7\win32-x64'
672+
$packageStateIndexPath = Join-Path $rootPath 'PackageAssignmentInventory.json'
673+
$null = New-Item -ItemType Directory -Path (Join-Path $newerInstallRoot 'bin') -Force
674+
Write-TestTextFile -Path (Join-Path $newerInstallRoot 'Code.exe') -Content 'fake'
675+
Write-TestTextFile -Path (Join-Path $newerInstallRoot 'bin\code.cmd') -Content "@echo off`r`necho 1.15.7`r`n"
676+
Write-TestJsonDocument -Path $packageStateIndexPath -Document @{
677+
records = @(
678+
@{
679+
installSlotId = 'OpenCodeCli:stable:win32-x64'
680+
definitionId = 'OpenCodeCli'
681+
releaseTrack = 'stable'
682+
artifactDistributionVariant = 'win32-x64'
683+
currentReleaseId = 'opencode-runtime-win32-x64-stable'
684+
currentVersion = '1.15.7'
685+
installDirectory = $newerInstallRoot
686+
ownershipKind = 'PackageInstalled'
687+
updatedAtUtc = [DateTime]::UtcNow.ToString('o')
688+
}
689+
)
690+
}
691+
692+
$sharedInstall = @{
693+
install = @{
694+
kind = 'expandArchive'
695+
installDirectory = 'opencode-runtime/{releaseTrack}/{version}/{artifactDistributionVariant}'
696+
expandedRoot = 'auto'
697+
}
698+
versionUpdatePolicy = @{
699+
whenAssigned = 'trackSelectedVersion'
700+
onSameSelectedVersion = 'reuseOrRepair'
701+
onNewSelectedVersion = 'replacePackageOwnedInstall'
702+
}
703+
}
704+
$readiness = New-TestReadiness -Version '1.14.46' -Directories @()
705+
$releaseLatest = New-TestPackageRelease -Id 'opencode-runtime-win32-x64-stable' -Version '1.15.7' -Architecture 'x64' -ArtifactDistributionVariant 'win32-x64' -FileName 'opencode-1.15.7.zip' -Readiness (New-TestReadiness -Version '1.15.7' -Directories @())
706+
$definitionDocument = New-TestVSCodeDefinitionDocument -DefinitionId 'OpenCodeCli' -Releases @($releaseLatest) -SharedInstall $sharedInstall -SharedReadiness $readiness -SharedExistingInstallDiscovery (New-TestExistingInstallDiscovery -Enabled $false)
707+
$definitionDocument.artifacts.releases += [ordered]@{
708+
version = '1.14.46'
709+
releaseTracks = @('stable')
710+
targetArtifacts = @{
711+
'opencode-runtime-win32-x64-stable' = @{
712+
artifactId = 'opencode-runtime-win32-x64-stable'
713+
fileName = 'opencode-1.14.46.zip'
714+
}
715+
}
716+
}
717+
$documents = Write-TestPackageDocuments -RootPath $rootPath -GlobalDocument (New-TestPackageGlobalDocument -PreferredTargetInstallDirectory $preferredInstallRoot -PackageAssignmentInventoryFilePath $packageStateIndexPath) -DefinitionDocument $definitionDocument
718+
719+
[Environment]::SetEnvironmentVariable($script:SourceInventoryEnvVarName, (Join-Path $TestDrive 'missing-inventory.json'), 'Process')
720+
Mock Get-PackageConfigPath { $documents.GlobalConfigPath }
721+
Mock Get-PackageDefinitionPath { param($DefinitionId) $documents.DefinitionPath }
722+
723+
$config = Get-PackageConfig -DefinitionId 'OpenCodeCli'
724+
$result = New-PackageResult -PackageConfig $config -PackageVersionSelector '1.14.46'
725+
$result = Resolve-PackagePackage -PackageResult $result
726+
$result = Resolve-PackagePaths -PackageResult $result
727+
$downgradeInstallRoot = $result.InstallDirectory
728+
$result = Find-PackageExistingPackage -PackageResult $result
729+
$result = Set-PackageExistingPackage -PackageResult $result
730+
$result = Resolve-PackageExistingPackageDecision -PackageResult $result
731+
732+
$result.Package.version | Should -Be '1.14.46'
733+
$result.ExistingPackage.SearchKind | Should -Be 'packageInventoryInstallSlot'
734+
$result.ExistingPackage.InstallDirectory | Should -Be ([System.IO.Path]::GetFullPath($newerInstallRoot))
735+
$result.ExistingPackage.Decision | Should -Be 'ReplacePackageOwnedInstall'
736+
$result.InstallDirectory | Should -Be $downgradeInstallRoot
737+
}
738+
739+
It 'fails an assigned version change when versionUpdatePolicy.onNewSelectedVersion is fail' {
740+
$rootPath = Join-Path $TestDrive 'opencode-inventory-update-fail'
741+
$preferredInstallRoot = Join-Path $rootPath 'installs'
742+
$oldInstallRoot = Join-Path $preferredInstallRoot 'opencode-runtime\stable\1.14.46\win32-x64'
743+
$packageStateIndexPath = Join-Path $rootPath 'PackageAssignmentInventory.json'
744+
$null = New-Item -ItemType Directory -Path (Join-Path $oldInstallRoot 'bin') -Force
745+
Write-TestTextFile -Path (Join-Path $oldInstallRoot 'Code.exe') -Content 'fake'
746+
Write-TestTextFile -Path (Join-Path $oldInstallRoot 'bin\code.cmd') -Content "@echo off`r`necho 1.14.46`r`n"
747+
Write-TestJsonDocument -Path $packageStateIndexPath -Document @{
748+
records = @(
749+
@{
750+
installSlotId = 'OpenCodeCli:stable:win32-x64'
751+
definitionId = 'OpenCodeCli'
752+
releaseTrack = 'stable'
753+
artifactDistributionVariant = 'win32-x64'
754+
currentReleaseId = 'opencode-runtime-win32-x64-stable'
755+
currentVersion = '1.14.46'
756+
installDirectory = $oldInstallRoot
757+
ownershipKind = 'PackageInstalled'
758+
updatedAtUtc = [DateTime]::UtcNow.ToString('o')
759+
}
760+
)
761+
}
762+
763+
$sharedInstall = @{
764+
install = @{
765+
kind = 'expandArchive'
766+
installDirectory = 'opencode-runtime/{releaseTrack}/{version}/{artifactDistributionVariant}'
767+
expandedRoot = 'auto'
768+
}
769+
versionUpdatePolicy = @{
770+
whenAssigned = 'trackSelectedVersion'
771+
onSameSelectedVersion = 'reuseOrRepair'
772+
onNewSelectedVersion = 'fail'
773+
}
774+
}
775+
$readiness = New-TestReadiness -Version '1.15.7' -Directories @()
776+
$release = New-TestPackageRelease -Id 'opencode-runtime-win32-x64-stable' -Version '1.15.7' -Architecture 'x64' -ArtifactDistributionVariant 'win32-x64' -FileName 'opencode-1.15.7.zip' -Readiness $readiness
777+
$documents = Write-TestPackageDocuments -RootPath $rootPath -GlobalDocument (New-TestPackageGlobalDocument -PreferredTargetInstallDirectory $preferredInstallRoot -PackageAssignmentInventoryFilePath $packageStateIndexPath) -DefinitionDocument (New-TestVSCodeDefinitionDocument -DefinitionId 'OpenCodeCli' -Releases @($release) -SharedInstall $sharedInstall -SharedReadiness $readiness -SharedExistingInstallDiscovery (New-TestExistingInstallDiscovery -Enabled $false))
778+
779+
[Environment]::SetEnvironmentVariable($script:SourceInventoryEnvVarName, (Join-Path $TestDrive 'missing-inventory.json'), 'Process')
780+
Mock Get-PackageConfigPath { $documents.GlobalConfigPath }
781+
Mock Get-PackageDefinitionPath { param($DefinitionId) $documents.DefinitionPath }
782+
783+
$config = Get-PackageConfig -DefinitionId 'OpenCodeCli'
784+
$result = New-PackageResult -PackageConfig $config
785+
$result = Resolve-PackagePackage -PackageResult $result
786+
$result = Resolve-PackagePaths -PackageResult $result
787+
$result = Find-PackageExistingPackage -PackageResult $result
788+
$result = Set-PackageExistingPackage -PackageResult $result
789+
790+
{ Resolve-PackageExistingPackageDecision -PackageResult $result } | Should -Throw -ExpectedMessage "*versionUpdatePolicy.onNewSelectedVersion='fail'*"
791+
}
792+
793+
It 'removes the replaced package-owned install directory after the new install is ready' {
794+
$rootPath = Join-Path $TestDrive 'opencode-replacement-cleanup'
795+
$preferredInstallRoot = Join-Path $rootPath 'installs'
796+
$oldInstallRoot = Join-Path $preferredInstallRoot 'opencode-runtime\stable\1.14.46\win32-x64'
797+
$newInstallRoot = Join-Path $preferredInstallRoot 'opencode-runtime\stable\1.15.7\win32-x64'
798+
$null = New-Item -ItemType Directory -Path $oldInstallRoot -Force
799+
$null = New-Item -ItemType Directory -Path $newInstallRoot -Force
800+
Write-TestTextFile -Path (Join-Path $oldInstallRoot 'old.txt') -Content 'old'
801+
Write-TestTextFile -Path (Join-Path $newInstallRoot 'new.txt') -Content 'new'
802+
803+
$result = [pscustomobject]@{
804+
ExistingPackage = [pscustomobject]@{
805+
Decision = 'ReplacePackageOwnedInstall'
806+
InstallDirectory = $oldInstallRoot
807+
}
808+
InstallDirectory = $newInstallRoot
809+
Readiness = [pscustomobject]@{
810+
Accepted = $true
811+
}
812+
Ownership = [pscustomobject]@{
813+
OwnershipRecord = [pscustomobject]@{
814+
ownershipKind = 'PackageInstalled'
815+
}
816+
}
817+
PackageConfig = [pscustomobject]@{
818+
PreferredTargetInstallRootDirectory = $preferredInstallRoot
819+
}
820+
}
821+
822+
$result = Remove-PackageReplacedPackageOwnedInstallDirectory -PackageResult $result
823+
824+
$result.ReplacementCleanup.Status | Should -Be 'Removed'
825+
Test-Path -LiteralPath $oldInstallRoot -PathType Container | Should -BeFalse
826+
Test-Path -LiteralPath $newInstallRoot -PathType Container | Should -BeTrue
827+
}
828+
607829
It 'discovers and reuses the current package target install path even when inventory is missing' {
608830
$rootPath = Join-Path $TestDrive 'reuse-managed-untracked'
609831
$installRoot = Join-Path $rootPath 'managed-install'

0 commit comments

Comments
 (0)