Merge origin/main into feature/protobuf_config_and_dynamic_ui

Resolve the 4 proto-refactored conflicts (Preset.cpp, Print.cpp,
PrintConfig.cpp, Tab.cpp) by keeping the branch's generated-include
versions; auto-merged non-conflict changes from main are preserved.

Reconcile main's new settings into the proto schema. main added 52 new
active init_fff_params settings not present in the proto; ported them all
(type/label/tooltip/default/enum/preset) into print/filament/printer.proto
so the config registers, profiles load, and the GUI does not crash on
missing defs. Added GuiType.plugin_picker to config_metadata.proto and
regenerated config_metadata_pb2.py.

Codegen: run_codegen validate PASSED (712 fields). UI layout (layout.yaml
placement) for the 52 new settings is a follow-up; they are registered and
serialized but not yet placed in GUI tabs.
This commit is contained in:
ExPikaPaka
2026-07-28 08:01:22 +02:00
1452 changed files with 2486750 additions and 1271936 deletions

View File

@@ -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' }}
@@ -134,7 +128,7 @@ jobs:
unit_tests_linux_aarch64:
name: Linux aarch64
needs: build_linux
if: ${{ !cancelled() && success() }}
if: ${{ !cancelled() && success() && !vars.SELF_HOSTED }}
uses: ./.github/workflows/unit_tests.yml
with:
os: ubuntu-24.04-arm
@@ -150,7 +144,7 @@ jobs:
unit_tests_windows_arm64:
name: Windows arm64
needs: build_windows
if: ${{ !cancelled() && success() }}
if: ${{ !cancelled() && success() && !vars.SELF_HOSTED }}
uses: ./.github/workflows/unit_tests.yml
with:
os: windows-11-arm
@@ -165,6 +159,30 @@ jobs:
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 repository
uses: actions/checkout@v7
- name: Download profile validator
uses: actions/download-artifact@v8
with:
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: |
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]

View File

@@ -240,10 +240,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
@@ -252,7 +283,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
@@ -261,7 +292,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
@@ -527,6 +558,20 @@ jobs:
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

View File

@@ -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]}
# 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
@@ -166,7 +175,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_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.
@@ -192,6 +201,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 "### BBL Filament Subtype Validation Failed"
echo ""
@@ -223,7 +241,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_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

View File

@@ -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:

View File

@@ -28,11 +28,15 @@ jobs:
- name: Checkout
uses: actions/checkout@v7
with:
# tests/data is referenced by absolute path (TEST_DATA_DIR).
# 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