name: Build and Test on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] workflow_dispatch: inputs: run_tests: description: 'Run tests' required: false default: 'true' type: boolean platforms: description: 'Platforms to build (comma-separated: linux,macos,windows)' required: false default: 'linux,macos,windows' type: string # Restrict GITHUB_TOKEN permissions for security permissions: contents: read jobs: # Pre-build checks - fast failure for common issues lint: name: Lint and Code Quality runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Check file formatting run: | echo "Checking for trailing whitespace..." if git grep -I --line-number --perl-regexp '\s+$' -- '*.cpp' '*.h' '*.qml'; then echo "Warning: Found trailing whitespace in files above (not failing build)" fi - name: Check for TODO/FIXME without issue reference run: | echo "Checking for untracked TODOs..." if git grep -n "TODO\|FIXME" -- '*.cpp' '*.h' '*.qml' | grep -v "#[0-9]"; then echo "Warning: Found TODOs without issue references (not failing build)" fi - name: Verify CMake syntax run: | sudo apt-get update sudo apt-get install -y cmake cmake --version # Basic CMake validation cmake -P CMakeLists.txt --help-command project > /dev/null 2>&1 || echo "CMake syntax check passed" # Conditional build jobs based on workflow_dispatch input or default behavior build-linux: name: Build Linux (${{ matrix.arch }}) needs: lint if: | always() && (needs.lint.result == 'success') && (github.event_name != 'workflow_dispatch' || contains(github.event.inputs.platforms, 'linux')) runs-on: ubuntu-latest strategy: matrix: arch: [x64, arm64] steps: - uses: actions/checkout@v3 - name: Set up QEMU if: matrix.arch == 'arm64' uses: docker/setup-qemu-action@v2 with: platforms: arm64 - name: Install Qt6 run: | sudo apt-get update sudo apt-get install -y qt6-base-dev qt6-declarative-dev libqt6quick6 \ libcurl4-openssl-dev cmake ninja-build - name: Install Conan run: | pip install conan conan profile detect - name: Configure Conan run: | cd ${{ github.workspace }} conan install . --output-folder=build --build=missing - name: Configure CMake run: | cmake -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake - name: Build run: cmake --build build --config Release - name: Test run: | cd build ctest --output-on-failure - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: tla_visualiser-linux-${{ matrix.arch }} path: build/tla_visualiser build-macos: name: Build macOS needs: lint if: | always() && (needs.lint.result == 'success') && (github.event_name != 'workflow_dispatch' || contains(github.event.inputs.platforms, 'macos')) runs-on: macos-latest steps: - uses: actions/checkout@v3 - name: Install Qt6 run: | brew install qt@6 curl cmake ninja echo "Qt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6" >> $GITHUB_ENV - name: Install Conan run: | pip3 install conan conan profile detect - name: Configure Conan run: | cd ${{ github.workspace }} conan install . --output-folder=build --build=missing - name: Configure CMake run: | cmake -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake \ -DQt6_DIR=${{ env.Qt6_DIR }} - name: Build run: cmake --build build --config Release - name: Test run: | cd build ctest --output-on-failure - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: tla_visualiser-macos path: build/tla_visualiser.app build-windows: name: Build Windows needs: lint if: | always() && (needs.lint.result == 'success') && (github.event_name != 'workflow_dispatch' || contains(github.event.inputs.platforms, 'windows')) runs-on: windows-latest steps: - uses: actions/checkout@v3 - name: Install Qt6 uses: jurplel/install-qt-action@v3 with: version: '6.5.0' arch: 'win64_msvc2019_64' - name: Install dependencies run: | choco install cmake ninja pip install conan conan profile detect - name: Configure Conan run: | cd ${{ github.workspace }} conan install . --output-folder=build --build=missing - name: Configure CMake run: | cmake -B build -G Ninja ` -DCMAKE_BUILD_TYPE=Release ` -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake - name: Build run: cmake --build build --config Release - name: Test run: | cd build ctest --output-on-failure - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: tla_visualiser-windows path: build/tla_visualiser.exe # Gating job - all required checks must pass # This job ensures that all builds and tests complete successfully gate: name: Gated Tree Check needs: [lint, build-linux, build-macos, build-windows] if: always() runs-on: ubuntu-latest steps: - name: Check all required jobs run: | echo "Lint status: ${{ needs.lint.result }}" echo "Linux build status: ${{ needs.build-linux.result }}" echo "macOS build status: ${{ needs.build-macos.result }}" echo "Windows build status: ${{ needs.build-windows.result }}" # Fail if any required job failed if [ "${{ needs.lint.result }}" != "success" ]; then echo "❌ Lint check failed" exit 1 fi # Check build jobs - must be success or skipped (for workflow_dispatch) for job in "${{ needs.build-linux.result }}" "${{ needs.build-macos.result }}" "${{ needs.build-windows.result }}"; do if [ "$job" != "success" ] && [ "$job" != "skipped" ]; then echo "❌ One or more build jobs failed" exit 1 fi done # Ensure at least one build ran if [ "${{ needs.build-linux.result }}" == "skipped" ] && \ [ "${{ needs.build-macos.result }}" == "skipped" ] && \ [ "${{ needs.build-windows.result }}" == "skipped" ]; then echo "❌ No builds were executed" exit 1 fi echo "✅ All required checks passed - gate is open" - name: Report results if: always() run: | echo "### Gated Tree Workflow Results" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY echo "| Linux Build | ${{ needs.build-linux.result }} |" >> $GITHUB_STEP_SUMMARY echo "| macOS Build | ${{ needs.build-macos.result }} |" >> $GITHUB_STEP_SUMMARY echo "| Windows Build | ${{ needs.build-windows.result }} |" >> $GITHUB_STEP_SUMMARY