Files
pipu-music/docs/ci-cd.md
T
mrleo1nidandClaude Opus 5.5 58fd82e52b
ci / api (push) Successful in 50s
ci / recommender (push) Successful in 37s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/recommender/Dockerfile, recommender, ) (push) Successful in 28s
ci / mobile (Metro-бандл Android) (push) Successful in 51s
ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 46s
ci / ts (packages + web) (push) Successful in 41s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (apps/web/Dockerfile, web, ) (push) Successful in 44s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, api, api) (push) Successful in 52s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, storage-agent, storage-agent) (push) Successful in 1m20s
release / verify (push) Successful in 1m16s
release / android + release (push) Canceled after 25m58s
ci(release): build the APK for arm64-v8a only and report disk usage
The v0.1.2 release ran out of disk while Gradle unpacked the NDK; building
React Native's native code for four ABIs needs several more GB. Print df
before the build and after a failure to make the next shortage obvious.

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

4.8 KiB
Raw Permalink Blame History

CI/CD (Gitea Actions)

Workflows лежат в .gitea/workflows/. Синтаксис совместим с GitHub Actions; runner — существующий act_runner с доступом к Docker.

Сборке APK нужно ~15 ГБ свободного места на хосте раннера (Android SDK, NDK ~2.5 ГБ, кэш Gradle, C++-сборка React Native). APK собирается только под arm64-v8a. Если job падает с No space left on device, освободите место на хосте раннера: docker system prune -af и старые кэши act в ~/.cache/act.

Версионирование

  • 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

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, проверка размера бандла
  docker:          # сборка всех Docker-образов без push (сервер собирает их сам — ADR-013)
  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 — по тегу

on:
  push:
    tags: ['v*.*.*']

jobs:
  verify:          # все проверки ci.yml (reusable workflow)

  android-release: # 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

    # changelog из Conventional Commits между тегами
    # создать Gitea Release через API (POST /repos/{owner}/{repo}/releases), prerelease по суффиксу
    # загрузить ассеты: APK и .sha256

Docker-образы не публикуются: сервер собирает их сам из клонированного репозитория (ADR-013). Чтобы сборка на сервере не ломалась, job docker в ci.yml собирает все образы без push на каждый PR.

Секреты

Секрет Назначение
RELEASE_TOKEN Создание релиза и загрузка ассетов
ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS, ANDROID_KEY_PASSWORD Подпись APK. Ключ один на всю жизнь приложения — хранить резервную копию вне Gitea. Без них финальный релиз падает; -rc собирается с отладочной подписью.

Деплой

Автодеплой не обязателен. На сервере в клоне репозитория: deploy/update.sh [vX.Y.Z] — checkout тега, docker compose build и up -d; миграции применяются при старте api (install-guide.md). Опционально — job deploy в release.yml по SSH на сервер для не-pre-release тегов (с ручным approval через environment).