Manual Release #13
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: Manual Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| tag_name: | |
| description: 'Release tag (example: v1.0.0)' | |
| required: true | |
| type: string | |
| release_name: | |
| description: 'Release title (optional)' | |
| required: false | |
| type: string | |
| make_latest: | |
| description: 'Mark as latest release' | |
| required: true | |
| default: true | |
| type: boolean | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-and-release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: 1.25 | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Accept Android licenses | |
| run: yes | sdkmanager --licenses | |
| - name: Decode Android signing keystore | |
| env: | |
| ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| run: | | |
| if [ -z "$ANDROID_KEYSTORE_BASE64" ]; then | |
| echo "Missing secret ANDROID_KEYSTORE_BASE64" | |
| exit 1 | |
| fi | |
| echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > android/release.jks | |
| ls -la android/release.jks | |
| - name: Install gomobile | |
| run: | | |
| MOBILE_TOOLS_VERSION=v0.0.0-20260312152759-81488f6aeb60 | |
| go install golang.org/x/mobile/cmd/gomobile@${MOBILE_TOOLS_VERSION} | |
| go install golang.org/x/mobile/cmd/gobind@${MOBILE_TOOLS_VERSION} | |
| echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | |
| - name: Build Go mobile AAR | |
| run: bash ./android/build_go_mobile.sh | |
| - name: Derive Android app version from tag | |
| run: | | |
| TAG="${{ inputs.tag_name }}" | |
| VERSION_NAME="${TAG#v}" | |
| if [[ ! "$VERSION_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "tag_name must be SemVer like v1.2.3" | |
| exit 1 | |
| fi | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION_NAME" | |
| VERSION_CODE=$((MAJOR * 10000 + MINOR * 100 + PATCH)) | |
| echo "ANDROID_VERSION_NAME=$VERSION_NAME" >> "$GITHUB_ENV" | |
| echo "ANDROID_VERSION_CODE=$VERSION_CODE" >> "$GITHUB_ENV" | |
| echo "Using ANDROID_VERSION_NAME=$VERSION_NAME ANDROID_VERSION_CODE=$VERSION_CODE" | |
| - name: Build Signed Release APKs (split + universal) | |
| working-directory: android | |
| env: | |
| ANDROID_SIGNING_ENABLED: "true" | |
| ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/android/release.jks | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| ANDROID_VERSION_NAME: ${{ env.ANDROID_VERSION_NAME }} | |
| ANDROID_VERSION_CODE: ${{ env.ANDROID_VERSION_CODE }} | |
| run: chmod +x gradlew && ./gradlew :app:assembleRelease --stacktrace | |
| - name: Prepare release files | |
| run: | | |
| mkdir -p release-artifacts | |
| APP_NAME="masterdnsvpn" | |
| VERSION_NAME="${ANDROID_VERSION_NAME}" | |
| cp android/app/libs/masterdnsvpn.aar release-artifacts/${APP_NAME}-${VERSION_NAME}-release.aar | |
| for apk in android/app/build/outputs/apk/release/*.apk; do | |
| filename=$(basename "$apk") | |
| if [[ "$filename" == "app-universal-release.apk" ]]; then | |
| suffix="universal" | |
| else | |
| suffix=$(echo "$filename" | sed -E 's|^app-(.*)-release\.apk$|\1|') | |
| fi | |
| cp "$apk" "release-artifacts/${APP_NAME}-${VERSION_NAME}-${suffix}-release.apk" | |
| done | |
| ls -la release-artifacts | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ inputs.tag_name }} | |
| name: ${{ inputs.release_name != '' && inputs.release_name || inputs.tag_name }} | |
| generate_release_notes: true | |
| make_latest: ${{ inputs.make_latest && 'true' || 'false' }} | |
| files: | | |
| release-artifacts/*.aar | |
| release-artifacts/*.apk |