From 395219cbbab32c0701cd4e55c4d7e2fbcc7932ea Mon Sep 17 00:00:00 2001 From: Gliniak <153369+Gliniak@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:12:32 +0100 Subject: [PATCH] [CI] CI Redesign: Initial Orchestrator & Removal of unused drone CI [Note] This is partially written by AI --- .drone.star | 390 --------------------- .github/workflows/Check_commit_message.yml | 56 +++ .github/workflows/Create_release.yml | 196 ++++++++--- .github/workflows/Lint.yml | 29 ++ .github/workflows/Linux_build.yml | 184 ---------- .github/workflows/Linux_x86.yml | 94 +++++ .github/workflows/Orchestrator.yml | 88 +++++ .github/workflows/Windows_build.yml | 159 --------- .github/workflows/Windows_x86.yml | 92 +++++ 9 files changed, 512 insertions(+), 776 deletions(-) delete mode 100644 .drone.star create mode 100644 .github/workflows/Check_commit_message.yml create mode 100644 .github/workflows/Lint.yml delete mode 100644 .github/workflows/Linux_build.yml create mode 100644 .github/workflows/Linux_x86.yml create mode 100644 .github/workflows/Orchestrator.yml delete mode 100644 .github/workflows/Windows_build.yml create mode 100644 .github/workflows/Windows_x86.yml diff --git a/.drone.star b/.drone.star deleted file mode 100644 index e0a17a96a..000000000 --- a/.drone.star +++ /dev/null @@ -1,390 +0,0 @@ -def main(ctx): - return [ - pipeline_lint(), - pipeline_linux_desktop('x86_64-linux-clang', image_linux_x86_64(), 'amd64', 'clang', True), - pipeline_linux_desktop('x86_64-linux-gcc', image_linux_x86_64(), 'amd64', 'gcc', False), # GCC release linking is really slow - pipeline_android('x86_64-android', image_linux_x86_64(), 'amd64', 'Android-x86_64'), - pipeline_android('aarch64-android', image_linux_x86_64(), 'amd64', 'Android-ARM64'), - ] - -def image_linux_x86_64(): - return 'xeniaproject/buildenv:2022-07-15' - -def volume_build(toolchain, path='/drone/src/build'): - return { - 'name': 'build-' + toolchain, - 'path': path, - } - -def command_cc(cc): - # set CC, CXX, ... - return 'export $(cat /{}.env | sed \'s/#.*//g\' | xargs)'.format(cc) - -def command_ndk_build(platform, configuration, target): - return '$ANDROID_NDK_ROOT/build/ndk-build NDK_PROJECT_PATH:=./bin/{configuration} NDK_APPLICATION_MK:=./xenia.Application.mk PREMAKE_ANDROIDNDK_PLATFORMS:={platform} PREMAKE_ANDROIDNDK_CONFIGURATIONS:={configuration} -j$(nproc) {target}'.format(platform=platform, configuration=configuration, target=target) - -def xenia_base_tests_filters(): - # https://github.com/xenia-project/xenia/issues/2036 - return 'exclude:"Wait on Timer" exclude:"Wait on Multiple Timers" exclude:"HighResolutionTimer"' - -# Run lint in a separate pipeline so that it will try building even if lint fails -def pipeline_lint(): - return { - 'kind': 'pipeline', - 'type': 'docker', - 'name': 'lint', - 'steps': [ - { - 'name': 'lint', - 'image': image_linux_x86_64(), - 'commands': [ - 'clang-format --version', - './xenia-build lint --all', - ], - }, - ], - } - -def pipeline_linux_desktop(name, image, arch, cc, build_release_all): - return { - 'kind': 'pipeline', - 'type': 'docker', - 'name': name, - 'platform': { - 'os': 'linux', - 'arch': arch, - }, - # These volumes will be mounted at the build directory, allowing to - # run different premake toolchains from the same source tree - 'volumes': [ - { - 'name': 'build-premake', - 'temp': {}, - }, - { - 'name': 'build-cmake', - 'temp': {}, - }, - ], - - 'steps': [ - # - # Setup the source tree - # - { - 'name': 'clone-submodules', - 'image': image, - 'commands': [ - 'pwd', - # May miss recursive submodules (but faster than xb setup) - 'git submodule update --init --depth 1 -j $(nproc)', - ], - }, - - - # - # Setup the two build systems - # - - # Native premake Makefiles for production - { - 'name': 'toolchain-premake', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - command_cc(cc), - '$CXX --version', - 'python3 --version', - './xenia-build premake --cc={}'.format(cc), - ], - 'depends_on': ['clone-submodules'], - }, - - # Development toolchain - { - 'name': 'toolchain-cmake', - 'image': image, - 'volumes': [volume_build('cmake')], - 'commands': [ - command_cc(cc), - ''' - ./xenia-build premake --cc={} --devenv=cmake - cd build - for c in Debug Release - do - mkdir cmake-$c - cmake -S . -B cmake-$c -G Ninja -DCMAKE_BUILD_TYPE=$c - done - '''.format(cc), - ], - # Premake itself needs to be build first: - 'depends_on': ['toolchain-premake'], - }, - - # - # Building - # - - { - 'name': 'build-premake-debug-tests', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - command_cc(cc), - './xenia-build build --no_premake -j$(nproc) --config=Debug --target=xenia-base-tests', - ], - 'depends_on': ['toolchain-premake'], - }, - { - 'name': 'build-premake-debug-all', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - command_cc(cc), - './xenia-build build --no_premake -j$(nproc) --config=Debug', - ], - 'depends_on': ['build-premake-debug-tests'], - }, - - { - 'name': 'build-premake-release-tests', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - command_cc(cc), - './xenia-build build --no_premake -j$(nproc) --config=Release --target=xenia-base-tests', - ], - 'depends_on': ['toolchain-premake'], - }, - ] + ([ - { - 'name': 'build-premake-release-all', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - command_cc(cc), - './xenia-build build --no_premake -j$(nproc) --config=Release', - ], - 'depends_on': ['build-premake-release-tests'], - }, - ] if build_release_all else []) + [ - - { - 'name': 'build-cmake-debug-all', - 'image': image, - 'volumes': [volume_build('cmake')], - 'commands': [ - command_cc(cc), - 'cd build/cmake-Debug', - 'cmake --build . -j$(nproc)', - ], - 'depends_on': ['toolchain-cmake'], - }, - - { - 'name': 'build-cmake-release-tests', - 'image': image, - 'volumes': [volume_build('cmake')], - 'commands': [ - command_cc(cc), - 'cd build/cmake-Release', - 'cmake --build . -j$(nproc) --target xenia-base-tests', - ], - 'depends_on': ['toolchain-cmake'], - }, - ] + ([ - { - 'name': 'build-cmake-release-all', - 'image': image, - 'volumes': [volume_build('cmake')], - 'commands': [ - command_cc(cc), - 'cd build/cmake-Release', - 'cmake --build . -j$(nproc)', - ], - 'depends_on': ['build-cmake-release-tests'], - }, - ] if build_release_all else []) + [ - - - # - # Tests - # - - { - 'name': 'test-premake-debug-valgrind', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - 'valgrind --error-exitcode=99 ./build/bin/Linux/Debug/xenia-base-tests --durations yes ' + xenia_base_tests_filters(), - ], - 'depends_on': ['build-premake-debug-tests'], - }, - - { - 'name': 'test-premake-release', - 'image': image, - 'volumes': [volume_build('premake')], - 'commands': [ - './build/bin/Linux/Release/xenia-base-tests --success --durations yes ' + xenia_base_tests_filters(), - ], - 'depends_on': ['build-premake-release-tests'], - }, - - { - 'name': 'test-cmake-release', - 'image': image, - 'volumes': [volume_build('cmake')], - 'commands': [ - './build/bin/Linux/Release/xenia-base-tests --success --durations yes ' + xenia_base_tests_filters(), - ], - 'depends_on': ['build-cmake-release-tests'], - }, - - - # - # Stat - # - - { - 'name': 'stat', - 'image': image, - 'volumes': [ - volume_build('premake', '/build-premake'), - volume_build('cmake', '/build-cmake'), - ], - 'commands': [ - ''' - header() { - SEP='============================================================' - echo - echo $SEP - echo $@ - echo $SEP - } - - for v in premake cmake - do - for c in Debug Release - do - header $v $c - p=/build-$v/bin/Linux/$c - ls -la $p - sha256sum $p/* - done - done - ''' - ], - 'depends_on': [ - 'build-premake-debug-all', - 'build-cmake-debug-all', - ] + ([ - 'build-premake-release-all', - 'build-cmake-release-all', - ] if build_release_all else [ - 'build-premake-release-tests', - 'build-cmake-release-tests', - ]), - }, - ], - } - - -def pipeline_android(name, image, arch, platform): - return { - 'kind': 'pipeline', - 'type': 'docker', - 'name': name, - 'platform': { - 'os': 'linux', - 'arch': arch, - }, - - 'steps': [ - # - # Setup the source tree - # - { - 'name': 'clone-submodules', - 'image': image, - 'commands': [ - 'pwd', - # May miss recursive submodules (but faster than xb setup) - 'git submodule update --init --depth 1 -j $(nproc)', - ], - }, - - - # - # Build premake and generate NDK makefiles - # - - # NDK Makefiles - { - 'name': 'toolchain', - 'image': image, - 'commands': [ - 'c++ --version', - 'python3 --version', - './xenia-build premake --target_os android', - ], - 'depends_on': ['clone-submodules'], - }, - - - # - # Building - # - { - 'name': 'build-debug', - 'image': image, - 'commands': [ - 'cd build', - command_ndk_build(platform, 'Debug', 'all'), - ], - 'depends_on': ['toolchain'], - }, - - { - 'name': 'build-release', - 'image': image, - 'commands': [ - 'cd build', - command_ndk_build(platform, 'Release', 'all'), - ], - 'depends_on': ['toolchain'], - }, - - - # - # Stat - # - { - 'name': 'stat', - 'image': image, - 'commands': [ - ''' - header() { - SEP='============================================================' - echo - echo $SEP - echo $@ - echo $SEP - } - - for c in Debug Release - do - header $c - p=build/bin/$c/obj/local/* - ls -la $p - sha256sum $p/* || true - done - ''' - ], - 'depends_on': [ - 'build-debug', - 'build-release', - ], - }, - ], - } diff --git a/.github/workflows/Check_commit_message.yml b/.github/workflows/Check_commit_message.yml new file mode 100644 index 000000000..f84d60828 --- /dev/null +++ b/.github/workflows/Check_commit_message.yml @@ -0,0 +1,56 @@ +name: Commit Message Check + +on: + workflow_call: + +jobs: + commit-message: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Validate commit messages + run: | + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + + COMMITS=$(git log --format="%H %s" "${BASE}..${HEAD}" --) + + if [ -z "${COMMITS}" ]; then + echo "No commits found in this PR." + exit 0 + fi + + FAILED=0 + while IFS= read -r LINE; do + SHA="${LINE%% *}" + MSG="${LINE#* }" + SHORT="${SHA::7}" + + if echo "${MSG}" | grep -qP '^\[.+?\]'; then + echo "✅ ${SHORT}: ${MSG}" + else + echo "❌ ${SHORT}: ${MSG}" + echo "::error::Commit ${SHORT} is missing a [Tag] prefix. Expected format: [Tag] Description (e.g. [CPU] Fix overflow in JIT)" + FAILED=1 + fi + done <<< "${COMMITS}" + + echo "" + + if [ "${FAILED}" -eq 1 ]; then + echo "::error::One or more commits are missing a [Tag] prefix." + echo "" + echo "Expected format: [Tag] Description" + echo "Examples: [CPU] " + echo " [GPU] " + echo " [UI] " + echo " [CI] " + exit 1 + fi + + echo "All commit messages have a valid [Tag] prefix." diff --git a/.github/workflows/Create_release.yml b/.github/workflows/Create_release.yml index 9c83a40da..694f89537 100644 --- a/.github/workflows/Create_release.yml +++ b/.github/workflows/Create_release.yml @@ -1,59 +1,169 @@ -name: Create release +name: Create Release on: workflow_call: inputs: - os: + tag: + description: 'Full commit SHA for tagging' required: true type: string - secrets: - RELEASE_TOKEN: - required: true + branch: + description: 'Branch name used as release tag suffix (e.g. canary_experimental)' + required: false + type: string + default: 'canary_experimental' jobs: release: - name: Release runs-on: ubuntu-latest + + permissions: + contents: write + steps: - #- uses: actions/checkout@main - # with: - # repository: ${{ github.repository_owner }}/xenia-canary-releases - - uses: actions/download-artifact@main - - name: Release + # Checkout for git log access — no submodules needed + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Build release notes + id: meta env: - GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} - GH_REPO: ${{ github.repository_owner }}/xenia-canary-releases - notes: ${{ github.event.head_commit.message }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} run: | - case ${{ inputs.os }} in - windows) - asset=xenia_canary_${{ inputs.os }}.zip - 7z a $asset -xr!'*.pdb' -mx9 -bb3 - ;; - linux) - asset=xenia_canary_${{ inputs.os }}.tar.xz - ;; - esac - if [ ! -f $asset ]; then - ls -R - echo "::error::$asset doesn't exist!" - exit 1 + FULL_SHA="${{ inputs.tag }}" + SHORT_SHA="${FULL_SHA::7}" + BRANCH="${{ inputs.branch }}" + TAG_NAME="${SHORT_SHA}_${BRANCH}" + + echo "tag_name=${TAG_NAME}" >> "$GITHUB_OUTPUT" + + PREV_TAG=$(gh release list \ + --repo "${REPO}" \ + --limit 1 \ + --json tagName \ + --jq '.[0].tagName' 2>/dev/null || echo "") + + if [ -n "${PREV_TAG}" ]; then + PREV_SHA=$(git rev-parse "${PREV_TAG}^{}" 2>/dev/null || \ + git rev-parse "${PREV_TAG}" 2>/dev/null || echo "") fi - if [ $(stat -c%s $asset) -lt 100000 ]; then - ls -R - echo "::error::$asset is too small!" - exit 1 + + if [ -n "${PREV_SHA}" ]; then + COMMITS=$(git log --format="- %s (\`%h\`)" --abbrev=7 "${PREV_SHA}..${FULL_SHA}" --) + COMPARE_URL="https://github.com/${REPO}/compare/${PREV_TAG}...${TAG_NAME}" + else + COMMITS=$(git log --format="- %s (\`%h\`)" --abbrev=7 -1 "${FULL_SHA}" --) + COMPARE_URL="" fi - create_or_edit_release() { - local tag=$1 - local title=$2 - if gh release view $tag; then - gh release edit $tag -t $title -n "$notes" - gh release upload $tag $asset --clobber - else - gh release create $tag $asset --target 925ed98d5dce604b651027c36fb522dc1ff0fa55 -t $title -n "$notes" + + # Assemble body + { + echo "body<> "$GITHUB_OUTPUT" + + # --- Download artifacts only for platforms that succeeded --- + + - name: Download Windows artifacts + uses: actions/download-artifact@v8 + with: + name: xenia_canary_windows + path: artifacts/windows/xenia_canary + + - name: Download Linux artifacts + uses: actions/download-artifact@v8 + with: + name: xenia_canary_linux.tar.xz + path: artifacts + + # Uncomment when platforms are enabled: + # - name: Download macOS artifacts + # uses: actions/download-artifact@v8 + # with: + # name: xenia_canary_macos + # path: artifacts/macos + + # - name: Download Android artifacts + # uses: actions/download-artifact@v8 + # with: + # name: xenia_canary_android + # path: artifacts/android + + # --- Package everything into release assets --- + + - name: Package release assets + run: | + mkdir -p release_assets + + # Windows + if [ -d "artifacts/windows/xenia_canary" ]; then + cd artifacts/windows/xenia_canary + zip -r ../../../release_assets/xenia_canary_windows.zip . -x "*.pdb" + cd ../../.. + fi + + # Linux (already tar.gz) + if [ -f "artifacts/xenia_canary_linux.tar.xz" ]; then + cp artifacts/xenia_canary_linux.tar.xz release_assets/ + fi + + # macOS (uncomment when enabled) + # if [ -f "artifacts/macos/xenia_canary_macos.tar.gz" ]; then + # cp artifacts/macos/xenia_canary_macos.tar.gz release_assets/ + # fi + + # Android (uncomment when enabled) + # if [ -f "artifacts/android/xenia_canary_android.zip" ]; then + # cp artifacts/android/xenia_canary_android.zip release_assets/ + # fi + + echo "=== Release assets ===" + ls -lh release_assets/ + + # --- Create the release --- + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + TAG: ${{ steps.meta.outputs.tag_name }} + BODY: ${{ steps.meta.outputs.body }} + TARGET: ${{ inputs.tag }} + run: | + echo "${BODY}" > release_notes.md + echo "Creating release: ${TAG}" + + # Check if tag/release already exists (re-run safety) + if gh release view "${TAG}" --repo "${REPO}" --json tagName 2>/dev/null; then + echo "Release ${TAG} exists, uploading new assets..." + gh release upload "${TAG}" \ + --repo "${REPO}" \ + --clobber \ + release_assets/* + else + gh release create "${TAG}" \ + --repo "${REPO}" \ + --target "${{ inputs.tag }}" \ + --title "${TAG}" \ + --notes-file release_notes.md \ + --notes "${BODY}" \ + --latest \ + release_assets/* + fi + + echo "✅ Release ${TAG} published" diff --git a/.github/workflows/Lint.yml b/.github/workflows/Lint.yml new file mode 100644 index 000000000..65b59c294 --- /dev/null +++ b/.github/workflows/Lint.yml @@ -0,0 +1,29 @@ +name: Lint + +on: + workflow_call: + +jobs: + lint: + name: Lint + runs-on: ubuntu-24.04 + outputs: + #LLVM_VERSION: ${{ steps.setup.outputs.LLVM_VERSION }} + UBUNTU_BASE: ${{ steps.setup.outputs.UBUNTU_BASE }} + steps: + - uses: actions/checkout@v6 + - name: Setup + id: setup + env: + LLVM_VERSION: 20 + run: | + UBUNTU_BASE=$(lsb_release -cs) + #echo "LLVM_VERSION=$LLVM_VERSION" >> "$GITHUB_OUTPUT" + echo "UBUNTU_BASE=$UBUNTU_BASE" >> "$GITHUB_OUTPUT" + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-$LLVM_VERSION main" + sudo apt-get -y update + sudo apt-get -y install clang-format-$LLVM_VERSION + - name: Lint + run: ./xenia-build.py lint --all + diff --git a/.github/workflows/Linux_build.yml b/.github/workflows/Linux_build.yml deleted file mode 100644 index 86c64167a..000000000 --- a/.github/workflows/Linux_build.yml +++ /dev/null @@ -1,184 +0,0 @@ -name: Linux build - -on: - push: - paths-ignore: - - '.clang-format' - - '.drone.star' - - '.gitattributes' - - '.gitignore' - - '.github/*' - - '.github/workflows/Windows_build.yml' - - '.github/*_TEMPLATE/**' - - '*.bat' - - '*.md' - - '*.ps1' - - '*.txt' - - '*.yml' - - 'docs/**' - - 'src/**/*_windows.*' - - 'src/**/*_android.*' - - 'src/**/*_mac.*' - - 'LICENSE' - pull_request: - paths-ignore: - - '.clang-format' - - '.drone.star' - - '.gitattributes' - - '.gitignore' - - '.github/*' - - '.github/workflows/Windows_build.yml' - - '.github/*_TEMPLATE/**' - - '*.bat' - - '*.md' - - '*.ps1' - - '*.txt' - - '*.yml' - - 'docs/**' - - 'src/**/*_windows.*' - - 'src/**/*_android.*' - - 'src/**/*_mac.*' - - 'LICENSE' - workflow_dispatch: - -jobs: - lint: - name: Lint - runs-on: ubuntu-24.04 - outputs: - #LLVM_VERSION: ${{ steps.setup.outputs.LLVM_VERSION }} - UBUNTU_BASE: ${{ steps.setup.outputs.UBUNTU_BASE }} - steps: - - uses: actions/checkout@main - - name: Setup - id: setup - env: - LLVM_VERSION: 20 - run: | - UBUNTU_BASE=$(lsb_release -cs) - #echo "LLVM_VERSION=$LLVM_VERSION" >> "$GITHUB_OUTPUT" - echo "UBUNTU_BASE=$UBUNTU_BASE" >> "$GITHUB_OUTPUT" - wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc - sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-$LLVM_VERSION main" - sudo apt-get -y update - sudo apt-get -y install clang-format-$LLVM_VERSION - - name: Lint - run: ./xenia-build.py lint --all - - build-clang: - name: Build (Clang ${{ matrix.LLVM_VERSION }}) - needs: lint - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - LLVM_VERSION: [20] # '${{ needs.lint.outputs.LLVM_VERSION }}' - steps: - - uses: actions/checkout@main - with: - fetch-depth: 0 - - name: Cache Vulkan SDK - id: cache-vulkan-sdk-linux - uses: actions/cache@v4 - with: - path: ~/vulkan-sdk - key: ${{ runner.os }}-vulkan-sdk-latest - - name: Setup - env: - UBUNTU_BASE: ${{ needs.lint.outputs.UBUNTU_BASE }} - run: | - wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc - sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-${{ matrix.LLVM_VERSION }} main" - sudo apt-get -y update - sudo apt-get -y install mesa-vulkan-drivers valgrind libc++-dev libc++abi-dev libgtk-3-dev libsdl2-dev libvulkan-dev libx11-xcb-dev clang-${{ matrix.LLVM_VERSION }} lld-${{ matrix.LLVM_VERSION }} ninja-build spirv-tools cmake - - # Install Vulkan SDK - if [ '${{ steps.cache-vulkan-sdk-linux.outputs.cache-hit }}' != 'true' ]; then - wget -qO vulkan-sdk.tar.xz https://sdk.lunarg.com/sdk/download/latest/linux/vulkan-sdk.tar.xz - mkdir -p ~/vulkan-sdk - tar -xf vulkan-sdk.tar.xz -C ~/vulkan-sdk - fi - VULKAN_SDK_VERSION=$(ls ~/vulkan-sdk) - echo "VULKAN_SDK=$HOME/vulkan-sdk/$VULKAN_SDK_VERSION/x86_64" >> $GITHUB_ENV - echo "$HOME/vulkan-sdk/$VULKAN_SDK_VERSION/x86_64/bin" >> $GITHUB_PATH - - # Verify shader tools are available - which glslangValidator && glslangValidator --version || echo "Warning: glslangValidator not found" - which spirv-opt && spirv-opt --version || echo "Warning: spirv-opt not found" - which spirv-dis || echo "Warning: spirv-dis not found" - - git submodule update --init --depth=1 -j$(getconf _NPROCESSORS_ONLN) $(grep -oP '(?<=path = )(?!third_party\/DirectXShaderCompiler).+' .gitmodules) - - name: Build - env: - CC: clang-${{ matrix.LLVM_VERSION }} - CXX: clang++-${{ matrix.LLVM_VERSION }} - run: ./xenia-build.py build --config=Release - - name: Prepare artifacts - id: prepare_artifacts - run: | - binary=build/bin/Linux/Release/xenia_canary - if [ $(stat -c%s $binary) -le 100000 ]; then - echo "::error::Binary is too small." - fi - chmod +x $binary - mkdir -p artifacts - XZ_OPT=-e9 tar cJvpf artifacts/xenia_canary_linux.tar.xz $binary LICENSE - - name: Upload xenia canary artifacts - if: steps.prepare_artifacts.outcome == 'success' - uses: actions/upload-artifact@main - with: - name: xenia_canary_linux - path: artifacts - if-no-files-found: error - -# build-gcc: -# name: Build (GCC ${{ matrix.GCC_VERSION }}) -# needs: lint -# runs-on: ubuntu-24.04 -# strategy: -# fail-fast: false -# matrix: -# GCC_VERSION: [14] -# steps: -# - uses: actions/checkout@main -# with: -# fetch-depth: 0 -# - name: Setup -# run: | -# sudo apt-get -y update -# sudo apt-get -y install mesa-vulkan-drivers valgrind libc++-dev libc++abi-dev libgtk-3-dev libsdl2-dev libvulkan-dev libx11-xcb-dev g++-${{ matrix.GCC_VERSION }} -# ./xenia-build.py setup -# - name: Build -# env: -# CC: gcc-${{ matrix.GCC_VERSION }} -# CXX: g++-${{ matrix.GCC_VERSION }} -# # AR: ar -# run: ./xenia-build.py build --config=Release -# - name: Prepare artifacts -# id: prepare_artifacts -# run: | -# if [ $(stat -c %s build/bin/Linux/Release/xenia_canary) -le 100000 ]; then -# echo "::error::Binary is too small." -# fi -# mkdir -p artifacts -# cp -r build/bin/Linux/Release/xenia_canary LICENSE artifacts -# - name: Upload xenia canary artifacts -# if: steps.prepare_artifacts.outcome == 'success' -# uses: actions/upload-artifact@main -# with: -# name: xenia_canary_linux_gcc -# path: artifacts -# if-no-files-found: error - - create-release: - name: Create release - needs: [lint, build-clang] #build-gcc - if: | - github.repository == 'xenia-canary/xenia-canary' && - github.event.action != 'pull_request' && - github.ref == 'refs/heads/canary_experimental' - uses: ./.github/workflows/Create_release.yml - with: - os: linux - secrets: - RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} diff --git a/.github/workflows/Linux_x86.yml b/.github/workflows/Linux_x86.yml new file mode 100644 index 000000000..91aea1ecd --- /dev/null +++ b/.github/workflows/Linux_x86.yml @@ -0,0 +1,94 @@ +name: Linux Build + +on: + workflow_call: + inputs: + config: + description: 'Build configuration (Release)' + required: false + default: 'release' + type: string + +jobs: + build: + name: Build + runs-on: ubuntu-24.04 + env: + LLVM_VERSION: 20 + UBUNTU_BASE: noble # We're running on ubuntu-24.04. Remember to change it after changing deploy env. + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Cache Vulkan SDK + id: cache-vulkan-sdk-linux + uses: actions/cache@v5 + with: + path: ~/vulkan-sdk + key: ${{ runner.os }}-vulkan-sdk-latest + + - name: Setup build environment + run: | + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + sudo apt-add-repository "deb http://apt.llvm.org/${{ env.UBUNTU_BASE }}/ llvm-toolchain-${{ env.UBUNTU_BASE }}-${{ env.LLVM_VERSION }} main" + sudo apt-get -y update + sudo apt-get -y install mesa-vulkan-drivers valgrind libc++-dev libc++abi-dev libgtk-3-dev libsdl2-dev libvulkan-dev libx11-xcb-dev clang-${{ env.LLVM_VERSION }} lld-${{ env.LLVM_VERSION }} ninja-build cmake spirv-tools + + # Pin clang to the correct version + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${{ env.LLVM_VERSION }} 200 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${{ env.LLVM_VERSION }} 200 + - name: Install Vulkan SDK + run: | + # Install Vulkan SDK + if [ '${{ steps.cache-vulkan-sdk-linux.outputs.cache-hit }}' != 'true' ]; then + wget -qO vulkan-sdk.tar.xz https://sdk.lunarg.com/sdk/download/latest/linux/vulkan-sdk.tar.xz + mkdir -p ~/vulkan-sdk + tar -xf vulkan-sdk.tar.xz -C ~/vulkan-sdk + fi + + VULKAN_SDK_VERSION=$(ls ~/vulkan-sdk) + echo "VULKAN_SDK=$HOME/vulkan-sdk/$VULKAN_SDK_VERSION/x86_64" >> $GITHUB_ENV + echo "$HOME/vulkan-sdk/$VULKAN_SDK_VERSION/x86_64/bin" >> $GITHUB_PATH + + # Verify shader tools are available + for tool in glslangValidator spirv-opt spirv-dis; do + which "$tool" && "$tool" --version 2>/dev/null || echo "Warning: $tool not found" + done + + - name: Download submodules + run: | + # Exclude not needed 3pp modules + EXCLUDE="DirectXShaderCompiler" + SUBMODULES=$(grep -oP '(?<=path = ).+' .gitmodules | grep -vE "$EXCLUDE") + git submodule update --init --depth=1 -j$(nproc) $SUBMODULES + + - name: Build Xenia + env: + CC: clang-${{ env.LLVM_VERSION }} + CXX: clang++-${{ env.LLVM_VERSION }} + run: ./xenia-build.py build --config=Release + + - name: Prepare artifacts + id: prepare_artifacts + run: | + binary=build/bin/Linux/Release/xenia_canary + if [ $(stat -c%s $binary) -le 100000 ]; then + echo "::error::Binary is too small." + exit 1 + fi + chmod +x $binary + mkdir -p artifacts + XZ_OPT=-e9 tar cJvpf artifacts/xenia_canary_linux.tar.xz --transform='s|build/bin/Linux/Release/||' $binary LICENSE + + - name: Upload Xenia Canary artifact + if: steps.prepare_artifacts.outcome == 'success' + uses: actions/upload-artifact@v7 + with: + name: xenia_canary_linux.tar.xz + path: artifacts + if-no-files-found: error + retention-days: 7 + archive: false diff --git a/.github/workflows/Orchestrator.yml b/.github/workflows/Orchestrator.yml new file mode 100644 index 000000000..b144c01be --- /dev/null +++ b/.github/workflows/Orchestrator.yml @@ -0,0 +1,88 @@ +name: Orchestrator + +on: + push: + paths-ignore: + - '*.md' + - 'docs/**' + - 'LICENSE' + pull_request: + paths-ignore: + - '*.md' + - 'docs/**' + - 'LICENSE' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # =========================================================================== + # Pre-requirements + # =========================================================================== + commit-message: + name: Commit Message Validation + if: github.event_name == 'pull_request' + uses: ./.github/workflows/Check_commit_message.yml + + lint: + name: Lint + uses: ./.github/workflows/Lint.yml + + # Add optional steps here + + # =========================================================================== + # Stage 2: Platform builds + # =========================================================================== + build-windows: + name: Windows (x86-64) + needs: [lint, commit-message] + if: ${{ !failure() && !cancelled() }} + uses: ./.github/workflows/Windows_x86.yml + + build-linux: + name: Linux (x86-64) + needs: [lint, commit-message] + if: ${{ !failure() && !cancelled() }} + uses: ./.github/workflows/Linux_x86.yml + + # Uncomment when platform support is ready: + # build-windows-arm64: + # name: Windows-ARM64 + # needs: [lint] + # uses: ./.github/workflows/build-win_arm64.yml + + # build-linux-arm64: + # name: Linux-ARM64 + # needs: [lint] + # uses: ./.github/workflows/build-linux_arm64.yml + + # build-macos: + # name: macOS + # needs: [lint] + # uses: ./.github/workflows/build-macos.yml + + # build-android: + # name: Android + # needs: [lint] + # uses: ./.github/workflows/build-android.yml + + # =========================================================================== + # Stage 3: Release + # =========================================================================== + release: + name: Create Release + needs: [build-windows, build-linux] + if: | + always() && + github.repository == 'xenia-canary/xenia-canary' && + github.event_name == 'push' && + github.ref == 'refs/heads/canary_experimental' && + (needs.build-windows.result == 'success' && needs.build-linux.result == 'success') + uses: ./.github/workflows/Create_release.yml + permissions: + contents: write + secrets: inherit + with: + tag: ${{ github.sha }} + branch: ${{ github.ref_name }} diff --git a/.github/workflows/Windows_build.yml b/.github/workflows/Windows_build.yml deleted file mode 100644 index c64c50561..000000000 --- a/.github/workflows/Windows_build.yml +++ /dev/null @@ -1,159 +0,0 @@ -name: Windows build - -on: - push: - paths-ignore: - - '.clang-format' - - '.drone.star' - - '.gitattributes' - - '.gitignore' - - '.gdbinit' - - '.github/*' - - '.github/workflows/Linux_build.yml' - - '.github/*_TEMPLATE/**' - - '*.md' - - '*.yml' - - '*.txt' - - 'docs/**' - - 'src/**/*_posix.*' - - 'src/**/*_linux.*' - - 'src/**/*_gnulinux.*' - - 'src/**/*_x11.*' - - 'src/**/*_gtk.*' - - 'src/**/*_android.*' - - 'src/**/*_mac.*' - - 'LICENSE' - pull_request: - paths-ignore: - - '.clang-format' - - '.drone.star' - - '.gitattributes' - - '.gitignore' - - '.gdbinit' - - '.github/*' - - '.github/workflows/Linux_build.yml' - - '.github/*_TEMPLATE/**' - - '*.md' - - '*.yml' - - '*.txt' - - 'docs/**' - - 'src/**/*_posix.*' - - 'src/**/*_linux.*' - - 'src/**/*_gnulinux.*' - - 'src/**/*_x11.*' - - 'src/**/*_gtk.*' - - 'src/**/*_android.*' - - 'src/**/*_mac.*' - - 'LICENSE' - workflow_dispatch: - -jobs: - lint: - name: Lint - runs-on: windows-latest - env: - POWERSHELL_TELEMETRY_OPTOUT: 1 - steps: - - uses: actions/checkout@main - - name: Lint - run: python xenia-build.py lint --all - - build: - name: Build - needs: lint - runs-on: windows-2025 - env: - POWERSHELL_TELEMETRY_OPTOUT: 1 - steps: - - uses: actions/checkout@main - with: - fetch-depth: 0 - - name: Cache Vulkan SDK - id: cache-vulkan-sdk - uses: actions/cache@v4 - with: - path: C:\VulkanSDK - key: ${{ runner.os }}-vulkan-sdk-${{ hashFiles('**/vulkan-sdk.exe') }} - restore-keys: | - ${{ runner.os }}-vulkan-sdk- - - name: Setup - run: | - # Install Vulkan SDK which includes spirv-tools - if (Test-Path -Path "C:\VulkanSDK") { - echo "Vulkan SDK found in cache." - } else { - Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe" -OutFile "vulkan-sdk.exe" - Start-Process -FilePath "vulkan-sdk.exe" -ArgumentList "--accept-licenses", "--default-answer", "--confirm-command", "install" -Wait - } - $env:VULKAN_SDK = "C:\VulkanSDK\$(Get-ChildItem -Path 'C:\VulkanSDK' -Directory | Select-Object -First 1 -ExpandProperty Name)" - $env:PATH = "$env:VULKAN_SDK\Bin;$env:PATH" - echo "VULKAN_SDK=$env:VULKAN_SDK" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "$env:VULKAN_SDK\Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - # Verify shader tools are available - $spirvOptPath = "$env:VULKAN_SDK\Bin\spirv-opt.exe" - if (Test-Path $spirvOptPath) { - & $spirvOptPath --version - echo "spirv-opt found at: $spirvOptPath" - } else { - echo "Warning: spirv-opt.exe not found at expected location" - } - - $glslangPath = "$env:VULKAN_SDK\Bin\glslangValidator.exe" - if (Test-Path $glslangPath) { - & $glslangPath --version - echo "glslangValidator found at: $glslangPath" - } else { - echo "Warning: glslangValidator.exe not found at expected location" - } - - $spirvDisPath = "$env:VULKAN_SDK\Bin\spirv-dis.exe" - if (Test-Path $spirvDisPath) { - echo "spirv-dis found at: $spirvDisPath" - } else { - echo "Warning: spirv-dis.exe not found at expected location" - } - - # Verify FXC is available (from Windows SDK) - $fxcPaths = Get-ChildItem -Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\fxc.exe" -ErrorAction SilentlyContinue | Sort-Object FullName - if ($fxcPaths) { - $fxcPath = $fxcPaths[-1].FullName - echo "FXC found at: $fxcPath" - } else { - echo "Warning: fxc.exe not found in Windows SDK" - } - - git submodule update --init --depth=1 -j $env:NUMBER_OF_PROCESSORS (Select-String -CaseSensitive '(?<=path = ).+' .gitmodules).Matches.Value - - name: Build - run: python xenia-build.py build --config=Release --target=xenia-app - - name: Prepare artifacts - id: prepare_artifacts - run: | - foreach ($file in 'build\bin\Windows\Release\xenia_canary.exe') { - if ((get-item $file).Length -le 100000) { - echo "::error::$file is too small." - } - } - robocopy . build\bin\Windows\Release LICENSE /r:0 /w:0 - robocopy build\bin\Windows\Release artifacts\xenia_canary xenia_canary.exe LICENSE /r:0 /w:0 - If ($LastExitCode -le 7) { echo "LastExitCode = $LastExitCode";$LastExitCode = 0 } - - name: Upload xenia canary artifacts - if: steps.prepare_artifacts.outcome == 'success' - uses: actions/upload-artifact@main - with: - name: xenia_canary_windows - path: artifacts\xenia_canary - if-no-files-found: error - - create-release: - name: Create release - needs: [lint, build] - if: | - github.repository == 'xenia-canary/xenia-canary' && - github.event.action != 'pull_request' && - github.ref == 'refs/heads/canary_experimental' - uses: ./.github/workflows/Create_release.yml - with: - os: windows - secrets: - RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} diff --git a/.github/workflows/Windows_x86.yml b/.github/workflows/Windows_x86.yml new file mode 100644 index 000000000..82dbdddd8 --- /dev/null +++ b/.github/workflows/Windows_x86.yml @@ -0,0 +1,92 @@ +name: Windows (x86-64) + +on: + workflow_call: + inputs: + config: + description: 'Build configuration (Release)' + required: false + default: 'release' + type: string + +jobs: + build: + runs-on: windows-2025 + + env: + POWERSHELL_TELEMETRY_OPTOUT: 1 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Cache Vulkan SDK + id: cache-vulkan-sdk + uses: actions/cache@v5 + with: + path: C:\VulkanSDK + key: ${{ runner.os }}-vulkan-sdk-${{ hashFiles('**/vulkan-sdk.exe') }} + restore-keys: | + ${{ runner.os }}-vulkan-sdk- + + - name: Install Vulkan SDK + run: | + # Install Vulkan SDK with spirv-tools + if (Test-Path -Path "C:\VulkanSDK") { + echo "Vulkan SDK found in cache." + } else { + Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe" -OutFile "vulkan-sdk.exe" + Start-Process -FilePath "vulkan-sdk.exe" -ArgumentList "--accept-licenses", "--default-answer", "--confirm-command", "install" -Wait + } + $env:VULKAN_SDK = "C:\VulkanSDK\$(Get-ChildItem -Path 'C:\VulkanSDK' -Directory | Select-Object -First 1 -ExpandProperty Name)" + $env:PATH = "$env:VULKAN_SDK\Bin;$env:PATH" + echo "VULKAN_SDK=$env:VULKAN_SDK" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "$env:VULKAN_SDK\Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + # Verify shader tools are available + foreach ($tool in @("glslangValidator", "spirv-opt", "spirv-dis")) { + $toolPath = "$env:VULKAN_SDK\Bin\$tool.exe" + if (Test-Path $toolPath) { + echo "$tool found at: $toolPath" + & $toolPath --version 2>$null + } else { + echo "Warning: $tool.exe not found at expected location" + } + } + + # Verify FXC is available (from Windows SDK) + $fxcPaths = Get-ChildItem -Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\fxc.exe" -ErrorAction SilentlyContinue | Sort-Object FullName + if ($fxcPaths) { + $fxcPath = $fxcPaths[-1].FullName + echo "FXC found at: $fxcPath" + } else { + echo "Warning: fxc.exe not found in Windows SDK" + } + + - name: Download submodules + run: git submodule update --init --depth=1 -j $env:NUMBER_OF_PROCESSORS + + - name: Build Xenia + run: python xenia-build.py build --config=Release --target=xenia-app + + - name: Prepare artifacts + id: prepare_artifacts + run: | + if ((Get-Item 'build\bin\Windows\Release\xenia_canary.exe').Length -le 100000) { + echo "::error:: Executable is too small." + exit 1 + } + robocopy . build\bin\Windows\Release LICENSE /r:0 /w:0 + robocopy build\bin\Windows\Release artifacts\xenia_canary xenia_canary.exe LICENSE /r:0 /w:0 + If ($LastExitCode -le 7) { echo "LastExitCode = $LastExitCode";$LastExitCode = 0 } + + - name: Upload Xenia Canary artifact + if: steps.prepare_artifacts.outcome == 'success' + uses: actions/upload-artifact@v7 + with: + name: xenia_canary_windows + path: artifacts\xenia_canary + if-no-files-found: error + retention-days: 7