ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 3m55s
ci / api (push) Successful in 51s
ci / mobile (Metro-бандл Android) (push) Canceled after 0s
release / images (services/api/Dockerfile, storage-agent, storage-agent) (push) Canceled after 0s
release / images (services/recommender/Dockerfile, recommender, ) (push) Canceled after 0s
ci / recommender (push) Successful in 1m11s
ci / ts (packages + web) (push) Canceled after 3s
release / verify (push) Successful in 1m16s
release / images (apps/web/Dockerfile, web, ) (push) Failing after 2m40s
release / android + release (push) Skipped
release / images (services/api/Dockerfile, api, api) (push) Canceled after 1s
- api/openapi.yaml: contract with /healthz, /readyz, /api/v1/server-info - services/api (Go): api with oapi-codegen strict server, goose migrations, readiness checks for Postgres/Redis; storage-agent stub with internal token - services/recommender (Python, uv): FastAPI health/readiness/internal status, `pipu-rec serve` and `pipu-rec analyze` entrypoints - packages: generated api-client, core (server URL + server check), i18n (ru/en + dictionary check), design-tokens (CSS vars + TS from tokens.json) - apps/web: Vite + React shell showing server status, language switch - apps/mobile: Expo (SDK 53) Android app with server connect screen - deploy: Dockerfiles, compose (prod + dev), nginx template, install/update scripts - .gitea/workflows: ci.yml and tag-based release.yml (images, signed APK, release) - scripts/version.mjs: version and Android versionCode from git tag - tests/fixtures/music/generate.sh: synthetic test library via ffmpeg - docs: versionCode formula, OpenAPI 3.0.3, dev instructions in README Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
4.2 KiB
Markdown
80 lines
4.2 KiB
Markdown
# 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 <version>` —
|
||
`docker compose pull && docker compose up -d` с `PIPU_VERSION=<version>`; миграции применяются при старте `api`.
|
||
Опционально — job `deploy` в `release.yml` по SSH на сервер для не-pre-release тегов (с ручным approval через environment).
|