Files
pipu-music/.gitea/workflows/release.yml
T
mrleo1nidandClaude Opus 5.5 42d64cd49f
ci / api (push) Successful in 52s
ci / recommender (push) Successful in 38s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/recommender/Dockerfile, recommender, ) (push) Successful in 32s
ci / mobile (Metro-бандл Android) (push) Successful in 51s
ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 53s
ci / ts (packages + web) (push) Successful in 38s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (apps/web/Dockerfile, web, ) (push) Successful in 57s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, api, api) (push) Successful in 51s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, storage-agent, storage-agent) (push) Successful in 53s
release / verify (push) Successful in 1m11s
release / android + release (push) Canceled after 24m53s
fix(mobile): keep Metro out of the native android/ios build directories
Expo's monorepo config watches all of apps/mobile, so during the release
build Metro crawled and hashed gigabytes of Gradle/CMake intermediates in
android/ and the createBundleReleaseJsAndAssets task appeared to hang.
Run the release build with CI=1 (no file watcher) and NODE_ENV=production.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 01:28:57 +03:00

152 lines
7.2 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Релиз по тегу vMAJOR.MINOR.PATCH[-rc.N] (docs/ci-cd.md): проверки → подписанный APK → Gitea Release.
# Docker-образы не публикуются: сервер собирает их сам из клонированного репозитория (deploy/update.sh).
#
# Секреты (Settings → Actions → Secrets):
# RELEASE_TOKEN — создание релиза и загрузка ассетов (scope: write:repository)
# ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS, ANDROID_KEY_PASSWORD — подпись APK
name: release
on:
push:
tags: ["v*.*.*"]
env:
GO_VERSION: "1.24"
NODE_VERSION: "22"
jobs:
verify:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.v.outputs.PIPU_VERSION }}
version_code: ${{ steps.v.outputs.PIPU_VERSION_CODE }}
prerelease: ${{ steps.v.outputs.PIPU_PRERELEASE }}
steps:
- uses: actions/checkout@v4
- id: v
run: node scripts/version.mjs "${GITHUB_REF_NAME}" | tee -a "$GITHUB_OUTPUT"
- uses: actions/setup-go@v5
with: { go-version: "${{ env.GO_VERSION }}", cache-dependency-path: services/api/go.sum }
- uses: astral-sh/setup-uv@v6
with: { version: "0.10.2" }
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "${{ env.NODE_VERSION }}", cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Go
working-directory: services/api
run: go vet ./... && go test ./...
- name: Python
working-directory: services/recommender
run: uv sync --frozen && uv run ruff check . && uv run mypy pipu_rec && uv run pytest -q
- name: TypeScript
run: pnpm i18n:check && pnpm test:scripts && pnpm typecheck && pnpm test
android-release:
name: android + release
needs: verify
runs-on: ubuntu-latest
env:
PIPU_VERSION: ${{ needs.verify.outputs.version }}
PIPU_VERSION_CODE: ${{ needs.verify.outputs.version_code }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: "17" }
- uses: android-actions/setup-android@v3
with:
# пакета `tools` (значение по умолчанию) в репозитории SDK больше нет — sdkmanager падает;
# build-tools нужны шагу подписи (apksigner), версии — как у React Native 0.79
packages: platform-tools platforms;android-35 build-tools;35.0.0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "${{ env.NODE_VERSION }}", cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Свободное место
run: df -h / /tmp
- name: Сборка APK
working-directory: apps/mobile
env:
# CI=1 — Metro без file watcher; NODE_ENV нужен expo для выбора .env-файлов
CI: "1"
NODE_ENV: production
# Только arm64-v8a: C++-часть React Native собирается под каждую ABI, и четыре ABI
# вместе с NDK (~2.5 ГБ) не помещаются на диск раннера. arm64 — все устройства с 2017+.
run: |
npx expo prebuild --platform android --clean --no-install
cd android && ./gradlew --no-daemon assembleRelease -PreactNativeArchitectures=arm64-v8a
- name: Свободное место после сбоя
if: failure()
run: df -h / /tmp; du -sh ~/.gradle ~/.android apps/mobile/android 2>/dev/null || true
- name: Подпись APK
env:
PRERELEASE: ${{ needs.verify.outputs.prerelease }}
KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
set -euo pipefail
src=apps/mobile/android/app/build/outputs/apk/release/app-release.apk
out="pipu-music-${PIPU_VERSION}.apk"
bt="$(ls -d "$ANDROID_HOME"/build-tools/* | sort -V | tail -1)"
if [ -n "${KEYSTORE_B64}" ]; then
echo "$KEYSTORE_B64" | base64 -d > release.keystore
"$bt/apksigner" sign --ks release.keystore --ks-pass env:KEYSTORE_PASSWORD \
--ks-key-alias "$KEY_ALIAS" --key-pass env:KEY_PASSWORD --out "$out" "$src"
rm release.keystore
elif [ "$PRERELEASE" = "true" ]; then
echo "::warning::ANDROID_KEYSTORE_BASE64 не задан — APK подписан отладочным ключом и не обновится поверх релизного"
cp "$src" "$out"
else
echo "::error::ANDROID_KEYSTORE_BASE64 не задан — релиз с отладочной подписью не выпускается (rc-теги допускают)"
exit 1
fi
"$bt/apksigner" verify --print-certs "$out" | head -3
sha256sum "$out" | cut -d' ' -f1 > "$out.sha256"
echo "APK=$out" >> "$GITHUB_ENV"
- name: Changelog
env:
PRERELEASE: ${{ needs.verify.outputs.prerelease }}
run: |
# для финального релиза — изменения с прошлого финального, а не с последнего rc
exclude=()
[ "$PRERELEASE" = "true" ] || exclude=(--exclude '*-rc*')
prev="$(git describe --tags --abbrev=0 "${exclude[@]}" "${GITHUB_REF_NAME}^" 2>/dev/null || true)"
range="${prev:+$prev..}${GITHUB_REF_NAME}"
{
echo "## Pipu Music ${PIPU_VERSION}"
echo
for t in feat fix perf refactor docs ci chore; do
lines="$(git log --no-merges --format='%s' "$range" | grep -E "^${t}(\(|:|!)" || true)"
[ -n "$lines" ] || continue
case $t in feat) h="Новое";; fix) h="Исправления";; perf) h="Производительность";; *) h="$t";; esac
echo "### $h"; echo "$lines" | sed 's/^/- /'; echo
done
} > CHANGELOG_RELEASE.md
cat CHANGELOG_RELEASE.md
- name: Gitea Release
env:
TOKEN: ${{ secrets.RELEASE_TOKEN }}
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
PRERELEASE: ${{ needs.verify.outputs.prerelease }}
run: |
set -euo pipefail
body="$(jq -n --arg tag "$GITHUB_REF_NAME" --arg name "Pipu Music $PIPU_VERSION" \
--rawfile notes CHANGELOG_RELEASE.md --argjson pre "$PRERELEASE" \
'{tag_name:$tag, name:$name, body:$notes, prerelease:$pre, draft:false}')"
id="$(curl -fsS -X POST -H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
-d "$body" "$API/releases" | jq -r .id)"
for f in "$APK" "$APK.sha256"; do
curl -fsS -X POST -H "Authorization: token $TOKEN" \
-F "attachment=@$f" "$API/releases/$id/assets?name=$(basename "$f")" > /dev/null
echo "uploaded $(basename "$f")"
done