diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 13f353dbcf..0000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -# These are supported funding model platforms - -github: [Kr328] diff --git a/.github/ISSUE_TEMPLATE/01-bug-report-en.yml b/.github/ISSUE_TEMPLATE/01-bug-report-en.yml index 647e1638ff..ea5f174aef 100644 --- a/.github/ISSUE_TEMPLATE/01-bug-report-en.yml +++ b/.github/ISSUE_TEMPLATE/01-bug-report-en.yml @@ -1,6 +1,7 @@ name: "[English] Bug Report" description: "Create a report to help us debug bugs" title: "[BUG] " +labels: ["bug"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/02-feature-request-en.yml b/.github/ISSUE_TEMPLATE/02-feature-request-en.yml index 66f06be70d..996d296e54 100644 --- a/.github/ISSUE_TEMPLATE/02-feature-request-en.yml +++ b/.github/ISSUE_TEMPLATE/02-feature-request-en.yml @@ -1,6 +1,7 @@ name: "[English] Feature Request" description: "Create a report to help us improve" title: "[Feature Request] " +labels: ["enhancement"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/03-bug-report-zh-cn.yml b/.github/ISSUE_TEMPLATE/03-bug-report-zh-cn.yml index b8259b291c..ff327b554f 100644 --- a/.github/ISSUE_TEMPLATE/03-bug-report-zh-cn.yml +++ b/.github/ISSUE_TEMPLATE/03-bug-report-zh-cn.yml @@ -1,6 +1,7 @@ name: "[简体中文] 错误报告" description: "创建错误报告以帮助我们修正应用" title: "[BUG] " +labels: ["bug"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/04-feature-request-zh-cn.yml b/.github/ISSUE_TEMPLATE/04-feature-request-zh-cn.yml index 6748d5a694..118041758b 100644 --- a/.github/ISSUE_TEMPLATE/04-feature-request-zh-cn.yml +++ b/.github/ISSUE_TEMPLATE/04-feature-request-zh-cn.yml @@ -1,6 +1,7 @@ name: "[简体中文] 功能请求" description: "您希望的能够在应用中增加功能" title: "[Feature Request] " +labels: ["enhancement"] body: - type: markdown attributes: diff --git a/.github/patch/disable_pidfd_on_android.patch b/.github/patch/disable_pidfd_on_android.patch new file mode 100644 index 0000000000..c9943fd3d6 --- /dev/null +++ b/.github/patch/disable_pidfd_on_android.patch @@ -0,0 +1,33 @@ +From 7115c480196f4bdcbdae5e14ebaa4510540680e9 Mon Sep 17 00:00:00 2001 +From: Brad Fitzpatrick +Date: Tue, 27 Jan 2026 09:52:22 -0800 +Subject: [PATCH] [tailscale] os: disable pidfd on Android + +Updates tailscale/tailscale#13452 +Updates golang/go#70508 +Updates tailscale/go#99 +--- + src/os/pidfd_linux.go | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/os/pidfd_linux.go b/src/os/pidfd_linux.go +index 796d8c018c7f2a..5cdbf1175e0db5 100644 +--- a/src/os/pidfd_linux.go ++++ b/src/os/pidfd_linux.go +@@ -138,6 +138,16 @@ func (p *Process) pidfdSendSignal(s syscall.Signal) error { + + // pidfdWorks returns whether we can use pidfd on this system. + func pidfdWorks() bool { ++ if runtime.GOOS == "android" { ++ // Tailscale-specific workaround since https://github.com/golang/go/pull/69543/commits/aad6b3b32c81795f86bc4a9e81aad94899daf520 ++ // does not solve https://github.com/golang/go/issues/69065 for Android apps using Go libraries. ++ // ++ // See: https://github.com/tailscale/tailscale/issues/13452 ++ // ++ // For now (2025-04-09), we'll just disable pidfd ++ // on all Android releases. ++ return false ++ } + return checkPidfdOnce() == nil + } + diff --git a/.github/patch/remove_64bits_syscall_on_32bit_linux.patch b/.github/patch/remove_64bits_syscall_on_32bit_linux.patch new file mode 100644 index 0000000000..bc0b9a0275 --- /dev/null +++ b/.github/patch/remove_64bits_syscall_on_32bit_linux.patch @@ -0,0 +1,56 @@ +Subject: [PATCH] remove 64bits syscall on 32bit linux +--- +Index: src/runtime/os_linux32.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/runtime/os_linux32.go b/src/runtime/os_linux32.go +--- a/src/runtime/os_linux32.go (revision 030384681641464bf71ed16500075c458363510f) ++++ b/src/runtime/os_linux32.go (date 1771666707318) +@@ -21,14 +21,14 @@ + + //go:nosplit + func futex(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32 { +- if !isFutexTime32bitOnly.Load() { +- ret := futex_time64(addr, op, val, ts, addr2, val3) +- // futex_time64 is only supported on Linux 5.0+ +- if ret != -_ENOSYS { +- return ret +- } +- isFutexTime32bitOnly.Store(true) +- } ++ //if !isFutexTime32bitOnly.Load() { ++ // ret := futex_time64(addr, op, val, ts, addr2, val3) ++ // // futex_time64 is only supported on Linux 5.0+ ++ // if ret != -_ENOSYS { ++ // return ret ++ // } ++ // isFutexTime32bitOnly.Store(true) ++ //} + // Downgrade ts. + var ts32 timespec32 + var pts32 *timespec32 +@@ -49,14 +49,14 @@ + + //go:nosplit + func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 { +- if !isSetTime32bitOnly.Load() { +- ret := timer_settime64(timerid, flags, new, old) +- // timer_settime64 is only supported on Linux 5.0+ +- if ret != -_ENOSYS { +- return ret +- } +- isSetTime32bitOnly.Store(true) +- } ++ //if !isSetTime32bitOnly.Load() { ++ // ret := timer_settime64(timerid, flags, new, old) ++ // // timer_settime64 is only supported on Linux 5.0+ ++ // if ret != -_ENOSYS { ++ // return ret ++ // } ++ // isSetTime32bitOnly.Store(true) ++ //} + + var newts, oldts itimerspec32 + var new32, old32 *itimerspec32 diff --git a/.github/workflows/build-debug.yaml b/.github/workflows/build-debug.yaml new file mode 100644 index 0000000000..5ee25b5d24 --- /dev/null +++ b/.github/workflows/build-debug.yaml @@ -0,0 +1,111 @@ +name: Build Debug +on: + pull_request: + types: [opened, reopened, synchronize] + workflow_dispatch: + push: + branches: + - main + +jobs: + BuildDebug: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Checkout submodules + run: git submodule update --init --recursive --force + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: 21 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: "1.26" + check-latest: true # Always check for the latest patch release + + - name: Apply Patches + run: | + cd $(go env GOROOT) + for p in $GITHUB_WORKSPACE/.github/patch/*.patch; do patch --verbose -p 1 < "$p"; done + + - uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Update CA + run: | + sudo apt-get update && sudo apt-get install ca-certificates + sudo update-ca-certificates + cp -f /etc/ssl/certs/ca-certificates.crt core/src/foss/golang/clash/component/ca/ca-certificates.crt + + # - name: Signing properties + # env: + # SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} + # SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} + # SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} + # run: | + # touch signing.properties + # echo keystore.password="$SIGNING_STORE_PASSWORD" > signing.properties + # echo key.alias="$SIGNING_KEY_ALIAS" >> signing.properties + # echo key.password="$SIGNING_KEY_PASSWORD" >> signing.properties + + # echo "cat signing.properties" + # cat signing.properties + + - name: Build + if: success() + run: ./gradlew --no-daemon app:assembleAlphaRelease + + - name: Upload Aritfact (universal) + uses: actions/upload-artifact@v4 + if: ${{ success() }} + with: + name: CMFA Debug Unsigned APK (universal) + path: | + app/build/outputs/apk/alpha/release/*-universal-*.apk + + - name: Upload Aritfact (arm64-v8a) + uses: actions/upload-artifact@v4 + if: ${{ success() }} + with: + name: CMFA Debug Unsigned APK (arm64-v8a) + path: | + app/build/outputs/apk/alpha/release/*-arm64-v8a-*.apk + + - name: Upload Aritfact (armeabi-v7a) + uses: actions/upload-artifact@v4 + if: ${{ success() }} + with: + name: CMFA Debug Unsigned APK (armeabi-v7a) + path: | + app/build/outputs/apk/alpha/release/*-armeabi-v7a-*.apk + + - name: Upload Aritfact (x86_64) + uses: actions/upload-artifact@v4 + if: ${{ success() }} + with: + name: CMFA Debug Unsigned APK (x86_64) + path: | + app/build/outputs/apk/alpha/release/*-x86_64-*.apk + + - name: Upload Aritfact (x86) + uses: actions/upload-artifact@v4 + if: ${{ success() }} + with: + name: CMFA Debug Unsigned APK (x86) + path: | + app/build/outputs/apk/alpha/release/*-x86-*.apk diff --git a/.github/workflows/build-pre-release.yaml b/.github/workflows/build-pre-release.yaml new file mode 100644 index 0000000000..d4715d7b79 --- /dev/null +++ b/.github/workflows/build-pre-release.yaml @@ -0,0 +1,95 @@ +name: Build Pre-Release +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + BuildPreRelease: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Checkout submodules + run: git submodule update --init --recursive --force + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: 21 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: "1.26" + check-latest: true # Always check for the latest patch release + + - name: Apply Patches + run: | + cd $(go env GOROOT) + for p in $GITHUB_WORKSPACE/.github/patch/*.patch; do patch --verbose -p 1 < "$p"; done + + - uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Update CA + run: | + sudo apt-get update && sudo apt-get install ca-certificates + sudo update-ca-certificates + cp -f /etc/ssl/certs/ca-certificates.crt core/src/foss/golang/clash/component/ca/ca-certificates.crt + + - name: Signing properties + env: + SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} + SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} + SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} + run: | + touch signing.properties + echo keystore.password="$SIGNING_STORE_PASSWORD" > signing.properties + echo key.alias="$SIGNING_KEY_ALIAS" >> signing.properties + echo key.password="$SIGNING_KEY_PASSWORD" >> signing.properties + + echo "cat signing.properties" + cat signing.properties + + - name: Pre-release Build + if: success() + run: ./gradlew --no-daemon app:assembleAlphaRelease + + # Delete old Prerelease-alpha + - uses: dev-drprasad/delete-tag-and-release@v1.1 + with: + tag_name: Prerelease-alpha + github_token: ${{ secrets.GITHUB_TOKEN }} + delete_release: true + + - name: Tag Repo + uses: richardsimko/update-tag@v1 + with: + tag_name: Prerelease-alpha + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Alpha + uses: softprops/action-gh-release@v2 + if: ${{ success() }} + with: + tag_name: Prerelease-alpha + files: app/build/outputs/apk/alpha/release/* + prerelease: true + generate_release_notes: true + + - name: Release Changelog Builder + uses: mikepenz/release-changelog-builder-action@v4 diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml new file mode 100644 index 0000000000..3f9c3e9fb4 --- /dev/null +++ b/.github/workflows/build-release.yaml @@ -0,0 +1,133 @@ +name: Build Release + +on: + workflow_dispatch: + inputs: + release-tag: + description: 'Release Tag (v2.x.x)' + required: true + +jobs: + BuildRelease: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Checkout submodules + run: git submodule update --init --recursive --force + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: 21 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: "1.26" + check-latest: true # Always check for the latest patch release + + - name: Apply Patches + run: | + cd $(go env GOROOT) + for p in $GITHUB_WORKSPACE/.github/patch/*.patch; do patch --verbose -p 1 < "$p"; done + + - uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Convert and set version env + id: process-version + run: | + VERSION_TAG=${{ inputs.release-tag }} + VERSION_TAG=${VERSION_TAG#v} # remove the 'v' prefix + IFS='.' read -ra VERSION_PARTS <<< "$VERSION_TAG" # split into array + VERSION_CODE=$(printf "%1d%02d%03d" "${VERSION_PARTS[0]}" "${VERSION_PARTS[1]}" "${VERSION_PARTS[2]}") + + echo "versonName=$VERSION_TAG" >> $GITHUB_OUTPUT # "1.2.3" + echo "versonCode=$VERSION_CODE" >> $GITHUB_OUTPUT # "102003" + + # Re-write version in build.gradle.kts + - name: Re-write version + uses: Devofure/advance-android-version-actions@v1.5 + with: + gradlePath: build.gradle.kts + versionCode: ${{ steps.process-version.outputs.versonCode }} + versionName: ${{ steps.process-version.outputs.versonName }} + + # If any change found, commit it and push + - name: Commit and push if changes + run: | + changes=$(git diff --name-only origin/main | wc -l) + if [ $changes -gt 0 ] + then + newVersionName=${{ steps.process-version.outputs.versonName }} + newVersionCode=${{ steps.process-version.outputs.versonCode }} + git config --global user.name 'GitHub Action' + git config --global user.email 'action@github.com' + git add build.gradle.kts + git commit -am "Bump version to $newVersionName ($newVersionCode)" + git tag "v$newVersionName" + git push --follow-tags + fi + + - name: Update CA + run: | + sudo apt-get update && sudo apt-get install ca-certificates + sudo update-ca-certificates + cp -f /etc/ssl/certs/ca-certificates.crt core/src/foss/golang/clash/component/ca/ca-certificates.crt + + - name: Signing properties + env: + SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} + SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} + SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} + run: | + touch signing.properties + echo keystore.password="$SIGNING_STORE_PASSWORD" > signing.properties + echo key.alias="$SIGNING_KEY_ALIAS" >> signing.properties + echo key.password="$SIGNING_KEY_PASSWORD" >> signing.properties + + echo "cat signing.properties" + cat signing.properties + + - name: Release Build + if: success() + run: ./gradlew --no-daemon app:assembleMetaRelease + + - name: Tag Repo + uses: richardsimko/update-tag@v1 + with: + tag_name: ${{ inputs.release-tag }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Release + uses: softprops/action-gh-release@v1 + if: ${{ success() }} + with: + tag_name: ${{ inputs.release-tag }} + files: app/build/outputs/apk/meta/release/* + generate_release_notes: true + + - name: Release Changelog Builder + uses: mikepenz/release-changelog-builder-action@v4.1.1 + with: + configurationJson: | + { + "ignore_labels": [ + "Update" + ], + } \ No newline at end of file diff --git a/.github/workflows/build-unsigned.yaml b/.github/workflows/build-unsigned.yaml deleted file mode 100644 index 31e47eaf7f..0000000000 --- a/.github/workflows/build-unsigned.yaml +++ /dev/null @@ -1,54 +0,0 @@ -name: Build Unsigned -on: - push: - branches: - - main - paths-ignore: - - '.github/**' - - '.idea/**' - - '.gitattributes' - - '.gitignore' - - '.gitmodules' - - '**.md' - - 'LICENSE' - - 'NOTICE' - pull_request: - paths-ignore: - - '.github/**' - - '.idea/**' - - '.gitattributes' - - '.gitignore' - - '.gitmodules' - - '**.md' - - 'LICENSE' - - 'NOTICE' - -jobs: - BuildUnsigned: - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - with: - submodules: recursive - - name: Setup Java - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: 17 - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: 1.18 - - uses: actions/cache@v3 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - name: Build - uses: gradle/gradle-build-action@v2 - with: - arguments: --no-daemon app:assembleFossRelease diff --git a/.github/workflows/update-dependencies.yaml b/.github/workflows/update-dependencies.yaml new file mode 100644 index 0000000000..71524443f9 --- /dev/null +++ b/.github/workflows/update-dependencies.yaml @@ -0,0 +1,87 @@ +name: Update Clash-Core and Go Modules +on: + repository_dispatch: + types: + - core-updated + workflow_dispatch: + +jobs: + update-dependencies: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Checkout and Update submodules + run: git submodule update --init --recursive --remote --force + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: 21 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: "1.26" + check-latest: true # Always check for the latest patch release + + - name: Apply Patches + run: | + cd $(go env GOROOT) + for p in $GITHUB_WORKSPACE/.github/patch/*.patch; do patch --verbose -p 1 < "$p"; done + + - uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Install update-go-mod-replace + run: | + go install github.com/metacubex/update-go-mod-replace@latest + + - name: Update Foss Gomod + run: | + cd ${{ github.workspace }}/core/src/foss/golang/ + update-go-mod-replace ${{ github.workspace }}/core/src/foss/golang/clash/go.mod $(pwd)/go.mod + go mod tidy + + - name: Update Main Gomod + run: | + cd ${{ github.workspace }}/core/src/main/golang/ + update-go-mod-replace ${{ github.workspace }}/core/src/foss/golang/clash/go.mod $(pwd)/go.mod + go mod tidy + + - uses: tibdex/github-app-token@v2 + id: generate-token + with: + app_id: ${{ secrets.MAINTAINER_APPID }} + private_key: ${{ secrets.MAINTAINER_APP_PRIVATE_KEY }} + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ steps.generate-token.outputs.token }} + commit-message: Update Dependencies + branch: update-dependencies + delete-branch: true + title: 'Update Dependencies' + draft: false + body: | + - Update Clash-Meta Core + - Update Go Module Dependecies + labels: | + Update + + - name: PR result + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" + diff --git a/.gitignore b/.gitignore index 14ce748009..a169a39695 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,9 @@ gradle-app.setting /core/src/premium/golang/.idea/* !/core/src/premium/golang/.idea/codeStyles +# Ignore builtin geofiles +app/src/main/assets + # KeyStore signing.properties *.keystore diff --git a/.gitmodules b/.gitmodules index 30d550f26b..4bbdf538de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,4 @@ [submodule "clash-foss"] path = core/src/foss/golang/clash - url = https://github.com/Kr328/clash.git -[submodule "clash-premium"] - path = core/src/premium/golang/clash - url = https://github.com/Kr328/clash.git + url = https://github.com/MetaCubeX/mihomo + branch = Alpha diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 446cdb2328..ccbbe1a7ad 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -20,15 +20,6 @@ -