diff --git a/scripts/check_profile.ps1 b/scripts/check_profile.ps1 index c016e8f299..c38d31167e 100644 --- a/scripts/check_profile.ps1 +++ b/scripts/check_profile.ps1 @@ -5,11 +5,13 @@ .DESCRIPTION The Windows counterpart of scripts/check_profile.sh, and kept deliberately close to it. - Runs the same five checks, in the same order, with the same validator flags, and with the + Runs the same six checks, in the same order, with the same validator flags, and with the same semantics: every check runs even after an earlier one fails (the workflow's continue-on-error), then the script exits non-zero once at the end. profile_tool scripts/orca_profile_tool.py check + legacy_compat scripts/orca_profile_tool.py legacy-compat --check against + the v2.4.2 profiles validate_system validator -p -l validate_slice validator -p -s -l validate_filament_subtypes validator -p -l -f @@ -20,8 +22,9 @@ never sees a profile no .json indexes, a preset name two files claim, or a file normalize and update-index would still rewrite. - Everything that has to be downloaded - the profile validator and the custom-preset fixture - archives - lands under a per-user cache directory (%LOCALAPPDATA%\orca-profile-check) and + Everything that has to be downloaded - the profile validator, the custom-preset fixture + archives and the v2.4.2 profile tree - lands under a per-user cache directory + (%LOCALAPPDATA%\orca-profile-check) and is reused on the next run. Being outside the checkout, that directory is shared by every worktree on the machine. It also holds one log per check plus a copy of the comment CI would post on the PR. @@ -48,7 +51,8 @@ check it cannot narrow is validate_slice for a vendor that ships no printers; the summary reports that one as skipped, and naming it explicitly still runs it. profile_tool keeps its two cross-vendor checks (setting_id and filament_id) tree-wide, so a scoped run can still - fail on another vendor's files. + fail on another vendor's files, and legacy_compat is tree-wide too: the map it checks covers + every vendor. .PARAMETER Validator OrcaSlicer_profile_validator.exe to use; also $env:ORCA_PROFILE_VALIDATOR. Default: the local @@ -116,7 +120,7 @@ $HostArch = switch ($HostArch) { default { 'x86' } } -$AllChecks = @('profile_tool', 'validate_system', 'validate_slice', 'validate_filament_subtypes', 'validate_custom') +$AllChecks = @('profile_tool', 'legacy_compat', 'validate_system', 'validate_slice', 'validate_filament_subtypes', 'validate_custom') $script:LogWriter = $null $script:Python = '' @@ -439,6 +443,43 @@ function Expand-VendorPresets([string] $Zip, [string] $Tree, [string] $Prefix) { return $kept } +# The profile tree of the release resources\info\legacy_compatible_printers.json is generated +# against. The tag is immutable, so the extracted tree is cached in the work dir and -Refresh +# re-extracts it. A checkout without the tag (a shallow clone, a fork that never fetched tags) +# gets it from upstream, as CI does. git archive writes a file rather than a pipe, which +# PowerShell would re-encode, and tar.exe ships with Windows 10 and later. +$LegacyBaseTag = 'v2.4.2' +$LegacyBaseUrl = 'https://github.com/OrcaSlicer/OrcaSlicer.git' + +function Get-LegacyBaseProfiles { + $ErrorActionPreference = 'Continue' + $base = Join-Path (Join-Path $WorkDir 'legacy-base') $LegacyBaseTag + $profiles = Join-Path (Join-Path $base 'resources') 'profiles' + if ($Refresh -or -not (Test-Path -LiteralPath $profiles -PathType Container)) { + & git -C $RepoRoot rev-parse -q --verify "refs/tags/$LegacyBaseTag^{commit}" 2>$null | Out-Null + if ($LASTEXITCODE -ne 0) { + Write-Host "fetching tag $LegacyBaseTag from $LegacyBaseUrl ..." + & git -C $RepoRoot fetch --no-tags $LegacyBaseUrl "refs/tags/${LegacyBaseTag}:refs/tags/${LegacyBaseTag}" + if ($LASTEXITCODE -ne 0) { throw "cannot fetch tag $LegacyBaseTag" } + } + # Extracted beside its final place and moved there whole, so an interrupted extraction is + # never mistaken for the tree on the next run. + $partial = "$base.partial" + foreach ($dir in $base, $partial) { + if (Test-Path -LiteralPath $dir) { Remove-Item -LiteralPath $dir -Recurse -Force } + } + New-Item -ItemType Directory -Force -Path $partial | Out-Null + $archive = Join-Path $partial 'profiles.tar' + & git -C $RepoRoot archive -o $archive $LegacyBaseTag resources/profiles + if ($LASTEXITCODE -ne 0) { throw "cannot archive resources/profiles of $LegacyBaseTag" } + & tar -xf $archive -C $partial + if ($LASTEXITCODE -ne 0) { throw "cannot extract $archive" } + Remove-Item -LiteralPath $archive -Force + Move-Item -LiteralPath $partial -Destination $base + } + return $profiles +} + # ---------------------------------------------------------------------------- checks $CheckBodies = @{ @@ -447,6 +488,14 @@ $CheckBodies = @{ Invoke-Tool -Exe (Resolve-Python) -Arguments (@((Join-Path $RepoRoot 'scripts\orca_profile_tool.py'), 'check', '--profiles', $ProfilesDir) + $VendorPyArgs) } + # The map says which printers a user filament preset made against 2.4.2 can be migrated + # back to, so a profile change that renames a filament preset or narrows its + # compatible_printers has to regenerate it (the CI comment gives the command). + legacy_compat = { + $base = Get-LegacyBaseProfiles + Invoke-Tool -Exe (Resolve-Python) -Arguments @((Join-Path $RepoRoot 'scripts\orca_profile_tool.py'), 'legacy-compat', '--profiles', $ProfilesDir, '--base', $base, '--check') + } + validate_system = { Invoke-Tool -Exe $Validator -Arguments (@('-p', $ProfilesDir) + $VendorArgs + @('-l', "$LogLevel")) } @@ -581,6 +630,7 @@ $CheckBodies = @{ # Heading CI puts above this check's log in the PR comment. $CommentHeadings = @{ profile_tool = '### Profile Check Failed (orca_profile_tool.py)' + legacy_compat = '### Legacy Compatible Printers Map Out of Date' validate_system = '### System Profile Validation Failed' validate_slice = '### Slice Validation Failed (custom g-code expansion)' validate_filament_subtypes = '### Filament Subtype Validation Failed' @@ -627,7 +677,7 @@ try { [Console]::OutputEncoding = New-Object Text.UTF8Encoding($false) Push-UserPresets - if ($Checks | Where-Object { $_ -ne 'profile_tool' }) { $Validator = Resolve-Validator } + if ($Checks | Where-Object { $_ -ne 'profile_tool' -and $_ -ne 'legacy_compat' }) { $Validator = Resolve-Validator } # An empty printer set is a failure to the sweep, so validate_slice is recorded as skipped # rather than run for a vendor that ships no printers (the filament-only OrcaFilamentLibrary); diff --git a/scripts/check_profile.sh b/scripts/check_profile.sh index a6d7ca3b2e..9eddf71d3a 100755 --- a/scripts/check_profile.sh +++ b/scripts/check_profile.sh @@ -2,12 +2,13 @@ # # Local twin of the "Check profiles" CI job (.github/workflows/check_profiles.yml). # -# Runs the same five checks, in the same order, with the same validator flags, and with the +# Runs the same six checks, in the same order, with the same validator flags, and with the # same semantics: every check runs even after an earlier one fails (the workflow's # continue-on-error), then the script exits non-zero once at the end. # -# Everything that has to be downloaded - the profile validator and the custom-preset fixture -# archives - lands under a per-user cache directory and is reused on the next run. Being outside +# Everything that has to be downloaded - the profile validator, the custom-preset fixture +# archives and the v2.4.2 profile tree - lands under a per-user cache directory and is reused on +# the next run. Being outside # the checkout, that directory is shared by every worktree on the machine. It also holds one log # per check plus a copy of the comment CI would post on the PR. # @@ -58,7 +59,7 @@ LOG_LEVEL=2 PREFER_DOWNLOAD=0 REFRESH=0 -ALL_CHECKS=(profile_tool validate_system validate_slice validate_filament_subtypes validate_custom) +ALL_CHECKS=(profile_tool legacy_compat validate_system validate_slice validate_filament_subtypes validate_custom) CHECKS=() # "pass|fail" per check that ran, plus "skipwhy" for one a vendor # scope left out; a string rather than an array because bash 3.2 (still the /bin/bash on macOS) @@ -73,6 +74,8 @@ Usage: scripts/check_profile.sh [OPTION]... [CHECK]... Checks (default: all, in this order): profile_tool scripts/orca_profile_tool.py check + legacy_compat scripts/orca_profile_tool.py legacy-compat --check against the + v2.4.2 profiles validate_system validator -p -l validate_slice validator -p -s -l validate_filament_subtypes validator -p -l -f @@ -100,7 +103,8 @@ Note: --vendor narrows validate_custom too, by keeping only that vendor's preset fixture tree. The one check it cannot narrow is validate_slice for a vendor that ships no printers; the summary reports that one as skipped, and naming it explicitly still runs it. profile_tool keeps its two cross-vendor checks (setting_id and filament_id) tree-wide, so a -scoped run can still fail on another vendor's files. +scoped run can still fail on another vendor's files, and legacy_compat is tree-wide too: the map +it checks covers every vendor. EOF } @@ -379,6 +383,44 @@ check_profile_tool() { python3 "${REPO_ROOT}/scripts/orca_profile_tool.py" check --profiles "${PROFILES_DIR}" --vendor "${VENDOR}" } +# The profile tree of the release resources/info/legacy_compatible_printers.json is generated +# against. The tag is immutable, so the extracted tree is cached in the work dir and --refresh +# re-extracts it. A checkout without the tag (a shallow clone, a fork that never fetched tags) +# gets it from upstream, as CI does. +LEGACY_BASE_TAG="v2.4.2" +LEGACY_BASE_URL="https://github.com/OrcaSlicer/OrcaSlicer.git" + +legacy_base_profiles() { + local base="${WORK_DIR}/legacy-base/${LEGACY_BASE_TAG}" + if [ "${REFRESH}" -eq 1 ] || [ ! -d "${base}/resources/profiles" ]; then + if ! git -C "${REPO_ROOT}" rev-parse -q --verify "refs/tags/${LEGACY_BASE_TAG}^{commit}" >/dev/null; then + msg "fetching tag ${LEGACY_BASE_TAG} from ${LEGACY_BASE_URL} ..." + git -C "${REPO_ROOT}" fetch --no-tags "${LEGACY_BASE_URL}" \ + "refs/tags/${LEGACY_BASE_TAG}:refs/tags/${LEGACY_BASE_TAG}" || return 1 + fi + # Extracted beside its final place and moved there whole, so an interrupted extraction is + # never mistaken for the tree on the next run. + local partial="${base}.partial" + rm -rf "${base}" "${partial}" + mkdir -p "${partial}" || return 1 + if ! git -C "${REPO_ROOT}" archive "${LEGACY_BASE_TAG}" resources/profiles | tar -x -C "${partial}"; then + rm -rf "${partial}" + return 1 + fi + mv "${partial}" "${base}" || return 1 + fi + printf '%s\n' "${base}/resources/profiles" +} + +# The map says which printers a user filament preset made against 2.4.2 can be migrated back +# to, so a profile change that renames a filament preset or narrows its compatible_printers has +# to regenerate it (the CI comment gives the command). +check_legacy_compat() { + local base + base="$(legacy_base_profiles)" || return 1 + python3 "${REPO_ROOT}/scripts/orca_profile_tool.py" legacy-compat --profiles "${PROFILES_DIR}" --base "${base}" --check +} + check_validate_system() { "${VALIDATOR}" -p "${PROFILES_DIR}" -v "${VENDOR}" -l "${LOG_LEVEL}" } @@ -563,6 +605,7 @@ EOF comment_heading() { case "$1" in profile_tool) echo "### Profile Check Failed (orca_profile_tool.py)" ;; + legacy_compat) echo "### Legacy Compatible Printers Map Out of Date" ;; validate_system) echo "### System Profile Validation Failed" ;; validate_slice) echo "### Slice Validation Failed (custom g-code expansion)" ;; validate_filament_subtypes) echo "### Filament Subtype Validation Failed" ;;