mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-01 14:27:00 +00:00
Merge branch 'main' into feature/filament_id
Brings in 560 commits (merge base 2026-07-04 .. origin/main af9fd10d7a).
19 conflicts resolved; the other 138 touched files auto-merged.
Conflict resolutions
- Snapmaker/Polymaker (7): main normalised JSON key order in #15039 while this
branch inserted filament_id/filament_vendor. Took main's key order and kept
this branch's values, inserting a single filament_id key rather than letting
git's line merge leave duplicate "from"/"instantiation" keys.
- re3D rPETG @0.8/@1.75 nozzle (2): main renamed these from "re3D Greengate
rPETG @*" and re-vendored GreenGate3D -> re3D (#15169). Git's rename-aware
merge produced a file with two filament_vendor keys; took main's version
wholesale instead. The id is reconciled by the tooling, not by hand.
- re3D rPP (1): kept main's inherits change (fdm_filament_pet -> fdm_filament_pp,
local filament_type override dropped) and its widened compatible_printers.
The flattened type is still PP, so the product triple and id OFfHGM1D are
unchanged.
- re3D Greengate rPETG.json, Afinia {ABS+,ABS,PLA,TPU,Value ABS,Value PLA}.json
(7 modify/delete): accepted main's deletions. The Afinia ids are not orphaned
- the surviving @HS presets resolve the same triple and already carry the
same ids, so nothing is retired.
- .github/workflows/check_profiles.yml: kept both main's new "validate slice"
step and this branch's tree-wide filament-subtype check.
- tests/libslic3r/CMakeLists.txt: kept both test_filament_id_succession.cpp and
main's test_preset_diff.cpp.
Verified
- No conflict markers; all 12795 profile JSONs parse with no duplicate keys.
- All branch artifacts (tooling, snapshot, ledger, doc, tests) intact and
unmodified by the merge.
- The succession-ledger C++ call sites survived main's refactors; audited
Preset.{cpp,hpp}, PresetBundle.cpp, DeviceManager.cpp, PresetComboBoxes.cpp,
CaliHistoryDialog.cpp, MoonrakerPrinterAgent.cpp against base/ours/theirs.
- scripts/tests: 115/116 pass.
Known follow-up: assign_filament_ids.py --check reports 243 errors, all from
filament data main added in the last month (BBL/addnorth, Qidi X5/Plus 5,
Snapmaker U1, re3D). The single failing unit test is the live-tree conformance
test asserting that count is zero. Reconciliation lands separately.
This commit is contained in:
10
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
10
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -32,9 +32,17 @@ body:
|
||||
attributes:
|
||||
label: OrcaSlicer Version
|
||||
description: Which version of Orca Slicer are you running? You can see the full version in `Help` -> `About Orca Slicer`.
|
||||
placeholder: e.g. 1.9.0
|
||||
placeholder: e.g. 2.5.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: working_version
|
||||
attributes:
|
||||
label: Regression compared to a previous version
|
||||
description: Did it work in a previous version?
|
||||
placeholder: e.g. 2.3.2
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
id: os_type
|
||||
attributes:
|
||||
|
||||
139
.github/workflows/build_all.yml
vendored
139
.github/workflows/build_all.yml
vendored
@@ -57,17 +57,13 @@ jobs:
|
||||
build_linux:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# Build both arches on every event (PRs included), through the same
|
||||
# build_check_cache -> build_deps -> build_orca chain (the AppImage).
|
||||
# aarch64 always uses the GitHub-hosted arm runner (there is no arm
|
||||
# self-hosted server). amd64's empty arch is load-bearing: it keeps the
|
||||
# historical 'linux-clang' deps cache key and the unsuffixed asset names.
|
||||
# SELF_HOSTED skips arm64 (no arm self-hosted server). amd64's empty arch
|
||||
# is load-bearing: it keeps the historical 'linux-clang' deps cache key and
|
||||
# the unsuffixed asset names.
|
||||
matrix:
|
||||
include:
|
||||
- arch: ""
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }}
|
||||
- arch: "aarch64"
|
||||
os: ubuntu-24.04-arm
|
||||
include: ${{ fromJSON(vars.SELF_HOSTED
|
||||
&& '[{"arch":"","os":"orca-lnx-server"}]'
|
||||
|| '[{"arch":"","os":"ubuntu-24.04"},{"arch":"aarch64","os":"ubuntu-24.04-arm"}]') }}
|
||||
# Don't run scheduled builds on forks:
|
||||
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
|
||||
uses: ./.github/workflows/build_check_cache.yml
|
||||
@@ -80,18 +76,16 @@ jobs:
|
||||
name: Build Windows ${{ matrix.arch }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# SELF_HOSTED skips arm64 (the self-hosted Windows server is x64-only).
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
os: windows-latest
|
||||
- arch: arm64
|
||||
os: windows-11-arm
|
||||
include: ${{ fromJSON(vars.SELF_HOSTED
|
||||
&& '[{"arch":"x64","os":"orca-win-server"}]'
|
||||
|| '[{"arch":"x64","os":"windows-latest"},{"arch":"arm64","os":"windows-11-arm"}]') }}
|
||||
# Don't run scheduled builds on forks:
|
||||
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
|
||||
uses: ./.github/workflows/build_check_cache.yml
|
||||
with:
|
||||
# Self-hosted runner is x64-only; ARM64 always uses the GitHub-hosted runner.
|
||||
os: ${{ (matrix.arch == 'x64' && vars.SELF_HOSTED) && 'orca-win-server' || matrix.os }}
|
||||
os: ${{ matrix.os }}
|
||||
arch: ${{ matrix.arch }}
|
||||
build-deps-only: ${{ inputs.build-deps-only || false }}
|
||||
force-build: ${{ github.event_name == 'schedule' }}
|
||||
@@ -122,54 +116,97 @@ jobs:
|
||||
arch: universal
|
||||
macos-combine-only: true
|
||||
secrets: inherit
|
||||
unit_tests:
|
||||
name: Unit Tests
|
||||
# Tests are built on the aarch64 leg by default (faster GitHub arm runner),
|
||||
# so run them there; self-hosted builds them on the amd64 server instead.
|
||||
runs-on: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04-arm' }}
|
||||
# One test job per built arch, on the runner that built it.
|
||||
unit_tests_linux_x86_64:
|
||||
name: Linux x86_64
|
||||
needs: build_linux
|
||||
if: ${{ !cancelled() && success() }}
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }}
|
||||
artifact: ${{ github.sha }}-tests-linux-x86_64
|
||||
unit_tests_linux_aarch64:
|
||||
name: Linux aarch64
|
||||
needs: build_linux
|
||||
if: ${{ !cancelled() && success() && !vars.SELF_HOSTED }}
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
os: ubuntu-24.04-arm
|
||||
artifact: ${{ github.sha }}-tests-linux-aarch64
|
||||
unit_tests_windows_x64:
|
||||
name: Windows x64
|
||||
needs: build_windows
|
||||
if: ${{ !cancelled() && success() }}
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-win-server' || 'windows-latest' }}
|
||||
artifact: ${{ github.sha }}-tests-windows-x64
|
||||
unit_tests_windows_arm64:
|
||||
name: Windows arm64
|
||||
needs: build_windows
|
||||
if: ${{ !cancelled() && success() && !vars.SELF_HOSTED }}
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
os: windows-11-arm
|
||||
artifact: ${{ github.sha }}-tests-windows-arm64
|
||||
test-dir: build-arm64/tests
|
||||
unit_tests_macos_arm64:
|
||||
name: macOS arm64
|
||||
needs: build_macos_arch
|
||||
if: ${{ !cancelled() && success() }}
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }}
|
||||
artifact: ${{ github.sha }}-tests-macos-arm64
|
||||
test-dir: build/arm64/tests
|
||||
# Slice a two-colour cube through every shipped printer so all custom g-code
|
||||
# (change_filament_gcode, machine start/end, etc.) is expanded - catches
|
||||
# slicing regressions the static profile checks and unit tests can't see.
|
||||
# Profile-only PRs are covered by check_profiles.yml's nightly binary; this
|
||||
# covers src/engine PRs with the PR-built binary.
|
||||
slice_check_linux:
|
||||
name: Slice check (Linux ${{ vars.SELF_HOSTED && 'x86_64' || 'aarch64' }})
|
||||
needs: build_linux
|
||||
if: ${{ !cancelled() && success() }}
|
||||
# Follows whichever Linux leg built the validator.
|
||||
runs-on: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04-arm' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github
|
||||
scripts
|
||||
tests
|
||||
- name: Apt-Install Dependencies
|
||||
if: ${{ !vars.SELF_HOSTED }}
|
||||
uses: ./.github/actions/apt-install-deps
|
||||
- name: Restore Test Artifact
|
||||
- name: Download profile validator
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: ${{ github.sha }}-tests
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "~4.3.0" # use most recent 4.3.x version
|
||||
useLocalCache: true # <--= Use the local cache (default is 'false').
|
||||
useCloudCache: true
|
||||
- name: Unpackage and Run Unit Tests
|
||||
timeout-minutes: 20
|
||||
name: ${{ github.sha }}-profile-validator-linux-${{ vars.SELF_HOSTED && 'x86_64' || 'aarch64' }}
|
||||
path: validator-bin
|
||||
- name: Validate slice (expand custom g-code)
|
||||
timeout-minutes: 60
|
||||
run: |
|
||||
tar -xvf build_tests.tar
|
||||
scripts/run_unit_tests.sh
|
||||
- name: Upload Test Logs
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ failure() }}
|
||||
chmod +x validator-bin/OrcaSlicer_profile_validator
|
||||
./validator-bin/OrcaSlicer_profile_validator -p "${{ github.workspace }}/resources/profiles" -s -l 2
|
||||
publish_test_results:
|
||||
name: Publish Test Results
|
||||
needs: [unit_tests_linux_x86_64, unit_tests_linux_aarch64, unit_tests_windows_x64, unit_tests_windows_arm64, unit_tests_macos_arm64]
|
||||
if: ${{ !cancelled() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download Test Results
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: unit-test-logs
|
||||
path: build/tests/**/*.log
|
||||
pattern: test-results-*
|
||||
path: test-results
|
||||
# Best-effort: a read-only token (e.g. fork PRs) can't write the check, so
|
||||
# don't let a publish failure fail the run. The test jobs gate correctness.
|
||||
- name: Publish Test Results
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
uses: EnricoMi/publish-unit-test-result-action@v2
|
||||
with:
|
||||
files: "ctest_results.xml"
|
||||
- name: Delete Test Artifact
|
||||
files: "test-results/**/*.xml"
|
||||
- name: Delete Test Results
|
||||
if: success()
|
||||
uses: geekyeggo/delete-artifact@v6
|
||||
with:
|
||||
name: ${{ github.sha }}-tests
|
||||
name: test-results-*
|
||||
failOnError: false
|
||||
flatpak:
|
||||
name: "Flatpak"
|
||||
container:
|
||||
|
||||
108
.github/workflows/build_orca.yml
vendored
108
.github/workflows/build_orca.yml
vendored
@@ -141,8 +141,26 @@ jobs:
|
||||
- name: Build slicer mac
|
||||
if: runner.os == 'macOS' && !inputs.macos-combine-only
|
||||
working-directory: ${{ github.workspace }}
|
||||
# arm64 only: build the tests here; the unit_tests_macos job runs them.
|
||||
env:
|
||||
ORCA_TESTS_BUILD_ONLY: ${{ inputs.arch == 'arm64' && '1' || '' }}
|
||||
run: |
|
||||
./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15
|
||||
./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15 ${{ inputs.arch == 'arm64' && '-T' || '' }}
|
||||
|
||||
- name: Pack unit tests mac
|
||||
if: runner.os == 'macOS' && !inputs.macos-combine-only && inputs.arch == 'arm64'
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: tar -cvf build_tests.tar build/arm64/tests
|
||||
|
||||
- name: Upload Test Artifact mac
|
||||
if: runner.os == 'macOS' && !inputs.macos-combine-only && inputs.arch == 'arm64'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ github.sha }}-tests-macos-arm64
|
||||
overwrite: true
|
||||
path: build_tests.tar
|
||||
retention-days: 5
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Pack macOS app bundle ${{ inputs.arch }}
|
||||
if: runner.os == 'macOS' && !inputs.macos-combine-only
|
||||
@@ -203,10 +221,41 @@ jobs:
|
||||
security import $CERTIFICATE_PATH -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $P12_PASSWORD $KEYCHAIN_PATH
|
||||
codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app
|
||||
# codesign --deep is deprecated and cannot sign the bundled Python
|
||||
# runtime (see relocate_python_runtime in build_release_macos.sh).
|
||||
# Sign every nested Mach-O in the bundle explicitly -- notarization
|
||||
# requires the hardened-runtime signature on each -- then seal the
|
||||
# bundle itself last, and verify so coverage gaps fail at CI time
|
||||
# rather than at notarization.
|
||||
ENTITLEMENTS=${{ github.workspace }}/scripts/disable_validation.entitlements
|
||||
sign() {
|
||||
codesign --force --options runtime --timestamp --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE_ID" "$@"
|
||||
}
|
||||
sign_app() {
|
||||
local app="$1"
|
||||
local machos=()
|
||||
# file is batched via xargs (per-file it costs minutes); universal
|
||||
# binaries also print per-architecture lines, dropped by grep -v.
|
||||
while IFS= read -r f; do machos+=("$f"); done < <(
|
||||
find "$app" -type f -print0 |
|
||||
xargs -0 file --no-pad --mime-type -- |
|
||||
grep -v ' (for architecture ' |
|
||||
grep ': application/x-mach-binary$' |
|
||||
sed 's|: application/x-mach-binary$||'
|
||||
)
|
||||
if [ "${#machos[@]}" -eq 0 ]; then
|
||||
echo "ERROR: no Mach-O files found in $app -- detection is broken" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "signing ${#machos[@]} Mach-O files in $app"
|
||||
sign "${machos[@]}"
|
||||
sign --verbose "$app"
|
||||
codesign --verify --deep --strict --verbose=2 "$app"
|
||||
}
|
||||
sign_app "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app"
|
||||
# Sign OrcaSlicer_profile_validator.app if it exists
|
||||
if [ -f "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then
|
||||
codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app
|
||||
sign_app "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app"
|
||||
fi
|
||||
|
||||
# Create main OrcaSlicer DMG without the profile validator helper
|
||||
@@ -215,7 +264,7 @@ jobs:
|
||||
cp -R ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app ${{ github.workspace }}/build/universal/OrcaSlicer_dmg/
|
||||
ln -sfn /Applications ${{ github.workspace }}/build/universal/OrcaSlicer_dmg/Applications
|
||||
retry hdiutil create -volname "OrcaSlicer" -srcfolder ${{ github.workspace }}/build/universal/OrcaSlicer_dmg -ov -format UDZO OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
|
||||
codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
|
||||
codesign --deep --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE_ID" OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
|
||||
|
||||
# Create separate OrcaSlicer_profile_validator DMG if the app exists
|
||||
if [ -f "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then
|
||||
@@ -224,7 +273,7 @@ jobs:
|
||||
cp -R ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg/
|
||||
ln -sfn /Applications ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg/Applications
|
||||
retry hdiutil create -volname "OrcaSlicer Profile Validator" -srcfolder ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg -ov -format UDZO OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
|
||||
codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
|
||||
codesign --deep --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE_ID" OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
|
||||
fi
|
||||
|
||||
# Notarize main DMG
|
||||
@@ -335,11 +384,28 @@ jobs:
|
||||
# env:
|
||||
# WindowsSdkDir: 'C:\Program Files (x86)\Windows Kits\10\'
|
||||
# WindowsSDKVersion: '10.0.26100.0\'
|
||||
# "tests" builds the unit tests too; the unit_tests_windows_* jobs run them.
|
||||
run: |
|
||||
$arch = "${{ inputs.arch }}"
|
||||
if ($arch -eq "arm64") { .\build_release_vs.bat slicer arm64 } else { .\build_release_vs.bat slicer }
|
||||
if ($arch -eq "arm64") { .\build_release_vs.bat slicer arm64 tests } else { .\build_release_vs.bat slicer tests }
|
||||
shell: pwsh
|
||||
|
||||
- name: Pack unit tests Win
|
||||
if: runner.os == 'Windows'
|
||||
working-directory: ${{ github.workspace }}
|
||||
shell: pwsh
|
||||
run: tar -cvf build_tests.tar ${{ env.BUILD_DIR }}/tests
|
||||
|
||||
- name: Upload Test Artifact Win
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ github.sha }}-tests-windows-${{ inputs.arch }}
|
||||
overwrite: true
|
||||
path: build_tests.tar
|
||||
retention-days: 5
|
||||
if-no-files-found: error
|
||||
|
||||
# NSIS is x86-only; it runs (and the installer it emits runs) under ARM64's
|
||||
# x86 emulation, packaging the native arm64 payload from build-arm64.
|
||||
- name: Create installer Win
|
||||
@@ -452,31 +518,41 @@ jobs:
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
# Build + tar the unit tests (-t) only on the leg that runs them: the
|
||||
# aarch64 leg by default (faster GitHub arm runner), or amd64 when using
|
||||
# self-hosted runners (no arm self-hosted server). unit_tests downloads
|
||||
# this tarball. The profile validator is built with -s, so amd64 keeps it.
|
||||
tests=${{ (!vars.SELF_HOSTED && inputs.arch == 'aarch64') || (vars.SELF_HOSTED && inputs.arch != 'aarch64') }}
|
||||
if $tests; then flags=-istrlL; else flags=-isrlL; fi
|
||||
./build_linux.sh "$flags"
|
||||
# Build + tar the unit tests (-t) on both Linux legs so each arch
|
||||
# (x86_64 + aarch64) gets tested by its own unit_tests_linux_* job.
|
||||
./build_linux.sh -istrlL
|
||||
./scripts/check_appimage_libs.sh ./build/package ./build/package/bin/orca-slicer
|
||||
appimage=./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}${{ env.arch_suffix }}_${{ env.ver }}.AppImage
|
||||
mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage "$appimage"
|
||||
chmod +x "$appimage"
|
||||
if $tests; then tar -cvpf build_tests.tar build/tests; fi
|
||||
tar -cvf build_tests.tar build/tests
|
||||
|
||||
# Use tar because upload-artifacts won't always preserve directory structure
|
||||
# and doesn't preserve file permissions
|
||||
- name: Upload Test Artifact
|
||||
if: runner.os == 'Linux' && ((!vars.SELF_HOSTED && inputs.arch == 'aarch64') || (vars.SELF_HOSTED && inputs.arch != 'aarch64'))
|
||||
if: runner.os == 'Linux'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ github.sha }}-tests
|
||||
name: ${{ github.sha }}-tests-linux-${{ inputs.arch == 'aarch64' && 'aarch64' || 'x86_64' }}
|
||||
overwrite: true
|
||||
path: build_tests.tar
|
||||
retention-days: 5
|
||||
if-no-files-found: error
|
||||
|
||||
# Ship the freshly-built validator so slice_check_linux (build_all.yml)
|
||||
# can slice-sweep the shipped profiles with this PR's engine. Taken from
|
||||
# the aarch64 leg so the sweep also exercises the arm build; x86_64 on
|
||||
# SELF_HOSTED, which skips arm64.
|
||||
- name: Upload profile validator (for slice check)
|
||||
if: ${{ runner.os == 'Linux' && (vars.SELF_HOSTED && inputs.arch != 'aarch64' || !vars.SELF_HOSTED && inputs.arch == 'aarch64') }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ github.sha }}-profile-validator-linux-${{ inputs.arch == 'aarch64' && 'aarch64' || 'x86_64' }}
|
||||
overwrite: true
|
||||
path: ./build/src/Release/OrcaSlicer_profile_validator
|
||||
retention-days: 5
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Run external slicer regression tests
|
||||
if: runner.os == 'Linux' && inputs.arch != 'aarch64'
|
||||
timeout-minutes: 20
|
||||
|
||||
47
.github/workflows/check_profiles.yml
vendored
47
.github/workflows/check_profiles.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
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
|
||||
# Validate all system profiles.
|
||||
- name: validate system profiles
|
||||
id: validate_system
|
||||
continue-on-error: true
|
||||
@@ -49,6 +49,15 @@ jobs:
|
||||
set +e
|
||||
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_system.log
|
||||
exit ${PIPESTATUS[0]}
|
||||
# Slice a two-colour cube through every printer so all custom g-code (incl. change_filament_gcode)
|
||||
# is expanded - catches undefined-placeholder / invalid-flow bugs the static checks above cannot see.
|
||||
- name: validate slice (expand custom g-code)
|
||||
id: validate_slice
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set +e
|
||||
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -s -l 2 2>&1 | tee ${{ runner.temp }}/validate_slice.log
|
||||
exit ${PIPESTATUS[0]}
|
||||
# All vendors' filament_id collisions were fixed (see scripts/filament_id_snapshot.json),
|
||||
# so the duplicate-filament-subtype check runs tree-wide.
|
||||
- name: validate filament subtype check
|
||||
@@ -58,20 +67,6 @@ jobs:
|
||||
set +e
|
||||
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 -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
|
||||
@@ -181,7 +176,7 @@ jobs:
|
||||
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') }}
|
||||
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_slice.outcome == 'failure' || steps.validate_filament_subtypes.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
|
||||
run: |
|
||||
{
|
||||
# Marker matched by check_profiles_comment.yml to delete prior comments.
|
||||
@@ -207,6 +202,15 @@ jobs:
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "${{ steps.validate_slice.outcome }}" = "failure" ]; then
|
||||
echo "### Slice Validation Failed (custom g-code expansion)"
|
||||
echo ""
|
||||
echo '```'
|
||||
head -c 30000 ${{ runner.temp }}/validate_slice.log || echo "No output captured"
|
||||
echo '```'
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "${{ steps.validate_filament_subtypes.outcome }}" = "failure" ]; then
|
||||
echo "### Filament Subtype Validation Failed"
|
||||
echo ""
|
||||
@@ -216,15 +220,6 @@ jobs:
|
||||
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 ""
|
||||
@@ -247,7 +242,7 @@ jobs:
|
||||
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') }}
|
||||
if: ${{ always() && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_slice.outcome == 'failure' || steps.validate_filament_subtypes.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
|
||||
run: |
|
||||
echo "One or more profile checks failed. See above for details."
|
||||
exit 1
|
||||
|
||||
2
.github/workflows/dedupe-issues.yml
vendored
2
.github/workflows/dedupe-issues.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
with:
|
||||
prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
claude_args: "--model claude-sonnet-4-5-20250929"
|
||||
model: "claude-sonnet-4-5-20250929"
|
||||
claude_env: |
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
86
.github/workflows/pr-label-bot.yml
vendored
86
.github/workflows/pr-label-bot.yml
vendored
@@ -79,6 +79,92 @@ jobs:
|
||||
throw error;
|
||||
}
|
||||
|
||||
localization-pr:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Auto-label and remind about the localization glossary
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
function isPermissionDenied(error) {
|
||||
return error && error.status === 403 && /Resource not accessible by integration/i.test(error.message || '');
|
||||
}
|
||||
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// List changed files once (mirrors the `localization/**` paths filter in check_locale.yml)
|
||||
const files = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
per_page: 100
|
||||
});
|
||||
const touchesLocalization = files.some((file) => file.filename.startsWith('localization/'));
|
||||
const onlyPoFiles = files.length > 0 && files.every((file) => file.filename.endsWith('.po'));
|
||||
|
||||
// If the PR changes only .po files, automatically apply the Localization label
|
||||
if (onlyPoFiles) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: ['Localization']
|
||||
});
|
||||
core.info('Applied Localization label (PR changes only .po files).');
|
||||
} catch (error) {
|
||||
if (isPermissionDenied(error)) {
|
||||
core.warning('Cannot add Localization label because token cannot write.');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!touchesLocalization) {
|
||||
core.info('No localization changes detected; skipping glossary reminder.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid posting the reminder twice (e.g. on reopen)
|
||||
const marker = '<!-- localization-glossary-reminder -->';
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
per_page: 100
|
||||
});
|
||||
if (comments.some((comment) => (comment.body || '').includes(marker))) {
|
||||
core.info('Glossary reminder already present; skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body:
|
||||
`${marker}\n` +
|
||||
`Hi @${pr.user.login}, this PR changes translations (\`localization/**\`).\n\n` +
|
||||
`Please make sure recurring terms follow the [Localization glossary](https://www.orcaslicer.com/wiki/localization_glossary), ` +
|
||||
`so the same English term is always rendered the same way within a language and terms that must stay in English ` +
|
||||
`(brand/product names, acronyms, file formats, G-code, macros/variables) are not translated.`
|
||||
});
|
||||
} catch (error) {
|
||||
if (isPermissionDenied(error)) {
|
||||
core.warning('Skipping glossary reminder because token cannot write comments.');
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
apply-label:
|
||||
if: github.event_name == 'issue_comment'
|
||||
permissions:
|
||||
|
||||
77
.github/workflows/unit_tests.yml
vendored
Normal file
77
.github/workflows/unit_tests.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Unit Tests
|
||||
|
||||
# Download a platform's test artifact, run ctest, and upload the JUnit
|
||||
# results for aggregation. Called once per arch from build_all.yml.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
os:
|
||||
required: true
|
||||
type: string
|
||||
artifact:
|
||||
description: Test artifact uploaded by the build leg
|
||||
required: true
|
||||
type: string
|
||||
test-dir:
|
||||
description: Built tests dir; defaults to build/tests, override for arch-separated builds
|
||||
required: false
|
||||
type: string
|
||||
default: build/tests
|
||||
|
||||
jobs:
|
||||
unit_tests:
|
||||
# Static "Unit Tests"; the per-arch label is the caller's job name, so the
|
||||
# graph shows e.g. "Windows x64 / Unit Tests".
|
||||
name: Unit Tests
|
||||
runs-on: ${{ inputs.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
# Tests reach outside tests/ at runtime: tests/data (TEST_DATA_DIR) and
|
||||
# resources/profiles (PROFILES_DIR) by baked-in absolute path, plus
|
||||
# resources/info (nozzle data) via resources_dir() during a real slice.
|
||||
# Check out all of resources/ so no test hits a missing-file path.
|
||||
sparse-checkout: |
|
||||
.github
|
||||
scripts
|
||||
tests
|
||||
resources
|
||||
- name: Apt-Install Dependencies
|
||||
if: runner.os == 'Linux' && !vars.SELF_HOSTED
|
||||
uses: ./.github/actions/apt-install-deps
|
||||
- name: Restore Test Artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: ${{ inputs.artifact }}
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "~4.3.0" # use most recent 4.3.x version
|
||||
useLocalCache: true
|
||||
useCloudCache: true
|
||||
- name: Unpackage and Run Unit Tests
|
||||
timeout-minutes: 20
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xvf build_tests.tar
|
||||
# Multi-config generators (Windows/macOS) need a config; Linux is single-config.
|
||||
scripts/run_unit_tests.sh "${{ inputs.test-dir }}" "${{ runner.os != 'Linux' && 'Release' || '' }}"
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: unit-test-logs-${{ inputs.artifact }}
|
||||
path: ${{ inputs.test-dir }}/**/*.log
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: test-results-${{ inputs.artifact }}
|
||||
path: ctest_results.xml
|
||||
retention-days: 5
|
||||
if-no-files-found: warn
|
||||
- name: Delete Test Artifact
|
||||
if: success()
|
||||
uses: geekyeggo/delete-artifact@v6
|
||||
with:
|
||||
name: ${{ inputs.artifact }}
|
||||
Reference in New Issue
Block a user