diff --git a/.github/ISSUE_TEMPLATE/blank_issue_template.yml b/.forgejo/ISSUE_TEMPLATE/blank_issue_template.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/blank_issue_template.yml rename to .forgejo/ISSUE_TEMPLATE/blank_issue_template.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.forgejo/ISSUE_TEMPLATE/bug_report.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/bug_report.yml rename to .forgejo/ISSUE_TEMPLATE/bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.forgejo/ISSUE_TEMPLATE/config.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/config.yml rename to .forgejo/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.forgejo/ISSUE_TEMPLATE/feature_request.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/feature_request.yml rename to .forgejo/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/workflows/android-build.yml b/.forgejo/workflows/android-build.yml similarity index 100% rename from .github/workflows/android-build.yml rename to .forgejo/workflows/android-build.yml diff --git a/.github/workflows/android-ea-play-release.yml b/.forgejo/workflows/android-ea-play-release.yml similarity index 100% rename from .github/workflows/android-ea-play-release.yml rename to .forgejo/workflows/android-ea-play-release.yml diff --git a/.github/workflows/android-mainline-play-release.yml b/.forgejo/workflows/android-mainline-play-release.yml similarity index 100% rename from .github/workflows/android-mainline-play-release.yml rename to .forgejo/workflows/android-mainline-play-release.yml diff --git a/.github/workflows/android-merge.js b/.forgejo/workflows/android-merge.js similarity index 100% rename from .github/workflows/android-merge.js rename to .forgejo/workflows/android-merge.js diff --git a/.github/workflows/android-publish.yml b/.forgejo/workflows/android-publish.yml similarity index 100% rename from .github/workflows/android-publish.yml rename to .forgejo/workflows/android-publish.yml diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000000..6be69600d9 --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2021 yuzu Emulator Project +# SPDX-FileCopyrightText: 2024 suyu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +# Actions Documentation: https://forgejo.org/docs/next/user/actions/#list-of-tasks-in-a-repository + +name: suyu-ci + +on: + push: + branches: [ "*" ] + tags: [ "*" ] + pull_request: + branches: [ "dev" ] + +jobs: +# We don't have transifex for now. +# transifex: +# runs-on: ubuntu-latest +# container: fijxu/build-environments:linux-transifex +# if: ${{ GITHUB_REPOSITORY == 'suyu/suyu' && !GITHUB_HEAD_REF }} +# steps: +# - uses: https://code.forgejo.org/actions/checkout@v3 +# with: +# submodules: recursive +# fetch-depth: 0 +# - name: Update Translation +# run: ./.ci/scripts/transifex/docker.sh +# env: +# TX_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }} + + reuse: + runs-on: ubuntu-latest + if: ${{ github.repository == 'suyu/suyu' }} + steps: + - uses: https://code.forgejo.org/actions/checkout@v3 + - uses: https://github.com/fsfe/reuse-action@v1 + diff --git a/.forgejo/workflows/codespell.yml b/.forgejo/workflows/codespell.yml new file mode 100644 index 0000000000..76fb7ef48c --- /dev/null +++ b/.forgejo/workflows/codespell.yml @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 yuzu Emulator Project +# SPDX-FileCopyrightText: 2024 suyu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later +# +# GitHub Action to automate the identification of common misspellings in text files. +# https://github.com/codespell-project/actions-codespell +# https://github.com/codespell-project/codespell + +# Actions Documentation: https://forgejo.org/docs/next/user/actions/#list-of-tasks-in-a-repository + +name: codespell +on: pull_request +permissions: {} +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + steps: + - uses: https://code.forgejo.org/actions/checkout@v3 + with: + persist-credentials: false + - uses: https://github.com/codespell-project/actions-codespell@master diff --git a/.forgejo/workflows/verify.yml b/.forgejo/workflows/verify.yml new file mode 100644 index 0000000000..26f19586e8 --- /dev/null +++ b/.forgejo/workflows/verify.yml @@ -0,0 +1,198 @@ +# SPDX-FileCopyrightText: 2022 yuzu Emulator Project +# SPDX-FileCopyrightText: 2024 suyu Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +# Actions Documentation: https://forgejo.org/docs/next/user/actions/#list-of-tasks-in-a-repository + +name: 'suyu verify' + +on: + pull_request: + branches: [ "dev" ] + push: + branches: [ "dev" ] +env: + PR_NUMBER: pr${{ github.event.number }} + +jobs: + format: + name: 'verify format' + runs-on: ubuntu-latest + steps: + - uses: https://code.forgejo.org/actions/checkout@v3 + with: + submodules: false + - name: set up JDK 17 + uses: https://github.com/actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: 'Verify Formatting' + run: bash -ex ./.ci/scripts/format/script.sh + build-linux: + name: 'test build' + needs: format + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - type: clang + image: linux-fresh + - type: linux + image: linux-fresh + - type: windows + image: linux-mingw + container: + image: fijxu/build-environments:${{ matrix.image }} + options: -u 1001 + steps: + - uses: https://code.forgejo.org/actions/checkout@v3 + with: + submodules: recursive + fetch-depth: 0 + - name: Set up cache + uses: https://code.forgejo.org/actions/cache@v3 + id: ccache-restore + with: + path: ~/.ccache + key: ${{ runner.os }}-${{ matrix.type }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-${{ matrix.type }}- + - name: Create ccache directory + if: steps.ccache-restore.outputs.cache-hit != 'true' + run: mkdir -p ~/.ccache + - name: Build + run: ./.ci/scripts/${{ matrix.type }}/docker.sh + env: + ENABLE_COMPATIBILITY_REPORTING: "ON" + - name: Pack + run: ./.ci/scripts/${{ matrix.type }}/upload.sh + env: + NO_SOURCE_PACK: "YES" + - name: Upload + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: ${{ matrix.type }} + path: artifacts/ + # build-mac: + # name: 'test build (macos)' + # needs: format + # runs-on: macos-14 + # steps: + # - uses: https://code.forgejo.org/actions/checkout@v3 + # with: + # submodules: recursive + # fetch-depth: 0 + # - name: Install dependencies + # run: | + # brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd + # - name: Build + # run: | + # mkdir build + # cd build + # export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake" + # cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DSUYU_USE_BUNDLED_VCPKG=OFF -DSUYU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF + # ninja + # build-msvc: + # name: 'test build (windows, msvc)' + # needs: format + # runs-on: windows-2022 + # steps: + # - uses: https://code.forgejo.org/actions/checkout@v3 + # with: + # submodules: recursive + # fetch-depth: 0 + # - name: Set up cache + # uses: https://code.forgejo.org/actions/cache@v3 + # with: + # path: ~/.buildcache + # key: ${{ runner.os }}-msvc-${{ github.sha }} + # restore-keys: | + # ${{ runner.os }}-msvc- + # - name: Install dependencies + # shell: pwsh + # run: | + # $ErrorActionPreference = "Stop" + # $BuildCacheVer = "v0.28.4" + # $File = "buildcache-windows.zip" + # $Uri = "https://github.com/mbitsnbites/buildcache/releases/download/$BuildCacheVer/$File" + # $WebClient = New-Object System.Net.WebClient + # $WebClient.DownloadFile($Uri, $File) + # 7z x $File + # $CurrentDir = Convert-Path . + # echo "$CurrentDir/buildcache/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + # - name: Install Vulkan SDK + # shell: pwsh + # run: .\.ci\scripts\windows\install-vulkan-sdk.ps1 + # - name: Set up MSVC + # uses: https://github.com/ilammy/msvc-dev-cmd@v1 + # - name: Configure + # env: + # CC: cl.exe + # CXX: cl.exe + # run: | + # glslangValidator --version + # mkdir build + # cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DSUYU_USE_BUNDLED_QT=1 -DSUYU_USE_BUNDLED_SDL2=1 -DSUYU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DSUYU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DSUYU_CRASH_DUMPS=ON + # - name: Build + # run: cmake --build build + # - name: Cache Summary + # run: buildcache -s + # - name: Pack + # shell: pwsh + # run: .\.ci\scripts\windows\upload.ps1 + # - name: Upload + # uses: https://code.forgejo.org/actions/upload-artifact@v3 + # with: + # name: msvc + # path: artifacts/ + # - name: Upload EXE + # uses: https://code.forgejo.org/actions/upload-artifact@v3 + # with: + # name: ${{ env.INDIVIDUAL_EXE }} + # path: ${{ env.INDIVIDUAL_EXE }} + android: + runs-on: ubuntu-latest + needs: format + steps: + - uses: https://code.forgejo.org/actions/checkout@v3 + with: + submodules: recursive + fetch-depth: 0 + - name: set up JDK 17 + uses: https://github.com/actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Set up cache + uses: https://code.forgejo.org/actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.ccache + key: ${{ runner.os }}-android-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-android- + - name: Query tag name + uses: https://github.com/olegtarasov/get-tag@v2.1.2 + id: tagName + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ccache apksigner glslang-dev glslang-tools + - name: Build + run: ./.ci/scripts/android/build.sh + - name: Copy and sign artifacts + env: + ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }} + run: ./.ci/scripts/android/upload.sh + - name: Upload + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: android + path: artifacts/ + diff --git a/.github-archive/ISSUE_TEMPLATE/blank_issue_template.yml b/.github-archive/ISSUE_TEMPLATE/blank_issue_template.yml new file mode 100644 index 0000000000..49b7f38228 --- /dev/null +++ b/.github-archive/ISSUE_TEMPLATE/blank_issue_template.yml @@ -0,0 +1,10 @@ +name: New Issue (Developers Only) +description: A blank issue template for developers only. If you are not a developer, do not use this issue template. Your issue WILL BE CLOSED if you do not use the appropriate issue template. +body: + - type: markdown + attributes: + value: | + **If you are not a developer, do not use this issue template. Your issue WILL BE CLOSED if you do not use the appropriate issue template.** + - type: textarea + attributes: + label: "Issue" diff --git a/.github-archive/ISSUE_TEMPLATE/bug_report.yml b/.github-archive/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..a274cf3607 --- /dev/null +++ b/.github-archive/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,64 @@ +name: Bug Report +description: File a bug report +body: + - type: markdown + attributes: + value: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with suyu. + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: input + attributes: + label: Affected Build(s) + description: List the affected build(s) that this issue applies to. + placeholder: Mainline 1234 / Early Access 1234 + validations: + required: true + - type: textarea + id: issue-desc + attributes: + label: Description of Issue + description: A brief description of the issue encountered along with any images and/or videos. + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Expected Behavior + description: A brief description of how it is expected to work along with any images and/or videos. + validations: + required: true + - type: textarea + id: reproduction-steps + attributes: + label: Reproduction Steps + description: A brief explanation of how to reproduce this issue. If possible, provide a save file to aid in reproducing the issue. + validations: + required: true + - type: textarea + id: log + attributes: + label: Log File + description: A log file will help our developers to better diagnose and fix the issue. Instructions can be found [here](https://suyu.dev/help/reference/log-files). + validations: + required: true + - type: textarea + id: system-config + attributes: + label: System Configuration + placeholder: | + CPU: Intel i5-10400 / AMD Ryzen 5 3600 + GPU/Driver: NVIDIA GeForce GTX 1060 (Driver 512.95) + RAM: 16GB DDR4-3200 + OS: Windows 11 22H2 (Build 22621.819) + value: | + CPU: + GPU/Driver: + RAM: + OS: + validations: + required: true diff --git a/.github-archive/ISSUE_TEMPLATE/config.yml b/.github-archive/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..0be63fdb7a --- /dev/null +++ b/.github-archive/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: suyu Discord + url: https://discord.com/invite/suyu + about: If you are experiencing an issue with suyu, and you need tech support, or if you have a general question, try asking in the official suyu Discord linked here. Piracy is not allowed. diff --git a/.github-archive/ISSUE_TEMPLATE/feature_request.yml b/.github-archive/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..e5a65dae89 --- /dev/null +++ b/.github-archive/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,28 @@ +name: Feature Request +description: File a feature request +labels: "request" +body: + - type: markdown + attributes: + value: Tech support does not belong here. You should only file an issue here if you are requesting a feature you believe would make suyu better. + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the feature you are requesting. + options: + - label: I have searched the existing issues + required: true + - type: textarea + id: what-feature + attributes: + label: What feature are you suggesting? + description: A brief description of the requested feature. + validations: + required: true + - type: textarea + id: why-feature + attributes: + label: Why would this feature be useful? + description: A brief description of why this feature would make suyu better. + validations: + required: true diff --git a/.github-archive/workflows/android-build.yml b/.github-archive/workflows/android-build.yml new file mode 100644 index 0000000000..5efda89230 --- /dev/null +++ b/.github-archive/workflows/android-build.yml @@ -0,0 +1,80 @@ +# SPDX-FileCopyrightText: 2022 yuzu Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +name: 'suyu-android-build' + +on: + push: + tags: [ "*" ] + +jobs: + android: + runs-on: ubuntu-latest + if: ${{ github.repository == 'suyu-emu/suyu-android' }} + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Set up cache + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.ccache + key: ${{ runner.os }}-android-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-android- + - name: Query tag name + uses: olegtarasov/get-tag@v2.1.2 + id: tagName + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ccache apksigner glslang-dev glslang-tools + - name: Build + run: ./.ci/scripts/android/build.sh + env: + ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }} + - name: Copy artifacts + run: ./.ci/scripts/android/upload.sh + - name: Upload + uses: actions/upload-artifact@v3 + with: + name: android + path: artifacts/ + # release steps + release-android: + runs-on: ubuntu-latest + needs: [android] + if: ${{ startsWith(github.ref, 'refs/tags/') }} + permissions: + contents: write + steps: + - uses: actions/download-artifact@v3 + - name: Query tag name + uses: olegtarasov/get-tag@v2.1.2 + id: tagName + - name: Create release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.tagName.outputs.tag }} + release_name: ${{ steps.tagName.outputs.tag }} + draft: false + prerelease: false + - name: Upload artifacts + uses: alexellis/upload-assets@0.2.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + asset_paths: '["./**/*.apk","./**/*.aab"]' diff --git a/.github-archive/workflows/android-ea-play-release.yml b/.github-archive/workflows/android-ea-play-release.yml new file mode 100644 index 0000000000..0f7406ba7e --- /dev/null +++ b/.github-archive/workflows/android-ea-play-release.yml @@ -0,0 +1,66 @@ +# SPDX-FileCopyrightText: 2024 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +name: suyu-android-ea-play-release + +on: + workflow_dispatch: + inputs: + release-track: + description: 'Play store release track (internal/alpha/beta/production)' + required: true + default: 'alpha' + +jobs: + android: + runs-on: ubuntu-latest + if: ${{ github.repository == 'suyu-emu/suyu' }} + steps: + - uses: actions/checkout@v3 + name: Checkout + with: + fetch-depth: 0 + submodules: true + token: ${{ secrets.ALT_GITHUB_TOKEN }} + - run: npm install execa@5 + - uses: actions/github-script@v5 + name: 'Merge and publish Android EA changes' + env: + ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }} + BUILD_EA: true + with: + script: | + const execa = require("execa"); + const mergebot = require('./.github/workflows/android-merge.js').mergebot; + process.chdir('${{ github.workspace }}'); + mergebot(github, context, execa); + - name: Get tag name + run: echo "GIT_TAG_NAME=$(cat tag-name.txt)" >> $GITHUB_ENV + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ccache apksigner glslang-dev glslang-tools + - name: Build + run: ./.ci/scripts/android/eabuild.sh + env: + EA_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }} + PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }} + PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }} + EA_SERVICE_ACCOUNT_KEY_B64: ${{ secrets.EA_SERVICE_ACCOUNT_KEY_B64 }} + STORE_TRACK: ${{ github.event.inputs.release-track }} + AUTO_VERSIONED: true + BUILD_EA: true + - name: Create release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ env.EA_TAG_NAME }} + name: ${{ env.EA_TAG_NAME }} + draft: false + prerelease: false + repository: suyu/suyu-android + token: ${{ secrets.ALT_GITHUB_TOKEN }} diff --git a/.github-archive/workflows/android-mainline-play-release.yml b/.github-archive/workflows/android-mainline-play-release.yml new file mode 100644 index 0000000000..91982ad538 --- /dev/null +++ b/.github-archive/workflows/android-mainline-play-release.yml @@ -0,0 +1,59 @@ +# SPDX-FileCopyrightText: 2024 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +name: suyu-android-mainline-play-release + +on: + workflow_dispatch: + inputs: + release-tag: + description: 'Tag # from suyu-android that you want to build and publish' + required: true + default: '200' + release-track: + description: 'Play store release track (internal/alpha/beta/production)' + required: true + default: 'alpha' + +jobs: + android: + runs-on: ubuntu-latest + if: ${{ github.repository == 'suyu-emu/suyu' }} + steps: + - uses: actions/checkout@v3 + name: Checkout + with: + fetch-depth: 0 + submodules: true + token: ${{ secrets.ALT_GITHUB_TOKEN }} + - run: npm install execa@5 + - uses: actions/github-script@v5 + name: 'Pull mainline tag' + env: + MAINLINE_TAG: ${{ github.event.inputs.release-tag }} + with: + script: | + const execa = require("execa"); + const mergebot = require('./.github/workflows/android-merge.js').getMainlineTag; + process.chdir('${{ github.workspace }}'); + mergebot(execa); + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ccache apksigner glslang-dev glslang-tools + - name: Build + run: | + echo "GIT_TAG_NAME=android-${{ github.event.inputs.releast-tag }}" >> $GITHUB_ENV + ./.ci/scripts/android/mainlinebuild.sh + env: + MAINLINE_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }} + PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }} + PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }} + SERVICE_ACCOUNT_KEY_B64: ${{ secrets.MAINLINE_SERVICE_ACCOUNT_KEY_B64 }} + STORE_TRACK: ${{ github.event.inputs.release-track }} + AUTO_VERSIONED: true diff --git a/.github-archive/workflows/android-merge.js b/.github-archive/workflows/android-merge.js new file mode 100644 index 0000000000..18e3c8a648 --- /dev/null +++ b/.github-archive/workflows/android-merge.js @@ -0,0 +1,318 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Note: This is a GitHub Actions script +// It is not meant to be executed directly on your machine without modifications + +const fs = require("fs"); +// which label to check for changes +const CHANGE_LABEL_MAINLINE = 'android-merge'; +const CHANGE_LABEL_EA = 'android-ea-merge'; +// how far back in time should we consider the changes are "recent"? (default: 24 hours) +const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000); +const BUILD_EA = process.env.BUILD_EA == 'true'; +const MAINLINE_TAG = process.env.MAINLINE_TAG; + +async function checkBaseChanges(github) { + // query the commit date of the latest commit on this branch + const query = `query($owner:String!, $name:String!, $ref:String!) { + repository(name:$name, owner:$owner) { + ref(qualifiedName:$ref) { + target { + ... on Commit { id pushedDate oid } + } + } + } + }`; + const variables = { + owner: 'suyu-emu', + name: 'suyu', + ref: 'refs/heads/master', + }; + const result = await github.graphql(query, variables); + const pushedAt = result.repository.ref.target.pushedDate; + console.log(`Last commit pushed at ${pushedAt}.`); + const delta = new Date() - new Date(pushedAt); + if (delta <= DETECTION_TIME_FRAME) { + console.info('New changes detected, triggering a new build.'); + return true; + } + console.info('No new changes detected.'); + return false; +} + +async function checkAndroidChanges(github) { + if (checkBaseChanges(github)) return true; + const pulls = getPulls(github, false); + for (let i = 0; i < pulls.length; i++) { + let pull = pulls[i]; + if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) { + console.info(`${pull.number} updated at ${pull.headRepository.pushedAt}`); + return true; + } + } + console.info("No changes detected in any tagged pull requests."); + return false; +} + +async function tagAndPush(github, owner, repo, execa, commit=false) { + let altToken = process.env.ALT_GITHUB_TOKEN; + if (!altToken) { + throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`; + } + const query = `query ($owner:String!, $name:String!) { + repository(name:$name, owner:$owner) { + refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) { + nodes { name } + } + } + }`; + const variables = { + owner: owner, + name: repo, + }; + const tags = await github.graphql(query, variables); + const tagList = tags.repository.refs.nodes; + let lastTag = 'android-1'; + for (let i = 0; i < tagList.length; ++i) { + if (tagList[i].name.includes('android-')) { + lastTag = tagList[i].name; + break; + } + } + const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0; + const channel = repo.split('-')[1]; + const newTag = `${channel}-${tagNumber + 1}`; + console.log(`New tag: ${newTag}`); + if (commit) { + let channelName = channel[0].toUpperCase() + channel.slice(1); + console.info(`Committing pending commit as ${channelName} ${tagNumber + 1}`); + await execa("git", ['commit', '-m', `${channelName} ${tagNumber + 1}`]); + } + console.info('Pushing tags to GitHub ...'); + await execa("git", ['tag', newTag]); + await execa("git", ['remote', 'add', 'target', `https://${altToken}@github.com/${owner}/${repo}.git`]); + await execa("git", ['push', 'target', 'master', '-f']); + await execa("git", ['push', 'target', 'master', '--tags']); + console.info('Successfully pushed new changes.'); +} + +async function tagAndPushEA(github, owner, repo, execa) { + let altToken = process.env.ALT_GITHUB_TOKEN; + if (!altToken) { + throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`; + } + const query = `query ($owner:String!, $name:String!) { + repository(name:$name, owner:$owner) { + refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) { + nodes { name } + } + } + }`; + const variables = { + owner: owner, + name: repo, + }; + const tags = await github.graphql(query, variables); + const tagList = tags.repository.refs.nodes; + let lastTag = 'ea-1'; + for (let i = 0; i < tagList.length; ++i) { + if (tagList[i].name.includes('ea-')) { + lastTag = tagList[i].name; + break; + } + } + const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0; + const newTag = `ea-${tagNumber + 1}`; + console.log(`New tag: ${newTag}`); + console.info('Pushing tags to GitHub ...'); + await execa("git", ["remote", "add", "android", "https://gitlab.com/suyu-emu/suyu-android.git"]); + await execa("git", ["fetch", "android"]); + + await execa("git", ['tag', newTag]); + await execa("git", ['push', 'android', `${newTag}`]); + + fs.writeFile('tag-name.txt', newTag, (err) => { + if (err) throw 'Could not write tag name to file!' + }) + + console.info('Successfully pushed new changes.'); +} + +async function generateReadme(pulls, context, mergeResults, execa) { + let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`; + let output = + "| Pull Request | Commit | Title | Author | Merged? |\n|----|----|----|----|----|\n"; + for (let pull of pulls) { + let pr = pull.number; + let result = mergeResults[pr]; + output += `| [${pr}](${baseUrl}/pull/${pr}) | [\`${result.rev || "N/A"}\`](${baseUrl}/pull/${pr}/files) | ${pull.title} | [${pull.author.login}](https://github.com/${pull.author.login}/) | ${result.success ? "Yes" : "No"} |\n`; + } + output += + "\n\nEnd of merge log. You can find the original README.md below the break.\n\n-----\n\n"; + output += fs.readFileSync("./README.md"); + fs.writeFileSync("./README.md", output); + await execa("git", ["add", "README.md"]); +} + +async function fetchPullRequests(pulls, repoUrl, execa) { + console.log("::group::Fetch pull requests"); + for (let pull of pulls) { + let pr = pull.number; + console.info(`Fetching PR ${pr} ...`); + await execa("git", [ + "fetch", + "-f", + "--no-recurse-submodules", + repoUrl, + `pull/${pr}/head:pr-${pr}`, + ]); + } + console.log("::endgroup::"); +} + +async function mergePullRequests(pulls, execa) { + let mergeResults = {}; + console.log("::group::Merge pull requests"); + await execa("git", ["config", "--global", "user.name", "suyubot"]); + await execa("git", [ + "config", + "--global", + "user.email", + "suyu\x40suyu-emu\x2eorg", // prevent email harvesters from scraping the address + ]); + let hasFailed = false; + for (let pull of pulls) { + let pr = pull.number; + console.info(`Merging PR ${pr} ...`); + try { + const process1 = execa("git", [ + "merge", + "--squash", + "--no-edit", + `pr-${pr}`, + ]); + process1.stdout.pipe(process.stdout); + await process1; + + const process2 = execa("git", ["commit", "-m", `Merge suyu-emu#${pr}`]); + process2.stdout.pipe(process.stdout); + await process2; + + const process3 = await execa("git", ["rev-parse", "--short", `pr-${pr}`]); + mergeResults[pr] = { + success: true, + rev: process3.stdout, + }; + } catch (err) { + console.log( + `::error title=#${pr} not merged::Failed to merge pull request: ${pr}: ${err}` + ); + mergeResults[pr] = { success: false }; + hasFailed = true; + await execa("git", ["reset", "--hard"]); + } + } + console.log("::endgroup::"); + if (hasFailed) { + throw 'There are merge failures. Aborting!'; + } + return mergeResults; +} + +async function resetBranch(execa) { + console.log("::group::Reset master branch"); + let hasFailed = false; + try { + await execa("git", ["remote", "add", "source", "https://gitlab.com/suyu-emu/suyu.git"]); + await execa("git", ["fetch", "source"]); + const process1 = await execa("git", ["rev-parse", "source/master"]); + const headCommit = process1.stdout; + + await execa("git", ["reset", "--hard", headCommit]); + } catch (err) { + console.log(`::error title=Failed to reset master branch`); + hasFailed = true; + } + console.log("::endgroup::"); + if (hasFailed) { + throw 'Failed to reset the master branch. Aborting!'; + } +} + +async function getPulls(github) { + const query = `query ($owner:String!, $name:String!, $label:String!) { + repository(name:$name, owner:$owner) { + pullRequests(labels: [$label], states: OPEN, first: 100) { + nodes { + number title author { login } + } + } + } + }`; + const mainlineVariables = { + owner: 'suyu-emu', + name: 'suyu', + label: CHANGE_LABEL_MAINLINE, + }; + const mainlineResult = await github.graphql(query, mainlineVariables); + const pulls = mainlineResult.repository.pullRequests.nodes; + if (BUILD_EA) { + const eaVariables = { + owner: 'suyu-emu', + name: 'suyu', + label: CHANGE_LABEL_EA, + }; + const eaResult = await github.graphql(query, eaVariables); + const eaPulls = eaResult.repository.pullRequests.nodes; + return pulls.concat(eaPulls); + } + return pulls; +} + +async function getMainlineTag(execa) { + console.log(`::group::Getting mainline tag android-${MAINLINE_TAG}`); + let hasFailed = false; + try { + await execa("git", ["remote", "add", "mainline", "https://gitlab.com/suyu-emu/suyu-android.git"]); + await execa("git", ["fetch", "mainline", "--tags"]); + await execa("git", ["checkout", `tags/android-${MAINLINE_TAG}`]); + await execa("git", ["submodule", "update", "--init", "--recursive"]); + } catch (err) { + console.log('::error title=Failed pull tag'); + hasFailed = true; + } + console.log("::endgroup::"); + if (hasFailed) { + throw 'Failed pull mainline tag. Aborting!'; + } +} + +async function mergebot(github, context, execa) { + // Reset our local copy of master to what appears on suyu-emu/suyu - master + await resetBranch(execa); + + const pulls = await getPulls(github); + let displayList = []; + for (let i = 0; i < pulls.length; i++) { + let pull = pulls[i]; + displayList.push({ PR: pull.number, Title: pull.title }); + } + console.info("The following pull requests will be merged:"); + console.table(displayList); + await fetchPullRequests(pulls, "https://gitlab.com/suyu-emu/suyu", execa); + const mergeResults = await mergePullRequests(pulls, execa); + + if (BUILD_EA) { + await tagAndPushEA(github, 'suyu-emu', `suyu-android`, execa); + } else { + await generateReadme(pulls, context, mergeResults, execa); + await tagAndPush(github, 'suyu-emu', `suyu-android`, execa, true); + } +} + +module.exports.mergebot = mergebot; +module.exports.checkAndroidChanges = checkAndroidChanges; +module.exports.tagAndPush = tagAndPush; +module.exports.checkBaseChanges = checkBaseChanges; +module.exports.getMainlineTag = getMainlineTag; diff --git a/.github-archive/workflows/android-publish.yml b/.github-archive/workflows/android-publish.yml new file mode 100644 index 0000000000..61f739e96a --- /dev/null +++ b/.github-archive/workflows/android-publish.yml @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2024 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +name: yuzu-android-publish + +on: + schedule: + - cron: '37 0 * * *' + workflow_dispatch: + inputs: + android: + description: 'Whether to trigger an Android build (true/false/auto)' + required: false + default: 'true' + +jobs: + android: + runs-on: ubuntu-latest + if: ${{ github.event.inputs.android != 'false' && github.repository == 'yuzu-emu/yuzu' }} + steps: + # this checkout is required to make sure the GitHub Actions scripts are available + - uses: actions/checkout@v3 + name: Pre-checkout + with: + submodules: false + - uses: actions/github-script@v6 + id: check-changes + name: 'Check for new changes' + env: + # 24 hours + DETECTION_TIME_FRAME: 86400000 + with: + script: | + if (context.payload.inputs && context.payload.inputs.android === 'true') return true; + const checkAndroidChanges = require('./.github/workflows/android-merge.js').checkAndroidChanges; + return checkAndroidChanges(github); + - run: npm install execa@5 + if: ${{ steps.check-changes.outputs.result == 'true' }} + - uses: actions/checkout@v3 + name: Checkout + if: ${{ steps.check-changes.outputs.result == 'true' }} + with: + path: 'yuzu-merge' + fetch-depth: 0 + submodules: true + token: ${{ secrets.ALT_GITHUB_TOKEN }} + - uses: actions/github-script@v5 + name: 'Check and merge Android changes' + if: ${{ steps.check-changes.outputs.result == 'true' }} + env: + ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }} + with: + script: | + const execa = require("execa"); + const mergebot = require('./.github/workflows/android-merge.js').mergebot; + process.chdir('${{ github.workspace }}/yuzu-merge'); + mergebot(github, context, execa); diff --git a/.github/workflows/ci.yml b/.github-archive/workflows/ci.yml similarity index 100% rename from .github/workflows/ci.yml rename to .github-archive/workflows/ci.yml diff --git a/.github/workflows/codespell.yml b/.github-archive/workflows/codespell.yml similarity index 100% rename from .github/workflows/codespell.yml rename to .github-archive/workflows/codespell.yml diff --git a/.github/workflows/verify.yml b/.github-archive/workflows/verify.yml similarity index 100% rename from .github/workflows/verify.yml rename to .github-archive/workflows/verify.yml diff --git a/README.md b/README.md index eeb0acf0a3..1c3c5f5803 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ It is written in C++ with portability in mind, and we're actively working on bui Building | Support | License | - Pipelines + Pipelines
## Status @@ -46,22 +46,24 @@ This project is completely free and open source, and anyone can contribute to he Most of the development happens on GitLab. For development discussion, please join us on [Discord](https://discord.gg/suyu). -If you want to contribute, please take a look at the [Contributor's Guide](https://gitlab.com/suyu-emu/suyu/-/wikis/Contributing) and [Developer Information](https://gitlab.com/suyu-emu/suyu/-/wikis/Developer-Information). +If you want to contribute, please take a look at the [Contributor's Guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing) and [Developer Information](https://git.suyu.dev/suyu/suyu/wiki/Developer-Information). You can also contact any of the developers on Discord to learn more about the current state of suyu. ## Downloads -* __Windows__: [Releases](https://gitlab.com/suyu-emu/suyu/-/releases) -* __Linux__: [Releases](https://gitlab.com/suyu-emu/suyu/-/releases) -* __macOS__: [Releases](https://gitlab.com/suyu-emu/suyu/-/releases) -* __Android__: [Releases](https://gitlab.com/suyu-emu/suyu/-/releases) +* __Windows__: [Releases](https://git.suyu.dev/suyu/suyu/releases) +* __Linux__: [Releases](https://git.suyu.dev/suyu/suyu/releases) +* __macOS__: [Releases](https://git.suyu.dev/suyu/suyu/releases) +* __Android__: [Releases](https://git.suyu.dev/suyu/suyu/releases) -We have official builds [here.](https://gitlab.com/suyu-emu/suyu/-/releases) If any website or person is claiming to have a build for suyu, take that with a grain of salt. +We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any website or person is claiming to have a build for suyu, take that with a grain of salt. ## Building -* __Windows__: [Wiki page](https://gitlab.com/suyu-emu/suyu/-/wikis/Building-for-Windows) -* __Linux__: [Wiki page](https://gitlab.com/suyu-emu/suyu/-/wikis/Building-for-Linux) +* __Windows__: [Windows Build](https://git.suyu.dev/suyu/suyu/wiki/Building-For-Windows) +* __Linux__: [Linux Build](https://git.suyu.dev/suyu/suyu/wiki/Building-For-Linux) +* __Android__: [Android Build](https://git.suyu.dev/suyu/suyu/wiki/Building-For-Android) +* __MacOS__: [MacOS Build](https://git.suyu.dev/suyu/suyu/wiki/Building-for-macOS) diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 3ffb03bc97..4048cb8704 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -47,6 +47,75 @@ bool ShouldCreateGuestApplet(AppletId applet_id) { return true; } +std::shared_ptr