fix and update
This commit is contained in:
@@ -74,4 +74,6 @@ DATA_ENCRYPTION_KEY=change-me-data-encryption-key-32-chars-min
|
|||||||
# NPM registry (опционально)
|
# NPM registry (опционально)
|
||||||
NPM_REGISTRY=https://registry.npmjs.org
|
NPM_REGISTRY=https://registry.npmjs.org
|
||||||
|
|
||||||
|
# Android APK (tauri_app): keystore создаётся автоматически в tauri_app/.secrets/ при ./install.sh --build-apk
|
||||||
|
|
||||||
COMPOSE_PROJECT_NAME=lendry-id
|
COMPOSE_PROJECT_NAME=lendry-id
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -20,3 +20,4 @@ apps/media-ws/media-ws.exe
|
|||||||
tauri_app/docker/agp-resolver/.gradle/
|
tauri_app/docker/agp-resolver/.gradle/
|
||||||
tauri_app/docker/agp-resolver/build/
|
tauri_app/docker/agp-resolver/build/
|
||||||
tauri_app/docker/offline-gradle/*.zip
|
tauri_app/docker/offline-gradle/*.zip
|
||||||
|
tauri_app/.secrets/
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function GET() {
|
|||||||
const apkPath = resolveApkPath();
|
const apkPath = resolveApkPath();
|
||||||
if (!apkPath) {
|
if (!apkPath) {
|
||||||
return new Response(
|
return new Response(
|
||||||
'APK ещё не собран. Запустите: docker compose up --build tauri-apk-builder. После сборки файл появится как apps/frontend/public/downloads/lendry-id.apk.',
|
'APK ещё не собран. Запустите: ./install.sh --build-apk (или пункт 12 в меню). После сборки файл появится как apps/frontend/public/downloads/lendry-id.apk.',
|
||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
67
install.sh
67
install.sh
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_VERSION="2.6.4"
|
SCRIPT_VERSION="2.6.5"
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
@@ -83,6 +83,7 @@ ${BOLD}Lendry ID v${SCRIPT_VERSION}${NC} — установка и управл
|
|||||||
./install.sh --fix-all Комплексное исправление: 502, прокси, порты, Nginx
|
./install.sh --fix-all Комплексное исправление: 502, прокси, порты, Nginx
|
||||||
./install.sh --status Статус сервисов
|
./install.sh --status Статус сервисов
|
||||||
./install.sh --reset-db Сброс PostgreSQL (новый пароль из .env, данные удалятся)
|
./install.sh --reset-db Сброс PostgreSQL (новый пароль из .env, данные удалятся)
|
||||||
|
./install.sh --build-apk Собрать подписанный Android APK (tauri_app → frontend/public/downloads)
|
||||||
./install.sh --remove-nginx Удалить конфиги Nginx IdP
|
./install.sh --remove-nginx Удалить конфиги Nginx IdP
|
||||||
|
|
||||||
${BOLD}Режим локальной сети (без интернета / AD-домены .local .lpr):${NC}
|
${BOLD}Режим локальной сети (без интернета / AD-домены .local .lpr):${NC}
|
||||||
@@ -170,6 +171,8 @@ parse_args() {
|
|||||||
--fix-all) ACTION="fix-all"; shift ;;
|
--fix-all) ACTION="fix-all"; shift ;;
|
||||||
--status) ACTION="status"; shift ;;
|
--status) ACTION="status"; shift ;;
|
||||||
--reset-db) ACTION="reset-db"; shift ;;
|
--reset-db) ACTION="reset-db"; shift ;;
|
||||||
|
--build-apk) ACTION="build-apk"; shift ;;
|
||||||
|
--remove-nginx) ACTION="remove-nginx"; shift ;;
|
||||||
--local) INSTALL_LOCAL=1; shift ;;
|
--local) INSTALL_LOCAL=1; shift ;;
|
||||||
--intranet) INSTALL_INTRANET=1; shift ;;
|
--intranet) INSTALL_INTRANET=1; shift ;;
|
||||||
--offline) OFFLINE=1; shift ;;
|
--offline) OFFLINE=1; shift ;;
|
||||||
@@ -4470,6 +4473,63 @@ action_fix_all_errors() {
|
|||||||
show_status
|
show_status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_build_tauri_apk() {
|
||||||
|
local image="${TAURI_APK_IMAGE:-lendry-id-tauri-apk-builder}"
|
||||||
|
local output_dir="${ROOT_DIR}/apps/frontend/public/downloads"
|
||||||
|
local output_apk="${output_dir}/lendry-id.apk"
|
||||||
|
local secrets_dir="${ROOT_DIR}/tauri_app/.secrets"
|
||||||
|
local public_api public_frontend npm_registry
|
||||||
|
|
||||||
|
load_env
|
||||||
|
public_api="$(env_get PUBLIC_API_URL "http://localhost:3000")"
|
||||||
|
public_frontend="$(env_get PUBLIC_FRONTEND_URL "http://localhost:3002")"
|
||||||
|
npm_registry="$(env_get NPM_REGISTRY "https://registry.npmjs.org")"
|
||||||
|
|
||||||
|
mkdir -p "${output_dir}" "${secrets_dir}"
|
||||||
|
chmod 700 "${secrets_dir}" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}Сборка подписанного Android APK (Tauri)${NC}"
|
||||||
|
echo " API: ${public_api}"
|
||||||
|
echo " Frontend: ${public_frontend}"
|
||||||
|
echo " Выход: ${output_apk}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ "${OFFLINE}" -eq 1 ]]; then
|
||||||
|
warn "OFFLINE=1: образ APK-builder должен быть уже собран локально"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Шаг 1/3: Docker-образ tauri_app (Android SDK + NDK)..."
|
||||||
|
configure_docker_build_env
|
||||||
|
docker_cmd build \
|
||||||
|
-f "${ROOT_DIR}/tauri_app/Dockerfile.apk" \
|
||||||
|
-t "${image}" \
|
||||||
|
--build-arg "NPM_REGISTRY=${npm_registry}" \
|
||||||
|
"${ROOT_DIR}"
|
||||||
|
|
||||||
|
log "Шаг 2/3: Сборка release APK с подписью..."
|
||||||
|
docker_cmd run --rm \
|
||||||
|
-v "${output_dir}:/out" \
|
||||||
|
-v "${secrets_dir}:/workspace/tauri_app/.secrets" \
|
||||||
|
-e "PUBLIC_API_URL=${public_api}" \
|
||||||
|
-e "PUBLIC_FRONTEND_URL=${public_frontend}" \
|
||||||
|
-e "VITE_API_URL=${public_api}" \
|
||||||
|
-e "VITE_FRONTEND_URL=${public_frontend}" \
|
||||||
|
"${image}"
|
||||||
|
|
||||||
|
log "Шаг 3/3: Проверка результата..."
|
||||||
|
[[ -f "${output_apk}" ]] || fail "APK не найден после сборки: ${output_apk}"
|
||||||
|
|
||||||
|
ok "Подписанный APK готов: ${output_apk}"
|
||||||
|
ls -lh "${output_apk}" 2>/dev/null || true
|
||||||
|
if [[ -f "${secrets_dir}/signing-credentials.env" ]]; then
|
||||||
|
warn "Пароли keystore: ${secrets_dir}/signing-credentials.env (не коммитьте в git)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo " Скачивание на сайте: /download/android"
|
||||||
|
echo " Перезапустите frontend, если контейнер уже работает: ./install.sh --restart"
|
||||||
|
}
|
||||||
|
|
||||||
action_restart() {
|
action_restart() {
|
||||||
load_env
|
load_env
|
||||||
prepare_compose_stack
|
prepare_compose_stack
|
||||||
@@ -4496,6 +4556,7 @@ show_menu() {
|
|||||||
echo " 3) SSL-сертификаты (обновить / включить custom / Let's Encrypt)"
|
echo " 3) SSL-сертификаты (обновить / включить custom / Let's Encrypt)"
|
||||||
echo " 4) Перезапуск / пересборка контейнеров (+ очистка Docker)"
|
echo " 4) Перезапуск / пересборка контейнеров (+ очистка Docker)"
|
||||||
echo " 11) Миграция БД и пересборка (после git pull)"
|
echo " 11) Миграция БД и пересборка (после git pull)"
|
||||||
|
echo " 12) Собрать Android APK (Tauri, подписанный → frontend/public/downloads)"
|
||||||
echo " 5) Статус сервисов"
|
echo " 5) Статус сервисов"
|
||||||
echo " 6) Удалить конфиги Nginx IdP"
|
echo " 6) Удалить конфиги Nginx IdP"
|
||||||
echo " 7) Сброс PostgreSQL (если ошибка P1000 / пароль БД)"
|
echo " 7) Сброс PostgreSQL (если ошибка P1000 / пароль БД)"
|
||||||
@@ -4505,7 +4566,7 @@ show_menu() {
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
local choice
|
local choice
|
||||||
read -r -p "Выберите пункт [0-11]: " choice
|
read -r -p "Выберите пункт [0-12]: " choice
|
||||||
|
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
1) NON_INTERACTIVE=0; action_full_install ;;
|
1) NON_INTERACTIVE=0; action_full_install ;;
|
||||||
@@ -4514,6 +4575,7 @@ show_menu() {
|
|||||||
3) action_renew_ssl ;;
|
3) action_renew_ssl ;;
|
||||||
4) action_restart ;;
|
4) action_restart ;;
|
||||||
11) action_migrate_rebuild ;;
|
11) action_migrate_rebuild ;;
|
||||||
|
12) action_build_tauri_apk ;;
|
||||||
5) show_status ;;
|
5) show_status ;;
|
||||||
6) remove_nginx_configs; ok "Готово" ;;
|
6) remove_nginx_configs; ok "Готово" ;;
|
||||||
7) action_reset_db; action_restart ;;
|
7) action_reset_db; action_restart ;;
|
||||||
@@ -4540,6 +4602,7 @@ main() {
|
|||||||
renew-ssl) action_renew_ssl ;;
|
renew-ssl) action_renew_ssl ;;
|
||||||
restart) action_restart ;;
|
restart) action_restart ;;
|
||||||
migrate-rebuild) action_migrate_rebuild ;;
|
migrate-rebuild) action_migrate_rebuild ;;
|
||||||
|
build-apk) action_build_tauri_apk ;;
|
||||||
fix-host-nginx|fix-docker-nginx) action_fix_docker_nginx ;;
|
fix-host-nginx|fix-docker-nginx) action_fix_docker_nginx ;;
|
||||||
docker-prune) action_docker_prune ;;
|
docker-prune) action_docker_prune ;;
|
||||||
fix-proxy) action_fix_host_proxy ;;
|
fix-proxy) action_fix_host_proxy ;;
|
||||||
|
|||||||
@@ -30,22 +30,39 @@ npm --workspace @lendry/tauri-app run ios:init
|
|||||||
|
|
||||||
## Docker APK build
|
## Docker APK build
|
||||||
|
|
||||||
При запуске общего `docker compose up --build` сервис `tauri-apk-builder` собирает Android APK и кладёт файл сюда:
|
Сборка подписанного release APK через `install.sh` (Docker + Android SDK + release keystore):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./install.sh --build-apk
|
||||||
|
```
|
||||||
|
|
||||||
|
Или пункт **12** в интерактивном меню `./install.sh`.
|
||||||
|
|
||||||
|
Готовый файл:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
apps/frontend/public/downloads/lendry-id.apk
|
apps/frontend/public/downloads/lendry-id.apk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Keystore и пароли создаются автоматически при первой сборке и сохраняются в `tauri_app/.secrets/` (не коммитятся в git).
|
||||||
|
|
||||||
После этого кнопка «Скачать приложение» на странице входа скачивает APK через:
|
После этого кнопка «Скачать приложение» на странице входа скачивает APK через:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
/download/android
|
/download/android
|
||||||
```
|
```
|
||||||
|
|
||||||
Собрать только APK:
|
Собрать только через Docker-образ (без install.sh):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up --build tauri-apk-builder
|
docker build -f tauri_app/Dockerfile.apk -t lendry-id-tauri-apk-builder .
|
||||||
|
mkdir -p apps/frontend/public/downloads tauri_app/.secrets
|
||||||
|
docker run --rm \
|
||||||
|
-v "$(pwd)/apps/frontend/public/downloads:/out" \
|
||||||
|
-v "$(pwd)/tauri_app/.secrets:/workspace/tauri_app/.secrets" \
|
||||||
|
-e PUBLIC_API_URL=https://sso.example.ru/idp-api \
|
||||||
|
-e PUBLIC_FRONTEND_URL=https://sso.example.ru \
|
||||||
|
lendry-id-tauri-apk-builder
|
||||||
```
|
```
|
||||||
|
|
||||||
## Переменные окружения
|
## Переменные окружения
|
||||||
|
|||||||
@@ -50,17 +50,26 @@ echo "==> Настройка Android SDK (offline, без загрузки platf
|
|||||||
echo "==> Настройка offline Gradle wrapper (если bundled zip доступен)"
|
echo "==> Настройка offline Gradle wrapper (если bundled zip доступен)"
|
||||||
/workspace/tauri_app/docker/install-offline-gradle.sh /workspace/tauri_app/src-tauri/gen/android
|
/workspace/tauri_app/docker/install-offline-gradle.sh /workspace/tauri_app/src-tauri/gen/android
|
||||||
|
|
||||||
echo "==> Сборка Android APK"
|
echo "==> Подготовка keystore для release-подписи APK"
|
||||||
|
/workspace/tauri_app/docker/ensure-android-keystore.sh
|
||||||
|
/workspace/tauri_app/docker/patch-android-signing.sh /workspace/tauri_app/src-tauri/gen/android
|
||||||
|
|
||||||
|
echo "==> Сборка Android APK (release, signed)"
|
||||||
npm run tauri -- android build --apk
|
npm run tauri -- android build --apk
|
||||||
|
|
||||||
APK_PATH="$(find /workspace/tauri_app/src-tauri/gen/android -type f -name '*.apk' | sort | tail -n 1 || true)"
|
APK_PATH="$(find /workspace/tauri_app/src-tauri/gen/android -type f -name '*release*.apk' ! -name '*unsigned*' | sort | tail -n 1 || true)"
|
||||||
|
if [[ -z "${APK_PATH}" ]]; then
|
||||||
|
APK_PATH="$(find /workspace/tauri_app/src-tauri/gen/android -type f -name '*.apk' ! -name '*unsigned*' | sort | tail -n 1 || true)"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "${APK_PATH}" ] || [ ! -f "${APK_PATH}" ]; then
|
if [ -z "${APK_PATH}" ] || [ ! -f "${APK_PATH}" ]; then
|
||||||
echo "APK не найден после сборки" >&2
|
echo "APK не найден после сборки" >&2
|
||||||
find /workspace/tauri_app/src-tauri/gen/android -maxdepth 8 -type f | sort >&2 || true
|
find /workspace/tauri_app/src-tauri/gen/android -maxdepth 8 -type f -name '*.apk' | sort >&2 || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
/workspace/tauri_app/docker/verify-apk-signature.sh "${APK_PATH}"
|
||||||
|
|
||||||
cp "${APK_PATH}" /out/lendry-id.apk
|
cp "${APK_PATH}" /out/lendry-id.apk
|
||||||
chmod 0644 /out/lendry-id.apk
|
chmod 0644 /out/lendry-id.apk
|
||||||
|
|
||||||
|
|||||||
79
tauri_app/docker/ensure-android-keystore.sh
Normal file
79
tauri_app/docker/ensure-android-keystore.sh
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Создаёт release keystore для подписи APK, если его ещё нет.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SECRETS_DIR="${ANDROID_SECRETS_DIR:-/workspace/tauri_app/.secrets}"
|
||||||
|
KEYSTORE_FILE="${ANDROID_KEYSTORE_FILE:-${SECRETS_DIR}/lendry-id-release.keystore}"
|
||||||
|
KEY_ALIAS="${ANDROID_KEY_ALIAS:-lendry-id}"
|
||||||
|
CREDENTIALS_FILE="${SECRETS_DIR}/signing-credentials.env"
|
||||||
|
KEYSTORE_PROPS_TEMPLATE="${SECRETS_DIR}/keystore.properties.template"
|
||||||
|
|
||||||
|
mkdir -p "${SECRETS_DIR}"
|
||||||
|
chmod 700 "${SECRETS_DIR}" || true
|
||||||
|
|
||||||
|
if [[ -f "${KEYSTORE_FILE}" ]]; then
|
||||||
|
echo "==> Android keystore уже существует: ${KEYSTORE_FILE}"
|
||||||
|
if [[ ! -f "${PROPS_TEMPLATE}" && -f "${CREDENTIALS_FILE}" ]]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "${CREDENTIALS_FILE}"
|
||||||
|
cat > "${PROPS_TEMPLATE}" <<EOF
|
||||||
|
storePassword=${ANDROID_KEYSTORE_PASSWORD}
|
||||||
|
keyPassword=${ANDROID_KEY_PASSWORD}
|
||||||
|
keyAlias=${ANDROID_KEY_ALIAS}
|
||||||
|
storeFile=../../../.secrets/lendry-id-release.keystore
|
||||||
|
EOF
|
||||||
|
chmod 600 "${PROPS_TEMPLATE}" || true
|
||||||
|
echo "==> Восстановлен keystore.properties.template из signing-credentials.env"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v keytool >/dev/null 2>&1; then
|
||||||
|
echo "keytool не найден — нужен JDK для генерации keystore" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
gen_secret() {
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 24
|
||||||
|
else
|
||||||
|
date +%s%N | sha256sum | head -c 24
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
STORE_PASSWORD="$(gen_secret)"
|
||||||
|
KEY_PASSWORD="$(gen_secret)"
|
||||||
|
|
||||||
|
echo "==> Генерация release keystore для подписи APK..."
|
||||||
|
keytool -genkeypair -v \
|
||||||
|
-storetype PKCS12 \
|
||||||
|
-keystore "${KEYSTORE_FILE}" \
|
||||||
|
-alias "${KEY_ALIAS}" \
|
||||||
|
-keyalg RSA \
|
||||||
|
-keysize 2048 \
|
||||||
|
-validity 10000 \
|
||||||
|
-storepass "${STORE_PASSWORD}" \
|
||||||
|
-keypass "${KEY_PASSWORD}" \
|
||||||
|
-dname "CN=Lendry ID, OU=Mobile, O=Lendry, C=RU"
|
||||||
|
|
||||||
|
chmod 600 "${KEYSTORE_FILE}" || true
|
||||||
|
|
||||||
|
cat > "${CREDENTIALS_FILE}" <<EOF
|
||||||
|
# Сгенерировано $(date -u +"%Y-%m-%dT%H:%M:%SZ") — храните в безопасном месте.
|
||||||
|
ANDROID_KEYSTORE_FILE=${KEYSTORE_FILE}
|
||||||
|
ANDROID_KEY_ALIAS=${KEY_ALIAS}
|
||||||
|
ANDROID_KEYSTORE_PASSWORD=${STORE_PASSWORD}
|
||||||
|
ANDROID_KEY_PASSWORD=${KEY_PASSWORD}
|
||||||
|
EOF
|
||||||
|
chmod 600 "${CREDENTIALS_FILE}" || true
|
||||||
|
|
||||||
|
cat > "${KEYSTORE_PROPS_TEMPLATE}" <<EOF
|
||||||
|
storePassword=${STORE_PASSWORD}
|
||||||
|
keyPassword=${KEY_PASSWORD}
|
||||||
|
keyAlias=${KEY_ALIAS}
|
||||||
|
storeFile=../../../.secrets/lendry-id-release.keystore
|
||||||
|
EOF
|
||||||
|
chmod 600 "${KEYSTORE_PROPS_TEMPLATE}" || true
|
||||||
|
|
||||||
|
echo "==> Keystore создан: ${KEYSTORE_FILE}"
|
||||||
|
echo "==> Пароли сохранены: ${CREDENTIALS_FILE}"
|
||||||
61
tauri_app/docker/patch-android-signing.sh
Normal file
61
tauri_app/docker/patch-android-signing.sh
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Подключает release-подпись APK через keystore.properties + Gradle script.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ANDROID_GEN="${1:-/workspace/tauri_app/src-tauri/gen/android}"
|
||||||
|
SECRETS_DIR="${ANDROID_SECRETS_DIR:-/workspace/tauri_app/.secrets}"
|
||||||
|
KEYSTORE_FILE="${ANDROID_KEYSTORE_FILE:-${SECRETS_DIR}/lendry-id-release.keystore}"
|
||||||
|
APP_GRADLE="${ANDROID_GEN}/app/build.gradle.kts"
|
||||||
|
KEYSTORE_PROPS="${ANDROID_GEN}/keystore.properties"
|
||||||
|
SIGNING_SCRIPT="${ANDROID_GEN}/app/release-signing.gradle.kts"
|
||||||
|
PROPS_TEMPLATE="${SECRETS_DIR}/keystore.properties.template"
|
||||||
|
|
||||||
|
if [[ ! -d "${ANDROID_GEN}" ]]; then
|
||||||
|
echo "Android project not found: ${ANDROID_GEN}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${KEYSTORE_FILE}" ]]; then
|
||||||
|
echo "Keystore не найден: ${KEYSTORE_FILE}. Запустите ensure-android-keystore.sh" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${PROPS_TEMPLATE}" ]]; then
|
||||||
|
cp "${PROPS_TEMPLATE}" "${KEYSTORE_PROPS}"
|
||||||
|
else
|
||||||
|
echo "keystore.properties.template не найден в ${SECRETS_DIR}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 600 "${KEYSTORE_PROPS}" || true
|
||||||
|
|
||||||
|
cat > "${SIGNING_SCRIPT}" <<'EOF'
|
||||||
|
import com.android.build.api.dsl.ApplicationExtension
|
||||||
|
import java.util.Properties
|
||||||
|
|
||||||
|
val keystoreProperties = Properties().apply {
|
||||||
|
rootProject.file("keystore.properties").inputStream().use { load(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.configure<ApplicationExtension>("android") {
|
||||||
|
signingConfigs {
|
||||||
|
create("release") {
|
||||||
|
keyAlias = keystoreProperties.getProperty("keyAlias")
|
||||||
|
keyPassword = keystoreProperties.getProperty("keyPassword")
|
||||||
|
storeFile = rootProject.file(keystoreProperties.getProperty("storeFile"))
|
||||||
|
storePassword = keystoreProperties.getProperty("storePassword")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
getByName("release") {
|
||||||
|
signingConfig = signingConfigs.getByName("release")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if ! grep -q 'release-signing.gradle.kts' "${APP_GRADLE}"; then
|
||||||
|
printf '\napply(from = "release-signing.gradle.kts")\n' >> "${APP_GRADLE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Android release signing patched (${KEYSTORE_PROPS})"
|
||||||
21
tauri_app/docker/verify-apk-signature.sh
Normal file
21
tauri_app/docker/verify-apk-signature.sh
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
APK_PATH="${1:-}"
|
||||||
|
ANDROID_HOME="${ANDROID_HOME:-/opt/android-sdk}"
|
||||||
|
|
||||||
|
if [[ -z "${APK_PATH}" || ! -f "${APK_PATH}" ]]; then
|
||||||
|
echo "APK не найден для проверки подписи: ${APK_PATH}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
APKSIGNER="$(find "${ANDROID_HOME}/build-tools" -name apksigner -type f 2>/dev/null | sort -V | tail -n 1 || true)"
|
||||||
|
|
||||||
|
if [[ -z "${APKSIGNER}" ]]; then
|
||||||
|
echo "apksigner не найден в ${ANDROID_HOME}/build-tools" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Проверка подписи APK: ${APK_PATH}"
|
||||||
|
"${APKSIGNER}" verify --verbose "${APK_PATH}"
|
||||||
|
echo "==> Подпись APK подтверждена (apksigner verify)"
|
||||||
Reference in New Issue
Block a user