Repository navigation
chore: bump version to 0.8.97+2026090101 #345
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| push: | |
| branches: | |
| - '**' | |
| tags: | |
| - 'v*' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| env: | |
| IS_STABLE: ${{ !contains(github.ref, '-') }} | |
| FLUTTER_VERSION: '3.47.1' | |
| jobs: | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| - name: Test commit message hook | |
| shell: bash | |
| run: bash tool/check_commit_msg_test.sh | |
| - name: Test comment density hook | |
| shell: bash | |
| run: bash tool/check_comment_density_test.sh | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: Install dependencies | |
| run: flutter pub get | |
| - name: Check format | |
| run: dart format --output=none --set-exit-if-changed lib test tool plugins setup.dart | |
| - name: Analyze | |
| run: flutter analyze --no-fatal-infos | |
| - name: Verify changelog | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') | |
| run: dart run tool/changelog.dart verify | |
| - name: Run tests | |
| run: flutter test --reporter expanded --coverage | |
| - name: Check coverage | |
| run: dart run tool/check_coverage.dart coverage/lcov.info 75 | |
| - name: Validate local Flutter packages | |
| shell: bash | |
| run: bash tool/check_plugins.sh | |
| - name: Validate setup build tool | |
| working-directory: plugins/setup/buildkit/build_tool | |
| run: | | |
| dart pub get | |
| dart analyze | |
| dart test | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.26.4' | |
| cache-dependency-path: core/go.sum | |
| - name: Validate Go core wrapper | |
| working-directory: core | |
| shell: bash | |
| env: | |
| CGO_ENABLED: 0 | |
| run: | | |
| # `go test` succeeds silently when a package has no test files, so | |
| # assert the wrapper actually ships tests before trusting the result. | |
| if ! compgen -G '*_test.go' > /dev/null; then | |
| echo 'No Go tests found in core/; the test step would pass vacuously.' >&2 | |
| exit 1 | |
| fi | |
| test -z "$(gofmt -l ./*.go ./platform ./tun)" || { | |
| gofmt -l ./*.go ./platform ./tun >&2 | |
| exit 1 | |
| } | |
| go test -count=1 . | |
| go vet . | |
| # `go vet .` only reaches the root package. `platform` and `tun` are | |
| # behind build constraints, so they need an explicit GOOS to compile | |
| # at all; without this they ship unvetted. | |
| GOOS=linux go vet ./platform | |
| - name: Setup NDK | |
| uses: nttld/setup-ndk@v1 | |
| id: core-ndk | |
| with: | |
| ndk-version: r28c | |
| - name: Validate the Android core library | |
| working-directory: core | |
| shell: bash | |
| env: | |
| ANDROID_NDK_HOME: ${{ steps.core-ndk.outputs.ndk-path }} | |
| run: | | |
| # The step above pins CGO_ENABLED=0, which excludes every `android && | |
| # cgo` file: lib.go, bride.go, tun/ and platform/limit.go. The job | |
| # that builds them needs the NDK and only runs on a `v*` tag, so | |
| # without this the entire Android surface of the core first compiles | |
| # at release time. | |
| CC="$(echo "$ANDROID_NDK_HOME"/toolchains/llvm/prebuilt/*/bin/aarch64-linux-android21-clang)" | |
| test -x "$CC" || { echo "NDK clang not found at $CC" >&2; exit 1; } | |
| # Same tags the shipped library is built with; read from the build | |
| # tool's config so the two cannot drift. | |
| tags="$(sed -n 's/^tags: *//p' ../plugins/setup/buildkit/build_tool/build_config.yaml)" | |
| test -n "$tags" || { echo 'Could not read tags from build_config.yaml' >&2; exit 1; } | |
| export CGO_ENABLED=1 GOOS=android GOARCH=arm64 CC | |
| go vet "-tags=$tags" . ./tun ./platform | |
| - name: Setup Java | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Run Android unit tests | |
| working-directory: android | |
| shell: bash | |
| run: | | |
| # settings.gradle.kts resolves the Flutter tooling through local.properties, | |
| # which only the Flutter build itself would otherwise generate. | |
| { | |
| echo "flutter.sdk=$FLUTTER_ROOT" | |
| echo "sdk.dir=$ANDROID_HOME" | |
| } > local.properties | |
| wrapper="$FLUTTER_ROOT/bin/cache/artifacts/gradle_wrapper" | |
| test -d "$wrapper" || flutter precache | |
| cp -R "$wrapper/." . | |
| chmod +x gradlew | |
| # Modules are listed explicitly: the aggregate testDebugUnitTest task would | |
| # also run third-party Flutter plugin suites. `:core` is omitted because its | |
| # only class loads the native library through System.loadLibrary. | |
| ./gradlew :common:testDebugUnitTest :service:testDebugUnitTest :app:testDebugUnitTest | |
| - name: Validate Rust components | |
| run: | | |
| cargo fmt --manifest-path services/helper/Cargo.toml -- --check | |
| cargo test --manifest-path services/helper/Cargo.toml | |
| cargo fmt --manifest-path plugins/rust_api/rust/Cargo.toml -- --check | |
| cargo test --manifest-path plugins/rust_api/rust/Cargo.toml | |
| windows-helper-test: | |
| name: Windows helper test | |
| runs-on: windows-2022 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Check format | |
| run: cargo fmt --manifest-path services/helper/Cargo.toml -- --check | |
| - name: Run Windows service tests | |
| run: cargo test --manifest-path services/helper/Cargo.toml --features windows-service | |
| build: | |
| if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') | |
| needs: [ test, windows-helper-test ] | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| include: | |
| - platform: android | |
| os: ubuntu-latest | |
| - platform: windows | |
| os: Windows-2022 | |
| arch: amd64 | |
| - platform: linux | |
| os: ubuntu-22.04 | |
| arch: amd64 | |
| - platform: macos | |
| os: macos-15-intel | |
| arch: amd64 | |
| - platform: macos | |
| os: macos-latest | |
| arch: arm64 | |
| - platform: windows | |
| os: windows-11-arm | |
| arch: arm64 | |
| - platform: linux | |
| os: ubuntu-24.04-arm | |
| arch: arm64 | |
| steps: | |
| - name: Setup rust | |
| if: startsWith(matrix.os, 'windows-11-arm') | |
| shell: pwsh | |
| run: | | |
| Invoke-WebRequest -Uri "https://win.rustup.rs/aarch64" -OutFile rustup-init.exe | |
| .\rustup-init.exe -y --default-toolchain stable | |
| $cargoPath = "$env:USERPROFILE\.cargo\bin" | |
| Add-Content $env:GITHUB_PATH $cargoPath | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| - name: Setup Android Signing | |
| if: startsWith(matrix.platform,'android') | |
| run: | | |
| echo "${{ secrets.KEYSTORE }}" | base64 --decode > android/app/keystore.jks | |
| echo "${{ secrets.SERVICE_JSON }}" | base64 --decode > android/app/google-services.json | |
| { | |
| echo "keyAlias=${{ secrets.KEY_ALIAS }}" | |
| echo "storePassword=${{ secrets.STORE_PASSWORD }}" | |
| echo "keyPassword=${{ secrets.KEY_PASSWORD }}" | |
| } >> android/local.properties | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.26.4' | |
| cache-dependency-path: | | |
| core/go.sum | |
| - name: Enable git long paths (Windows) | |
| if: startsWith(matrix.os, 'windows') | |
| run: git config --global core.longpaths true | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: master | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: Setup Xcode | |
| if: startsWith(matrix.platform,'macos') | |
| run: | | |
| sudo xcode-select -s /Applications/Xcode_26.3.app || sudo xcode-select -s /Applications/Xcode_26.2.app | |
| xcodebuild -version | |
| - name: Setup NDK | |
| if: startsWith(matrix.platform,'android') | |
| uses: nttld/setup-ndk@v1 | |
| with: | |
| ndk-version: r28c | |
| add-to-path: true | |
| link-to-sdk: true | |
| - name: Get Flutter Dependency | |
| run: | | |
| flutter --version | |
| flutter pub get | |
| - name: Setup | |
| run: dart setup.dart ${{ matrix.platform }} ${{ env.IS_STABLE == 'true' && '--env stable' || '' }} -v | |
| - name: Upload | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: artifact-${{ matrix.platform }}${{ matrix.arch && format('-{0}', matrix.arch) }} | |
| path: ./dist | |
| overwrite: true | |
| upload: | |
| permissions: | |
| contents: write | |
| needs: [ build ] | |
| runs-on: ubuntu-latest | |
| services: | |
| telegram-bot-api: | |
| image: aiogram/telegram-bot-api:latest | |
| env: | |
| TELEGRAM_API_ID: ${{ secrets.TELEGRAM_API_ID }} | |
| TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} | |
| ports: | |
| - 8081:8081 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./dist/ | |
| pattern: artifact-* | |
| merge-multiple: true | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: Install dependencies | |
| run: flutter pub get | |
| - name: Generate release notes | |
| shell: bash | |
| env: | |
| IS_STABLE: ${{ env.IS_STABLE }} | |
| TAG: ${{ github.ref_name }} | |
| run: | | |
| target=() | |
| if [[ "$IS_STABLE" == 'true' ]]; then | |
| target=(--tag "$TAG") | |
| else | |
| dart run tool/changelog.dart build --unreleased | |
| fi | |
| dart run tool/changelog.dart render release "${target[@]}" --out release.md | |
| dart run tool/changelog.dart render telegram "${target[@]}" --out telegram.md | |
| - name: Push to telegram | |
| env: | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TAG: ${{ github.ref_name }} | |
| RUN_ID: ${{ github.run_id }} | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install requests | |
| python release_telegram.py | |
| - name: Patch release.md | |
| run: | | |
| version=$(echo "${{ github.ref_name }}" | sed 's/^v//') | |
| sed "s|VERSION|$version|g" ./.github/release_template.md >> release.md | |
| - name: Generate sha256 | |
| if: ${{ env.IS_STABLE == 'true' }} | |
| run: | | |
| cd ./dist | |
| sha256sum ./* > SHA256SUMS | |
| - name: Release | |
| if: ${{ env.IS_STABLE == 'true' }} | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: ./dist/* | |
| body_path: './release.md' | |
| - name: Create Homebrew Cask Source Dir | |
| if: ${{ env.IS_STABLE == 'true' }} | |
| run: | | |
| version=$(echo "${{ github.ref_name }}" | sed 's/^v//') | |
| arm_sha=$(sha256sum "./dist/FlClash-${version}-macos-arm64.dmg" | awk '{print $1}') | |
| amd_sha=$(sha256sum "./dist/FlClash-${version}-macos-amd64.dmg" | awk '{print $1}') | |
| mkdir -p ./brew/Casks | |
| sed \ | |
| -e "s|VERSION|$version|g" \ | |
| -e "s|ARM_SHA256|$arm_sha|g" \ | |
| -e "s|AMD_SHA256|$amd_sha|g" \ | |
| ./.github/homebrew_cask_template.rb > ./brew/Casks/flclash.rb | |
| - name: Push to Homebrew tap | |
| if: ${{ env.IS_STABLE == 'true' }} | |
| uses: cpina/github-action-push-to-another-repository@v1.7.2 | |
| env: | |
| SSH_DEPLOY_KEY: ${{ secrets.HOMEBREW_SSH_DEPLOY_KEY }} | |
| with: | |
| source-directory: ./brew/ | |
| destination-github-username: chen08209 | |
| destination-repository-name: homebrew-tap | |
| user-name: 'chen08029' | |
| user-email: 'chen08209@gmail.com' | |
| target-branch: main | |
| commit-message: Update Homebrew cask from ${{ github.ref_name }} | |
| target-directory: / | |
| - name: Create Fdroid Source Dir | |
| if: ${{ env.IS_STABLE == 'true' }} | |
| run: | | |
| mkdir -p ./tmp | |
| cp ./dist/*android-arm64-v8a* ./tmp/ || true | |
| echo "Files copied successfully" | |
| - name: Push to fdroid repo | |
| if: ${{ env.IS_STABLE == 'true' }} | |
| uses: cpina/github-action-push-to-another-repository@v1.7.2 | |
| env: | |
| SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} | |
| with: | |
| source-directory: ./tmp/ | |
| destination-github-username: chen08209 | |
| destination-repository-name: FlClash-fdroid-repo | |
| user-name: 'chen08029' | |
| user-email: 'chen08209@gmail.com' | |
| target-branch: main | |
| commit-message: Update from ${{ github.ref_name }} | |
| target-directory: /tmp/ |