feat: upstream sync v2026.04.11.044523-0639f8b + Android fixes #13
Workflow file for this run
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
| # MasterDnsVPN — Manual Android Build & Release | |
| # | |
| # Trigger: Actions → Run workflow | |
| # Required secrets: KEYSTORE_BASE64, KEYSTORE_PASSWORD, KEY_ALIAS, KEY_PASSWORD | |
| name: Build & Release Android | |
| on: | |
| push: | |
| tags: | |
| - 'v[0-9]*' | |
| workflow_dispatch: | |
| inputs: | |
| version_name: | |
| description: "Version name (e.g. 1.3.0) — empty = auto from tag or date" | |
| required: false | |
| default: "" | |
| upstream_version: | |
| description: "Upstream MasterDnsVPN version built into this release (e.g. v2026.04.01.080348-951927f)" | |
| required: false | |
| default: "" | |
| prerelease: | |
| description: "Mark as pre-release?" | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| JAVA_VERSION: "17" | |
| NDK_VERSION: "27.3.13750724" | |
| ANDROID_API: "26" | |
| jobs: | |
| build: | |
| name: "Build & Release" | |
| runs-on: ubuntu-latest | |
| steps: | |
| # ── Checkout ───────────────────────────────────────────────────────── | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| # ── Go ──────────────────────────────────────────────────────────────── | |
| - name: Set up Go (version from go.mod) | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| # ── Java ───────────────────────────────────────────────────────────── | |
| - name: Set up Java ${{ env.JAVA_VERSION }} | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: ${{ env.JAVA_VERSION }} | |
| distribution: temurin | |
| cache: gradle | |
| # ── Android NDK ────────────────────────────────────────────────────── | |
| - name: Install Android NDK ${{ env.NDK_VERSION }} | |
| run: | | |
| yes | "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" \ | |
| --licenses > /dev/null 2>&1 || true | |
| "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" \ | |
| "ndk;${{ env.NDK_VERSION }}" \ | |
| "build-tools;35.0.0" \ | |
| "platforms;android-35" | |
| echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/${{ env.NDK_VERSION }}" >> "$GITHUB_ENV" | |
| # ── Override local.properties (CI uses Linux paths) ────────────────── | |
| - name: Write android/local.properties for CI | |
| run: | | |
| printf 'sdk.dir=%s\nndk.dir=%s/ndk/%s\n' \ | |
| "$ANDROID_SDK_ROOT" \ | |
| "$ANDROID_SDK_ROOT" \ | |
| "${{ env.NDK_VERSION }}" \ | |
| > android/local.properties | |
| echo "local.properties:" | |
| cat android/local.properties | |
| # ── Version ────────────────────────────────────────────────────────── | |
| - name: Determine version | |
| id: version | |
| run: | | |
| # Priority: manual input > git tag > date fallback | |
| if [[ -n "${{ inputs.version_name }}" ]]; then | |
| VER="${{ inputs.version_name }}" | |
| PRERELEASE="${{ inputs.prerelease || 'false' }}" | |
| elif [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| VER="${GITHUB_REF#refs/tags/v}" | |
| PRERELEASE=false | |
| else | |
| VER="$(date -u +%Y.%m.%d)-${{ github.run_number }}" | |
| PRERELEASE=true | |
| fi | |
| # Derive versionCode from version segments: 1.0.7 → 10007 | |
| # Falls back to github.run_number if parsing fails. | |
| CODE=$(echo "$VER" | awk -F. '{ if (NF>=3) printf "%d", $1*10000+$2*100+$3; else print 0 }') | |
| if [[ "$CODE" -le 0 ]]; then | |
| CODE=${{ github.run_number }} | |
| fi | |
| # Read upstream version from build.gradle.kts default | |
| UPSTREAM="${{ inputs.upstream_version }}" | |
| if [[ -z "$UPSTREAM" ]]; then | |
| UPSTREAM=$(grep -oP ':\s*"v\K[^"]+' android/app/build.gradle.kts | head -1 || echo "unknown") | |
| if [[ -n "$UPSTREAM" ]]; then UPSTREAM="v${UPSTREAM}"; fi | |
| fi | |
| UPSTREAM="${UPSTREAM:-unknown}" | |
| echo "version_name=$VER" >> "$GITHUB_OUTPUT" | |
| echo "version_code=$CODE" >> "$GITHUB_OUTPUT" | |
| echo "is_prerelease=$PRERELEASE" >> "$GITHUB_OUTPUT" | |
| echo "release_tag=v${VER}" >> "$GITHUB_OUTPUT" | |
| echo "upstream=$UPSTREAM" >> "$GITHUB_OUTPUT" | |
| echo "Version: $VER code: $CODE pre: $PRERELEASE upstream: $UPSTREAM" | |
| # ── gomobile ───────────────────────────────────────────────────────── | |
| - name: Install gomobile | |
| run: | | |
| go install golang.org/x/mobile/cmd/gomobile@latest | |
| go install golang.org/x/mobile/cmd/gobind@latest | |
| echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | |
| - name: gomobile init | |
| run: GOFLAGS="-mod=mod" gomobile init | |
| - name: Build gomobile .aar | |
| run: | | |
| mkdir -p android/app/libs | |
| GOFLAGS="-mod=mod" gomobile bind \ | |
| -v \ | |
| -target android \ | |
| -androidapi "${{ env.ANDROID_API }}" \ | |
| -javapkg com.masterdnsvpn.gomobile \ | |
| -o android/app/libs/masterdnsvpn.aar \ | |
| masterdnsvpn-go/cmd/android | |
| echo "--- .aar output ---" | |
| ls -lh android/app/libs/ | |
| # ── Signing keystore ────────────────────────────────────────────────── | |
| - name: Restore signing keystore | |
| env: | |
| KEYSTORE_B64: ${{ secrets.KEYSTORE_BASE64 }} | |
| run: | | |
| if [ -n "$KEYSTORE_B64" ]; then | |
| echo "$KEYSTORE_B64" | base64 --decode > /tmp/masterdnsvpn-release.jks | |
| echo "KEYSTORE_PATH=/tmp/masterdnsvpn-release.jks" >> "$GITHUB_ENV" | |
| echo "KEYSTORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> "$GITHUB_ENV" | |
| echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> "$GITHUB_ENV" | |
| echo "KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> "$GITHUB_ENV" | |
| echo "Keystore: from secret KEYSTORE_BASE64" | |
| else | |
| echo "KEYSTORE_PATH=$GITHUB_WORKSPACE/android/masterdnsvpn-release.jks" >> "$GITHUB_ENV" | |
| echo "KEYSTORE_PASSWORD=MasterDnsVPN2024!" >> "$GITHUB_ENV" | |
| echo "KEY_ALIAS=masterdnsvpn" >> "$GITHUB_ENV" | |
| echo "KEY_PASSWORD=MasterDnsVPN2024!" >> "$GITHUB_ENV" | |
| echo "WARNING: KEYSTORE_BASE64 not set - using bundled keystore." | |
| fi | |
| # ── Gradle APKs ────────────────────────────────────────────────────── | |
| - name: Make gradlew executable | |
| run: | | |
| # Download official Gradle wrapper script from Gradle GitHub | |
| GRADLE_VER=$(grep distributionUrl android/gradle/wrapper/gradle-wrapper.properties \ | |
| | grep -oP 'gradle-\K[0-9.]+(?=-)') | |
| echo "Gradle version from wrapper: $GRADLE_VER" | |
| curl -fsSL \ | |
| "https://raw.githubusercontent.com/gradle/gradle/v${GRADLE_VER}.0/gradlew" \ | |
| -o android/gradlew 2>/dev/null \ | |
| || curl -fsSL \ | |
| "https://raw.githubusercontent.com/gradle/gradle/master/gradlew" \ | |
| -o android/gradlew | |
| chmod +x android/gradlew | |
| ls -la android/gradlew | |
| - name: Build release APKs | |
| working-directory: android | |
| run: | | |
| ./gradlew assembleRelease \ | |
| -PversionCode=${{ steps.version.outputs.version_code }} \ | |
| -PversionName=${{ steps.version.outputs.version_name }} \ | |
| "-PupstreamVersion=${{ steps.version.outputs.upstream }}" \ | |
| --no-daemon \ | |
| --stacktrace | |
| echo "--- Output APKs ---" | |
| ls -lh app/build/outputs/apk/release/ | |
| # ── Upload artifact ─────────────────────────────────────────────────── | |
| - name: Upload APKs as workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: apks-${{ steps.version.outputs.version_name }} | |
| path: android/app/build/outputs/apk/release/*.apk | |
| retention-days: 30 | |
| # ── GitHub Release ──────────────────────────────────────────────────── | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.release_tag }} | |
| name: "MasterDnsVPN-GG ${{ steps.version.outputs.version_name }} — upstream ${{ steps.version.outputs.upstream }}" | |
| prerelease: ${{ steps.version.outputs.is_prerelease }} | |
| generate_release_notes: true | |
| fail_on_unmatched_files: false | |
| files: android/app/build/outputs/apk/release/*.apk | |
| body: | | |
| ## MasterDnsVPN-GG ${{ steps.version.outputs.version_name }} | |
| | | | | |
| |---|---| | |
| | **Version Code** | `${{ steps.version.outputs.version_code }}` | | |
| | **Upstream Engine** | `${{ steps.version.outputs.upstream }}` | | |
| | **Commit** | [`${{ github.sha }}`](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}) | | |
| | **Build** | #${{ github.run_number }} | | |
| | **Triggered by** | `${{ github.event_name }}` | | |
| ## APK Downloads | |
| | File | Architecture | Use | | |
| |------|-------------|-----| | |
| | `...-arm64-v8a.apk` | ARM 64-bit | Most modern phones | | |
| | `...-armeabi-v7a.apk` | ARM 32-bit | Older phones | | |
| | `...-x86_64.apk` | x86 64-bit | Chromebook / emulator | | |
| | `...-universal.apk` | Universal | When not sure | |