From 1b3f780aa1a4da060c31402e6bcdbbf2b9a0aafb Mon Sep 17 00:00:00 2001 From: forbes-0023 Date: Tue, 3 Feb 2026 10:54:47 -0600 Subject: [PATCH] chore: migrate submodules to public repos, rework docs and CI/CD - Update .gitmodules: ztools, silo, and OndselSolver now reference public git.kindred-systems.com URLs instead of internal Gitea - Merge OndselSolver numerical solver with ML solver scaffolding into unified kindred/solver repository - Rewrite README.md for conciseness - Add docs/CI_CD.md with full pipeline documentation - Rework CI/CD workflows for public dockerized runners - Add multi-platform release builds (Linux, macOS, Windows) - Release workflow triggers on v* tags only - Update docs/REPOSITORY_STATE.md and docs/INTEGRATION_PLAN.md --- .gitea/workflows/build.yml | 158 ++--------- .gitea/workflows/release.yml | 333 +++++++++++++++++------ .gitmodules | 6 +- README.md | 290 +++++---------------- docs/CI_CD.md | 273 +++++++++++++++++++ docs/INTEGRATION_PLAN.md | 493 +++++++---------------------------- docs/REPOSITORY_STATE.md | 425 +++++++++++------------------- src/3rdParty/OndselSolver | 2 +- 8 files changed, 877 insertions(+), 1103 deletions(-) create mode 100644 docs/CI_CD.md diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 3092707df7..68db911130 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -10,7 +10,10 @@ on: jobs: build: - runs-on: app-builder + runs-on: ubuntu-latest + container: + image: ubuntu:24.04 + options: --security-opt seccomp=unconfined env: CCACHE_DIR: /tmp/ccache-kindred-create @@ -19,35 +22,16 @@ jobs: CCACHE_MAXSIZE: "4G" CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros" CCACHE_BASEDIR: ${{ github.workspace }} + DEBIAN_FRONTEND: noninteractive steps: - - name: Trust FreeIPA CA certificate - shell: bash + - name: Install system prerequisites run: | - # Download and install the FreeIPA CA certificate for SSL verification - echo "Downloading FreeIPA CA certificate..." - curl -fsSL -o /tmp/ipa-ca.crt https://ipa.kindred.internal/ipa/config/ca.crt - - # Verify the certificate is valid (just show subject and dates) - echo "Verifying certificate..." - openssl x509 -in /tmp/ipa-ca.crt -subject -dates -noout - - # Set NODE_EXTRA_CA_CERTS for Node.js-based actions (used by upload-artifact) - echo "NODE_EXTRA_CA_CERTS=/tmp/ipa-ca.crt" >> $GITHUB_ENV - - # Verify SSL connection to Gitea works with the CA cert - echo "Testing SSL connection to Gitea..." - curl -fsSL --cacert /tmp/ipa-ca.crt https://gitea.kindred.internal/api/v1/version - echo "" - echo "SSL certificate setup complete" - - - name: Install node if needed - shell: bash - run: | - if ! command -v node &> /dev/null; then - curl -fsSL https://nodejs.org/dist/v20.18.0/node-v20.18.0-linux-x64.tar.xz | sudo tar -xJ -C /usr/local --strip-components=1 - fi - node --version + apt-get update -qq + apt-get install -y --no-install-recommends \ + ca-certificates curl git xvfb xauth openssl \ + libgl1-mesa-dev libglu1-mesa-dev libx11-dev libxkbcommon-dev \ + libxcb-xkb-dev libfontconfig1-dev - name: Checkout repository uses: https://github.com/actions/checkout@v4 @@ -55,14 +39,11 @@ jobs: submodules: recursive fetch-depth: 0 - - name: Install pixi if needed - shell: bash + - name: Install pixi run: | - if ! command -v pixi &> /dev/null; then - curl -fsSL https://pixi.sh/install.sh | bash - echo "$HOME/.pixi/bin" >> $GITHUB_PATH - export PATH="$HOME/.pixi/bin:$PATH" - fi + curl -fsSL https://pixi.sh/install.sh | bash + echo "$HOME/.pixi/bin" >> $GITHUB_PATH + export PATH="$HOME/.pixi/bin:$PATH" pixi --version - name: Restore ccache @@ -76,32 +57,18 @@ jobs: ccache-build-main- - name: Prepare ccache - shell: bash run: | mkdir -p $CCACHE_DIR pixi run ccache -z - echo "=== ccache configuration ===" - pixi run ccache -p - echo "" - echo "=== ccache status before build ===" - pixi run ccache -s - name: Configure (CMake) - shell: bash - run: | - pixi run cmake --preset conda-linux-release + run: pixi run cmake --preset conda-linux-release - name: Build run: pixi run cmake --build build/release -j$(nproc) - name: Show ccache statistics - shell: bash - run: | - echo "=== ccache statistics after build ===" - pixi run ccache -s - echo "" - echo "=== ccache cache directory size ===" - du -sh $CCACHE_DIR + run: pixi run ccache -s - name: Save ccache if: always() @@ -111,30 +78,18 @@ jobs: key: ccache-build-${{ github.ref_name }}-${{ github.sha }} - name: Run C++ unit tests - shell: bash continue-on-error: true timeout-minutes: 15 run: | - # Set discovery timeout to prevent hangs during test enumeration export CTEST_DISCOVERY_TIMEOUT=60 - - # Use xvfb for tests that require a display (Qt GUI tests) - # Exclude Assembly tests which hang during discovery pixi run xvfb-run -a ctest --test-dir build/release \ --output-on-failure \ --timeout 120 \ --exclude-regex "Assembly_tests" \ 2>&1 || true - echo "" - echo "=== Test Summary ===" - echo "Note: Assembly_tests excluded due to discovery timeout issues" - cat build/release/Testing/Temporary/LastTestsFailed.log 2>/dev/null || echo "All included tests passed (or no failures logged)" - - name: Install - run: | - # Install to a custom prefix for packaging - pixi run cmake --install build/release --prefix build/release/install + run: pixi run cmake --install build/release --prefix build/release/install - name: Run Python CLI tests timeout-minutes: 10 @@ -145,79 +100,13 @@ jobs: run: pixi run timeout 300 xvfb-run -a build/release/bin/FreeCAD -t 0 || true - name: Package build artifacts - shell: bash run: | - # Create a distributable tarball from the installed build ARTIFACT_NAME="kindred-create-$(git describe --tags --always)-linux-x86_64" - echo "Creating artifact: ${ARTIFACT_NAME}" - - # The install step puts files in build/release/install cd build/release - if [ -d "install" ]; then - cp -a install "${ARTIFACT_NAME}" - tar -cJf "${ARTIFACT_NAME}.tar.xz" "${ARTIFACT_NAME}" - sha256sum "${ARTIFACT_NAME}.tar.xz" > "${ARTIFACT_NAME}.tar.xz.sha256" - echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV - ls -lh "${ARTIFACT_NAME}.tar.xz" - else - echo "ERROR: install directory not found" - ls -la - exit 1 - fi - - - name: Prepare bundled environment for .deb - shell: bash - run: | - # Create a bundled environment with all dependencies (like AppImage) - # The .deb needs all libraries bundled since we can't rely on system packages - # We need BOTH the pixi environment (dependencies) AND the built FreeCAD - BUNDLE_DIR="build/release/bundle" - mkdir -p "${BUNDLE_DIR}" - - echo "Copying pixi environment (dependencies)..." - cp -a .pixi/envs/default/* "${BUNDLE_DIR}/" - echo "After pixi copy: $(du -sh ${BUNDLE_DIR} | cut -f1)" - - echo "Copying built FreeCAD into bundle..." - # Copy the built FreeCAD (bin, lib, Mod, share, etc.) over the pixi env - cp -a build/release/install/* "${BUNDLE_DIR}/" - echo "After FreeCAD copy: $(du -sh ${BUNDLE_DIR} | cut -f1)" - - # Remove unnecessary files to reduce size significantly - echo "Removing unnecessary files..." - rm -rf "${BUNDLE_DIR}/include" - rm -rf "${BUNDLE_DIR}/conda-meta" - rm -rf "${BUNDLE_DIR}/doc" - rm -rf "${BUNDLE_DIR}/man" - rm -rf "${BUNDLE_DIR}/share/doc" - rm -rf "${BUNDLE_DIR}/share/man" - rm -rf "${BUNDLE_DIR}/share/gtk-doc" - rm -rf "${BUNDLE_DIR}/share/info" - rm -rf "${BUNDLE_DIR}/lib/cmake" - rm -rf "${BUNDLE_DIR}/lib/pkgconfig" - rm -rf "${BUNDLE_DIR}/share/pkgconfig" - - # Remove static libraries and dev files - find "${BUNDLE_DIR}" -name "*.a" -delete 2>/dev/null || true - find "${BUNDLE_DIR}" -name "*.la" -delete 2>/dev/null || true - find "${BUNDLE_DIR}" -name "*.cmake" -delete 2>/dev/null || true - find "${BUNDLE_DIR}" -path "*/__pycache__/*" -delete 2>/dev/null || true - find "${BUNDLE_DIR}" -name "*.pyc" -delete 2>/dev/null || true - find "${BUNDLE_DIR}" -name "*.pyo" -delete 2>/dev/null || true - - # List key binaries to verify FreeCAD is there - echo "Key binaries in bundle:" - ls -la "${BUNDLE_DIR}/bin/FreeCAD" "${BUNDLE_DIR}/bin/FreeCADCmd" 2>/dev/null || echo "FreeCAD binaries not found!" - - echo "Final bundle size: $(du -sh ${BUNDLE_DIR} | cut -f1)" - - - name: Build .deb package - shell: bash - run: | - # Build .deb package from bundled environment - # The build-deb.sh script handles version conversion to Debian format - # (e.g., weekly-2025.01.28 -> 0~weekly.2025.01.28) - ./package/debian/build-deb.sh build/release/bundle build/release + cp -a install "${ARTIFACT_NAME}" + tar -cJf "${ARTIFACT_NAME}.tar.xz" "${ARTIFACT_NAME}" + sha256sum "${ARTIFACT_NAME}.tar.xz" > "${ARTIFACT_NAME}.tar.xz.sha256" + echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV - name: Upload build artifact uses: https://github.com/actions/upload-artifact@v3 @@ -225,6 +114,5 @@ jobs: name: ${{ env.ARTIFACT_NAME }} path: | build/release/*.tar.xz - build/release/*.deb build/release/*.sha256 - retention-days: 30 + retention-days: 14 diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 969ad80c75..e87043f6df 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -3,17 +3,23 @@ name: Release Build on: push: - tags: ["v*", "weekly-*"] + tags: ["v*"] workflow_dispatch: inputs: tag: - description: "Release tag (e.g., v1.0.0)" + description: "Release tag (e.g., v0.1.0)" required: true type: string jobs: - build-linux-appimage: - runs-on: app-builder + # --------------------------------------------------------------------------- + # Linux: AppImage + .deb + # --------------------------------------------------------------------------- + build-linux: + runs-on: ubuntu-latest + container: + image: ubuntu:24.04 + options: --security-opt seccomp=unconfined env: CCACHE_DIR: /tmp/ccache-kindred-create @@ -23,38 +29,18 @@ jobs: CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros" CCACHE_BASEDIR: ${{ github.workspace }} BUILD_TAG: ${{ github.ref_name || inputs.tag }} - MAKE_INSTALLER: "true" CFLAGS: "-O3" CXXFLAGS: "-O3" + DEBIAN_FRONTEND: noninteractive steps: - - name: Trust FreeIPA CA certificate - shell: bash + - name: Install system prerequisites run: | - # Download and install the FreeIPA CA certificate for SSL verification - echo "Downloading FreeIPA CA certificate..." - curl -fsSL -o /tmp/ipa-ca.crt https://ipa.kindred.internal/ipa/config/ca.crt - - # Verify the certificate is valid (just show subject and dates) - echo "Verifying certificate..." - openssl x509 -in /tmp/ipa-ca.crt -subject -dates -noout - - # Set NODE_EXTRA_CA_CERTS for Node.js-based actions (used by upload-artifact) - echo "NODE_EXTRA_CA_CERTS=/tmp/ipa-ca.crt" >> $GITHUB_ENV - - # Verify SSL connection to Gitea works with the CA cert - echo "Testing SSL connection to Gitea..." - curl -fsSL --cacert /tmp/ipa-ca.crt https://gitea.kindred.internal/api/v1/version - echo "" - echo "SSL certificate setup complete" - - - name: Install node if needed - shell: bash - run: | - if ! command -v node &> /dev/null; then - curl -fsSL https://nodejs.org/dist/v20.18.0/node-v20.18.0-linux-x64.tar.xz | sudo tar -xJ -C /usr/local --strip-components=1 - fi - node --version + apt-get update -qq + apt-get install -y --no-install-recommends \ + ca-certificates curl git file fuse3 xvfb xauth openssl dpkg-dev \ + libgl1-mesa-dev libglu1-mesa-dev libx11-dev libxkbcommon-dev \ + libxcb-xkb-dev libfontconfig1-dev - name: Checkout repository uses: https://github.com/actions/checkout@v4 @@ -63,14 +49,11 @@ jobs: fetch-depth: 0 fetch-tags: true - - name: Install pixi if needed - shell: bash + - name: Install pixi run: | - if ! command -v pixi &> /dev/null; then - curl -fsSL https://pixi.sh/install.sh | bash - echo "$HOME/.pixi/bin" >> $GITHUB_PATH - export PATH="$HOME/.pixi/bin:$PATH" - fi + curl -fsSL https://pixi.sh/install.sh | bash + echo "$HOME/.pixi/bin" >> $GITHUB_PATH + export PATH="$HOME/.pixi/bin:$PATH" pixi --version - name: Restore ccache @@ -78,24 +61,15 @@ jobs: uses: https://github.com/actions/cache/restore@v4 with: path: /tmp/ccache-kindred-create - key: ccache-release-${{ github.ref_name }}-${{ github.sha }} + key: ccache-release-linux-${{ github.sha }} restore-keys: | - ccache-release- + ccache-release-linux- ccache-build-main- - name: Prepare ccache - shell: bash run: | mkdir -p $CCACHE_DIR pixi run ccache -z - echo "=== ccache configuration ===" - pixi run ccache -p - echo "" - echo "=== ccache status before build ===" - pixi run ccache -s - - - name: Write version info - run: python3 package/scripts/write_version_info.py ../freecad_version.txt - name: Build release package (AppImage) working-directory: package/rattler-build @@ -104,54 +78,267 @@ jobs: pixi run -e package create_bundle - name: Show ccache statistics - shell: bash - run: | - echo "=== ccache statistics after build ===" - pixi run ccache -s - echo "" - echo "=== ccache cache directory size ===" - du -sh $CCACHE_DIR + run: pixi run ccache -s - name: Save ccache if: always() uses: https://github.com/actions/cache/save@v4 with: path: /tmp/ccache-kindred-create - key: ccache-release-${{ github.ref_name }}-${{ github.sha }} + key: ccache-release-linux-${{ github.sha }} - name: Build .deb package - shell: bash run: | - # Build .deb package from the AppDir used for AppImage - # The build-deb.sh script handles version conversion to Debian format - # (e.g., weekly-2025.01.28 -> 0~weekly.2025.01.28) ./package/debian/build-deb.sh \ package/rattler-build/linux/AppDir/usr \ package/rattler-build/linux \ "${BUILD_TAG}" - name: List built artifacts - shell: bash run: | - echo "Built artifacts:" - ls -lah package/rattler-build/linux/*.AppImage* 2>/dev/null || echo "No AppImage files found" - ls -lah package/rattler-build/linux/*.deb* 2>/dev/null || echo "No .deb files found" - ls -lah package/rattler-build/linux/*-SHA256.txt 2>/dev/null || echo "No SHA256 files found" + echo "=== Linux release artifacts ===" + ls -lah package/rattler-build/linux/*.AppImage* 2>/dev/null || true + ls -lah package/rattler-build/linux/*.deb* 2>/dev/null || true + ls -lah package/rattler-build/linux/*-SHA256.txt 2>/dev/null || true - - name: Upload AppImage artifact + - name: Upload Linux artifacts uses: https://github.com/actions/upload-artifact@v3 with: - name: kindred-create-appimage + name: release-linux path: | package/rattler-build/linux/*.AppImage + package/rattler-build/linux/*.deb package/rattler-build/linux/*-SHA256.txt + package/rattler-build/linux/*.sha256 if-no-files-found: error - - name: Upload .deb artifact + # --------------------------------------------------------------------------- + # macOS: DMG (Intel + Apple Silicon) + # --------------------------------------------------------------------------- + build-macos: + strategy: + matrix: + include: + - runner: macos-13 + arch: x86_64 + preset: conda-macos-release + - runner: macos-14 + arch: arm64 + preset: conda-macos-release + + runs-on: ${{ matrix.runner }} + + env: + CCACHE_DIR: /tmp/ccache-kindred-create + CCACHE_COMPRESS: "true" + CCACHE_COMPRESSLEVEL: "6" + CCACHE_MAXSIZE: "4G" + CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros" + CCACHE_BASEDIR: ${{ github.workspace }} + BUILD_TAG: ${{ github.ref_name || inputs.tag }} + CFLAGS: "-O3" + CXXFLAGS: "-O3" + + steps: + - name: Checkout repository + uses: https://github.com/actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + fetch-tags: true + + - name: Install pixi + run: | + curl -fsSL https://pixi.sh/install.sh | bash + echo "$HOME/.pixi/bin" >> $GITHUB_PATH + export PATH="$HOME/.pixi/bin:$PATH" + pixi --version + + - name: Restore ccache + id: ccache-restore + uses: https://github.com/actions/cache/restore@v4 + with: + path: /tmp/ccache-kindred-create + key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }} + restore-keys: | + ccache-release-macos-${{ matrix.arch }}- + + - name: Prepare ccache + run: | + mkdir -p $CCACHE_DIR + pixi run ccache -z + + - name: Build release package (DMG) + working-directory: package/rattler-build + run: | + pixi install + pixi run -e package create_bundle + + - name: Show ccache statistics + run: pixi run ccache -s + + - name: Save ccache + if: always() + uses: https://github.com/actions/cache/save@v4 + with: + path: /tmp/ccache-kindred-create + key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }} + + - name: List built artifacts + run: | + echo "=== macOS ${{ matrix.arch }} release artifacts ===" + ls -lah package/rattler-build/osx/*.dmg* 2>/dev/null || true + + - name: Upload macOS artifacts uses: https://github.com/actions/upload-artifact@v3 with: - name: kindred-create-deb + name: release-macos-${{ matrix.arch }} path: | - package/rattler-build/linux/*.deb - package/rattler-build/linux/*.deb.sha256 - if-no-files-found: warn + package/rattler-build/osx/*.dmg + package/rattler-build/osx/*-SHA256.txt + if-no-files-found: error + + # --------------------------------------------------------------------------- + # Windows: .exe installer + .7z archive + # --------------------------------------------------------------------------- + build-windows: + runs-on: windows-latest + + env: + CCACHE_DIR: C:\ccache-kindred-create + CCACHE_COMPRESS: "true" + CCACHE_COMPRESSLEVEL: "6" + CCACHE_MAXSIZE: "4G" + CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros" + CCACHE_BASEDIR: ${{ github.workspace }} + BUILD_TAG: ${{ github.ref_name || inputs.tag }} + CFLAGS: "/O2" + CXXFLAGS: "/O2" + MAKE_INSTALLER: "true" + + steps: + - name: Checkout repository + uses: https://github.com/actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + fetch-tags: true + + - name: Install pixi + shell: bash + run: | + curl -fsSL https://pixi.sh/install.sh | bash + echo "$HOME/.pixi/bin" >> $GITHUB_PATH + export PATH="$HOME/.pixi/bin:$PATH" + pixi --version + + - name: Restore ccache + id: ccache-restore + uses: https://github.com/actions/cache/restore@v4 + with: + path: C:\ccache-kindred-create + key: ccache-release-windows-${{ github.sha }} + restore-keys: | + ccache-release-windows- + + - name: Build release package + shell: bash + working-directory: package/rattler-build + run: | + pixi install + pixi run -e package create_bundle + + - name: Build NSIS installer + shell: bash + working-directory: package/rattler-build/windows + run: | + if [ "${MAKE_INSTALLER}" == "true" ]; then + # The create_bundle.sh script builds the 7z archive. + # NSIS installer is built as part of the bundle script when + # MAKE_INSTALLER is set and NSIS is available. + echo "Installer build completed as part of create_bundle" + fi + + - name: Save ccache + if: always() + uses: https://github.com/actions/cache/save@v4 + with: + path: C:\ccache-kindred-create + key: ccache-release-windows-${{ github.sha }} + + - name: List built artifacts + shell: bash + run: | + echo "=== Windows release artifacts ===" + ls -lah package/rattler-build/windows/*.7z* 2>/dev/null || true + ls -lah package/rattler-build/windows/*.exe 2>/dev/null || true + ls -lah package/rattler-build/windows/*-SHA256.txt 2>/dev/null || true + + - name: Upload Windows artifacts + uses: https://github.com/actions/upload-artifact@v3 + with: + name: release-windows + path: | + package/rattler-build/windows/*.7z + package/rattler-build/windows/*.exe + package/rattler-build/windows/*-SHA256.txt + if-no-files-found: error + + # --------------------------------------------------------------------------- + # Create Gitea release from all platform artifacts + # --------------------------------------------------------------------------- + publish-release: + needs: [build-linux, build-macos, build-windows] + runs-on: ubuntu-latest + + env: + BUILD_TAG: ${{ github.ref_name || inputs.tag }} + + steps: + - name: Download all artifacts + uses: https://github.com/actions/download-artifact@v3 + with: + path: artifacts + + - name: List all release artifacts + run: | + echo "=== All release artifacts ===" + find artifacts -type f | sort + + - name: Collect release files + run: | + mkdir -p release + find artifacts -type f \( \ + -name "*.AppImage" -o \ + -name "*.deb" -o \ + -name "*.dmg" -o \ + -name "*.7z" -o \ + -name "*.exe" -o \ + -name "*SHA256*" -o \ + -name "*.sha256" \ + \) -exec cp {} release/ \; + echo "=== Release files ===" + ls -lah release/ + + - name: Create release + uses: https://gitea.com/actions/release-action@main + with: + files: release/* + title: "Kindred Create ${{ env.BUILD_TAG }}" + body: | + ## Kindred Create ${{ env.BUILD_TAG }} + + ### Downloads + + | Platform | File | + |----------|------| + | Linux (AppImage) | `KindredCreate-*-Linux-x86_64.AppImage` | + | Linux (Debian/Ubuntu) | `kindred-create_*.deb` | + | macOS (Intel) | `KindredCreate-*-macOS-x86_64.dmg` | + | macOS (Apple Silicon) | `KindredCreate-*-macOS-arm64.dmg` | + | Windows (Installer) | `KindredCreate-*-Windows-x86_64-installer.exe` | + | Windows (Portable) | `KindredCreate-*-Windows-x86_64.7z` | + + SHA256 checksums are provided alongside each artifact. + prerelease: ${{ contains(github.ref_name, 'rc') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') }} + api_key: ${{ secrets.RELEASE_TOKEN }} diff --git a/.gitmodules b/.gitmodules index 632ba8d10d..c60efbd9de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "src/3rdParty/OndselSolver"] path = src/3rdParty/OndselSolver - url = https://gitea.kindred.internal/kindred/ondsel.git + url = https://git.kindred-systems.com/kindred/solver.git [submodule "tests/lib"] path = tests/lib url = https://github.com/google/googletest @@ -12,7 +12,7 @@ url = https://github.com/FreeCAD/AddonManager.git [submodule "mods/ztools"] path = mods/ztools - url = https://gitea.kindred.internal/kindred/ztools-0065.git + url = https://git.kindred-systems.com/forbes/ztools.git [submodule "mods/silo"] path = mods/silo - url = https://gitea.kindred.internal/kindred/silo-0062.git + url = https://git.kindred-systems.com/kindred/silo.git diff --git a/README.md b/README.md index 631fa61bb5..380bd5f6e3 100644 --- a/README.md +++ b/README.md @@ -2,179 +2,50 @@ **An engineering-focused parametric 3D CAD platform built on FreeCAD 1.0+** -[Website](https://www.kindred-systems.com/create) • -[FreeCAD Documentation](https://wiki.freecad.org) • -[FreeCAD Forum](https://forum.freecad.org/) +[Website](https://www.kindred-systems.com/create) | +[Downloads](https://git.kindred-systems.com/kindred/create/releases) | +[Issue Tracker](https://git.kindred-systems.com/kindred/create/issues) -> **MVP Release** - Kindred Create is currently in active development. Features and interfaces may change. +> Kindred Create is in active development. Features and interfaces may change. --- -## Overview +## What is Kindred Create? -Kindred Create is a fork of FreeCAD 1.0+ that integrates custom workbenches and tooling for professional engineering workflows. It combines the power of FreeCAD's parametric modeling with purpose-built extensions for part design, assembly management, and parts database integration. +Kindred Create is a fork of [FreeCAD](https://www.freecad.org) that adds integrated tooling for professional engineering workflows. It ships two custom workbenches and a purpose-built dark theme on top of FreeCAD's parametric modeling core. -**Key additions over base FreeCAD:** +**ztools** -- A unified workbench that consolidates part design, assembly, and sketcher tools into a single interface. Adds custom datum creation (planes, axes, points with 16 creation modes), pattern tools for assemblies, an enhanced pocket with flip-side cutting, and spreadsheet formatting commands. -- **ztools Workbench** - Unified interface consolidating part design, assembly, and drawing tools with custom engineering features -- **Silo Integration** - Parts database system for tracking, versioning, and managing CAD files across teams, with an interactive browsing panel for searching, opening, and inspecting parts directly from the dock -- **Catppuccin Mocha Theme** - Dark theme with spanning tree branch indicators, optimized for extended work sessions +**Silo** -- A parts database system for managing CAD files, part numbers, revisions, and bills of materials across teams. Includes a Go REST API server backed by PostgreSQL and MinIO, with FreeCAD commands for opening, saving, and syncing files directly from the application. A dock panel provides in-viewport browsing and search. + +**Catppuccin Mocha theme** -- A dark theme applied across the entire application, including the 3D viewport, sketch editor, spreadsheet view, and tree view. Uses spanning-line branch indicators instead of disclosure arrows. Kindred Create is maintained by [Kindred Systems LLC](https://www.kindred-systems.com). --- -## Features - -### ztools Workbench - -The ztools workbench provides a unified interface that consolidates functionality from multiple FreeCAD workbenches while adding custom engineering-oriented tools. - -#### Consolidated Toolbars (17 total) - -ztools exposes commands from PartDesign, Sketcher, Assembly, and Spreadsheet workbenches through a single unified interface: - -- **Structure & Sketcher Tools** - Body/Sketch creation, editing, mapping, validation -- **PartDesign Datums** - Planes, lines, points, coordinate systems, binders, clones -- **Additive Features** - Pad, revolution, loft, pipe, helix, and primitives -- **Subtractive Features** - Pocket, hole, groove, loft, pipe, helix, and primitives -- **Transformations** - Mirror, linear pattern, polar pattern, multi-transform -- **Dress-Up Features** - Fillet, chamfer, draft, thickness -- **Boolean Operations** - Union, intersection, difference -- **Assembly Tools** - Create assembly, insert link, insert new part -- **Assembly Joints** - 13 joint types (fixed, revolute, cylindrical, slider, ball, distance, parallel, perpendicular, angle, rack-pinion, screw, gears, belt) -- **Assembly Management** - Toggle grounded, solve, create view, create BOM, export -- **Spreadsheet Tools** - Create, import, export, aliases, merge/split cells - -#### Custom Datum Tools - -ztools includes a custom datum creation system with 16 creation modes, using a purpose-built attachment system that stores geometry references for reliable parametric updates. - -**Datum Planes (7 modes):** -- Offset from Face - Distance offset perpendicular to a face -- Offset from Plane - Distance offset from an existing datum plane -- Midplane - Plane equidistant between two parallel faces -- 3 Points - Plane defined by three vertices -- Normal to Edge - Plane perpendicular to an edge at a specified parameter -- Angled - Plane rotated about an edge by a specified angle -- Tangent to Cylinder - Plane tangent to a cylindrical surface - -**Datum Axes (4 modes):** -- 2 Points - Axis through two vertices -- From Edge - Axis aligned with a linear edge -- Cylinder Center - Axis at the center of a cylindrical face -- Plane Intersection - Axis at the intersection of two planes - -**Datum Points (5 modes):** -- At Vertex - Point at a selected vertex -- XYZ Coordinates - Point at absolute coordinates -- On Edge - Point at a parameter along an edge -- Face Center - Point at the centroid of a face -- Circle Center - Point at the center of a circular edge - -#### Custom Pattern Tools - -- **Rotated Linear Pattern** - Linear pattern with incremental rotation per instance -- **Assembly Linear Pattern** - Pattern assembly components linearly with spacing control -- **Assembly Polar Pattern** - Pattern assembly components around a rotation axis - -#### Enhanced Pocket - -SOLIDWORKS-style "Flip Side to Cut" feature that removes material outside the sketch profile instead of inside, using boolean operations internally. - -#### Spreadsheet Formatting Tools - -Dark-theme compatible formatting commands for spreadsheets: -- Bold, italic, underline toggles -- Left, center, right alignment -- Background and text color pickers -- Quick alias creation from cell labels - -### Silo Parts Database - -Silo is a parts database system designed for managing CAD files, part numbers, and revision history across engineering teams. - -**Architecture:** -- **Server Daemon** - Go-based REST API server -- **PostgreSQL** - Relational data storage for part metadata, relationships, and revision history -- **MinIO** - S3-compatible object storage for CAD file versioning -- **FreeCAD Workbench** - Integrated commands for check-in, check-out, and synchronization - -**Core Capabilities:** -- Configurable part numbering schemas defined in YAML -- Full revision history with status tracking (draft, review, released, obsolete) -- Bill of materials management with relationship types and quantities -- Project-based organization and tagging -- CSV import/export for bulk operations -- Web interface for browsing and searching parts - -**FreeCAD Integration:** -- Open, save, and commit files directly to Silo -- Pull latest revisions and push changes -- View item metadata and revision history -- **Database Activity Panel** - Interactive dock panel for browsing, searching, and opening parts without leaving the 3D viewport. Includes search filtering, type filtering (part/assembly), a details pane showing metadata (part number, description, type, revision, projects), and direct open/info actions. - -Silo documentation is available in the `mods/silo/` directory. - -### Catppuccin Mocha Theme - -A comprehensive dark theme using the [Catppuccin Mocha](https://github.com/catppuccin/catppuccin) color palette, applied across: - -- Main window, toolbars, and menus -- 3D viewport backgrounds and selection colors -- Sketch editor colors for edges, vertices, and constraints -- Python console and code editor syntax highlighting -- Spreadsheet backgrounds and text -- Property editor and tree view -- All dialog and widget styling -- Tree view branch indicators using spanning lines (`├`, `└`, `│`) instead of disclosure arrows - -The theme is automatically applied when using Kindred Create. - ---- - ## Installing -### Prebuilt Binaries +### Prebuilt packages (Linux) -Prebuilt packages for Linux are available on the [releases page](https://git.kindred-systems.com/kindred/create/releases). +Download from the [releases page](https://git.kindred-systems.com/kindred/create/releases). -#### Debian/Ubuntu (.deb) - -Download the `.deb` package from the releases page and install with: - -```bash -sudo dpkg -i kindred-create_*.deb -sudo apt-get install -f # Install any missing dependencies -``` - -Or install directly with apt: +**Debian/Ubuntu:** ```bash sudo apt install ./kindred-create_*.deb ``` -#### AppImage - -Download the `.AppImage` file from the releases page, make it executable, and run: +**AppImage:** ```bash chmod +x KindredCreate-*.AppImage ./KindredCreate-*.AppImage ``` -After installation, launch Kindred Create from your application menu or run `kindred-create` from the terminal. +### Building from source -### Building from Source - -Kindred Create uses [pixi](https://pixi.sh) for dependency management and CMake for building. Pixi handles all build dependencies automatically via conda packages. - -#### Prerequisites - -- [pixi](https://pixi.sh) (conda-based package manager) -- Git with submodule support - -#### Build Steps +Kindred Create uses [pixi](https://pixi.sh) for dependency management and CMake for building. ```bash git clone --recursive ssh://git@git.kindred-systems.com:2222/kindred/create.git @@ -182,91 +53,61 @@ cd create pixi run configure pixi run build pixi run install -``` - -To launch the built application: - -```bash pixi run freecad ``` -#### Platform Support +Debug and release variants are available (`pixi run build-debug`, `pixi run build-release`). See `CMakePresets.json` for platform-specific presets covering Linux, macOS, and Windows. -CMake presets are available for: - -- **Linux** (x86-64, aarch64) - Clang compiler -- **macOS** (Intel, Apple Silicon) - Clang compiler -- **Windows** - MSVC compiler - -See `CMakePresets.json` for platform-specific configuration. For general FreeCAD build guidance: - -- [Linux](https://wiki.freecad.org/Compile_on_Linux) -- [Windows](https://wiki.freecad.org/Compile_on_Windows) -- [macOS](https://wiki.freecad.org/Compile_on_MacOS) +For general FreeCAD compilation guidance, see the FreeCAD wiki for [Linux](https://wiki.freecad.org/Compile_on_Linux), [Windows](https://wiki.freecad.org/Compile_on_Windows), or [macOS](https://wiki.freecad.org/Compile_on_MacOS). --- ## Usage -### Getting Started +Kindred Create is compatible with standard FreeCAD workflows. The [FreeCAD wiki](https://wiki.freecad.org/Getting_started) covers general usage. -Kindred Create is compatible with standard FreeCAD workflows. The FreeCAD wiki provides documentation on general usage: +### ztools -- [Getting started](https://wiki.freecad.org/Getting_started) -- [Features list](https://wiki.freecad.org/Feature_list) -- [Workbenches](https://wiki.freecad.org/Workbenches) -- [Scripting](https://wiki.freecad.org/Power_users_hub) +Select the ztools workbench from the workbench selector. It presents consolidated toolbars from PartDesign, Sketcher, Assembly, and Spreadsheet in a single interface. ZTools commands are also injected into the PartDesign workbench menus and toolbars automatically. -### ztools Workbench +See `mods/ztools/` for workbench-specific documentation. -The ztools workbench is available from the workbench selector. On activation, it presents consolidated toolbars and applies the Catppuccin Mocha theme to spreadsheets. +### Silo -### Silo Setup +Silo requires a running server instance. See `mods/silo/README.md` for server deployment instructions. -Silo requires a running server instance with PostgreSQL and MinIO. See `mods/silo/README.md` for server deployment instructions. +The FreeCAD workbench reads configuration from: +- `SILO_API_URL` -- Server API endpoint (default: `http://localhost:8080/api`) +- `SILO_PROJECTS_DIR` -- Local projects directory (default: `~/projects`) -Configure the FreeCAD workbench with environment variables: -- `SILO_API_URL` - Silo server API endpoint (default: `http://localhost:8080/api`) -- `SILO_PROJECTS_DIR` - Local projects directory (default: `~/projects`) +On first launch, Kindred Create prompts for Silo server configuration. Silo commands (Open, Save, Commit, Pull, Push, BOM) are available in the File menu across all workbenches. --- -## Project Structure +## Project structure ``` -kindred-create/ -├── src/ # FreeCAD core source -│ ├── App/ # Core application logic -│ ├── Base/ # Base classes and utilities -│ ├── Gui/ # GUI framework -│ │ └── Stylesheets/ # Theme stylesheets and assets -│ ├── Mod/ # FreeCAD modules (PartDesign, Assembly, Sketcher, etc.) -│ │ └── Create/ # Kindred Create module (loads addon workbenches) +create/ +├── src/ +│ ├── App/ # Core application (C++) +│ ├── Base/ # Base classes (C++) +│ ├── Gui/ # GUI framework and stylesheets (C++) +│ ├── Mod/ # FreeCAD modules (PartDesign, Assembly, Sketcher, ...) +│ │ └── Create/ # Kindred bootstrap module -- loads ztools and Silo │ └── 3rdParty/ # Vendored dependencies (OndselSolver, GSL) -├── mods/ # Kindred Create addon modules (git submodules) +├── mods/ # Kindred addon workbenches (git submodules) │ ├── ztools/ # ztools workbench -│ │ ├── ztools/ # Workbench package -│ │ │ ├── InitGui.py # Workbench registration -│ │ │ └── ztools/ # Commands and resources -│ │ └── CatppuccinMocha/ # Theme preference pack │ └── silo/ # Silo parts database -│ ├── cmd/ # Go server entry points -│ ├── internal/ # Go API, database, storage packages -│ ├── pkg/freecad/ # FreeCAD workbench (Python) -│ ├── deployments/ # Docker configuration -│ └── migrations/ # PostgreSQL migrations -├── resources/ # Branding and preferences -│ ├── branding/ # Splash screens and logos -│ ├── preferences/ # Default preference packs -│ └── icons/ # Application icons (16x16 to 512x512) -├── package/ # Packaging (debian, AppImage) -├── .gitea/workflows/ # CI/CD workflows (build, release) -├── CMakeLists.txt # Root CMake configuration -├── CMakePresets.json # Platform-specific CMake presets -└── pixi.toml # Pixi environment and dependency definition +├── resources/preferences/ # Default preferences and theme +├── package/ # Packaging (Debian, AppImage, Windows installer, RPM) +├── .gitea/workflows/ # CI/CD (build and release pipelines) +├── docs/ # Architecture and integration docs +├── CMakeLists.txt # Root build configuration +├── CMakePresets.json # Platform build presets +└── pixi.toml # Pixi environment and tasks ``` -The `mods/ztools` and `mods/silo` directories are git submodules. After cloning, initialize them with: +The `mods/` workbenches are git submodules. If you cloned without `--recursive`, initialize them with: ```bash git submodule update --init --recursive @@ -274,34 +115,37 @@ git submodule update --init --recursive --- -## Reporting Issues +## Contributing -Report issues at [git.kindred-systems.com/kindred/create/issues](https://git.kindred-systems.com/kindred/create/issues). +Contributions follow the [FreeCAD Contribution Process](CONTRIBUTING.md) (FCP). Submit changes as pull requests against the `main` branch. -When reporting: +Code quality tools are configured and enforced via pre-commit hooks: +- **C/C++**: clang-format, clang-tidy +- **Python**: black (100-char lines), pylint -1. Specify whether the issue is with Kindred Create additions (ztools, Silo, theme) or base FreeCAD functionality -2. Include version info from `Help > About FreeCAD > Copy to clipboard` -3. Provide steps to reproduce the issue -4. Attach example files if applicable (FCStd as ZIP) +Install pre-commit hooks locally: -For base FreeCAD issues, consider also checking the [FreeCAD issue tracker](https://github.com/FreeCAD/FreeCAD/issues). +```bash +pip install pre-commit +pre-commit install +``` + +## Reporting issues + +Report issues at the [issue tracker](https://git.kindred-systems.com/kindred/create/issues). When reporting: + +1. Note whether the issue involves Kindred Create additions (ztools, Silo, theme) or base FreeCAD +2. Include version info from **Help > About FreeCAD > Copy to clipboard** +3. Provide reproduction steps and attach example files (FCStd as ZIP) if applicable + +For base FreeCAD issues, also check the [FreeCAD issue tracker](https://github.com/FreeCAD/FreeCAD/issues). --- ## License -Kindred Create is licensed under the [LGPL-2.1-or-later](LICENSE) license, consistent with FreeCAD. - ---- +[LGPL-2.1-or-later](LICENSE), consistent with FreeCAD. ## Acknowledgments -Kindred Create is built on [FreeCAD](https://www.freecad.org), an open-source parametric 3D modeler. We acknowledge the FreeCAD community and contributors for their foundational work. - -**Underlying Technology:** -- [OpenCASCADE](https://www.opencascade.com/) - Geometry kernel -- [Coin3D](https://github.com/coin3d/coin) - 3D scene representation -- [Qt](https://www.qt.io/) - GUI framework -- [Python](https://www.python.org/) - Scripting and workbench development -- [Catppuccin](https://github.com/catppuccin/catppuccin) - Color palette +Built on [FreeCAD](https://www.freecad.org) and its ecosystem: [OpenCASCADE](https://www.opencascade.com/), [Coin3D](https://github.com/coin3d/coin), [Qt](https://www.qt.io/), [Python](https://www.python.org/). Theme colors from [Catppuccin](https://github.com/catppuccin/catppuccin). diff --git a/docs/CI_CD.md b/docs/CI_CD.md new file mode 100644 index 0000000000..ba4f89febf --- /dev/null +++ b/docs/CI_CD.md @@ -0,0 +1,273 @@ +# CI/CD + +Kindred Create uses Gitea Actions for continuous integration and release builds. Workflows are defined in `.gitea/workflows/`. + +## Overview + +| Workflow | Trigger | Purpose | Artifacts | +|----------|---------|---------|-----------| +| `build.yml` | Push to `main`, pull requests | Build + test | Linux tarball | +| `release.yml` | Tags matching `v*` | Multi-platform release | AppImage, .deb, .dmg, .exe, .7z | + +All builds run on public runners in dockerized mode. No host-mode or internal infrastructure is required. + +--- + +## Build workflow (`build.yml`) + +Runs on every push to `main` and on pull requests. Builds the project in an Ubuntu 24.04 container and runs the test suite. + +### Steps + +1. Install system prerequisites (GL, X11, fontconfig headers) +2. Checkout with recursive submodules +3. Install pixi +4. Restore ccache from prior builds +5. Configure via `pixi run cmake --preset conda-linux-release` +6. Build with `pixi run cmake --build build/release -j$(nproc)` +7. Run C++ unit tests under xvfb (Assembly_tests excluded due to discovery timeouts) +8. Install to `build/release/install` +9. Run Python CLI tests (`FreeCADCmd -t 0`) +10. Run GUI tests headless (`xvfb-run FreeCAD -t 0`) +11. Package as `.tar.xz` with SHA256 checksum +12. Upload artifact (14-day retention) + +### Caching + +ccache is persisted between builds using `actions/cache`. Cache keys are scoped by branch and commit SHA, with fallback to the branch key then `main`. + +``` +Key: ccache-build-{branch}-{sha} +Fallback: ccache-build-{branch}- +Fallback: ccache-build-main- +``` + +ccache configuration: 4 GB max, zlib compression level 6, sloppy mode for include timestamps and PCH. + +--- + +## Release workflow (`release.yml`) + +Triggered by pushing a tag matching `v*` (e.g., `v0.1.0`, `v1.0.0-rc1`). Builds release packages for all platforms in parallel, then creates a Gitea release with all artifacts. + +### Triggering a release + +```bash +git tag v0.1.0 +git push origin v0.1.0 +``` + +Or manually via `workflow_dispatch` with a tag input. + +Tags containing `rc`, `beta`, or `alpha` are marked as pre-releases. + +### Platform matrix + +| Job | Runner | Container | Preset | Output | +|-----|--------|-----------|--------|--------| +| `build-linux` | `ubuntu-latest` | `ubuntu:24.04` | `conda-linux-release` | AppImage, .deb | +| `build-macos` (Intel) | `macos-13` | native | `conda-macos-release` | .dmg (x86_64) | +| `build-macos` (Apple Silicon) | `macos-14` | native | `conda-macos-release` | .dmg (arm64) | +| `build-windows` | `windows-latest` | native | `conda-windows-release` | .exe (NSIS), .7z | + +All four jobs run concurrently. After all succeed, `publish-release` collects artifacts and creates the Gitea release. + +### Linux build + +Uses the rattler-build packaging pipeline: + +1. `pixi install` in `package/rattler-build/` +2. `pixi run -e package create_bundle` -- invokes `linux/create_bundle.sh` +3. The bundle script: + - Copies the pixi conda environment to an AppDir + - Strips unnecessary files (includes, static libs, cmake files, `__pycache__`) + - Downloads `appimagetool` and creates a squashfs AppImage (zstd compressed) + - Generates SHA256 checksums +4. `package/debian/build-deb.sh` builds a .deb from the AppDir + - Installs to `/opt/kindred-create/` with wrapper scripts in `/usr/bin/` + - Sets up LD_LIBRARY_PATH, QT_PLUGIN_PATH, PYTHONPATH in wrappers + - Creates desktop entry, MIME types, AppStream metainfo + +### macOS build + +Builds natively on macOS runners (Intel via `macos-13`, Apple Silicon via `macos-14`): + +1. `pixi run -e package create_bundle` invokes `osx/create_bundle.sh` +2. The bundle script: + - Creates `FreeCAD.app` bundle with conda environment in `Contents/Resources/` + - Runs `fix_macos_lib_paths.py` to convert absolute rpaths to `@loader_path` + - Builds native macOS launcher from `launcher/CMakeLists.txt` + - Patches `Info.plist` with version info + - Creates DMG via `dmgbuild` + - If `SIGN_RELEASE=true`: signs and notarizes via `macos_sign_and_notarize.zsh` + +### Windows build + +Builds natively on Windows runner: + +1. `pixi run -e package create_bundle` invokes `windows/create_bundle.sh` (bash via Git for Windows) +2. The bundle script: + - Copies conda environment DLLs, Python, and FreeCAD binaries to `FreeCAD_Windows/` + - Applies SSL certificate patch (`ssl-patch.py`) + - Creates `qt6.conf` for Qt6 plugin paths + - Creates `.exe` wrapper shims via Chocolatey `shimgen` + - Compresses to `.7z` (compression level 9) + - If `MAKE_INSTALLER=true` and NSIS available: builds NSIS installer +3. NSIS installer (`package/WindowsInstaller/`): + - Multi-language support (28 languages) + - File associations for `.FCStd` + - Start menu and desktop shortcuts + - LZMA compression + +### Publish step + +`publish-release` runs after all platform builds succeed: + +1. Downloads all artifacts from `build-linux`, `build-macos`, `build-windows` +2. Collects release files (AppImage, .deb, .dmg, .7z, .exe, checksums) +3. Creates a Gitea release via `gitea.com/actions/release-action` +4. Requires `RELEASE_TOKEN` secret with repository write permissions + +--- + +## Runner configuration + +### Public runner setup + +Workflows target public Gitea-compatible runners. The Linux build job runs inside a Docker container (`ubuntu:24.04`) for isolation and reproducibility. macOS and Windows jobs run directly on hosted runners. + +**Required runner labels:** +- `ubuntu-latest` -- Linux builds (dockerized) +- `macos-13` -- macOS Intel builds +- `macos-14` -- macOS Apple Silicon builds +- `windows-latest` -- Windows builds + +### Registering a self-hosted runner + +If using self-hosted runners instead of hosted: + +```bash +# Download the Gitea runner binary +curl -fsSL -o act_runner https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-linux-amd64 +chmod +x act_runner + +# Register with your Gitea instance +./act_runner register \ + --instance https://git.kindred-systems.com \ + --token \ + --labels ubuntu-latest:docker://ubuntu:24.04 + +# Start the runner +./act_runner daemon +``` + +For dockerized mode, the runner executes jobs inside containers. Ensure Docker is installed on the runner host. + +The runner config file (`config.yaml`) should set: + +```yaml +runner: + labels: + - "ubuntu-latest:docker://ubuntu:24.04" +container: + privileged: false + network: bridge +``` + +--- + +## Secrets + +| Secret | Used by | Purpose | +|--------|---------|---------| +| `RELEASE_TOKEN` | `release.yml` (publish) | Gitea API token for creating releases | +| `SIGNING_KEY_ID` | macOS build (optional) | Apple Developer signing identity | + +--- + +## Build tools + +### pixi + +[pixi](https://pixi.sh) manages all build dependencies via conda-forge. It ensures consistent toolchains (clang, cmake, Qt6, OpenCASCADE, etc.) across all platforms without relying on system packages. + +Key pixi tasks (defined in root `pixi.toml`): + +| Task | Description | +|------|-------------| +| `pixi run configure` | CMake configure (defaults to debug) | +| `pixi run build` | CMake build (defaults to debug) | +| `pixi run install` | CMake install | +| `pixi run test` | Run ctest | +| `pixi run freecad` | Launch built FreeCAD | +| `pixi run build-release` | CMake build (release) | + +### CMake presets + +Defined in `CMakePresets.json`. Release builds use: + +| Platform | Preset | Compiler | Linker | +|----------|--------|----------|--------| +| Linux | `conda-linux-release` | clang/clang++ | mold | +| macOS | `conda-macos-release` | clang/clang++ | default | +| Windows | `conda-windows-release` | MSVC | default | + +### ccache + +Compiler cache is used across all builds to speed up incremental compilation. Cache is persisted between CI runs via `actions/cache`. Configuration: + +- Max size: 4 GB +- Compression: zlib level 6 +- Sloppy mode: include timestamps, PCH defines, time macros + +--- + +## Adding a new platform or package format + +1. Create a bundle script at `package/rattler-build//create_bundle.sh` +2. Add the platform to `package/rattler-build/pixi.toml` if needed +3. Add a new job to `release.yml` following the existing pattern +4. Add the new artifact pattern to the `publish-release` job's `find` command +5. Update the release body template with the new download entry + +--- + +## Troubleshooting + +### Build fails with missing system libraries + +The Docker container installs only minimal dependencies. If a new dependency is needed, add it to the `apt-get install` step in the workflow. Check the pixi environment first -- most dependencies should come from conda-forge, not system packages. + +### ccache misses are high + +ccache misses spike when: +- The compiler version changes (pixi update) +- CMake presets change configuration flags +- The cache key doesn't match (new branch, force-pushed SHA) + +Check `pixi run ccache -s` output for hit/miss ratios. + +### Submodule checkout fails + +Submodules pointing to internal Gitea instances require either: +- Public mirrors of the submodule repositories +- Runner network access to the Gitea instance +- Submodule URLs updated to public-facing addresses in `.gitmodules` + +### macOS signing + +Code signing and notarization require: +- `SIGNING_KEY_ID` secret set to the Apple Developer identity +- `SIGN_RELEASE=true` environment variable +- Valid Apple Developer account credentials in the runner keychain + +Without signing, the DMG is created unsigned. Users will see Gatekeeper warnings. + +### Windows NSIS installer not created + +The NSIS installer requires: +- NSIS 3.x installed in the runner environment (available via conda or Chocolatey) +- `MAKE_INSTALLER=true` environment variable +- Chocolatey `shimgen.exe` for wrapper executables + +If NSIS is unavailable, only the `.7z` portable archive is produced. diff --git a/docs/INTEGRATION_PLAN.md b/docs/INTEGRATION_PLAN.md index d41d8e679e..bf97e476db 100644 --- a/docs/INTEGRATION_PLAN.md +++ b/docs/INTEGRATION_PLAN.md @@ -1,460 +1,159 @@ -# Kindred Create Integration Plan +# Integration Plan -This document outlines the strategy for integrating ztools and Silo workbenches as built-in addons in Kindred Create while maintaining clear boundaries with FreeCAD core. +Strategy for integrating ztools and Silo as built-in addons while maintaining clear boundaries with FreeCAD core. ## Goals -1. **Native feel** - ztools and Silo should feel like first-class citizens, not bolted-on addons -2. **Clean boundaries** - Clear separation between FreeCAD core, Kindred extensions, and addon code -3. **Minimal core modifications** - Preserve FreeCAD's container models (Part, Body, Assembly) -4. **Maintainability** - Easy to pull upstream FreeCAD changes without merge conflicts -5. **Extensibility** - Architecture that supports future Kindred-specific features +1. **Native feel** -- ztools and Silo behave as first-class citizens, not bolted-on addons +2. **Clean boundaries** -- Clear separation between FreeCAD core, Kindred extensions, and addon code +3. **Minimal core modifications** -- Preserve FreeCAD's container models (Part, Body, Assembly) +4. **Maintainability** -- Easy to pull upstream FreeCAD changes without merge conflicts +5. **Extensibility** -- Architecture supports future Kindred-specific features -## Current State - -### Repository Structure -``` -kindred-create/ -├── src/Mod/ # FreeCAD core modules (PartDesign, Sketcher, Assembly, etc.) -├── mods/ # Kindred addons (git submodules) -│ ├── ztools/ # Part design extensions, theme -│ └── silo/ # Parts database integration -└── resources/ # Branding, default preferences -``` - -### Integration Points Today -- **ztools**: Pure Python addon wrapping FreeCAD commands with enhanced UX -- **Silo**: Pure Python addon with REST API integration -- **Theme**: Preference pack + runtime stylesheet application - -## Architecture Layers +## Architecture layers ``` -┌─────────────────────────────────────────────────────────────────┐ -│ Kindred Create Application │ -├─────────────────────────────────────────────────────────────────┤ -│ Layer 4: Kindred Workbenches (mods/) │ -│ ┌─────────────────────┐ ┌─────────────────────┐ │ -│ │ ztools │ │ Silo │ │ -│ │ - Datum Creator │ │ - Open/Save/Commit │ │ -│ │ - Enhanced Pocket │ │ - Part numbering │ │ -│ │ - Assembly Patterns│ │ - Revision control │ │ -│ │ - Spreadsheet fmt │ │ - BOM management │ │ -│ └─────────────────────┘ └─────────────────────┘ │ -├─────────────────────────────────────────────────────────────────┤ -│ Layer 3: Kindred Core Extensions (src/Mod/Kindred/) │ -│ ┌─────────────────────────────────────────────────────────────┐│ -│ │ - KindredFeatures: Flip-side pocket, custom geometry ops ││ -│ │ - KindredGui: Shared UI components, selection helpers ││ -│ │ - Theme integration hooks ││ -│ └─────────────────────────────────────────────────────────────┘│ -├─────────────────────────────────────────────────────────────────┤ -│ Layer 2: FreeCAD Python API │ -│ ┌─────────────────────────────────────────────────────────────┐│ -│ │ FreeCAD, FreeCADGui, Part, PartDesign, Sketcher, Assembly ││ -│ └─────────────────────────────────────────────────────────────┘│ -├─────────────────────────────────────────────────────────────────┤ -│ Layer 1: FreeCAD Core (C++) │ -│ ┌─────────────────────────────────────────────────────────────┐│ -│ │ App::Document, Part::Feature, PartDesign::Body, etc. ││ -│ └─────────────────────────────────────────────────────────────┘│ -└─────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────┐ +│ Kindred Create Application │ +├─────────────────────────────────────────────────────────────┤ +│ Layer 4: Kindred Workbenches (mods/) │ +│ ┌──────────────────┐ ┌──────────────────┐ │ +│ │ ztools │ │ Silo │ │ +│ │ Datum Creator │ │ Open/Save/Commit│ │ +│ │ Enhanced Pocket │ │ Part numbering │ │ +│ │ Assembly Patterns│ │ Revision control│ │ +│ │ Spreadsheet fmt │ │ BOM management │ │ +│ └──────────────────┘ └──────────────────┘ │ +├─────────────────────────────────────────────────────────────┤ +│ Layer 3: Kindred Bootstrap (src/Mod/Create/) │ +│ ┌─────────────────────────────────────────────────────────┐│ +│ │ Addon loading, theme application, global menu/toolbar ││ +│ │ injection via WorkbenchManipulator API ││ +│ └─────────────────────────────────────────────────────────┘│ +├─────────────────────────────────────────────────────────────┤ +│ Layer 2: FreeCAD Python API │ +│ ┌─────────────────────────────────────────────────────────┐│ +│ │ FreeCAD, FreeCADGui, Part, PartDesign, Sketcher, ││ +│ │ Assembly, WorkbenchManipulator ││ +│ └─────────────────────────────────────────────────────────┘│ +├─────────────────────────────────────────────────────────────┤ +│ Layer 1: FreeCAD Core (C++) │ +│ ┌─────────────────────────────────────────────────────────┐│ +│ │ App::Document, Part::Feature, PartDesign::Body, etc. ││ +│ └─────────────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────┘ ``` -## Boundary Definitions +## Boundary definitions -### Layer 1: FreeCAD Core (DO NOT MODIFY) -**Location**: `src/Mod/PartDesign/App/`, `src/Mod/Part/App/`, etc. +### Layer 1: FreeCAD Core -- do not modify -These are FreeCAD's fundamental data structures and should remain untouched: -- `PartDesign::Body` - Feature container -- `PartDesign::Pocket`, `PartDesign::Pad` - Additive/subtractive features -- `Part::Feature` - Base geometric feature -- `App::Document` - Document container -- `Sketcher::SketchObject` - 2D constraint system +FreeCAD's fundamental data structures: `PartDesign::Body`, `PartDesign::Pocket`, `Part::Feature`, `App::Document`, `Sketcher::SketchObject`. Modifying these creates merge conflicts with upstream and risks breaking FCStd file compatibility. -**Rationale**: Modifying these creates merge conflicts with upstream FreeCAD and risks breaking compatibility with existing FCStd files. +### Layer 2: FreeCAD Python API -- use as-is -### Layer 2: FreeCAD Python API (USE AS-IS) -**Access via**: `import FreeCAD`, `import FreeCADGui`, `import Part`, etc. +The Python API provides everything needed for feature creation, command registration, and geometry access. ZTools and Silo operate entirely through this layer. -The Python API provides everything needed for feature creation: -- Create objects: `body.newObject("PartDesign::Pocket", "Pocket")` -- Set properties: `pocket.Length = 10.0` -- Register commands: `FreeCADGui.addCommand("Name", CommandClass())` -- Access geometry: `shape.Faces`, `shape.Edges`, `shape.Vertexes` +### Layer 3: Kindred Bootstrap -- `src/Mod/Create/` -### Layer 3: Kindred Core Extensions (NEW - MINIMAL) -**Location**: `src/Mod/Kindred/` (to be created) +The Create module is a thin Python loader that: +- Adds `mods/` addon paths to `sys.path` and executes their `Init.py`/`InitGui.py` files +- Installs `SiloMenuManipulator` for global File menu/toolbar injection +- Sets up deferred Silo dock panels (auth, activity) via `QTimer` +- Handles first-start configuration -A thin C++ module providing capabilities that cannot be achieved in pure Python: +This layer does not contain C++ code. It uses FreeCAD's `WorkbenchManipulator` API for menu/toolbar injection. -| Component | Purpose | Justification | -|-----------|---------|---------------| -| `CreateFeatures` | Custom PartDesign-like features | Python feature objects have performance limitations for complex boolean operations | -| `CreateGui` | Shared UI utilities | Common selection helpers, task panel base classes | -| `ThemeHooks` | Theme application entry points | Ensure theme applies before any workbench loads | +### Layer 4: Kindred Workbenches -- `mods/` -**Namespace**: All Kindred Create features use the `Create::` prefix (e.g., `Create::FlipPocket`). +Pure Python workbenches following FreeCAD's addon pattern. Self-contained with `InitGui.py`, `Init.py`, and `package.xml`. Developed and versioned independently as git submodules. -**Design principle**: Only add C++ code when Python cannot achieve the requirement. Document why each component exists. +--- -### Layer 4: Kindred Workbenches (ADDON PATTERN) -**Location**: `mods/ztools/`, `mods/silo/` +## Phase status -Pure Python workbenches following FreeCAD's addon pattern: -- Self-contained with `InitGui.py`, `Init.py`, `package.xml` -- Register commands via `FreeCADGui.addCommand()` -- Define toolbars/menus via `Workbench.appendToolbar()` -- Can be developed/tested independently +### Phase 1: Addon auto-loading -- DONE -## Detailed Integration Plan +**Implementation:** `src/Mod/Create/Init.py` and `InitGui.py` load workbenches from `mods/` at startup using `exec()`. Addons degrade gracefully if submodule is absent. -### Phase 1: Addon Auto-Loading +**Default workbench:** `ZToolsWorkbench` (set in `resources/preferences/KindredCreate/KindredCreate.cfg`). -**Goal**: ztools and Silo load automatically without user intervention. +### Phase 2: Enhanced Pocket as C++ feature -- NOT STARTED -**Implementation**: +**Goal:** Replace the Python boolean-operation workaround in `ZTools_EnhancedPocket` with a proper `Create::FlipPocket` C++ feature inheriting from `PartDesign::ProfileBased`. -1. **Create addon manifest** (`src/Mod/Kindred/addons.json`): -```json -{ - "builtin_addons": [ - { - "name": "ztools", - "path": "mods/ztools/ztools", - "autoload": true, - "workbench": "ZToolsWorkbench" - }, - { - "name": "silo", - "path": "mods/silo/pkg/freecad", - "autoload": true, - "workbench": "SiloWorkbench" - } - ] -} -``` +**Rationale:** The current Python implementation creates a standard Pocket then applies a boolean Common. A native feature would integrate properly with the feature tree, support undo/redo correctly, and perform better on complex geometry. -2. **Modify addon path discovery** (`src/Mod/Kindred/Init.py`): -```python -# Add mods/ directory to FreeCAD's module search path -import FreeCAD -import os +**Scope:** +- `src/Mod/Create/App/FeatureFlipPocket.cpp` -- Feature implementation +- `src/Mod/Create/Gui/TaskFlipPocket.cpp` -- Task panel +- `src/Mod/Create/Gui/ViewProviderFlipPocket.cpp` -- View provider +- Update `ZTools_EnhancedPocket` to create `Create::FlipPocket` instead of the workaround -mods_dir = os.path.join(FreeCAD.getHomePath(), "mods") -if os.path.isdir(mods_dir): - for addon in os.listdir(mods_dir): - addon_path = os.path.join(mods_dir, addon) - if os.path.isdir(addon_path) and addon_path not in sys.path: - sys.path.insert(0, addon_path) -``` +**Decision:** Deferred. The Python approach is functional for current needs. Revisit when performance or feature-tree integration becomes a problem. -3. **Set default workbench** in preferences: -```xml - -ZToolsWorkbench -``` +### Phase 3: Datum C++ helpers -- NOT STARTED (SUPERSEDED) -**Files to create/modify**: -- Create: `src/Mod/Kindred/Init.py` -- Create: `src/Mod/Kindred/InitGui.py` -- Create: `src/Mod/Kindred/CMakeLists.txt` -- Modify: `src/Mod/CMakeLists.txt` (add Kindred subdirectory) -- Modify: `resources/preferences/KindredCreate/KindredCreate.cfg` +**Original goal:** Create C++ geometry helper functions for datum calculations. -### Phase 2: Enhanced Pocket as Separate Feature +**Current state:** The Python implementation now uses FreeCAD's built-in `Part::AttachExtension` for automatic parametric updates. Each datum type maps to a native MapMode (`FlatFace`, `ThreePointsPlane`, `NormalToEdge`, etc.) with appropriate `AttachmentSupport` and `AttachmentOffset`. This eliminates the need for custom geometry calculations. -**Goal**: "Flip Side to Cut" becomes a proper feature, not a command wrapper. +**Decision:** Superseded by the AttachExtension approach. Only `tangent_to_cylinder` still uses manual placement (requires a vertex reference not currently collected by the UI). -**Current state** (in ztools): -```python -# ztools/commands/pocket_commands.py -class ZTools_EnhancedPocket: - def Activated(self): - # Creates standard Pocket, then applies boolean Common - # Workaround using existing features -``` +### Phase 4: Theme system -- PARTIAL -**Proposed architecture**: +**Goal:** Theme applies consistently at startup regardless of active workbench. -``` -src/Mod/Create/ -├── App/ -│ ├── CreateFeatures.cpp # Feature implementations -│ ├── FeatureFlipPocket.cpp # Flip-side pocket feature -│ └── FeatureFlipPocket.h -├── Gui/ -│ ├── Command.cpp # Command registrations -│ ├── TaskFlipPocket.cpp # Task panel -│ └── ViewProviderFlipPocket.cpp -└── CMakeLists.txt -``` +**Current state:** The Catppuccin Mocha theme is set as the default via the KindredCreate preference pack. Four copies of the QSS file exist and must be kept in sync manually: +1. `resources/preferences/KindredCreate/KindredCreate.qss` (canonical) +2. `src/Gui/Stylesheets/KindredCreate.qss` +3. `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss` +4. `mods/ztools/CatppuccinMocha/CatppuccinMocha.qss` -**Feature design** (`Create::FlipPocket`): +**Remaining work:** Eliminate QSS duplication via build-time copy or symlinks. Move theme responsibility out of ztools and into the Create module. -```cpp -// Inherits from PartDesign::ProfileBased (same base as Pocket) -class FeatureFlipPocket : public PartDesign::ProfileBased { -public: - // Properties (same as Pocket, plus flip flag) - App::PropertyLength Length; - App::PropertyEnumeration Type; // Dimension, ThroughAll, ToFirst, UpToFace - App::PropertyBool Symmetric; - App::PropertyBool FlipSide; // NEW: Cut outside instead of inside - - // Implementation uses Boolean Common instead of Cut when FlipSide=true - App::DocumentObjectExecReturn* execute(); -}; -``` +### Phase 5: Silo deep integration -- DONE -**Separation of concerns**: -- **FreeCAD Core** (`PartDesign::Pocket`): Standard inside-cut behavior, unchanged -- **Create Extension** (`Create::FlipPocket`): Outside-cut using boolean common -- **ztools Workbench**: Provides UI command that creates `Create::FlipPocket` +**Goal:** Silo commands available globally, not just in the Silo workbench. -**Files to create**: -- `src/Mod/Create/App/FeatureFlipPocket.cpp` -- `src/Mod/Create/App/FeatureFlipPocket.h` -- `src/Mod/Create/Gui/TaskFlipPocket.cpp` -- `src/Mod/Create/Gui/ViewProviderFlipPocket.cpp` +**Implementation:** `SiloMenuManipulator` in `src/Mod/Create/InitGui.py` uses `FreeCADGui.addWorkbenchManipulator()` to inject Silo commands into the File menu and toolbar across all workbenches. `Silo_ToggleMode` provides a one-click swap of Ctrl+O/S/N between standard FreeCAD and Silo file commands. -**ztools update**: -```python -# mods/ztools/ztools/commands/pocket_commands.py -class ZTools_EnhancedPocket: - def Activated(self): - # Now creates Create::FlipPocket instead of workaround - body = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("pdbody") - pocket = body.newObject("Create::FlipPocket", "FlipPocket") - pocket.Profile = sketch - # Show task panel... -``` +**Dock panels:** Database Auth (1500ms) and Database Activity (4000ms) panels are created via deferred QTimers and docked in the right panel area. -### Phase 3: Datum System Integration +### Phase 6: Build system integration -- PARTIAL -**Goal**: ztools datum creation uses stable, efficient C++ geometry calculations. +**Goal:** CMake install rules for `mods/` submodules so packages include ztools and Silo automatically. -**Current state**: Pure Python geometry calculations in `ztools/datums/core.py`. +**CI/CD status:** Release workflows (`.gitea/workflows/release.yml`) now build for Linux (AppImage + .deb), macOS (DMG for Intel + Apple Silicon), and Windows (.exe NSIS installer + .7z archive). Builds run on public runners in dockerized mode. Releases are triggered by `v*` tags. See `docs/CI_CD.md` for details. -**Issue**: Python geometry operations can be slow and less precise for complex cases. - -**Proposed solution**: Create C++ helper functions, expose via Python. - -```cpp -// src/Mod/Create/App/DatumHelpers.cpp -namespace Create { - // Calculate midplane between two parallel faces - gp_Pln computeMidplane(const TopoDS_Face& face1, const TopoDS_Face& face2); - - // Calculate plane through three points - gp_Pln computePlaneFrom3Points(gp_Pnt p1, gp_Pnt p2, gp_Pnt p3); - - // Calculate axis at cylinder center - gp_Ax1 computeCylinderAxis(const TopoDS_Face& cylinderFace); - - // ... other datum calculations ... -} -``` - -**Python binding**: -```python -# In ztools after Create module is available -from Create import DatumHelpers - -plane = DatumHelpers.computeMidplane(face1, face2) -``` - -**Separation of concerns**: -- **FreeCAD Core** (`PartDesign::DatumPlane`): Data structure, unchanged -- **Create Extension** (`DatumHelpers`): Geometry calculation utilities -- **ztools Workbench**: UI, selection handling, property storage - -### Phase 4: Theme System Refinement - -**Goal**: Theme applies consistently at startup, no workbench dependency. - -**Current state**: Theme applied when ztools workbench activates. - -**Issue**: If user opens FreeCAD and doesn't activate ztools, theme isn't applied. - -**Proposed solution**: - -1. **Move theme to Create module** (`src/Mod/Create/InitGui.py`): -```python -# This runs at GUI startup, before any workbench -def applyKindredTheme(): - from PySide import QtWidgets - qss_path = os.path.join(FreeCAD.getResourceDir(), - "preferences", "KindredCreate", "KindredCreate.qss") - with open(qss_path) as f: - QtWidgets.QApplication.instance().setStyleSheet(f.read()) - - # Apply spreadsheet colors - applySpreadsheetColors() - -# Run at import time -applyKindredTheme() -``` - -2. **Remove theme code from ztools**: ztools focuses on commands, not theming. - -3. **Ensure load order**: Create module loads before other workbenches via `src/Mod/CMakeLists.txt` ordering. - -### Phase 5: Silo Deep Integration - -**Goal**: Silo commands available globally, not just in Silo workbench. - -**Current state**: Must switch to Silo workbench to access commands. - -**Proposed solution**: - -1. **Global menu registration** (`src/Mod/Create/InitGui.py`): -```python -def setupSiloMenu(): - # Add Silo menu to menu bar regardless of active workbench - import silo_commands - - mw = FreeCADGui.getMainWindow() - menuBar = mw.menuBar() - - siloMenu = QtWidgets.QMenu("Silo", mw) - menuBar.addMenu(siloMenu) - - for cmd in ["Silo_Open", "Silo_Save", "Silo_Commit", "Silo_Pull", "Silo_Push"]: - action = FreeCADGui.Command.get(cmd).getAction() - siloMenu.addAction(action[0]) -``` - -2. **Keyboard shortcuts** (global): -```python -# Ctrl+Shift+O: Silo Open -# Ctrl+Shift+S: Silo Save -# Ctrl+Shift+C: Silo Commit -``` - -3. **Status bar integration**: Show current Silo item info in status bar. - -### Phase 6: Build System Integration - -**Goal**: mods/ submodules installed correctly during build. - -**Implementation** (`src/Mod/Create/CMakeLists.txt`): +**Remaining work:** CMake install rules should be formalized in `src/Mod/Create/CMakeLists.txt` so that `cmake --install` includes mods/ submodules without relying on the packaging scripts to copy them: ```cmake -# Install ztools workbench install(DIRECTORY ${CMAKE_SOURCE_DIR}/mods/ztools/ztools DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/ztools) install(DIRECTORY ${CMAKE_SOURCE_DIR}/mods/ztools/CatppuccinMocha DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/ztools) -install(FILES ${CMAKE_SOURCE_DIR}/mods/ztools/package.xml - DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/ztools) -# Install Silo workbench install(DIRECTORY ${CMAKE_SOURCE_DIR}/mods/silo/pkg/freecad/ DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Silo) ``` -## File Organization Summary +--- -### New files to create +## Design decisions -``` -src/Mod/Create/ # NEW: Kindred Create core extensions -├── CMakeLists.txt -├── Init.py # Addon path setup -├── InitGui.py # Theme application, global menus -├── App/ -│ ├── CMakeLists.txt -│ ├── CreateModule.cpp # Module registration -│ ├── FeatureFlipPocket.cpp/h # Flip-side pocket feature -│ └── DatumHelpers.cpp/h # Datum geometry utilities -└── Gui/ - ├── CMakeLists.txt - ├── CreateGuiModule.cpp - ├── Command.cpp # Create-specific commands - ├── TaskFlipPocket.cpp/h - └── ViewProviderFlipPocket.cpp/h -``` +1. **`Create::` namespace prefix.** All Kindred Create features use this prefix to distinguish them from FreeCAD core. -### Files to modify +2. **No upstream contribution.** Kindred Create is a standalone product. This allows divergent design decisions without upstream coordination. -| File | Change | -|------|--------| -| `src/Mod/CMakeLists.txt` | Add `add_subdirectory(Create)` | -| `resources/preferences/KindredCreate/KindredCreate.cfg` | Set default workbench | -| `mods/ztools/ztools/commands/pocket_commands.py` | Use `Create::FlipPocket` | -| `mods/ztools/ztools/datums/core.py` | Use `Create.DatumHelpers` when available | +3. **Silo server distributed separately.** Users deploy the Silo server independently. Setup instructions live in `mods/silo/README.md`. -### Files to remove/deprecate from ztools - -| File | Reason | -|------|--------| -| `ztools/resources/theme.py` | Moved to Create module | -| Theme application in `InitGui.py` | Handled globally | - -## Implementation Priority - -| Priority | Phase | Effort | Impact | -|----------|-------|--------|--------| -| 1 | Phase 1: Addon Auto-Loading | Low | High - Seamless user experience | -| 2 | Phase 4: Theme System | Low | High - Consistent appearance | -| 3 | Phase 5: Silo Global Menu | Medium | High - Always-available database access | -| 4 | Phase 2: Enhanced Pocket | High | Medium - Proper feature architecture | -| 5 | Phase 3: Datum Helpers | Medium | Medium - Performance improvement | -| 6 | Phase 6: Build System | Low | High - Clean distribution | - -## Testing Strategy - -### Unit Tests -- Create feature creation and execution -- Datum helper calculations -- Theme application verification - -### Integration Tests -- Addon auto-loading on fresh install -- Feature creation via ztools commands -- Silo operations with mock server -- Theme persistence across sessions - -### Compatibility Tests -- Open existing FCStd files (no regressions) -- Export to STEP/IGES (geometry unchanged) -- Upstream FreeCAD file compatibility - -## Migration Notes - -### For existing ztools/silo users -- No changes required - workbenches continue to function -- Enhanced features available automatically when Create module present -- Theme applies globally instead of per-workbench - -### For developers -- ztools can check for Create module availability: -```python -try: - import Create - HAS_CREATE = True -except ImportError: - HAS_CREATE = False - -# Use C++ implementation if available, fall back to Python -if HAS_CREATE: - plane = Create.DatumHelpers.computeMidplane(f1, f2) -else: - plane = compute_midplane_python(f1, f2) -``` - -## Design Decisions - -1. **Naming convention**: Kindred Create features use the `Create::` prefix (e.g., `Create::FlipPocket`, `Create::DatumHelpers`) to clearly identify them as Kindred Create extensions separate from FreeCAD core. - -2. **Upstream contribution**: Kindred Create is a standalone product and does not plan to contribute features upstream to FreeCAD. This allows for divergent design decisions optimized for Kindred Create's target use cases. - -3. **Silo server distribution**: Silo server is distributed separately from Kindred Create. Users download and deploy the Silo server independently. Setup instructions are documented in `mods/silo/README.md`. - -4. **Version synchronization**: ztools and Silo versions are determined by pinned git submodule commits. Updates are deliberate and tested before each Kindred Create release. To update: +4. **Version synchronization via submodule pins.** ztools and Silo versions are pinned git submodule commits. Updates are deliberate: ```bash cd mods/ztools && git pull origin main && cd ../.. - git add mods/ztools && git commit -m "Update ztools to " + git add mods/ztools && git commit -m "Update ztools submodule" ``` + +5. **Python-first approach.** C++ extensions are deferred until Python cannot achieve the requirement. The AttachExtension approach for datums validated this strategy. + +6. **Graceful degradation.** The Create module loads successfully even if submodules are absent. Each addon load is wrapped in try/except with console logging. diff --git a/docs/REPOSITORY_STATE.md b/docs/REPOSITORY_STATE.md index 79690d9e68..44f69d990f 100644 --- a/docs/REPOSITORY_STATE.md +++ b/docs/REPOSITORY_STATE.md @@ -1,332 +1,215 @@ -# Kindred Create Repository State Report +# Repository State -**Generated:** 2026-01-31 -**Branch:** main -**Parent repo:** create-0070 @ `364a7057ef` -**Submodules:** -- ztools @ `8d1f195` (ztools-0065, main) -- silo @ `c778825` (silo-0062, main) +**Last updated:** 2026-02-03 +**Branch:** main @ `0ef9ffcf51` +**Kindred Create:** v0.1.0 +**FreeCAD base:** v1.0.0 + +## Submodules + +| Submodule | Path | Source | Pinned commit | +|-----------|------|--------|---------------| +| ztools | `mods/ztools` | `gitea.kindred.internal/kindred/ztools-0065` | `d2f94c3` | +| silo | `mods/silo` | `gitea.kindred.internal/kindred/silo-0062` | `17a10ab` | +| OndselSolver | `src/3rdParty/OndselSolver` | `gitea.kindred.internal/kindred/ondsel` | `e32c9cd` | +| GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` | `756c91a` | +| AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` | `01e242e` | +| googletest | `tests/lib` | `github.com/google/googletest` | `56efe39` | --- -## Recent Changes (This Session) +## Architecture -### Assembly Solver Fix -- `610fd43` — PartDesign datum planes (including ZTools datums) now work - correctly as joint references in Assembly. `findPlacement()` in - `src/Mod/Assembly/UtilsAssembly.py` extracts geometry from - `PartDesign::Plane` and `PartDesign::Point` objects instead of returning - zero placements. - -### ZTools Bug Fixes -- `665bdb2` — Three fixes in the ztools submodule: - - Removed `int()` wrapper from `getStandardButtons()` (Qt6/PySide6 - compatibility — `StandardButton` enum is not int-castable). - - Guarded `_setup_ztools_viewprovider()` against C++ ViewProviders - that lack a `Proxy` attribute (`PartDesign::Plane` uses - `ViewProviderDatumPlane`, pure C++). - - Changed `setEditorMode(prop, 2)` to `setPropertyStatus(prop, "Hidden")` - for persistent attachment property hiding across save/reload. - -### ZTools Parametric Datums via AttachExtension -- `2c716b4` — ZTools datum planes now leverage FreeCAD's built-in - `Part::AttachExtension` for automatic parametric updates. Instead of - `MapMode = "Deactivated"` with manual placement, each datum type maps to a - vanilla `MapMode` (`FlatFace`, `ThreePointsPlane`, `NormalToEdge`, etc.) - with appropriate `AttachmentSupport` and `AttachmentOffset`. Datums update - automatically when source geometry changes on recompute. - -### Stylesheet Fixes (Uncommitted — Staged) -- **Tree branch indicators**: Created `branch_closed.svg` and - `branch_open.svg` in `images_dark-light/` with Catppuccin `#cdd6f4` - chevrons. Added `QTreeView::branch` image rules for expand/collapse states. -- **Spinbox/combobox arrows**: Synced all three QSS copies so the CSS - border-triangle arrow fix (previously only in `resources/preferences/`) - now applies at runtime via `src/Gui/Stylesheets/KindredCreate.qss`. -- **Header clipping**: Added `min-height: 20px` to `QHeaderView::section`. -- **QSS sync**: All four copies (`resources/preferences/`, `src/Gui/Stylesheets/`, - `src/Gui/PreferencePacks/`, `mods/ztools/CatppuccinMocha/`) are now - byte-identical. Merged dock widget padding and spreadsheet cell editor - styling improvements that existed only in the Stylesheets copy. - -### ZTools-PartDesign Merge (Uncommitted — Staged) -- `_ZToolsPartDesignManipulator` in `mods/ztools/ztools/InitGui.py` uses - `Gui.addWorkbenchManipulator()` to inject ZTools commands into PartDesign's - C++ toolbars: - - `ZTools_DatumCreator` + `ZTools_DatumManager` → "Part Design Helper Features" - - `ZTools_EnhancedPocket` → "Part Design Modeling Features" - - `ZTools_RotatedLinearPattern` → "Part Design Transformation Features" - - Same commands also inserted into the Part Design menu after `PartDesign_Boolean`. - -### Silo Enhancements (Uncommitted — Staged) -- **File menu integration**: `SiloMenuManipulator` in `src/Mod/Create/InitGui.py` - injects `Silo_New`, `Silo_Open`, `Silo_Save`, `Silo_Commit`, `Silo_Pull`, - `Silo_Push`, and `Silo_BOM` into the File menu across all workbenches. -- **Toolbar toggle**: `Silo_ToggleMode` checkable command swaps `Ctrl+O/S/N` - between standard FreeCAD file commands and Silo equivalents. Appended to the - global File toolbar via the manipulator. -- **SSL certificate browsing**: Settings dialog now includes a file browser for - custom CA certificates (`SslCertPath` preference). `_get_ssl_context()` loads - the custom cert before system CAs. -- **BOM integration**: Upstream BOM feature (`Silo_BOM` command with tabbed - dialog — BOM + Where Used) merged with local changes and added to the - Create File menu manipulator. - ---- - -## Architecture Overview - -``` -create-0070/ Kindred Create (FreeCAD 1.0+ fork) -├── src/ -│ ├── Mod/ -│ │ ├── Assembly/ Assembly solver (OndselSolver) -│ │ ├── PartDesign/ Part modeling (C++ workbench) -│ │ ├── Sketcher/ 2D constraint sketcher -│ │ ├── Create/ Kindred bootstrap module (Python) -│ │ │ └── InitGui.py Loads ztools+silo, installs manipulators -│ │ └── ... Other FreeCAD modules -│ └── Gui/ -│ ├── Stylesheets/ QSS themes + arrow/branch SVGs -│ ├── PreferencePacks/ Preference pack bundles -│ └── WorkbenchManipulatorPython.cpp Menu/toolbar injection API -├── mods/ -│ ├── ztools/ [submodule] ztools-0065 -│ │ └── ztools/ -│ │ ├── InitGui.py ZToolsWorkbench + PartDesign manipulator -│ │ └── ztools/ -│ │ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet -│ │ ├── datums/core.py Datum creation with AttachExtension -│ │ └── resources/ Icons, theme utilities -│ └── silo/ [submodule] silo-0062 -│ └── pkg/freecad/ -│ ├── InitGui.py SiloWorkbench -│ └── silo_commands.py 12 commands + SiloClient API -└── resources/ - └── preferences/KindredCreate/ Canonical QSS + preference pack -``` - -### Integration Flow +### Bootstrap flow ``` FreeCAD startup - └─ src/Mod/Create/InitGui.py exec() - ├─ exec(mods/ztools/ztools/InitGui.py) - │ ├─ registers ZToolsWorkbench - │ └─ installs _ZToolsPartDesignManipulator (global) - ├─ exec(mods/silo/pkg/freecad/InitGui.py) - │ └─ registers SiloWorkbench - └─ QTimer.singleShot(2000): - ├─ _setup_silo_menu() - │ └─ installs SiloMenuManipulator (global) - │ ├─ modifyMenuBar: Silo commands in File menu - │ └─ modifyToolBars: Silo_ToggleMode in File toolbar - ├─ _check_silo_first_start() - └─ _setup_silo_activity_panel() + └─ src/Mod/Create/Init.py + └─ setup_kindred_addons() + ├─ exec(mods/ztools/ztools/Init.py) + └─ exec(mods/silo/pkg/freecad/Init.py) + + └─ src/Mod/Create/InitGui.py + ├─ setup_kindred_workbenches() + │ ├─ exec(mods/ztools/ztools/InitGui.py) + │ │ ├─ registers ZToolsWorkbench + │ │ └─ installs _ZToolsPartDesignManipulator (global) + │ └─ exec(mods/silo/pkg/freecad/InitGui.py) + │ └─ registers SiloWorkbench + └─ Deferred setup (QTimer): + ├─ 1500ms: _setup_silo_auth_panel() → "Database Auth" dock + ├─ 2000ms: _setup_silo_menu() → SiloMenuManipulator + ├─ 3000ms: _check_silo_first_start() → settings prompt + └─ 4000ms: _setup_silo_activity_panel() → "Database Activity" dock +``` + +### Key source layout + +``` +src/Mod/Create/ Kindred bootstrap module (Python) + ├── Init.py Adds mods/ addon paths, loads Init.py files + └── InitGui.py Loads workbenches, installs Silo manipulators + +mods/ztools/ [submodule] ztools workbench + ├── ztools/InitGui.py ZToolsWorkbench + PartDesign manipulator + ├── ztools/ztools/ + │ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet + │ ├── datums/core.py Datum creation via Part::AttachExtension + │ └── resources/ Icons, theme utilities + └── CatppuccinMocha/ Theme preference pack (QSS) + +mods/silo/ [submodule] Silo parts database + ├── cmd/ Go server entry points + ├── internal/ Go API, database, storage packages + ├── pkg/freecad/ FreeCAD workbench (Python) + │ ├── InitGui.py SiloWorkbench + │ └── silo_commands.py Commands + SiloClient API + ├── deployments/ Docker compose configuration + └── migrations/ PostgreSQL schema migrations + +src/Gui/Stylesheets/ QSS themes and SVG assets +resources/preferences/ Canonical preference pack (KindredCreate) ``` --- -## Submodule Status +## Component status -### ztools (ztools-0065) +### ztools workbench -| Commit | Description | -|--------|-------------| -| `8d1f195` | Add PartDesign WorkbenchManipulator and sync Catppuccin theme | -| `005348b` | Leverage FreeCAD AttachExtension for parametric datum updates | -| `0e95d1c` | Fix Qt6 StandardButton TypeError and C++ ViewProvider Proxy errors | -| `98bd444` | Fix workbench init and spreadsheet syntax errors | +**Registered commands (9):** -**Custom commands**: 9 registered -- `ZTools_DatumCreator`, `ZTools_DatumManager` -- `ZTools_RotatedLinearPattern` -- `ZTools_EnhancedPocket` -- `ZTools_AssemblyLinearPattern`, `ZTools_AssemblyPolarPattern` -- `ZTools_SpreadsheetStyle{Bold,Italic,Underline}`, `ZTools_SpreadsheetAlign{Left,Center,Right}`, `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` +| Command | Function | +|---------|----------| +| `ZTools_DatumCreator` | Create datum planes, axes, points (16 modes) | +| `ZTools_DatumManager` | Manage existing datum objects | +| `ZTools_EnhancedPocket` | Flip-side pocket (cut outside sketch profile) | +| `ZTools_RotatedLinearPattern` | Linear pattern with incremental rotation | +| `ZTools_AssemblyLinearPattern` | Pattern assembly components linearly | +| `ZTools_AssemblyPolarPattern` | Pattern assembly components around axis | +| `ZTools_SpreadsheetStyle{Bold,Italic,Underline}` | Text style toggles | +| `ZTools_SpreadsheetAlign{Left,Center,Right}` | Cell alignment | +| `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` | Colors and alias creation | -**Datum types supported**: offset_from_face, offset_from_plane, midplane, -3_points, normal_to_edge, angled, tangent_to_cylinder +**PartDesign integration** via `_ZToolsPartDesignManipulator`: +- `ZTools_DatumCreator`, `ZTools_DatumManager` → "Part Design Helper Features" toolbar +- `ZTools_EnhancedPocket` → "Part Design Modeling Features" toolbar +- `ZTools_RotatedLinearPattern` → "Part Design Transformation Features" toolbar +- Same commands inserted into Part Design menu after `PartDesign_Boolean` -### silo (silo-0062) +**Datum types (7):** offset_from_face, offset_from_plane, midplane, 3_points, normal_to_edge, angled, tangent_to_cylinder. All except tangent_to_cylinder use `Part::AttachExtension` for automatic parametric updates. -| Commit | Description | -|--------|-------------| -| `c778825` | Add Silo mode toggle, SSL cert browsing, and BOM menu integration | -| `8c06899` | (upstream) Various fixes | -| `bce7d5a` | Add BOM handling and routes to API and web UI | -| `3a79d89` | feat: add BOM system with API, database repository, and FreeCAD command | -| `8e44ed2` | Fix SIGSEGV: defer document open after dialog close | +### Silo workbench -**FreeCAD commands**: 12 registered -- `Silo_Open`, `Silo_New`, `Silo_Save`, `Silo_Commit` -- `Silo_Pull`, `Silo_Push`, `Silo_Info`, `Silo_BOM` -- `Silo_TagProjects`, `Silo_Rollback`, `Silo_SetStatus` -- `Silo_Settings`, `Silo_ToggleMode` +**Registered commands (13):** -**API surface**: 38 REST routes covering items, revisions, files, BOM, -projects, schemas, and Odoo integration stubs. See -`mods/silo/docs/REPOSITORY_STATUS.md` for full route table. +| Command | Function | +|---------|----------| +| `Silo_New` | Create new Silo-tracked document | +| `Silo_Open` | Open file from Silo database | +| `Silo_Save` | Save to Silo (create revision) | +| `Silo_Commit` | Commit current revision | +| `Silo_Pull` | Pull latest revision from server | +| `Silo_Push` | Push local changes to server | +| `Silo_Info` | View item metadata and history | +| `Silo_BOM` | Bill of materials dialog (BOM + Where Used) | +| `Silo_TagProjects` | Assign project tags | +| `Silo_Rollback` | Rollback to previous revision | +| `Silo_SetStatus` | Set revision status (draft/review/released/obsolete) | +| `Silo_Settings` | Configure API URL, projects dir, SSL certificates | +| `Silo_ToggleMode` | Swap Ctrl+O/S/N between FreeCAD and Silo commands | -**BOM API methods** (new): -- `get_bom()`, `get_bom_expanded()`, `get_bom_where_used()` -- `add_bom_entry()`, `update_bom_entry()`, `delete_bom_entry()` +**Global integration** via `SiloMenuManipulator` in `src/Mod/Create/InitGui.py`: +- File menu: Silo_New, Silo_Open, Silo_Save, Silo_Commit, Silo_Pull, Silo_Push, Silo_BOM +- File toolbar: Silo_ToggleMode button + +**Server architecture:** Go REST API (38 routes) + PostgreSQL + MinIO. See `mods/silo/docs/REPOSITORY_STATUS.md` for route details. + +### Theme + +**Canonical source:** `resources/preferences/KindredCreate/KindredCreate.qss` + +Four copies must stay in sync: +1. `resources/preferences/KindredCreate/KindredCreate.qss` (canonical) +2. `src/Gui/Stylesheets/KindredCreate.qss` +3. `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss` +4. `mods/ztools/CatppuccinMocha/CatppuccinMocha.qss` --- -## Potential Issues +## Known issues ### Critical -1. **Three QSS copies can drift again.** The canonical source is - `resources/preferences/KindredCreate/KindredCreate.qss`. The other copies - (`src/Gui/Stylesheets/`, `src/Gui/PreferencePacks/`, `mods/ztools/CatppuccinMocha/`) - must be kept in sync manually. Consider a build step or symlinks to - eliminate duplication. +1. **QSS duplication.** Four copies of the stylesheet must be kept in sync manually. A build step or symlinks should eliminate this. -2. **WorkbenchManipulator command registration timing.** The - `_ZToolsPartDesignManipulator` appends commands by name (e.g. - `ZTools_DatumCreator`). If the ZTools workbench has not been initialized - (first activation) when the user switches to PartDesign, the commands may - not be registered yet. The `Create/InitGui.py` `exec()` loads the - workbench class but `Initialize()` only runs on first activation. The - manipulator API tolerates missing commands silently (toolbar append - returns without error), but the buttons won't appear until ZTools - initializes. Mitigation: force-activate ZToolsWorkbench during Create - module load, or defer manipulator installation. +2. **WorkbenchManipulator timing.** The `_ZToolsPartDesignManipulator` appends commands by name. If ZToolsWorkbench hasn't been activated when the user switches to PartDesign, the commands may not be registered. The manipulator API tolerates missing commands silently, but buttons won't appear. -3. **Silo toggle mode shortcut persistence.** `_swap_shortcuts()` stores - original shortcuts in a module-level dict (`_original_shortcuts`). If - FreeCAD crashes with Silo mode ON, the original shortcuts are lost and - standard commands will have no keyboard shortcuts on next launch. Consider - persisting original shortcuts to preferences. +3. **Silo shortcut persistence.** `Silo_ToggleMode` stores original shortcuts in a module-level dict. If FreeCAD crashes with Silo mode on, original shortcuts are lost on next launch. ### High -4. **Silo has no authentication.** All API endpoints are publicly accessible. - Required before multi-user deployment. See - `mods/silo/docs/REPOSITORY_STATUS.md` for full list. +4. **No authentication on Silo server.** All API endpoints are publicly accessible. Required before multi-user deployment. -5. **No unit tests for silo FreeCAD commands or ztools.** Python code has zero - test coverage. The Go backend also lacks tests per the silo status report. +5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests. -6. **Assembly solver `findPlacement()` geometry extraction is minimal.** The - fix at `UtilsAssembly.py:1006` extracts placement from `obj.Shape.Faces[0]` - for `PartDesign::Plane`. This works for planar datums but does not handle - edge cases like empty shapes or non-planar datum objects. +6. **Assembly solver datum handling is minimal.** The `findPlacement()` fix extracts placement from `obj.Shape.Faces[0]` for `PartDesign::Plane`. Does not handle empty shapes or non-planar datum objects. ### Medium -7. **`Silo_BOM` depends on `get_tracked_object()`** which looks for a - `SiloPartNumber` property on document objects. Documents not registered - with Silo show a warning dialog. The UX could be improved with a - one-click registration flow from the BOM dialog. +7. **`Silo_BOM` requires Silo-tracked document.** Depends on `SiloPartNumber` property. Unregistered documents show a warning with no registration path. -8. **`_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after - `PartDesign_Boolean`.** If upstream FreeCAD renames or removes this - command, the menu insertions silently fail. The toolbar appends (by - toolbar name) are more robust. +8. **PartDesign menu insertion fragility.** `_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after `PartDesign_Boolean`. If upstream renames this command, insertions silently fail. -9. **ZTools `plane_tangent_to_cylinder` falls back to manual placement** - because the TangentPlane MapMode requires a vertex reference not currently - collected by the UI. This is the only datum type that does not benefit - from automatic parametric updates. +9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI. -10. **Silo `delete_bom_entry()` uses raw `urllib.request`** instead of the - `_request()` helper method on `SiloClient`. This bypasses error - normalization. Should be refactored to use `self._request("DELETE", ...)`. +10. **`delete_bom_entry()` bypasses error normalization.** Uses raw `urllib.request` instead of `SiloClient._request()`. --- -## Feature Stubs and TODOs +## Incomplete features -### From silo REPOSITORY_STATUS +### Silo -| Feature | Status | Location | -|---------|--------|----------| -| Odoo ERP integration | Stub (returns "not yet implemented") | `internal/odoo/` | -| Part number date segments | Broken (`formatDate()` returns error) | `internal/partnum/generator.go:102` | -| Location/Inventory APIs | Tables exist, no handlers | `migrations/001_initial.sql` | -| File locking | Not implemented | — | -| Authentication/Authorization | Not implemented | — | +| Feature | Status | Notes | +|---------|--------|-------| +| Authentication/authorization | Not implemented | Required for multi-user | +| File locking | Not implemented | Needed to prevent concurrent edits | +| Odoo ERP integration | Stub only | Returns "not yet implemented" | +| Part number date segments | Broken | `formatDate()` returns error | +| Location/inventory APIs | Tables exist, no handlers | | | CSRF protection | Not implemented | Web UI only | -| CSV import transaction rollback | Not implemented | `bom_handlers.go` | +| CSV import rollback | Not implemented | `bom_handlers.go` | -### From ztools +### ztools -| Feature | Status | Location | -|---------|--------|----------| -| Tangent-to-cylinder attachment | Manual fallback (no vertex ref) | `datums/core.py` | -| Angled datum live editing | AttachmentOffset rotation not updated in panel | `datum_viewprovider.py` | -| Assembly pattern undo support | Not implemented | `assembly_pattern_commands.py` | +| Feature | Status | Notes | +|---------|--------|-------| +| Tangent-to-cylinder attachment | Manual fallback | No vertex ref in UI | +| Angled datum live editing | Incomplete | AttachmentOffset not updated in panel | +| Assembly pattern undo | Not implemented | | -### From Create integration plan +### Integration plan | Phase | Feature | Status | |-------|---------|--------| -| 1 | Addon auto-loading | Done (`src/Mod/Create/InitGui.py`) | +| 1 | Addon auto-loading | Done | | 2 | Enhanced Pocket as C++ feature | Not started | -| 3 | Datum C++ helpers | Not started (Python AttachExtension approach used instead) | -| 4 | Theme system refinement | Partially done (QSS synced, not moved to Create module) | -| 5 | Silo deep integration | Done (manipulator-based menu/toolbar injection) | -| 6 | Build system integration | Not started | +| 3 | Datum C++ helpers | Not started (Python approach used) | +| 4 | Theme moved to Create module | Partial (QSS synced, not relocated) | +| 5 | Silo deep integration | Done | +| 6 | Build system install rules for mods/ | Partial (CI/CD done, CMake install rules pending) | --- -## File Change Summary (Uncommitted) +## Next steps -### Parent repo (create-0070) +1. **Authentication** -- LDAP/FreeIPA integration for Silo multi-user deployment. Server needs auth middleware; FreeCAD client needs credential storage. -| File | Change | -|------|--------| -| `resources/preferences/KindredCreate/KindredCreate.qss` | Branch indicators, header min-height, dock/actiongroup improvements, spreadsheet cell editor | -| `src/Gui/Stylesheets/KindredCreate.qss` | Synced with canonical | -| `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss` | Synced with canonical | -| `src/Gui/Stylesheets/images_dark-light/branch_closed.svg` | New: right-pointing chevron | -| `src/Gui/Stylesheets/images_dark-light/branch_open.svg` | New: down-pointing chevron | -| `src/Mod/Create/InitGui.py` | Expanded SiloMenuManipulator (BOM, full commands, toolbar toggle) | -| `mods/silo` | Submodule pointer updated | -| `mods/ztools` | Submodule pointer updated | +2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save. -### ztools submodule (committed + pushed) +3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display. -| File | Change | -|------|--------| -| `ztools/InitGui.py` | Added `_ZToolsPartDesignManipulator` | -| `CatppuccinMocha/CatppuccinMocha.qss` | Synced with canonical KindredCreate.qss | +4. **Build system** -- CMake install rules for `mods/` submodules so packages include ztools and Silo without manual steps. -### silo submodule (committed + pushed) - -| File | Change | -|------|--------| -| `pkg/freecad/silo_commands.py` | SSL cert browsing, `Silo_ToggleMode`, BOM merge | -| `pkg/freecad/InitGui.py` | Added `Silo_ToggleMode` to toolbar | - ---- - -## Silo Integration Path - -Based on `mods/silo/docs/REPOSITORY_STATUS.md` and the existing -`docs/INTEGRATION_PLAN.md`, the integration path forward is: - -### Completed -- Addon auto-loading via `src/Mod/Create/InitGui.py` -- Global File menu injection via `WorkbenchManipulator` -- Toolbar toggle for Silo mode (shortcut swapping) -- SSL certificate configuration for internal CAs -- BOM command integrated into File menu - -### Next Steps -1. **Authentication** — LDAP/FreeIPA integration for multi-user. Silo server - needs auth middleware; FreeCAD client needs credential storage in preferences. -2. **BOM-Assembly bridge** — Auto-populate Silo BOM from FreeCAD Assembly - component links. When a user saves an assembly, extract child part numbers - from `Assembly_InsertLink` objects and sync to Silo BOM. -3. **File locking** — Pessimistic locks on checkout (`Silo_Open`) to prevent - concurrent edits. Requires server-side lock table and client-side - lock-status display. -4. **Status bar integration** — Show current Silo item part number, revision, - and sync status in FreeCAD's status bar. Use - `FreeCADGui.getMainWindow().statusBar()`. -5. **Build system** — CMake install rules for `mods/` submodules so `.deb` - packages include ztools and silo without manual intervention. +5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints. diff --git a/src/3rdParty/OndselSolver b/src/3rdParty/OndselSolver index e32c9cd793..5d1988b513 160000 --- a/src/3rdParty/OndselSolver +++ b/src/3rdParty/OndselSolver @@ -1 +1 @@ -Subproject commit e32c9cd7934c62df3ea47899bf5be3a37797384d +Subproject commit 5d1988b51355264667087d5079c155a2d22f4eff