diff --git a/.github/scripts/sync-optional-submodules.sh b/.github/scripts/sync-optional-submodules.sh new file mode 100644 index 0000000000..8df3b9e942 --- /dev/null +++ b/.github/scripts/sync-optional-submodules.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +set -euo pipefail + +mode="init" +depth="" +declare -a paths=() + +while (($# > 0)); do + case "$1" in + --init) + mode="init" + shift + ;; + --remote) + mode="remote" + shift + ;; + --depth) + depth="$2" + shift 2 + ;; + --) + shift + paths+=("$@") + break + ;; + *) + paths+=("$1") + shift + ;; + esac +done + +if ((${#paths[@]} == 0)); then + echo "Usage: $0 [--init|--remote] [--depth N] path [path ...]" >&2 + exit 64 +fi + +is_submodule_path() { + local path="$1" + + git config -f .gitmodules --get-regexp '^submodule\..*\.path$' 2>/dev/null \ + | awk '{ print $2 }' \ + | grep -Fxq "$path" +} + +for path in "${paths[@]}"; do + if ! is_submodule_path "$path"; then + echo "Skipping $path: not configured as a submodule in .gitmodules." + continue + fi + + if [[ "$mode" == "remote" ]]; then + echo "Updating submodule: $path" + git submodule update --remote "$path" + continue + fi + + if [[ -n "$depth" ]]; then + echo "Initializing submodule: $path (depth=$depth)" + git submodule update --init --depth "$depth" "$path" + continue + fi + + echo "Initializing submodule: $path" + git submodule update --init "$path" +done diff --git a/.github/workflows/ci-avalonia.yml b/.github/workflows/ci-avalonia.yml new file mode 100644 index 0000000000..5b1670cab0 --- /dev/null +++ b/.github/workflows/ci-avalonia.yml @@ -0,0 +1,189 @@ +name: Build MAAUnified (Avalonia + MaaCore Runtime) + +on: + workflow_dispatch: + pull_request: + paths: + - "src/MAAUnified" + - "src/MAAUnified/**" + - "src/MaaCore/**" + - "src/MaaUtils/**" + - "include/**" + - "resource/**" + - "tools/maadeps-download.py" + - "CMakeLists.txt" + - "CMakePresets.json" + push: + branches: + - dev + paths: + - "src/MAAUnified" + - "src/MAAUnified/**" + - "src/MaaCore/**" + - "src/MaaUtils/**" + - "include/**" + - "resource/**" + - "tools/maadeps-download.py" + - "CMakeLists.txt" + - "CMakePresets.json" + +jobs: + meta: + name: Resolve version tag + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.out.outputs.tag }} + steps: + - id: out + run: | + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" + else + echo "tag=preview-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" + fi + + build: + name: Build ${{ matrix.name }} + needs: meta + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: windows-x64 + os: windows-latest + rid: win-x64 + self_contained: true + cmake_preset: windows-publish-x64 + maadeps_triplet: x64-windows + - name: linux-x64 + os: ubuntu-latest + rid: linux-x64 + self_contained: true + cmake_preset: linux-publish-x64 + maadeps_triplet: x64-linux + - name: macos-x64 + os: macos-latest + rid: osx-x64 + self_contained: true + cmake_preset: macos-publish-x64 + maadeps_triplet: x64-osx + + steps: + - uses: actions/checkout@v6 + + - name: Fetch required submodules + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MAAUnified src/MaaUtils + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: "10.0.x" + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: "3.x" + + - name: Restore app + run: dotnet restore src/MAAUnified/App/MAAUnified.App.csproj + + - name: Restore tests + if: matrix.name != 'macos-x64' + run: dotnet restore src/MAAUnified/Tests/MAAUnified.Tests.csproj + + - name: Run Linux baseline consistency gate + if: matrix.name == 'linux-x64' + run: > + dotnet test src/MAAUnified/Tests/MAAUnified.Tests.csproj -c Release --no-restore --disable-build-servers -m:1 + --results-directory TestResults/${{ matrix.name }} + --logger "trx;LogFileName=baseline-consistency.trx" + --filter "FullyQualifiedName~BaselineContractTests|FullyQualifiedName~BaselineCoverageTests|FullyQualifiedName~BaselineRenderSyncTests|FullyQualifiedName~ParityMatrixSyncTests" + + - name: Run Linux full MAAUnified test gate + if: matrix.name == 'linux-x64' + run: > + dotnet test src/MAAUnified/Tests/MAAUnified.Tests.csproj -c Release --no-restore --disable-build-servers -m:1 + --results-directory TestResults/${{ matrix.name }} + --logger "trx;LogFileName=full-maaunified-tests.trx" + + - name: Run Windows platform capability contract gate + if: matrix.name == 'windows-x64' + run: > + dotnet test src/MAAUnified/Tests/MAAUnified.Tests.csproj -c Release --no-restore --disable-build-servers -m:1 + --results-directory TestResults/${{ matrix.name }} + --logger "trx;LogFileName=platform-capability-contract.trx" + --filter "FullyQualifiedName~PlatformCapabilityContractTests" + + - name: Run Windows native capability smoke gate + if: matrix.name == 'windows-x64' + run: > + dotnet test src/MAAUnified/Tests/MAAUnified.Tests.csproj -c Release --no-restore --disable-build-servers -m:1 + --results-directory TestResults/${{ matrix.name }} + --logger "trx;LogFileName=platform-windows-native-smoke.trx" + --filter "FullyQualifiedName~PlatformWindowsNativeSmokeTests" + + - name: Upload test result artifacts on failure + if: failure() && matrix.name != 'macos-x64' + uses: actions/upload-artifact@v6 + with: + name: MAAUnified-TestResults-${{ matrix.name }} + path: TestResults/${{ matrix.name }}/*.trx + if-no-files-found: ignore + + - name: Bootstrap MaaDeps + run: python tools/maadeps-download.py ${{ matrix.maadeps_triplet }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Build MaaCore runtime + run: | + cmake --preset ${{ matrix.cmake_preset }} -DINSTALL_PYTHON=OFF -DMAA_HASH_VERSION='${{ needs.meta.outputs.tag }}' + cmake --build --preset ${{ matrix.cmake_preset }} + cmake --install build --config RelWithDebInfo + + - name: Publish MAAUnified app + run: dotnet publish src/MAAUnified/App/MAAUnified.App.csproj -c Release -r ${{ matrix.rid }} --self-contained ${{ matrix.self_contained }} -o publish + + - name: Merge MaaCore runtime (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + Copy-Item install\* publish\ -Recurse -Force + if (!(Test-Path "publish\MaaCore.dll")) { throw "MaaCore.dll not found in publish output." } + if (!(Test-Path "publish\resource")) { throw "resource directory not found in publish output." } + + - name: Merge MaaCore runtime (Unix) + if: runner.os != 'Windows' + shell: bash + run: | + cp -a install/. publish/ + if [[ "$RUNNER_OS" == "Linux" ]]; then + test -f publish/libMaaCore.so + else + test -f publish/libMaaCore.dylib + fi + test -d publish/resource + + - name: Package (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + New-Item -ItemType Directory -Path release -Force | Out-Null + $name = "MAAUnified-${{ needs.meta.outputs.tag }}-${{ matrix.name }}" + Compress-Archive -Path publish\* -DestinationPath "release\$name.zip" + + - name: Package (Unix) + if: runner.os != 'Windows' + shell: bash + run: | + mkdir -p release + name="MAAUnified-${{ needs.meta.outputs.tag }}-${{ matrix.name }}" + tar -czf "release/${name}.tar.gz" -C publish . + + - name: Upload artifact + uses: actions/upload-artifact@v6 + with: + name: MAAUnified-${{ matrix.name }} + path: release/* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2c57b590b..b44e3fdf42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,9 +110,8 @@ jobs: show-progress: false - name: Fetch submodules - run: | - git submodule update --init --depth 1 src/MaaUtils - git submodule update --init --depth 1 3rdparty/EmulatorExtras + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MaaUtils 3rdparty/EmulatorExtras - name: Cache MaaDeps id: cache-maadeps @@ -241,10 +240,8 @@ jobs: show-progress: false - name: Fetch submodules - run: | - git submodule update --init --depth 1 src/MaaUtils - git submodule update --init --depth 1 3rdparty/EmulatorExtras - git submodule update --init --depth 1 src/maa-cli + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MaaUtils 3rdparty/EmulatorExtras src/maa-cli - name: Cache MaaDeps id: cache-maadeps @@ -348,8 +345,8 @@ jobs: show-progress: false - name: Fetch submodules - run: | - git submodule update --init --depth 1 src/MaaUtils + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MaaUtils # ninja 1.13.1 is already installed and up-to-date. # - name: Install dependencies diff --git a/.github/workflows/release-nightly-ota.yml b/.github/workflows/release-nightly-ota.yml index f3e1692bdf..b939c276ad 100644 --- a/.github/workflows/release-nightly-ota.yml +++ b/.github/workflows/release-nightly-ota.yml @@ -52,9 +52,8 @@ jobs: git fetch --depth=250 --tags - name: Fetch submodules - run: | - git submodule update --init --depth 1 src/MaaUtils - git submodule update --init --depth 1 3rdparty/EmulatorExtras + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MaaUtils 3rdparty/EmulatorExtras - name: Checkout ref (if provided) if: inputs.ref != '' diff --git a/.github/workflows/res-update-game.yml b/.github/workflows/res-update-game.yml index 57cd05a6cd..34d9c28b00 100644 --- a/.github/workflows/res-update-game.yml +++ b/.github/workflows/res-update-game.yml @@ -165,8 +165,8 @@ jobs: - name: Fetch submodules if: steps.resupd-cache.outputs.cache-hit != 'true' - run: | - git submodule update --init --depth 1 src/MaaUtils + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MaaUtils - name: Cache MaaDeps if: steps.resupd-cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/smoke-testing.yml b/.github/workflows/smoke-testing.yml index b8b09a1c80..6efef6574f 100644 --- a/.github/workflows/smoke-testing.yml +++ b/.github/workflows/smoke-testing.yml @@ -70,8 +70,8 @@ jobs: - name: Fetch submodules if: steps.smoke-cache.outputs.cache-hit != 'true' - run: | - git submodule update --init --depth 1 src/MaaUtils + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --init --depth 1 src/MaaUtils - name: Cache MaaDeps if: steps.smoke-cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/update-submodules.yml b/.github/workflows/update-submodules.yml index be243dbdd4..6e3c006092 100644 --- a/.github/workflows/update-submodules.yml +++ b/.github/workflows/update-submodules.yml @@ -17,15 +17,14 @@ jobs: submodules: true - name: Update submodules - run: | - git submodule update --remote src/MaaMacGui - git submodule update --remote src/maa-cli + shell: bash + run: bash ./.github/scripts/sync-optional-submodules.sh --remote src/MAAUnified src/MaaMacGui src/maa-cli - name: Commit and push changes uses: actions-js/push@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - message: "feat: Update Submodules MaaMacGui, maa-cli + message: "feat: Update Submodules MAAUnified, MaaMacGui, maa-cli https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/.gitmodules b/.gitmodules index ff83e318b0..40217fe452 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,7 @@ [submodule "src/MaaUtils"] path = src/MaaUtils url = https://github.com/MaaXYZ/MaaUtils +[submodule "src/MAAUnified"] + path = src/MAAUnified + url = https://github.com/MaaAssistantArknights/MaaUnified.git + branch = main diff --git a/src/MAAUnified b/src/MAAUnified new file mode 160000 index 0000000000..2544c5eeaf --- /dev/null +++ b/src/MAAUnified @@ -0,0 +1 @@ +Subproject commit 2544c5eeaf59b91c6c176f092bda7dbe123c7cbb