mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-02 16:41:11 +00:00
# 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)
253 lines
9.7 KiB
YAML
253 lines
9.7 KiB
YAML
name: Check profiles
|
|
on:
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- 'resources/profiles/**'
|
|
- ".github/workflows/check_profiles.yml"
|
|
|
|
workflow_dispatch:
|
|
inputs:
|
|
logLevel:
|
|
description: 'Log level'
|
|
required: true
|
|
default: 'warning'
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
|
|
jobs:
|
|
check_profiles:
|
|
name: Check profiles
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Run extra JSON check
|
|
id: extra_json_check
|
|
continue-on-error: true
|
|
run: |
|
|
set +e
|
|
python3 ./scripts/orca_extra_profile_check.py 2>&1 | tee ${{ runner.temp }}/extra_json_check.log
|
|
exit ${PIPESTATUS[0]}
|
|
|
|
# download
|
|
- name: Download
|
|
working-directory: ${{ github.workspace }}
|
|
run: |
|
|
curl -L -o OrcaSlicer_profile_validator https://github.com/OrcaSlicer/OrcaSlicer/releases/download/nightly-builds/OrcaSlicer_profile_validator_Linux_Ubuntu2404_nightly
|
|
chmod +x ./OrcaSlicer_profile_validator
|
|
|
|
# validate profiles
|
|
- name: validate system profiles
|
|
id: validate_system
|
|
continue-on-error: true
|
|
run: |
|
|
set +e
|
|
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_system.log
|
|
exit ${PIPESTATUS[0]}
|
|
# For now run filament subtype check only for BBL profiles until we fix other vendors' profiles.
|
|
- name: validate filament subtype check for BBL profiles
|
|
id: validate_filament_subtypes
|
|
continue-on-error: true
|
|
run: |
|
|
set +e
|
|
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 -v BBL -f 2>&1 | tee ${{ runner.temp }}/validate_filament_subtypes.log
|
|
exit ${PIPESTATUS[0]}
|
|
# Flag inherits/compatible_printers/compatible_prints references that point at a deleted or
|
|
# renamed preset. Opt-in per vendor for now (via -r); enabled for BBL and Qidi until other
|
|
# vendors' profiles are cleaned up. Runs before the custom-preset injection below.
|
|
- name: validate preset references for BBL and Qidi profiles
|
|
id: validate_preset_references
|
|
continue-on-error: true
|
|
run: |
|
|
set +e
|
|
rc=0
|
|
for v in BBL Qidi; do
|
|
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 -v "$v" -r 2>&1 | tee -a ${{ runner.temp }}/validate_preset_references.log
|
|
[ ${PIPESTATUS[0]} -ne 0 ] && rc=1
|
|
done
|
|
exit $rc
|
|
|
|
- name: validate custom presets
|
|
id: validate_custom
|
|
continue-on-error: true
|
|
working-directory: ${{ github.workspace }}
|
|
run: |
|
|
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' }}
|
|
run: |
|
|
mkdir -p ${{ runner.temp }}/profile-check-results
|
|
echo "${{ github.event.pull_request.number }}" > ${{ runner.temp }}/profile-check-results/pr_number.txt
|
|
|
|
- name: Prepare comment artifact
|
|
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_filament_subtypes.outcome == 'failure' || steps.validate_preset_references.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
|
|
run: |
|
|
{
|
|
# Marker matched by check_profiles_comment.yml to delete prior comments.
|
|
echo "<!-- profile-validation-comment -->"
|
|
echo "## :x: Profile Validation Errors"
|
|
echo ""
|
|
|
|
if [ "${{ steps.extra_json_check.outcome }}" = "failure" ]; then
|
|
echo "### Extra JSON Check Failed"
|
|
echo ""
|
|
echo '```'
|
|
head -c 30000 ${{ runner.temp }}/extra_json_check.log || echo "No output captured"
|
|
echo '```'
|
|
echo ""
|
|
fi
|
|
|
|
if [ "${{ steps.validate_system.outcome }}" = "failure" ]; then
|
|
echo "### System Profile Validation Failed"
|
|
echo ""
|
|
echo '```'
|
|
head -c 30000 ${{ runner.temp }}/validate_system.log || echo "No output captured"
|
|
echo '```'
|
|
echo ""
|
|
fi
|
|
|
|
if [ "${{ steps.validate_filament_subtypes.outcome }}" = "failure" ]; then
|
|
echo "### BBL Filament Subtype Validation Failed"
|
|
echo ""
|
|
echo '```'
|
|
head -c 30000 ${{ runner.temp }}/validate_filament_subtypes.log || echo "No output captured"
|
|
echo '```'
|
|
echo ""
|
|
fi
|
|
|
|
if [ "${{ steps.validate_preset_references.outcome }}" = "failure" ]; then
|
|
echo "### BBL/Qidi Preset Reference Validation Failed"
|
|
echo ""
|
|
echo '```'
|
|
head -c 30000 ${{ runner.temp }}/validate_preset_references.log || echo "No output captured"
|
|
echo '```'
|
|
echo ""
|
|
fi
|
|
|
|
if [ "${{ steps.validate_custom.outcome }}" = "failure" ]; then
|
|
echo "### Custom Preset Validation Failed"
|
|
echo ""
|
|
echo '```'
|
|
head -c 30000 ${{ runner.temp }}/validate_custom.log || echo "No output captured"
|
|
echo '```'
|
|
echo ""
|
|
fi
|
|
|
|
echo "---"
|
|
echo "*Please fix the above errors and push a new commit.*"
|
|
} > ${{ runner.temp }}/profile-check-results/pr_comment.md
|
|
|
|
- name: Upload comment artifact
|
|
if: ${{ always() && github.event_name == 'pull_request' }}
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: profile-check-results
|
|
path: ${{ runner.temp }}/profile-check-results/
|
|
retention-days: 1
|
|
|
|
- name: Fail if any check failed
|
|
if: ${{ always() && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_filament_subtypes.outcome == 'failure' || steps.validate_preset_references.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
|
|
run: |
|
|
echo "One or more profile checks failed. See above for details."
|
|
exit 1
|