# CI/CD (Gitea Actions) Workflows лежат в `.gitea/workflows/`. Синтаксис совместим с GitHub Actions; runner — существующий `act_runner` с доступом к Docker. ## Версионирование - SemVer, тег `vMAJOR.MINOR.PATCH` (предрелизы: `v1.2.0-rc.1` — помечаются как pre-release, мобильное их предлагает только при включённой настройке «бета-версии»). - Одна версия на весь продукт: образы, APK и веб собираются с одним номером. - Android `versionCode = MAJOR·1 000 000 + MINOR·10 000 + PATCH·100 + (99 для релиза | N для -rc.N)`, так что `1.2.0-rc.1 < 1.2.0-rc.2 < 1.2.0 < 1.2.1`; MINOR и PATCH ≤ 99. Считает `scripts/version.mjs` (тесты — `pnpm test:scripts`). - Changelog — `git-cliff` из Conventional Commits. ## `ci.yml` — на каждый push и PR ```yaml on: push: { branches: [main] } pull_request: jobs: changes: # фильтр путей: api / recommender / web / mobile / packages / docs contract: # spectral lint openapi.yaml; регенерация Go + TS клиентов; git diff --exit-code api: # go vet, golangci-lint, go test -race ./... (testcontainers), покрытие recommender: # uv sync; ruff; mypy --strict; pytest (вкл. оффлайн-оценку качества) ts: # pnpm install --frozen-lockfile; turbo lint typecheck test; i18n:check web-build: # vite build, проверка размера бандла mobile-check: # tsc, jest, expo prebuild + ./gradlew assembleDebug (только если менялся mobile/) e2e: # needs: api, web-build; docker compose -f deploy/compose.test.yaml up; playwright test ``` - Кэши: Go modules / build cache, pnpm store, uv cache, Gradle, сгенерированные тестовые аудио. - Ветка `main` защищена: обязательны `contract`, `api`, `recommender`, `ts`, `e2e`. - Ночью (`schedule`) — Maestro E2E на эмуляторе и полный прогон без фильтров путей. ## `release.yml` — по тегу ```yaml on: push: tags: ['v*.*.*'] jobs: verify: # все проверки ci.yml (reusable workflow) images: # needs: verify strategy: { matrix: { service: [api, storage-agent, recommender, web] } } # docker buildx build --push # ${REGISTRY}/${OWNER}/pipu-music-${service}:${VERSION} и :latest (кроме pre-release) # web-образ = nginx + собранная SPA + конфиг android: # needs: verify # setup-java 17, Android SDK, pnpm install # VERSION / VERSION_CODE из тега → app.config.ts # expo prebuild --platform android --clean # ./gradlew assembleRelease (signingConfig из секретов) # apksigner verify; sha256sum > pipu-music-${VERSION}.apk.sha256 release: # needs: [images, android] # git-cliff --latest > CHANGELOG_RELEASE.md # создать Gitea Release через API (POST /repos/{owner}/{repo}/releases), prerelease по суффиксу # загрузить ассеты: APK, .sha256, deploy/compose.yaml, deploy/.env.example ``` ## Секреты | Секрет | Назначение | |---|---| | `REGISTRY_USER`, `REGISTRY_TOKEN` | Push в Gitea Container Registry | | `RELEASE_TOKEN` | Создание релиза и загрузка ассетов | | `ANDROID_KEYSTORE_BASE64`, `ANDROID_KEYSTORE_PASSWORD`, `ANDROID_KEY_ALIAS`, `ANDROID_KEY_PASSWORD` | Подпись APK. **Ключ один на всю жизнь приложения** — хранить резервную копию вне Gitea. | ## Деплой Автодеплой не обязателен. Рекомендуемый вариант: на сервере `deploy/update.sh ` — `docker compose pull && docker compose up -d` с `PIPU_VERSION=`; миграции применяются при старте `api`. Опционально — job `deploy` в `release.yml` по SSH на сервер для не-pre-release тегов (с ручным approval через environment).