The Gitea runner assigns a different workspace directory hash on each
run (e.g. /var/lib/gitea-runner/.cache/act/<hash>/hostexecutor/). When
CCACHE_DIR was set to ${{ github.workspace }}/.ccache, the actions/cache
save and restore operated on a path that changed every run, making the
restored cache land in the wrong location. This caused 0% hit rate on
the second build despite the cache being saved successfully.
Fix by using a fixed path (/tmp/ccache-kindred-create) for CCACHE_DIR
and the cache action path. CCACHE_BASEDIR remains set to the workspace
so ccache stores relative source paths, making cache entries portable
across different workspace directories.
231 lines
8.4 KiB
YAML
231 lines
8.4 KiB
YAML
# 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
|