feat: M0 monorepo skeleton with services, clients, deploy and CI
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>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-19 23:55:11 +03:00
1 parent 9eb1c25147
commit ebf296542c
98 files changed
+12130 -4

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Детерминированно генерирует тестовую библиотеку (docs/testing.md#тестовая-музыка) в tests/fixtures/music/out.
# Реальная музыка в репозиторий не кладётся: звук — синусы и шум разного темпа, теги — вымышленные.
# Требуется ffmpeg. Запуск: tests/fixtures/music/generate.sh [out_dir]
set -euo pipefail
OUT="${1:-$(dirname "$0")/out}"
rm -rf "$OUT"
mkdir -p "$OUT"
# Метроном с заданным BPM: короткие щелчки на синусе — даёт стабильный темп для проверки анализа.
tone() { # tone <file> <freq> <bpm> <seconds> [ffmpeg metadata args...]
local file="$1" freq="$2" bpm="$3" secs="$4"; shift 4
mkdir -p "$(dirname "$file")"
ffmpeg -nostdin -loglevel error -y \
-f lavfi -i "sine=frequency=${freq}:duration=${secs}:sample_rate=44100" \
-f lavfi -i "sine=frequency=1800:duration=${secs}:sample_rate=44100" \
-filter_complex "[1]volume='if(lt(mod(t,60/${bpm}),0.03),1,0)':eval=frame[clk];[0][clk]amix=inputs=2:normalize=0[a]" \
-map "[a]" -ac 2 "$@" -map_metadata -1 -fflags +bitexact -flags:a +bitexact "$file"
}
meta() { # meta artist album year track title [genre]
local args=(-metadata "artist=$1" -metadata "album_artist=$1" -metadata "album=$2" -metadata "date=$3" -metadata "track=$4" -metadata "title=$5")
[ -n "${6:-}" ] && args+=(-metadata "genre=$6")
printf '%s\n' "${args[@]}"
}
with_meta() { # with_meta <file> <freq> <bpm> <secs> <artist> <album> <year> <track> <title> <genre|""> [encoder args...]
local file="$1" freq="$2" bpm="$3" secs="$4"; shift 4
mapfile -t m < <(meta "$1" "$2" "$3" "$4" "$5" "$6")
shift 6
tone "$file" "$freq" "$bpm" "$secs" "${m[@]}" "$@"
}
# 1. Структура «Исполнитель/Год - Альбом/NN - Название» — полные теги, разные форматы.
with_meta "$OUT/Тестовый Ансамбль/2019 - Первый альбом/01 - Утро.flac" 440 90 8 "Тестовый Ансамбль" "Первый альбом" 2019 1 "Утро" "Rock"
with_meta "$OUT/Тестовый Ансамбль/2019 - Первый альбом/02 - День.flac" 494 128 8 "Тестовый Ансамбль" "Первый альбом" 2019 2 "День" "Rock"
with_meta "$OUT/Тестовый Ансамбль/2019 - Первый альбом/03 - Вечер.flac" 523 170 8 "Тестовый Ансамбль" "Первый альбом" 2019 3 "Вечер" "Rock"
with_meta "$OUT/Test Collective/2021 - Second Album/01 - Signal.mp3" 330 120 6 "Test Collective" "Second Album" 2021 1 "Signal" "Electronic" -b:a 192k
with_meta "$OUT/Test Collective/2021 - Second Album/02 - Noise.opus" 349 140 6 "Test Collective" "Second Album" 2021 2 "Noise" "Electronic" -b:a 96k
with_meta "$OUT/Test Collective/2021 - Second Album/03 - Drift.m4a" 392 100 6 "Test Collective" "Second Album" 2021 3 "Drift" "Electronic" -c:a aac -b:a 160k
# 2. Многодисковый альбом: «1-01 - …».
with_meta "$OUT/Тестовый Ансамбль/2020 - Двойной/1-01 - Сторона А.mp3" 587 110 5 "Тестовый Ансамбль" "Двойной" 2020 1 "Сторона А" "" -b:a 128k
with_meta "$OUT/Тестовый Ансамбль/2020 - Двойной/2-01 - Сторона Б.mp3" 622 115 5 "Тестовый Ансамбль" "Двойной" 2020 1 "Сторона Б" "" -b:a 128k
# 3. Без тегов — данные только из пути (проверка регэкспов).
tone "$OUT/Безымянный/2018 - Только путь/01 - Без тегов.flac" 660 95 5
tone "$OUT/Безымянный/2018 - Только путь/02 - Тоже без тегов.mp3" 698 105 5 -b:a 128k
# 4. Другая структура: «Жанр/Исполнитель/Альбом (Год)/NN. Название».
with_meta "$OUT/Jazz/Quiet Trio/Night Set (2015)/01. Blue.flac" 262 75 6 "Quiet Trio" "Night Set" 2015 1 "Blue" "Jazz"
# 5. Сборник: «Compilations/Альбом/NN - Исполнитель - Название».
with_meta "$OUT/Compilations/Best Of Tests/01 - Test Collective - Signal (Edit).mp3" 330 120 4 "Test Collective" "Best Of Tests" 2022 1 "Signal (Edit)" "" -b:a 192k
# 6. Дубли: та же запись в другом формате и точная копия файла (проверка дедупликации).
with_meta "$OUT/_dupes/День (mp3).mp3" 494 128 8 "Тестовый Ансамбль" "Первый альбом" 2019 2 "День" "Rock" -b:a 192k
mkdir -p "$OUT/_dupes/copy"
cp "$OUT/Тестовый Ансамбль/2019 - Первый альбом/01 - Утро.flac" "$OUT/_dupes/copy/01 - Утро.flac"
# 7. Мусор, который сканер должен пропустить или пометить ошибкой.
printf 'not audio' > "$OUT/Безымянный/2018 - Только путь/broken.mp3"
printf 'cover' > "$OUT/Тестовый Ансамбль/2019 - Первый альбом/notes.txt"
echo "generated $(find "$OUT" -type f | wc -l) files in $OUT"