godotengine/godot

8 workflows · maturity 50% · 6 patterns · GitHub ↗

Security 0/100

Practices

✓ Matrix○ Permissions○ Security scan○ AI review✓ Cache✓ Concurrency✓ Reusable workflows

Detected patterns

Security dimensions

permissions
0
security scan
0
supply chain
0
secret handling
0
harden runner
0

Workflows (8)

android_builds matrix .github/workflows/android_builds.yml
Triggers
workflow_call, workflow_dispatch
Runs on
ubuntu-24.04
Jobs
build-android
Matrix
include, include.cache-name, include.instrumented_tests, include.name, include.scons-flags, include.target→ Editor (target=editor), False, Template arm32 (target=template_debug, arch=arm32), Template arm64 (target=template_debug, arch=arm64), True, android-editor, android-template-arm32, android-template-arm64, arch=arm32, arch=arm64, arch=arm64 production=yes, editor, template_debug
Actions
google-github-actions/auth, google-github-actions/setup-gcloud
Commands
  • python ./misc/scripts/install_swappy_android.py
  • cd platform/android/java ./gradlew generateGodotTemplates cd ../../.. ls -l bin/
  • cd platform/android/java ./gradlew generateGodotEditor ./gradlew generateGodotHorizonOSEditor ./gradlew generateGodotPicoOSEditor cd ../../.. ls -l bin/android_editor_builds/ # Separate different editors for multiple artifacts mkdir horizonos mv bin/android_editor_builds/*-horizonos-* horizonos mkdir picoos mv bin/android_editor_builds/*-picoos-* picoos
  • cd platform/android/java ./gradlew :app:assembleAndroidTest :app:assembleInstrumentedDebug -Pperform_signing=true cd ../../..
  • set +e output=$(gcloud firebase test android run \ --type instrumentation \ --app platform/android/java/app/build/outputs/apk/instrumented/debug/android_debug.apk \ --test platform/android/java/app/build/outputs/apk/androidTest/instrumented/debug/app-instrumented-debug-androidTest.apk \ --device model=pa3q,version=35,orientation=landscape \ --device model=java,version=30,orientation=landscape \ --device model=MediumPhone.arm,version=26,orientation=landscape \ --use-orchestrator \ --timeout 2m 2>&1) exit_code=$? echo "$output" if [[ $exit_code -eq 1 && "$output" == *"TEST_QUOTA_EXCEEDED"* ]]; then echo "::warning title=Firebase Test Lab::Test quota exceeded." exit_code=0 fi exit "$exit_code"
View raw YAML
name: 🤖 Android Builds
on:
  workflow_call:
    secrets:
      SERVICE_ACCOUNT_KEY:
        required: true

  workflow_dispatch:

# Global Settings
env:
  SCONS_FLAGS: >-
    dev_mode=yes
    module_text_server_fb_enabled=yes
    swappy=yes

jobs:
  build-android:
    runs-on: ubuntu-24.04
    name: ${{ matrix.name }}
    timeout-minutes: 60
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Editor (target=editor)
            cache-name: android-editor
            target: editor
            instrumented_tests: false
            scons-flags: >-
              arch=arm64
              production=yes

          - name: Template arm32 (target=template_debug, arch=arm32)
            cache-name: android-template-arm32
            target: template_debug
            instrumented_tests: false
            scons-flags: arch=arm32

          - name: Template arm64 (target=template_debug, arch=arm64)
            cache-name: android-template-arm64
            target: template_debug
            instrumented_tests: true
            scons-flags: arch=arm64

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Set up Java 17
        uses: actions/setup-java@v5
        with:
          distribution: temurin
          java-version: 17

      - name: Restore Godot build cache
        uses: ./.github/actions/godot-cache-restore
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Setup Python and SCons
        uses: ./.github/actions/godot-deps

      - name: Download Swappy
        run: python ./misc/scripts/install_swappy_android.py

      - name: Compilation
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }}
          platform: android
          target: ${{ matrix.target }}

      - name: Save Godot build cache
        uses: ./.github/actions/godot-cache-save
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Generate Godot templates
        if: matrix.target == 'template_debug'
        run: |
          cd platform/android/java
          ./gradlew generateGodotTemplates
          cd ../../..
          ls -l bin/

      - name: Generate Godot editor
        if: matrix.target == 'editor'
        run: |
          cd platform/android/java
          ./gradlew generateGodotEditor
          ./gradlew generateGodotHorizonOSEditor
          ./gradlew generateGodotPicoOSEditor
          cd ../../..
          ls -l bin/android_editor_builds/

          # Separate different editors for multiple artifacts
          mkdir horizonos
          mv bin/android_editor_builds/*-horizonos-* horizonos
          mkdir picoos
          mv bin/android_editor_builds/*-picoos-* picoos

      - name: Upload artifact
        uses: ./.github/actions/upload-artifact
        with:
          name: ${{ matrix.cache-name }}

      - name: Upload artifact (Horizon OS)
        if: matrix.target == 'editor'
        uses: ./.github/actions/upload-artifact
        with:
          name: ${{ matrix.cache-name }}-horizonos
          path: horizonos

      - name: Upload artifact (PICO OS)
        if: matrix.target == 'editor'
        uses: ./.github/actions/upload-artifact
        with:
          name: ${{ matrix.cache-name }}-picoos
          path: picoos

      - name: Generate Instrumented test APKs
        if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
        run: |
          cd platform/android/java
          ./gradlew :app:assembleAndroidTest :app:assembleInstrumentedDebug -Pperform_signing=true
          cd ../../..

      - name: Create credentials file
        if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
        uses: google-github-actions/auth@v3
        with:
          credentials_json: ${{ secrets.SERVICE_ACCOUNT_KEY }}

      - name: Set up gcloud CLI
        if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
        uses: google-github-actions/setup-gcloud@v3

      - name: Run tests on Firebase Test Lab
        if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
        run: |
          set +e
          output=$(gcloud firebase test android run \
            --type instrumentation \
            --app platform/android/java/app/build/outputs/apk/instrumented/debug/android_debug.apk \
            --test platform/android/java/app/build/outputs/apk/androidTest/instrumented/debug/app-instrumented-debug-androidTest.apk \
            --device model=pa3q,version=35,orientation=landscape \
            --device model=java,version=30,orientation=landscape \
            --device model=MediumPhone.arm,version=26,orientation=landscape \
            --use-orchestrator \
            --timeout 2m 2>&1)
          exit_code=$?
          echo "$output"
          if [[ $exit_code -eq 1 && "$output" == *"TEST_QUOTA_EXCEEDED"* ]]; then
            echo "::warning title=Firebase Test Lab::Test quota exceeded."
            exit_code=0
          fi
          exit "$exit_code"
ios_builds .github/workflows/ios_builds.yml
Triggers
workflow_call, workflow_dispatch
Runs on
macos-26
Jobs
ios-template
View raw YAML
name: 🍏 iOS Builds
on:
  workflow_call:
  workflow_dispatch:

# Global Settings
env:
  SCONS_FLAGS: >-
    dev_mode=yes
    module_text_server_fb_enabled=yes
    debug_symbols=no

jobs:
  ios-template:
    # From https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#choosing-github-hosted-runners
    runs-on: macos-26
    name: Template (target=template_release)
    timeout-minutes: 60

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Restore Godot build cache
        uses: ./.github/actions/godot-cache-restore
        continue-on-error: true

      - name: Setup Python and SCons
        uses: ./.github/actions/godot-deps

      - name: Compilation (arm64)
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }}
          platform: ios
          target: template_release

      - name: Save Godot build cache
        uses: ./.github/actions/godot-cache-save
        continue-on-error: true

      - name: Upload artifact
        uses: ./.github/actions/upload-artifact
linux_builds matrix .github/workflows/linux_builds.yml
Triggers
workflow_call, workflow_dispatch
Runs on
ubuntu-22.04
Jobs
build-linux
Matrix
include, include.api-compat, include.artifact, include.bin, include.build-mono, include.cache-name, include.clangd-tidy, include.doc-test, include.godot-cpp, include.legacy-scons, include.name, include.proj-conv, include.proj-export, include.proj-test, include.scons-flags, include.target→ ./bin/godot.linuxbsd.editor.dev.double.x86_64.san, ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san, ./bin/godot.linuxbsd.editor.x86_64.mono, ./bin/godot.linuxbsd.template_debug.x86_64.mono, ./bin/godot.linuxbsd.template_release.x86_64, ./bin/godot.linuxbsd.template_release.x86_64.mono, Editor w/ Mono (target=editor), Editor with ThreadSanitizer (target=editor, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld), Editor with clang sanitizers (target=editor, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld), Editor with doubles and GCC sanitizers (target=editor, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=mold), Minimal template (target=template_release, everything disabled), Template w/ Mono, debug (target=template_debug), Template w/ Mono, release (target=template_release), True, dev_build=yes scu_build=yes debug_symbols=no precision=double use_asan=yes use_ubsan=yes linker=mold, dev_build=yes use_asan=yes use_ubsan=yes use_llvm=yes linker=lld, dev_build=yes use_tsan=yes use_llvm=yes linker=lld, editor, linux-editor-double-sanitizers, linux-editor-llvm-sanitizers, linux-editor-mono, linux-editor-thread-sanitizer, linux-template-minimal, linux-template-mono, linux-template-mono-debug, module_mono_enabled=yes, module_mono_enabled=yes compiledb=yes, modules_enabled_by_default=no module_text_server_fb_enabled=no disable_3d=yes disable_advanced_gui=yes disable_physics_2d=yes disable_physics_3d=yes deprecated=no minizip=no brotli=no, template_debug, template_release
Actions
rui314/setup-mold
Commands
  • sudo apt-get update sudo apt-get install libwayland-bin # TODO: Figure out somehow how to embed this one. if [ "${{ matrix.proj-test }}" == "true" -o "${{ matrix.proj-export }}" == "true" ]; then sudo apt-get install mesa-vulkan-drivers fi
  • echo "Disk usage before:" && df -h sudo rm -rf /usr/local/lib/android echo "Disk usage after:" && df -h
  • sudo rm -rf /usr/share/dotnet/sdk/*
  • if python ./misc/scripts/install_accesskit.py; then echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::AccessKit SDK installation failed, building without AccessKit support." echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • ${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue
  • dotnet --info ./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd --werror
  • rm -rf ./bin/build_deps strip bin/godot.* chmod +x bin/godot.*
  • ${{ matrix.bin }} --version ${{ matrix.bin }} --help ${{ matrix.bin }} --headless --test --force-colors
View raw YAML
name: 🐧 Linux Builds
on:
  workflow_call:
    inputs:
      changed-files:
        description: A list of changed files, pre-filtered for parsing by clangd-tidy.
        required: true
        type: string
  workflow_dispatch:

# Global Settings
env:
  SCONS_FLAGS: >-
    dev_mode=yes
    module_text_server_fb_enabled=yes
  GODOT_CPP_BRANCH: 4.5
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true
  ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt
  LSAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/lsan.txt
  TSAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/tsan.txt
  UBSAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/ubsan.txt

jobs:
  build-linux:
    # Stay one LTS before latest to increase portability of Linux artifacts.
    runs-on: ubuntu-22.04
    name: ${{ matrix.name }}
    timeout-minutes: 120
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Editor w/ Mono (target=editor)
            cache-name: linux-editor-mono
            target: editor
            scons-flags: module_mono_enabled=yes compiledb=yes
            bin: ./bin/godot.linuxbsd.editor.x86_64.mono
            build-mono: true
            doc-test: true
            proj-conv: true
            proj-export: true
            api-compat: true
            artifact: true
            # Validate godot-cpp compatibility on one arbitrary editor build.
            godot-cpp: true
            clangd-tidy: true

          - name: Editor with doubles and GCC sanitizers (target=editor, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=mold)
            cache-name: linux-editor-double-sanitizers
            target: editor
            # Debug symbols disabled as they're huge on this build and we hit the 14 GB limit for runners.
            scons-flags: >-
              dev_build=yes
              scu_build=yes
              debug_symbols=no
              precision=double
              use_asan=yes
              use_ubsan=yes
              linker=mold
            bin: ./bin/godot.linuxbsd.editor.dev.double.x86_64.san
            proj-test: true

          - name: Editor with clang sanitizers (target=editor, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)
            cache-name: linux-editor-llvm-sanitizers
            target: editor
            scons-flags: >-
              dev_build=yes
              use_asan=yes
              use_ubsan=yes
              use_llvm=yes
              linker=lld
            bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
            # Test our oldest supported SCons/Python versions on one arbitrary editor build.
            legacy-scons: true

          - name: Editor with ThreadSanitizer (target=editor, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)
            cache-name: linux-editor-thread-sanitizer
            target: editor
            scons-flags: >-
              dev_build=yes
              use_tsan=yes
              use_llvm=yes
              linker=lld
            bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san

          - name: Template w/ Mono, release (target=template_release)
            cache-name: linux-template-mono
            target: template_release
            scons-flags: module_mono_enabled=yes
            bin: ./bin/godot.linuxbsd.template_release.x86_64.mono
            artifact: true

          - name: Template w/ Mono, debug (target=template_debug)
            cache-name: linux-template-mono-debug
            target: template_debug
            scons-flags: module_mono_enabled=yes
            bin: ./bin/godot.linuxbsd.template_debug.x86_64.mono
            artifact: true

          - name: Minimal template (target=template_release, everything disabled)
            cache-name: linux-template-minimal
            target: template_release
            scons-flags: >-
              modules_enabled_by_default=no
              module_text_server_fb_enabled=no
              disable_3d=yes
              disable_advanced_gui=yes
              disable_physics_2d=yes
              disable_physics_3d=yes
              deprecated=no
              minizip=no
              brotli=no
            bin: ./bin/godot.linuxbsd.template_release.x86_64
            artifact: true

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Setup dependencies
        run: |
          sudo apt-get update
          sudo apt-get install libwayland-bin  # TODO: Figure out somehow how to embed this one.
          if [ "${{ matrix.proj-test }}" == "true" -o "${{ matrix.proj-export }}" == "true" ]; then
            sudo apt-get install mesa-vulkan-drivers
          fi

      - name: Free disk space on runner
        run: |
          echo "Disk usage before:" && df -h
          sudo rm -rf /usr/local/lib/android
          echo "Disk usage after:" && df -h

      - name: Restore Godot build cache
        uses: ./.github/actions/godot-cache-restore
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Setup Python and SCons
        if: "!matrix.legacy-scons"
        uses: ./.github/actions/godot-deps

      - name: Setup Python and SCons (legacy versions)
        if: matrix.legacy-scons
        uses: ./.github/actions/godot-deps
        with:
          # Sync with Ensure*Version in SConstruct.
          python-version: 3.9
          scons-version: 4.0

      - name: Force remove preinstalled .NET SDKs
        if: matrix.build-mono
        run: |
          sudo rm -rf /usr/share/dotnet/sdk/*

      - name: Setup older .NET SDK as baseline
        if: matrix.build-mono
        uses: actions/setup-dotnet@v4
        with:
          # Targeting the oldest version we want to support to ensure it still builds.
          dotnet-version: 8.0.100

      - name: Download pre-built AccessKit
        shell: sh
        id: accesskit-sdk
        run: |
          if python ./misc/scripts/install_accesskit.py; then
            echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
            echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi

      - name: Install mold linker
        if: matrix.proj-test
        uses: rui314/setup-mold@v1

      - name: Compilation
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }}
          platform: linuxbsd
          target: ${{ matrix.target }}

      - name: Style checks via clangd-tidy
        if: matrix.clangd-tidy
        uses: ./.github/actions/clangd-tidy
        with:
          changed-files: ${{ inputs.changed-files }}

      - name: Compilation (godot-cpp)
        uses: ./.github/actions/godot-cpp-build
        if: matrix.godot-cpp
        with:
          bin: ${{ matrix.bin }}
          scons-flags: target=template_debug dev_build=yes verbose=yes
          godot-cpp-branch: ${{ env.GODOT_CPP_BRANCH }}

      - name: Save Godot build cache
        uses: ./.github/actions/godot-cache-save
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Generate C# glue
        if: matrix.build-mono
        run: |
          ${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue

      - name: Build .NET solutions
        if: matrix.build-mono
        run: |
          dotnet --info
          ./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd --werror

      - name: Prepare artifact
        if: matrix.artifact
        run: |
          rm -rf ./bin/build_deps
          strip bin/godot.*
          chmod +x bin/godot.*

      - name: Upload artifact
        uses: ./.github/actions/upload-artifact
        if: matrix.artifact
        with:
          name: ${{ matrix.cache-name }}

      - name: Unit tests
        run: |
          ${{ matrix.bin }} --version
          ${{ matrix.bin }} --help
          ${{ matrix.bin }} --headless --test --force-colors

      - name: .NET source generators tests
        if: matrix.build-mono
        run: |
          dotnet test modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests

      # Check class reference
      - name: Check for class reference updates
        if: matrix.doc-test
        run: |
          echo "Running --doctool to see if this changes the public API without updating the documentation."
          echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
          ${{ matrix.bin }} --doctool --headless 2>&1 > /dev/null || true
          git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'

      # Check API backwards compatibility
      - name: Check for GDExtension compatibility – JSON check
        if: matrix.api-compat
        run: |
          ./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}"

      - name: Test GDExtension compatibility – load methods
        uses: ./.github/actions/godot-compat-test
        if: matrix.api-compat
        with:
          bin: ${{ matrix.bin }}
          reftags: "4.5-stable,4.4-stable"

      # Download and run the test project
      - name: Test Godot project
        uses: ./.github/actions/godot-project-test
        if: matrix.proj-test
        with:
          bin: ${{ matrix.bin }}

      # Test project export
      - name: Test project export
        uses: ./.github/actions/godot-project-export
        if: matrix.proj-export
        with:
          bin: ${{ matrix.bin }}

      # Test the project converter
      - name: Test project converter
        uses: ./.github/actions/godot-converter-test
        if: matrix.proj-conv
        with:
          bin: ${{ matrix.bin }}
macos_builds matrix .github/workflows/macos_builds.yml
Triggers
workflow_call, workflow_dispatch
Runs on
macos-26
Jobs
build-macos
Matrix
include, include.bin, include.cache-name, include.name, include.scons-flags, include.target→ ./bin/godot.macos.editor.universal, ./bin/godot.macos.template_release.universal, Editor (target=editor), Template (target=template_release), debug_symbols=no, editor, macos-editor, macos-template, template_release
Commands
  • if python ./misc/scripts/install_angle.py; then echo "ANGLE_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::ANGLE SDK installation failed, building without ANGLE support." echo "ANGLE_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • if python3 ./misc/scripts/install_accesskit.py; then echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::AccessKit SDK installation failed, building without AccessKit support." echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • if sh misc/scripts/install_vulkan_sdk_macos.sh; then echo "VULKAN_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::macOS: Vulkan SDK installation failed, building without Vulkan support." echo "VULKAN_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • lipo -create ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64 -output ./bin/godot.macos.${{ matrix.target }}.universal rm ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64 rm -rf ./bin/build_deps strip bin/godot.* chmod +x bin/godot.*
  • ${{ matrix.bin }} --version ${{ matrix.bin }} --help ${{ matrix.bin }} --test --force-colors
View raw YAML
name: 🍎 macOS Builds
on:
  workflow_call:
  workflow_dispatch:

# Global Settings
env:
  SCONS_FLAGS: >-
    dev_mode=yes
    module_text_server_fb_enabled=yes

jobs:
  build-macos:
    # From https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#choosing-github-hosted-runners
    runs-on: macos-26
    name: ${{ matrix.name }}
    timeout-minutes: 120
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Editor (target=editor)
            cache-name: macos-editor
            target: editor
            bin: ./bin/godot.macos.editor.universal

          - name: Template (target=template_release)
            cache-name: macos-template
            target: template_release
            scons-flags: debug_symbols=no
            bin: ./bin/godot.macos.template_release.universal

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Restore Godot build cache
        uses: ./.github/actions/godot-cache-restore
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Setup Python and SCons
        uses: ./.github/actions/godot-deps

      - name: Download pre-built ANGLE
        shell: sh
        id: angle-sdk
        run: |
          if python ./misc/scripts/install_angle.py; then
            echo "ANGLE_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::ANGLE SDK installation failed, building without ANGLE support."
            echo "ANGLE_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi

      - name: Download pre-built AccessKit
        shell: sh
        id: accesskit-sdk
        run: |
          if python3 ./misc/scripts/install_accesskit.py; then
            echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
            echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi

      - name: Setup Vulkan SDK
        id: vulkan-sdk
        run: |
          if sh misc/scripts/install_vulkan_sdk_macos.sh; then
            echo "VULKAN_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::macOS: Vulkan SDK installation failed, building without Vulkan support."
            echo "VULKAN_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi
        continue-on-error: true

      - name: Compilation (x86_64)
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=x86_64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }} angle=${{ steps.angle-sdk.outputs.ANGLE_ENABLED }}
          platform: macos
          target: ${{ matrix.target }}

      - name: Compilation (arm64)
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=arm64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }} angle=${{ steps.angle-sdk.outputs.ANGLE_ENABLED }}
          platform: macos
          target: ${{ matrix.target }}

      - name: Save Godot build cache
        uses: ./.github/actions/godot-cache-save
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Prepare artifact
        run: |
          lipo -create ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64 -output ./bin/godot.macos.${{ matrix.target }}.universal
          rm ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64
          rm -rf ./bin/build_deps
          strip bin/godot.*
          chmod +x bin/godot.*

      - name: Upload artifact
        uses: ./.github/actions/upload-artifact
        with:
          name: ${{ matrix.cache-name }}

      - name: Unit tests
        run: |
          ${{ matrix.bin }} --version
          ${{ matrix.bin }} --help
          ${{ matrix.bin }} --test --force-colors
runner .github/workflows/runner.yml
Triggers
push, pull_request, merge_group, workflow_dispatch
Runs on
Jobs
static-checks, android-build, ios-build, linux-build, macos-build, windows-build, web-build
View raw YAML
name: 🔗 GHA
on: [push, pull_request, merge_group, workflow_dispatch]

concurrency:
  group: ${{ github.workflow }}|${{ github.ref_name }}
  cancel-in-progress: true

jobs:
  # First stage: Only static checks, fast and prevent expensive builds from running.

  static-checks:
    if: ${{ !vars.DISABLE_GODOT_CI || github.run_attempt > 1 || github.event_name == 'workflow_dispatch' }}
    name: 📊 Static checks
    uses: ./.github/workflows/static_checks.yml

  # Second stage: Run all the builds and some of the tests.

  android-build:
    name: 🤖 Android
    needs: static-checks
    if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
    uses: ./.github/workflows/android_builds.yml
    secrets:
      SERVICE_ACCOUNT_KEY: ${{ secrets.SERVICE_ACCOUNT_KEY }}

  ios-build:
    name: 🍏 iOS
    needs: static-checks
    if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
    uses: ./.github/workflows/ios_builds.yml

  linux-build:
    name: 🐧 Linux
    needs: static-checks
    if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
    uses: ./.github/workflows/linux_builds.yml
    with:
      changed-files: ${{ needs.static-checks.outputs.changed-files }}

  macos-build:
    name: 🍎 macOS
    needs: static-checks
    if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
    uses: ./.github/workflows/macos_builds.yml

  windows-build:
    name: 🏁 Windows
    needs: static-checks
    if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
    uses: ./.github/workflows/windows_builds.yml

  web-build:
    name: 🌐 Web
    needs: static-checks
    if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
    uses: ./.github/workflows/web_builds.yml
static_checks .github/workflows/static_checks.yml
Triggers
workflow_call, workflow_dispatch
Runs on
ubuntu-24.04
Jobs
static-checks
Actions
tj-actions/changed-files, pre-commit/action
Commands
  • bash ./misc/scripts/gitignore_check.sh
View raw YAML
name: 📊 Static Checks
on:
  workflow_call:
    outputs:
      changed-files:
        description: A list of changed files, pre-filtered for parsing by clangd-tidy.
        value: ${{ jobs.static-checks.outputs.changed-files }}
      sources-changed:
        description: Determines if any source files were changed.
        value: ${{ jobs.static-checks.outputs.sources-changed }}
  workflow_dispatch:

jobs:
  static-checks:
    name: Code style, file formatting, and docs
    runs-on: ubuntu-24.04
    timeout-minutes: 30
    outputs:
      changed-files: '"${{ steps.changed-files.outputs.clangd_all_changed_files }}"' # Wrap with quotes to bookend internal quote separators.
      sources-changed: ${{ steps.changed-files.outputs.sources_any_changed }}
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0 # Treeless clone. Slightly less performant than a shallow clone, but makes finding diffs instantaneous.
          filter: tree:0 # See: https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/

      # This needs to happen before Python and npm execution; it must happen before any extra files are written.
      - name: .gitignore checks (gitignore_check.sh)
        run: |
          bash ./misc/scripts/gitignore_check.sh

      - name: Get changed files
        id: changed-files
        uses: tj-actions/changed-files@v47
        with:
          safe_output: false # Output passed to environment variable to avoid command injection.
          separator: '" "' # To account for paths with spaces, ensure our items are split by quotes internally.
          skip_initial_fetch: true
          files_yaml_from_source_file: .github/changed_files.yml

      - name: Style checks via pre-commit
        uses: pre-commit/action@v3.0.1
        env:
          CHANGED_FILES: '"${{ steps.changed-files.outputs.everything_all_changed_files }}"' # Wrap with quotes to bookend internal quote separators.
        with:
          extra_args: --files ${{ env.CHANGED_FILES }}
web_builds matrix .github/workflows/web_builds.yml
Triggers
workflow_call, workflow_dispatch
Runs on
ubuntu-24.04
Jobs
web-template
Matrix
include, include.artifact, include.cache-name, include.name, include.scons-flags, include.target→ Template w/ threads, 64-bit (target=template_release, threads=yes, arch=wasm64), Template w/o threads, 32-bit (target=template_release, threads=no, arch=wasm32), True, template_release, threads=no arch=wasm32, threads=yes arch=wasm64, web-nothreads-template, web-template
Actions
mymindstorm/setup-emsdk
Commands
  • emcc -v
View raw YAML
name: 🌐 Web Builds
on:
  workflow_call:
  workflow_dispatch:

# Global Settings
env:
  SCONS_FLAGS: >-
    dev_mode=yes
    debug_symbols=no
    use_closure_compiler=yes
  EM_VERSION: 4.0.11

jobs:
  web-template:
    runs-on: ubuntu-24.04
    name: ${{ matrix.name }}
    timeout-minutes: 60
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Template w/ threads, 64-bit (target=template_release, threads=yes, arch=wasm64)
            cache-name: web-template
            target: template_release
            scons-flags: threads=yes arch=wasm64
            artifact: true

          - name: Template w/o threads, 32-bit (target=template_release, threads=no, arch=wasm32)
            cache-name: web-nothreads-template
            target: template_release
            scons-flags: threads=no arch=wasm32
            artifact: true

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Set up Emscripten latest
        uses: mymindstorm/setup-emsdk@v14
        with:
          version: ${{ env.EM_VERSION }}
          no-cache: true

      - name: Verify Emscripten setup
        run: |
          emcc -v

      - name: Restore Godot build cache
        uses: ./.github/actions/godot-cache-restore
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Setup Python and SCons
        uses: ./.github/actions/godot-deps

      - name: Compilation
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }}
          platform: web
          target: ${{ matrix.target }}

      - name: Save Godot build cache
        uses: ./.github/actions/godot-cache-save
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Upload artifact
        uses: ./.github/actions/upload-artifact
        if: matrix.artifact
        with:
          name: ${{ matrix.cache-name }}
windows_builds matrix .github/workflows/windows_builds.yml
Triggers
workflow_call, workflow_dispatch
Runs on
windows-latest
Jobs
build-windows
Matrix
include, include.bin, include.cache-name, include.compiler, include.name, include.scons-flags, include.target→ ./bin/godot.windows.editor.x86_64.exe, ./bin/godot.windows.editor.x86_64.llvm.exe, ./bin/godot.windows.template_release.x86_64.console.exe, Editor (target=editor), Editor w/ clang-cl (target=editor, use_llvm=yes), Template (target=template_release), Template w/ GCC (target=template_release, use_mingw=yes), clang, editor, gcc, msvc, template_release, use_mingw=yes, windows-editor, windows-editor-clang, windows-template, windows-template-gcc, windows_subsystem=console use_llvm=yes, windows_subsystem=console vsproj=yes vsproj_gen_only=no
Commands
  • if python ./misc/scripts/install_d3d12_sdk_windows.py; then echo "D3D12_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::Windows: Direct3D 12 SDK installation failed, building without Direct3D 12 support." echo "D3D12_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • if python ./misc/scripts/install_angle.py; then echo "ANGLE_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::ANGLE SDK installation failed, building without ANGLE support." echo "ANGLE_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • if python ./misc/scripts/install_accesskit.py; then echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT" else echo "::warning::AccessKit SDK installation failed, building without AccessKit support." echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT" fi
  • Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
  • ${{ matrix.bin }} --version ${{ matrix.bin }} --help ${{ matrix.bin }} --test --force-colors
View raw YAML
name: 🏁 Windows Builds
on:
  workflow_call:
  workflow_dispatch:

# Global Settings
env:
  SCONS_FLAGS: >-
    dev_mode=yes
    module_text_server_fb_enabled=yes
    debug_symbols=no
  SCONS_CACHE_MSVC_CONFIG: true
  PYTHONIOENCODING: utf8

jobs:
  build-windows:
    # Windows 10 with latest image
    runs-on: windows-latest
    name: ${{ matrix.name }}
    timeout-minutes: 120
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Editor (target=editor)
            cache-name: windows-editor
            target: editor
            scons-flags: >-
              windows_subsystem=console
              vsproj=yes
              vsproj_gen_only=no
            bin: ./bin/godot.windows.editor.x86_64.exe
            compiler: msvc

          - name: Editor w/ clang-cl (target=editor, use_llvm=yes)
            cache-name: windows-editor-clang
            target: editor
            scons-flags: >-
              windows_subsystem=console
              use_llvm=yes
            bin: ./bin/godot.windows.editor.x86_64.llvm.exe
            compiler: clang

          - name: Template (target=template_release)
            cache-name: windows-template
            target: template_release
            bin: ./bin/godot.windows.template_release.x86_64.console.exe
            compiler: msvc

          - name: Template w/ GCC (target=template_release, use_mingw=yes)
            cache-name: windows-template-gcc
            # MinGW takes MUCH longer to compile; save time by only targeting Template.
            target: template_release
            scons-flags: use_mingw=yes
            bin: ./bin/godot.windows.template_release.x86_64.console.exe
            compiler: gcc

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Restore Godot build cache
        uses: ./.github/actions/godot-cache-restore
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Setup Python and SCons
        uses: ./.github/actions/godot-deps

      - name: Download Direct3D 12 SDK components
        shell: sh
        id: d3d12-sdk
        run: |
          if python ./misc/scripts/install_d3d12_sdk_windows.py; then
            echo "D3D12_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::Windows: Direct3D 12 SDK installation failed, building without Direct3D 12 support."
            echo "D3D12_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi
        continue-on-error: true

      - name: Download pre-built ANGLE
        shell: sh
        id: angle-sdk
        run: |
          if python ./misc/scripts/install_angle.py; then
            echo "ANGLE_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::ANGLE SDK installation failed, building without ANGLE support."
            echo "ANGLE_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi

      - name: Download pre-built AccessKit
        shell: sh
        id: accesskit-sdk
        run: |
          if python ./misc/scripts/install_accesskit.py; then
            echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
          else
            echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
            echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
          fi

      - name: Compilation
        uses: ./.github/actions/godot-build
        with:
          scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} d3d12=${{ steps.d3d12-sdk.outputs.D3D12_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }} angle=${{ steps.angle-sdk.outputs.ANGLE_ENABLED }}
          platform: windows
          target: ${{ matrix.target }}

      - name: Save Godot build cache
        uses: ./.github/actions/godot-cache-save
        with:
          cache-name: ${{ matrix.cache-name }}
        continue-on-error: true

      - name: Prepare artifact
        if: matrix.compiler == 'msvc'
        run: |
          Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force

      - name: Upload artifact
        if: matrix.compiler == 'msvc'
        uses: ./.github/actions/upload-artifact
        with:
          name: ${{ matrix.cache-name }}

      - name: Unit tests
        run: |
          ${{ matrix.bin }} --version
          ${{ matrix.bin }} --help
          ${{ matrix.bin }} --test --force-colors