Feat/update preset validator (#14507)

# Description

This PR expands profile validation so we can catch backward
compatibility issues with custom presets generated by older OrcaSlicer
releases. It also adds missing `renamed_from` metadata for presets that
were renamed or moved, so older user presets can resolve their original
parent names against the current system profiles.

## Background

Many users have reported missing preset issues after upgrading past
2.4.1. Investigation showed two common causes:

- preset lookup and compatibility checks did not always account for
`renamed_from`
- some renamed base presets were missing the old preset name in their
`renamed_from` metadata

The existing profile workflow validates the current system profile tree
and a single nightly-generated custom preset bundle. That is useful for
catching current profile errors, but it does not validate user presets
generated by older OrcaSlicer versions against the current system
profiles. As a result, older missing-parent compatibility gaps can slip
through.

## Changes

- Update `check_profiles.yml` to validate historical custom preset
fixtures from `OrcaSlicer/OrcaSlicer-profile-validator`.
- Download the fixture manifest from the public `fixture-archive`
release.
- Validate each `orca_custom_presets_<version>.zip` fixture
independently against the current PR's `resources/profiles`.
- Generate per-version validation logs and upload them as workflow
artifacts.
- Fail profile validation if any historical fixture version fails.
- Add missing `renamed_from` aliases for renamed/moved presets found by
the historical fixture validation.

## Profile Compatibility Fixes

This PR adds aliases for older parent names including:

- `0.20mm Bambu Support W @BBL X1C` -> `0.20mm Standard @BBL X1C`
- `Bambu PLA Impact @BBL X1C` -> `Bambu PLA Impact @System`
- `Ginger Generic rPLA` -> `Ginger Generic PLA`
- `Ginger Generic rPETG` -> `Ginger Generic PETG`
- legacy `Panchroma PLA Stain` BBL filament names -> current `Panchroma
PLA Satin` names
- legacy Elegoo casing/name variants such as `Elegoo RAPID PLA+`,
`Elegoo RAPID PETG`, `Elegoo RAPID PETG+`, and `Elegoo PETG Pro @System`

## Validation Flow

The custom preset validation step now:

1. Downloads `manifest.json` from the `fixture-archive` release.
2. Iterates over every fixture listed in the manifest.
3. Copies the current branch's `resources/profiles` into a temporary
profile tree.
4. Removes any existing `user` directory from that temporary tree.
5. Unzips exactly one historical fixture into the temporary tree.
6. Runs `OrcaSlicer_profile_validator -p <temp profile tree> -l 2`.
7. Writes a version-specific log and a consolidated summary.

This keeps validation scoped per fixture version and avoids mixing
generated user presets from different OrcaSlicer releases.

## Fixture Source

Historical fixtures are stored as public release assets in:

`OrcaSlicer/OrcaSlicer-profile-validator`, release tag `fixture-archive`

Each release asset is expected to be named like:

```text
orca_custom_presets_v2.4.1.zip
```

## Testing

Validated locally with:

- current system profile validation
- BBL filament subtype validation
- historical custom preset fixture validation
- extra profile JSON check in a clean profile tree

The affected historical fixture set passed after adding the missing
`renamed_from` aliases.

The release manifest controls which fixture versions are validated.
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
This commit is contained in:
SoftFever
2026-07-02 18:47:49 +08:00
committed by GitHub
24 changed files with 132 additions and 9 deletions

View File

@@ -77,11 +77,101 @@ jobs:
continue-on-error: true
working-directory: ${{ github.workspace }}
run: |
set +e
curl -LJO https://github.com/OrcaSlicer/OrcaSlicer/releases/download/nightly-builds/orca_custom_preset_tests.zip
unzip -q ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_custom.log
exit ${PIPESTATUS[0]}
fixtures_dir="${{ runner.temp }}/profile-fixtures"
output_dir="${{ runner.temp }}/custom-preset-validation"
combined_log="${{ runner.temp }}/validate_custom.log"
summary="${output_dir}/summary.md"
release_url="https://github.com/OrcaSlicer/OrcaSlicer-profile-validator/releases/download/fixture-archive"
rm -rf "${fixtures_dir}" "${output_dir}"
mkdir -p "${fixtures_dir}" "${output_dir}"
curl -fsSL -o "${fixtures_dir}/manifest.json" "${release_url}/manifest.json"
MANIFEST_PATH="${fixtures_dir}/manifest.json" python3 <<'PY' > "${fixtures_dir}/fixtures.tsv"
import json
import os
with open(os.environ["MANIFEST_PATH"], encoding="utf-8") as fh:
manifest = json.load(fh)
if isinstance(manifest, dict):
entries = manifest.get("fixtures", [])
else:
entries = manifest
for entry in entries:
version = entry.get("version", "")
asset = entry.get("asset", "")
sha256 = entry.get("asset_sha256", "")
if not version or not asset:
continue
print(f"{version}\t{asset}\t{sha256}")
PY
if [ ! -s "${fixtures_dir}/fixtures.tsv" ]; then
echo "No custom preset fixtures found in ${release_url}/manifest.json" | tee "${combined_log}"
exit 1
fi
{
echo "## Custom Preset Fixture Validation"
echo ""
echo "| Version | Status | Log |"
echo "| --- | --- | --- |"
} > "${summary}"
status=0
failed_logs=()
while IFS=$'\t' read -r version asset expected_sha256; do
fixture_zip="${fixtures_dir}/${asset}"
asset_url_name="$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "${asset}")"
profile_tree="${output_dir}/profiles-${version}"
log_path="${output_dir}/${version}.log"
curl -fsSL -o "${fixture_zip}" "${release_url}/${asset_url_name}"
if [ -n "${expected_sha256}" ] && [ "${expected_sha256}" != "<sha256>" ]; then
echo "${expected_sha256} ${fixture_zip}" | sha256sum -c -
fi
rm -rf "${profile_tree}"
mkdir -p "${profile_tree}"
cp -a "${{ github.workspace }}/resources/profiles/." "${profile_tree}/"
rm -rf "${profile_tree}/user"
unzip -q "${fixture_zip}" -d "${profile_tree}"
set +e
./OrcaSlicer_profile_validator -p "${profile_tree}" -l 2 > "${log_path}" 2>&1
result=$?
set -e
if [ "${result}" -eq 0 ]; then
echo "| ${version} | PASS | ${version}.log |" >> "${summary}"
else
echo "| ${version} | FAIL | ${version}.log |" >> "${summary}"
failed_logs+=("${log_path}")
status=1
fi
done < "${fixtures_dir}/fixtures.tsv"
{
cat "${summary}"
if [ "${#failed_logs[@]}" -gt 0 ]; then
echo ""
echo "## Failed Fixture Logs"
for log_path in "${failed_logs[@]}"; do
echo ""
echo "### $(basename "${log_path}" .log)"
echo '```'
head -c 12000 "${log_path}" || echo "No output captured"
echo '```'
done
fi
} | tee "${combined_log}"
exit "${status}"
- name: Prepare PR number for comment workflow
if: ${{ always() && github.event_name == 'pull_request' }}

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.20mm Optimal 0.6 nozzle @Anker",
"renamed_from": "0.20mm Optimal 0.6 nozzle @Anker.json",
"inherits": "fdm_process_anker_common_0_6",
"from": "system",
"setting_id": "re5qmcOFJ1OJP3Ip",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Bambu PLA Tough @BBL X1C",
"renamed_from": "Bambu PLA Impact @BBL X1C",
"inherits": "Bambu PLA Tough @base",
"from": "system",
"setting_id": "GFSA09_02",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Panchroma PLA Satin @BBL A1",
"renamed_from": "Panchroma PLA Stain @BBL A1",
"inherits": "Panchroma PLA Satin @base",
"from": "system",
"setting_id": "GFSPM005_00",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Panchroma PLA Satin @BBL A1M",
"renamed_from": "Panchroma PLA Stain @BBL A1M",
"inherits": "Panchroma PLA Satin @base",
"from": "system",
"setting_id": "GFSPM005_02",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Panchroma PLA Satin @BBL P1P",
"renamed_from": "Panchroma PLA Stain @BBL P1P",
"inherits": "Panchroma PLA Satin @base",
"from": "system",
"setting_id": "GFSPM005_04",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Panchroma PLA Satin @BBL X1",
"renamed_from": "Panchroma PLA Stain @BBL X1",
"inherits": "Panchroma PLA Satin @base",
"from": "system",
"setting_id": "GFSPM005_06",

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.20mm Standard @BBL X1C",
"renamed_from": "0.20mm Bambu Support W @BBL X1C",
"inherits": "fdm_process_single_0.20",
"from": "system",
"setting_id": "GP004",

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.12mm Fine @Creality Ender3V3SE 0.4",
"renamed_from": "0.12mm Fine @Creality Ender3V3SE",
"inherits": "fdm_process_creality_common",
"from": "system",
"setting_id": "W68mSPdmat2rCXuD",

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.16mm Optimal @Creality Ender3V3SE 0.4",
"renamed_from": "0.16mm Optimal @Creality Ender3V3SE",
"inherits": "fdm_process_creality_common",
"from": "system",
"setting_id": "jvnrh3jh6Btbs1Ja",

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.20mm Standard @Creality Ender3V3SE 0.4",
"renamed_from": "0.20mm Standard @Creality Ender3V3SE",
"inherits": "fdm_process_creality_common",
"from": "system",
"setting_id": "YLkw9eyyK7cm97ek",

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.20mm Standard @Creality K1 SE",
"renamed_from": "0.20mm Fast @Creality K1 SE 0.4",
"inherits": "fdm_process_creality_common",
"from": "system",
"setting_id": "eR9pRC1qPENNx8U9",
@@ -264,4 +265,4 @@
"wipe_tower_extra_spacing": "100%",
"wipe_tower_rotation_angle": "0",
"wiping_volumes_extruders": "70,70,70,70,70,70,70,70,70,70"
}
}

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.24mm Draft @Creality Ender3V3SE 0.4",
"renamed_from": "0.24mm Draft @Creality Ender3V3SE",
"inherits": "fdm_process_creality_common",
"from": "system",
"setting_id": "Hg10EUNCLMEYYBN1",

View File

@@ -1,6 +1,7 @@
{
"type": "process",
"name": "0.48mm Draft @Creality K1C",
"renamed_from": "0.48mm Draft @Creality K1C (0.8 nozzle)",
"inherits": "fdm_process_common_klipper",
"from": "system",
"setting_id": "qaiff3f8gSQ1GVj1",

View File

@@ -2,6 +2,7 @@
"type": "filament",
"setting_id": "pKzSR8XeyyUDbrNW",
"name": "Generic PETG PRO @Elegoo",
"renamed_from": "Elegoo Generic PETG PRO",
"from": "system",
"instantiation": "true",
"inherits": "Generic PETG @base",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Ginger Generic PETG",
"renamed_from": "Ginger Generic rPETG",
"inherits": "fdm_filament_common",
"from": "system",
"setting_id": "ue95N2e65rdp5K6c",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Ginger Generic PLA",
"renamed_from": "Ginger Generic rPLA",
"inherits": "fdm_filament_common",
"from": "system",
"setting_id": "Z1scjKDBFoDaTa2C",

View File

@@ -18,5 +18,5 @@
"5"
],
"compatible_printers": [],
"renamed_from": "Elegoo PETG PRO"
"renamed_from": "Elegoo PETG PRO;Elegoo PETG Pro @System"
}

View File

@@ -33,5 +33,5 @@
"250"
],
"compatible_printers": [],
"renamed_from": "Elegoo Rapid PETG;Elegoo Rapid PETG+"
"renamed_from": "Elegoo Rapid PETG;Elegoo Rapid PETG+;Elegoo RAPID PETG;Elegoo RAPID PETG+"
}

View File

@@ -45,5 +45,5 @@
"; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}"
],
"compatible_printers": [],
"renamed_from": "Elegoo Rapid PLA+"
"renamed_from": "Elegoo Rapid PLA+;Elegoo RAPID PLA+"
}

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Peopoly Generic PLA",
"renamed_from": "Peopoly Generic PLA 0.8 nozzle",
"inherits": "fdm_filament_pla",
"from": "system",
"setting_id": "KNsVV4dvEWAAkzDE",

View File

@@ -1,6 +1,7 @@
{
"type": "filament",
"name": "Snapmaker PLA",
"renamed_from": "PolyLite PLA",
"inherits": "Snapmaker PLA @base",
"from": "system",
"setting_id": "cW1b4nGxE9yXIXJP",

View File

@@ -206,6 +206,10 @@
"name": "0.24mm Fine 0.8 nozzle @Voron",
"sub_path": "process/0.24mm Fine 0.8 nozzle @Voron.json"
},
{
"name": "0.32mm Optimal 0.8 nozzle @Voron",
"sub_path": "process/0.32mm Optimal 0.8 nozzle @Voron.json"
},
{
"name": "0.40mm Standard 0.8 nozzle @Voron",
"sub_path": "process/0.40mm Standard 0.8 nozzle @Voron.json"

View File

@@ -0,0 +1,11 @@
{
"type": "process",
"name": "0.32mm Optimal 0.8 nozzle @Voron",
"inherits": "fdm_process_voron_common_0_8",
"from": "system",
"setting_id": "ivS6U4AuIoj1cJhZ",
"instantiation": "true",
"bottom_shell_layers": "3",
"top_shell_layers": "3",
"layer_height": "0.32"
}