name: Lagom Template on: workflow_call: inputs: toolchain: required: true type: string os_name: required: true type: string runner_labels: required: true type: string arch: required: true type: string build_preset: required: true type: string clang_plugins: required: false type: boolean default: false container: required: false type: string default: 'null' env: # runner.workspace = /home/runner/work/ladybird # github.workspace = /home/runner/work/ladybird/ladybird LADYBIRD_SOURCE_DIR: ${{ github.workspace }} CCACHE_DIR: ${{ github.workspace }}/.ccache VCPKG_ROOT: ${{ github.workspace }}/Build/vcpkg # Use the compiler version for the ccache compiler hash. Otherwise, if plugins are enabled, the plugin .so files # are included in the hash. This results in clean builds on every run as the .so files are rebuilt. # # Note: This only works because our plugins do not transform any code. If that becomes untrue, we must revisit this. CCACHE_COMPILERCHECK: "%compiler% -v" jobs: CI: runs-on: ${{ fromJSON(inputs.runner_labels) }} container: ${{ fromJSON(inputs.container) }} steps: # Pull requests can trail behind `master` and can cause breakage if merging before running the CI checks on an updated branch. # Luckily, GitHub creates and maintains a merge branch that is updated whenever the target or source branch is modified. By # checking this branch out, we gain a stabler `master` at the cost of reproducibility. - uses: actions/checkout@v7.0.0 if: ${{ github.event_name != 'pull_request' }} - uses: actions/checkout@v7.0.0 if: ${{ github.event_name == 'pull_request' }} with: ref: refs/pull/${{ github.event.pull_request.number }}/merge - name: Set Up Environment uses: ./.github/actions/setup id: 'setup' with: os: ${{ inputs.os_name }} arch: ${{ inputs.arch }} toolchain: ${{ inputs.toolchain }} # === PREPARE FOR BUILDING === - name: Assign Build Parameters if: ${{ inputs.os_name != 'Windows' }} id: 'build-parameters' run: | CMAKE_OPTIONS="-DENABLE_CI_BASELINE_CPU=ON" if ${{ inputs.os_name == 'Linux' }} ; then # FIXME: https://github.com/WebAssembly/wabt/issues/2533 # wabt doesn't have binary releases for arm64 Linux if ${{ inputs.arch == 'arm64' }} ; then PKGCONFIG=$(which pkg-config) CMAKE_OPTIONS="$CMAKE_OPTIONS -DPKG_CONFIG_EXECUTABLE=$PKGCONFIG" fi if ${{ inputs.toolchain == 'Clang' }} ; then echo "host_cc=clang" >> "$GITHUB_OUTPUT" echo "host_cxx=clang++" >> "$GITHUB_OUTPUT" elif ${{ inputs.toolchain == 'GNU' }} ; then echo "host_cc=gcc" >> "$GITHUB_OUTPUT" echo "host_cxx=g++" >> "$GITHUB_OUTPUT" fi elif ${{ inputs.os_name == 'macOS' }} ; then echo "host_cc=$(xcrun --find clang)" >> "$GITHUB_OUTPUT" echo "host_cxx=$(xcrun --find clang++)" >> "$GITHUB_OUTPUT" fi if ${{ inputs.os_name == 'Linux' && inputs.build_preset == 'Sanitizer' }} ; then CMAKE_OPTIONS="$CMAKE_OPTIONS -DLADYBIRD_GUI_FRAMEWORK=Gtk" fi if ${{ inputs.clang_plugins }} ; then echo "ccache_key=${{ inputs.build_preset }}-CLANG_PLUGINS" >> "$GITHUB_OUTPUT" CMAKE_OPTIONS="$CMAKE_OPTIONS -DENABLE_CLANG_PLUGINS=ON" else echo "ccache_key=${{ inputs.build_preset }}" >> "$GITHUB_OUTPUT" CMAKE_OPTIONS="$CMAKE_OPTIONS -DINCLUDE_WASM_SPEC_TESTS=ON -DWASM_SPEC_TEST_SKIP_FORMATTING=ON" fi echo "cmake_options=$CMAKE_OPTIONS" >> "$GITHUB_OUTPUT" - name: Restore Caches uses: ./.github/actions/cache-restore id: 'cache-restore' with: os: ${{ inputs.os_name }} arch: ${{ inputs.arch }} toolchain: ${{ inputs.toolchain }} cache_key_extra: ${{ inputs.os_name == 'Windows' && inputs.build_preset || steps.build-parameters.outputs.ccache_key }} ccache_path: ${{ steps.setup.outputs.ccache_path }} vcpkg_cache_path: ${{ steps.setup.outputs.vcpkg_cache_path }} - name: Cache the WebAssembly spec test suite if: ${{ inputs.os_name != 'Windows' }} uses: actions/cache@v5 with: path: ${{ github.workspace }}/caches/WasmSpecTests key: wasm-spec-test-suite | ${{ hashFiles('Meta/CMake/wasm_spec_tests.cmake') }} - name: Set dynamic environment variables if: ${{ inputs.os_name != 'Windows' }} run: | # Note: Required for vcpkg to use this compiler for its own builds. echo "CC=${{ steps.build-parameters.outputs.host_cc }}" >> "$GITHUB_ENV" echo "CXX=${{ steps.build-parameters.outputs.host_cxx }}" >> "$GITHUB_ENV" - name: Create Build Environment if: ${{ inputs.os_name != 'Windows' && inputs.build_preset != 'Fuzzers' }} working-directory: ${{ github.workspace }} env: VCPKG_CACHE_SAS: ${{ github.ref == 'refs/heads/master' && secrets.VCPKG_CACHE_SAS || '' }} VCPKG_CACHE_MODE: ${{ github.ref == 'refs/heads/master' && 'write' || '' }} run: | cmake --preset ${{ inputs.build_preset }} -B Build \ ${{ steps.build-parameters.outputs.cmake_options }} \ -DPython3_EXECUTABLE=${{ env.pythonLocation }}/bin/python \ -DCMAKE_C_COMPILER=${{ steps.build-parameters.outputs.host_cc }} \ -DCMAKE_CXX_COMPILER=${{ steps.build-parameters.outputs.host_cxx }} - name: Create Build Environment (Windows) if: ${{ inputs.os_name == 'Windows' }} working-directory: ${{ github.workspace }} env: VCPKG_CACHE_SAS: ${{ github.ref == 'refs/heads/master' && secrets.VCPKG_CACHE_SAS || '' }} VCPKG_CACHE_MODE: ${{ github.ref == 'refs/heads/master' && 'write' || '' }} run: | cmake --preset ${{ inputs.build_preset }} -B Build ` -DENABLE_CI_BASELINE_CPU=ON - name: Create Build Environment (Fuzzers) if: ${{ inputs.build_preset == 'Fuzzers' }} working-directory: ${{ github.workspace }} env: VCPKG_CACHE_SAS: ${{ github.ref == 'refs/heads/master' && secrets.VCPKG_CACHE_SAS || '' }} VCPKG_CACHE_MODE: ${{ github.ref == 'refs/heads/master' && 'write' || '' }} run: | cmake --preset ${{ inputs.build_preset }} -B Build \ ${{ steps.build-parameters.outputs.cmake_options }} \ -DPython3_EXECUTABLE=${{ env.pythonLocation }}/bin/python \ -DCMAKE_C_COMPILER=${{ steps.build-parameters.outputs.host_cc }} \ -DCMAKE_CXX_COMPILER=${{ steps.build-parameters.outputs.host_cxx }} # === BUILD === - name: Build working-directory: ${{ github.workspace }}/Build run: | cmake --build . cmake --install . --strip --prefix "${GITHUB_WORKSPACE}/Install" - name: Build with Qt if: ${{ (inputs.os_name == 'macOS' || inputs.os_name == 'Linux') && inputs.build_preset == 'Sanitizer' }} working-directory: ${{ github.workspace }} run: | cmake --preset ${{ inputs.build_preset }} -B Build -DLADYBIRD_GUI_FRAMEWORK=Qt cmake --build Build - name: Save Caches uses: ./.github/actions/cache-save with: arch: ${{ inputs.arch }} ccache_path: ${{ steps.setup.outputs.ccache_path }} ccache_primary_key: ${{ steps.cache-restore.outputs.ccache_primary_key }} vcpkg_cache_path: ${{ steps.setup.outputs.vcpkg_cache_path }} vcpkg_cache_primary_key: ${{ steps.cache-restore.outputs.vcpkg_cache_primary_key }} # === TEST === - name: Start PulseAudio if: ${{ inputs.os_name == 'Linux' }} run: | echo "PULSE_SERVER=unix:/tmp/pulse-native" >> "$GITHUB_ENV" pulseaudio --system -D --exit-idle-time=1800 \ --load="module-native-protocol-unix auth-anonymous=1 socket=/tmp/pulse-native" \ --load="module-null-sink sink_name=virtual_sink" - name: Check new tests for flakiness if: ${{ github.event_name == 'pull_request' && inputs.build_preset == 'Sanitizer' && (inputs.os_name == 'Linux' || inputs.os_name == 'macOS') }} timeout-minutes: 30 working-directory: ${{ github.workspace }} shell: bash run: | git fetch --no-tags --depth=1 origin ${{ github.event.pull_request.base.sha }} "${{ env.pythonLocation }}/bin/python" Meta/check-test-flakiness.py \ --test-web-binary Build/bin/test-web \ --base-ref ${{ github.event.pull_request.base.sha }} \ --deadline-seconds 1200 \ --python-executable "${{ env.pythonLocation }}/bin/python" \ | tee -a "$GITHUB_STEP_SUMMARY" - name: Test if: ${{ inputs.build_preset == 'Sanitizer' }} working-directory: ${{ github.workspace }} run: ctest --preset ${{ inputs.build_preset }} --output-on-failure --test-dir Build --timeout 1800 env: TESTS_ONLY: 1 # NOTE: These are appended to the preset's options. ASAN_OPTIONS: 'log_path=asan.log' UBSAN_OPTIONS: 'log_path=ubsan.log' - name: Test if: ${{ inputs.build_preset != 'Fuzzers' && inputs.build_preset != 'All_Debug' && inputs.build_preset != 'Sanitizer' }} working-directory: ${{ github.workspace }} run: ctest --output-on-failure --test-dir Build --timeout 1800 env: TESTS_ONLY: 1 - name: Upload LibWeb Test Artifacts if: ${{ always() && inputs.build_preset != 'Fuzzers' && inputs.build_preset != 'All_Debug' }} uses: actions/upload-artifact@v7 with: name: libweb-test-artifacts-${{ inputs.os_name }}-${{ inputs.arch }}-${{ inputs.build_preset }}-${{ inputs.toolchain }}-${{ inputs.clang_plugins }} path: | Build/Tests/LibWeb/test-web/test-dumps/ Build/**/asan.log.* Build/**/ubsan.log.* retention-days: 0 if-no-files-found: ignore - name: Sanitizer Output if: ${{ !cancelled() && inputs.os_name != 'Windows' && inputs.build_preset == 'Sanitizer' }} working-directory: ${{ github.workspace }} run: | log_output=$(find Build \( -name 'asan.log.*' -o -name 'ubsan.log.*' \) -exec cat {} \; ) if [ -z "$log_output" ]; then echo "No sanitizer issues found." else echo "$log_output" echo "Sanitizer errors happened while running tests; see the Test step above." fi