# SPDX-License-Identifier: LGPL-2.1-or-later name: Build and Test on: push: branches: [main] pull_request: branches: [main] workflow_dispatch: jobs: build: runs-on: app-builder 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 }} steps: - name: Trust FreeIPA CA certificate shell: bash 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 - name: Checkout repository uses: https://github.com/actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Install pixi if needed shell: bash 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 pixi --version - name: Restore ccache id: ccache-restore uses: https://github.com/actions/cache/restore@v4 with: path: /tmp/ccache-kindred-create key: ccache-build-${{ github.ref_name }}-${{ github.sha }} restore-keys: | ccache-build-${{ github.ref_name }}- 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 - 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 - name: Save ccache if: always() uses: https://github.com/actions/cache/save@v4 with: path: /tmp/ccache-kindred-create 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 - name: Run Python CLI tests timeout-minutes: 10 run: pixi run timeout 300 build/release/bin/FreeCADCmd -t 0 || true - name: Run GUI tests (headless) timeout-minutes: 10 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 - name: Upload build artifact uses: https://github.com/actions/upload-artifact@v3 with: name: ${{ env.ARTIFACT_NAME }} path: | build/release/*.tar.xz build/release/*.deb build/release/*.sha256 retention-days: 30