diff --git a/images.CI/macos/anka/CreateCleanAnkaTemplate.ps1 b/images.CI/macos/anka/CreateCleanAnkaTemplate.ps1 index a140c3948..634734b69 100644 --- a/images.CI/macos/anka/CreateCleanAnkaTemplate.ps1 +++ b/images.CI/macos/anka/CreateCleanAnkaTemplate.ps1 @@ -81,8 +81,9 @@ function Invoke-SoftwareUpdate { Write-Host "`t[*] Fetching Software Updates ready to install on '$TemplateName' VM:" Show-StringWithFormat $newUpdates + $listOfNewUpdates = $($($newUpdates.Split("*")).Split("Title") | Where-Object {$_ -match "Label:"}).Replace("Label: ", '') Write-Host "`t[*] Installing Software Updates on '$TemplateName' VM:" - Install-SoftwareUpdate -HostName $ipAddress | Show-StringWithFormat + Install-SoftwareUpdate -HostName $ipAddress -listOfUpdates $listOfNewUpdates | Show-StringWithFormat # Check if Action: restart if ($newUpdates.Contains("Action: restart")) { @@ -145,10 +146,16 @@ $env:SSHUSER = $TemplateUsername $env:SSHPASS = $TemplatePassword Write-Host "`n[#1] Download macOS application installer:" -$macOSInstaller = Get-MacOSInstaller -MacOSVersion $MacOSVersion -DownloadLatestVersion $DownloadLatestVersion -BetaSearch $BetaSearch $shortMacOSVersion = Get-ShortMacOSVersion -MacOSVersion $MacOSVersion if ([string]::IsNullOrEmpty($TemplateName)) { - $TemplateName = "clean_macos_${shortMacOSVersion}_${DiskSizeGb}gb" + $osArch = $(arch) + if ($osArch -eq "arm64"){ + $macOSInstaller = Get-MacOSIPSWInstaller -MacOSVersion $MacOSVersion -DownloadLatestVersion $DownloadLatestVersion -BetaSearch $BetaSearch + $TemplateName = "clean_macos_${shortMacOSVersion}_${osArch}_${DiskSizeGb}gb" + } else { + $macOSInstaller = Get-MacOSInstaller -MacOSVersion $MacOSVersion -DownloadLatestVersion $DownloadLatestVersion -BetaSearch $BetaSearch + $TemplateName = "clean_macos_${shortMacOSVersion}_${DiskSizeGb}gb" + } } Write-Host "`n[#2] Create a VM template:" diff --git a/images.CI/macos/anka/Service.Helpers.psm1 b/images.CI/macos/anka/Service.Helpers.psm1 index 5d659d8da..96a663a18 100644 --- a/images.CI/macos/anka/Service.Helpers.psm1 +++ b/images.CI/macos/anka/Service.Helpers.psm1 @@ -37,6 +37,84 @@ function Get-AvailableVersions { $allVersions } +function Get-AvailableIPSWVersions { + param ( + [bool] $IsBeta = $false, + [bool] $IsLatest = $true, + [string] $MacOSCodeNameOrVersion + ) + + if ($IsBeta) { + $command = { mist list installer "$MacOSCodeNameOrVersion" --include-betas --latest --export "/Applications/export.json"} + } elseif ($IsLatest) { + $command = { mist list installer "$MacOSCodeNameOrVersion" --latest --export "/Applications/export.json" } + } else { + $command = { mist list installer "$MacOSCodeNameOrVersion" --export "/Applications/export.json" } + } + + $condition = { $LASTEXITCODE -eq 0 } + Invoke-WithRetry -Command $command -BreakCondition $condition | Out-Null + $softwareList = get-content -Path "/Applications/export.json" + $turgetVersion = ($softwareList | ConvertFrom-Json).version + if ($null -eq $turgetVersion) { + Write-Host "Requested macOS '$MacOSCodeNameOrVersion' version not found in the list of available installers." + $command = { mist list installer "$($MacOSCodeNameOrVersion.split('.')[0])" } + Invoke-WithRetry -Command $command -BreakCondition $condition + exit 1 + } + return $turgetVersion +} + +function Get-MacOSIPSWInstaller { + param ( + [Parameter(Mandatory)] + [version] $MacOSVersion, + + [bool] $DownloadLatestVersion = $false, + [bool] $BetaSearch = $false + ) + + if ($MacOSVersion -eq [version] "12.0") { + $MacOSName = "macOS Monterey" + } elseif ($MacOSVersion -eq [version] "13.0") { + $MacOSName = "macOS Ventura" + } else { + $MacOSName = $MacOSVersion.ToString() + } + + + Write-Host "`t[*] Finding available full installers" + if ($DownloadLatestVersion -eq $true) { + $targetVersion = Get-AvailableIPSWVersions -IsLatest $true -MacOSCodeNameOrVersion $MacOSName + Write-host "`t[*] The 'DownloadLatestVersion' flag is set to true. Latest macOS version is '$MacOSName' - '$targetVersion' now" + } elseif ($BetaSearch -eq $true) { + $targetVersion = Get-AvailableIPSWVersions -IsBeta $true -MacOSCodeNameOrVersion $MacOSName + Write-host "`t[*] The 'BetaSearch' flag is set to true. Latestbeta macOS version is '$MacOSName' - '$targetVersion' now" + } else { + $targetVersion = Get-AvailableIPSWVersions -MacOSCodeNameOrVersion $MacOSName + Write-host "`t[*] The exact version was specified - '$MacOSName' " + } + + $installerPathPattern = "/Applications/Install ${macOSName}*.ipsw" + if (Test-Path $installerPathPattern) { + $previousInstallerPath = Get-Item -Path $installerPathPattern + Write-Host "`t[*] Removing '$previousInstallerPath' installation app before downloading the new one" + sudo rm -rf "$previousInstallerPath" + } + + # Download macOS installer + $installerDir = "/Applications/" + $installerName = "Install ${macOSName}.ipsw" + Write-Host "`t[*] Requested macOS '$targetVersion' version installer found, fetching it from mist database" + Invoke-WithRetry { mist download firmware "$targetVersion" --output-directory $installerDir --firmware-name "$installerName" } {$LASTEXITCODE -eq 0} | Out-Null + if (Test-Path "$installerDir$installerName") { + $result = "$installerDir$installerName" + } else { + Write-host "`t[*] Requested macOS '$targetVersion' version installer failed to download" + exit 1 + } + return $result +} function Get-MacOSInstaller { param ( [Parameter(Mandatory)] @@ -71,7 +149,7 @@ function Get-MacOSInstaller { Show-StringWithFormat $availableVersions exit 1 } - Show-StringWithFormat $filteredVersions + Show-StringWithFormat $filteredVersions $osVersions = $filteredVersions.OSVersion | Sort-Object {[version]$_} $MacOSVersion = $osVersions | Select-Object -Last 1 Write-Host "`t[*] The 'DownloadLatestVersion' flag is set. Latest macOS version is '$MacOSVersion' now" @@ -150,11 +228,24 @@ function Install-SoftwareUpdate { param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] - [string] $HostName + [string] $HostName, + [array] $listOfUpdates ) - - $command = "sudo /usr/sbin/softwareupdate --all --install --restart --verbose" - Invoke-SSHPassCommand -HostName $HostName -Command $command + $osVersion = [Environment]::OSVersion + $osVersionMajorMinor = $osVersion.Version.ToString(2) + # If an update is happening on macOS 12 we will use the prepared list of updates, otherwise, we will install all updates. + if ($osVersion.Version.Major -eq "12") { + foreach ($update in $listOfUpdates){ + # Filtering updates that contain "Ventura" word + if ($update -notmatch "Ventura") { + $command = "sudo /usr/sbin/softwareupdate --restart --verbose --install $update" + Invoke-SSHPassCommand -HostName $HostName -Command $command + } + } + } else { + $command = "sudo /usr/sbin/softwareupdate --all --install --restart --verbose" + Invoke-SSHPassCommand -HostName $HostName -Command $command + } } function Invoke-SSHPassCommand { @@ -232,7 +323,7 @@ function Show-StringWithFormat { [Parameter(ValuefromPipeline)] [object] $string ) - + process { ($string | Out-String).Trim().split("`n") | ForEach-Object { Write-Host "`t $_" } }