ZapretKVN-android/.github/workflows/release.yml
2026-07-24 23:20:48 +03:00

252 lines
10 KiB
YAML

name: Verify published stable
on:
workflow_dispatch:
inputs:
tag:
description: Existing locally published stable tag
required: true
type: string
permissions:
contents: read
concurrency:
group: verify-release-${{ inputs.tag || github.ref_name }}
cancel-in-progress: false
jobs:
verify:
runs-on: ubuntu-latest
timeout-minutes: 180
env:
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
ZAPRET_UPDATE_REPOSITORY: ${{ github.repository }}
ZAPRET_REQUIRE_SIGNED_RELEASE: "1"
steps:
- name: Checkout exact release tag
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
ref: ${{ inputs.tag || github.ref }}
- name: Set up OpenJDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
distribution: temurin
java-version: "17"
- name: Read pinned versions and release version
id: versions
shell: bash
run: |
source core.properties
echo "go=$GO_VERSION" >> "$GITHUB_OUTPUT"
echo "android_compile_sdk=$ANDROID_COMPILE_SDK" >> "$GITHUB_OUTPUT"
scripts/derive-release-version.sh "$RELEASE_TAG" >> "$GITHUB_ENV"
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version: ${{ steps.versions.outputs.go }}
cache: false
- name: Set up Android SDK
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3
- name: Install pinned Android packages
shell: bash
run: |
source core.properties
sdkmanager --licenses >/dev/null < <(yes)
sdkmanager \
"platforms;android-$ANDROID_COMPILE_SDK" \
"build-tools;$ANDROID_BUILD_TOOLS" \
"ndk;$ANDROID_NDK_VERSION"
- name: Set up Gradle cache
uses: gradle/actions/setup-gradle@0b6dd653ba04f4f93bf581ec31e66cbd7dcb644d # v4
- name: Set up native core artifact cache
id: core-artifacts
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
app/libs/libbox.aar
app/libs/libbox.properties
core-build/output
key: native-core-artifacts-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('core.properties', 'core-patches/**', 'scripts/core-patchset.sh', 'scripts/build-core.sh', 'scripts/build-native-symbols.sh', 'scripts/verify-core-cache.sh', 'scripts/verify-core-version.sh', 'scripts/verify-fixtures.sh', 'audit/*.go', 'testdata/**', 'app/src/main/assets/rule-sets/**', 'app/src/main/res/raw/sing_box_extended_license.txt') }}
- name: Set up native core toolchain cache
if: steps.core-artifacts.outputs.cache-hit != 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
~/.cache/go-build
core-build/gopath/bin
core-build/gopath/pkg/mod
core-build/source
key: native-core-toolchain-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('core.properties') }}
restore-keys: |
native-core-toolchain-${{ runner.os }}-${{ runner.arch }}-v1-
- name: Create ephemeral verification key
shell: bash
run: |
keytool -genkeypair \
-keystore "$RUNNER_TEMP/verification-release.jks" \
-storepass verification-only \
-keypass verification-only \
-alias verification \
-keyalg RSA \
-keysize 3072 \
-validity 2 \
-dname "CN=Zapret KVN background verification" \
>/dev/null 2>&1
chmod 600 "$RUNNER_TEMP/verification-release.jks"
- name: Verify, test and build signed APK
env:
ZAPRET_SIGNING_STORE_FILE: ${{ runner.temp }}/verification-release.jks
ZAPRET_SIGNING_STORE_PASSWORD: verification-only
ZAPRET_SIGNING_KEY_ALIAS: verification
ZAPRET_SIGNING_KEY_PASSWORD: verification-only
ZAPRET_CORE_CACHE_HIT: ${{ steps.core-artifacts.outputs.cache-hit }}
run: scripts/ci-build.sh
- name: Free runner disk for Android emulator
shell: bash
run: |
df -h /
sudo rm -rf -- \
/usr/share/dotnet \
/opt/ghc \
/usr/local/share/boost \
/opt/hostedtoolcache/CodeQL
sudo apt-get clean
df -h /
- name: Resolve Android emulator cache path
id: android-emulator
shell: bash
run: echo "sdk_root=$ANDROID_SDK_ROOT" >> "$GITHUB_OUTPUT"
- name: Restore Android emulator packages
id: android-emulator-packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
${{ steps.android-emulator.outputs.sdk_root }}/emulator
${{ steps.android-emulator.outputs.sdk_root }}/system-images/android-${{ steps.versions.outputs.android_compile_sdk }}/google_apis/x86_64
key: android-emulator-${{ runner.os }}-${{ runner.arch }}-api${{ steps.versions.outputs.android_compile_sdk }}-google-apis-x86_64-v1
- name: Install or verify Android emulator packages
shell: bash
run: |
source core.properties
if [[ "${{ steps.android-emulator-packages.outputs.cache-hit }}" != true ]]; then
sdkmanager \
"platform-tools" \
"emulator" \
"system-images;android-$ANDROID_COMPILE_SDK;google_apis;x86_64"
else
echo "Using cached Android emulator and API $ANDROID_COMPILE_SDK system image"
fi
test -x "$ANDROID_SDK_ROOT/emulator/emulator"
test -f "$ANDROID_SDK_ROOT/system-images/android-$ANDROID_COMPILE_SDK/google_apis/x86_64/package.xml"
- name: Run Android and no-background-traffic gates
shell: bash
env:
ZAPRET_REQUIRE_SIGNED_RELEASE: "0"
run: |
source core.properties
sudo apt-get update
sudo apt-get install -y socat
export ANDROID_AVD_HOME="$RUNNER_TEMP/android-avd"
mkdir -p "$ANDROID_AVD_HOME"
printf 'no\n' | avdmanager create avd \
--force \
--name release_gate_api36 \
--package "system-images;android-$ANDROID_COMPILE_SDK;google_apis;x86_64"
sudo chown "$(id -un)" /dev/kvm || true
EMULATOR="$ANDROID_SDK_ROOT/emulator/emulator"
test -x "$EMULATOR"
"$EMULATOR" -list-avds | grep -Fx release_gate_api36
: > emulator.log
start_emulator() {
local attempt emulator_pid deadline
for attempt in 1 2; do
echo "Starting Android emulator (attempt $attempt/2)" | tee -a emulator.log
"$EMULATOR" -avd release_gate_api36 -no-window -no-audio -no-boot-anim \
-gpu swiftshader_indirect -no-snapshot -wipe-data >> emulator.log 2>&1 &
emulator_pid=$!
deadline=$((SECONDS + 90))
while (( SECONDS < deadline )); do
if ! kill -0 "$emulator_pid" 2>/dev/null; then
echo "Emulator process exited before ADB became ready" >&2
break
fi
if [[ "$(adb get-state 2>/dev/null || true)" == "device" ]]; then
if timeout 240 bash -c 'until [[ "$(adb shell getprop sys.boot_completed | tr -d "\r")" == 1 ]]; do sleep 2; done'; then
return 0
fi
echo "Emulator did not finish booting within 240 seconds" >&2
break
fi
sleep 2
done
echo "Emulator attempt $attempt failed; recent log follows" >&2
tail -n 200 emulator.log >&2 || true
timeout 10 adb emu kill >/dev/null 2>&1 || true
kill "$emulator_pid" >/dev/null 2>&1 || true
wait "$emulator_pid" >/dev/null 2>&1 || true
adb kill-server >/dev/null 2>&1 || true
done
return 1
}
start_emulator
./gradlew connectedDebugAndroidTest
mkdir -p build/gate6-process-recreation build/gate8-stress
scripts/verify-process-recreation.sh | tee build/gate6-process-recreation/result.txt
scripts/verify-gate8-stress.sh | tee build/gate8-stress/result.txt
scripts/verify-gate8-performance.sh
- name: Verify locally published release assets
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
test "$(gh release view "$RELEASE_TAG" --json isPrerelease --jq .isPrerelease)" = false
mkdir published-release
gh release download "$RELEASE_TAG" --dir published-release
scripts/verify-release-bundle.sh "$RELEASE_TAG" published-release
- name: Upload release proof
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: zapret-kvn-${{ env.RELEASE_TAG }}-proof
if-no-files-found: error
path: |
published-release/**
app/build/permissions.txt
app/build/manifest-tree.txt
app/build/outputs/mapping/release/mapping.txt
core-build/output/core-version.txt
core-build/output/core-build-metadata.json
core-build/output/native-debug-symbols.zip
core-build/output/native-symbols-metadata.json
core-build/output/native-symbols-SHA256SUMS
build/release-candidate/security-report-*.json
build/gate6-process-recreation/**
build/gate8-stress/**
build/gate8-performance/**
app/build/reports/androidTests/connected/**
emulator.log
- name: Remove ephemeral verification key
if: always()
shell: bash
run: |
rm -f "$RUNNER_TEMP/verification-release.jks"
adb emu kill >/dev/null 2>&1 || true