ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 48s
ci / api (push) Successful in 51s
ci / recommender (push) Canceled after 2s
ci / ts (packages + web) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (apps/web/Dockerfile, web, ) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, api, api) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, storage-agent, storage-agent) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/recommender/Dockerfile, recommender, ) (push) Canceled after 0s
ci / mobile (Metro-бандл Android) (push) Canceled after 0s
Security and robustness: - storage-agent rejects an empty INTERNAL_TOKEN (config notEmpty + middleware) - api takes the client IP only from X-Real-IP (chi RealIP trusted True-Client-IP) - /readyz reports ok/fail and logs the cause; checks run in parallel with a timeout - storage-agent shuts down gracefully; shared httpx.NewServer/Serve with IdleTimeout - goose migrations take a Postgres advisory lock - recommender readyz: per-check timeout, redis socket timeouts Clients: - Android release allows cleartext HTTP for LAN servers (expo-build-properties) - checkServer times out after 10s; connect button is disabled while checking Deploy and CI: - install.sh hands cache/uploads/updates/models to the non-root service users - update.sh refuses downgrades unless PIPU_ALLOW_DOWNGRADE=1 - recommender/analyzer get only the env they need; required secrets fail fast - nginx security headers and CSP; strip True-Client-IP - dev compose binds ports to 127.0.0.1; postgres/redis images pinned - version.mjs fails on a malformed explicit tag instead of releasing 0.0.0-dev - contract check catches untracked generated files - final releases fail without a release keystore; changelog skips rc tags Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
112 lines
4.0 KiB
YAML
112 lines
4.0 KiB
YAML
# Проверки на каждый push в main и на каждый PR (docs/ci-cd.md).
|
||
name: ci
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
pull_request:
|
||
|
||
concurrency:
|
||
group: ci-${{ github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
env:
|
||
GO_VERSION: "1.24"
|
||
NODE_VERSION: "22"
|
||
|
||
jobs:
|
||
contract:
|
||
name: contract (сгенерированный код совпадает с openapi.yaml)
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions/setup-go@v5
|
||
with: { go-version: "${{ env.GO_VERSION }}", cache-dependency-path: services/api/go.sum }
|
||
- 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-сервера, TS-клиента и дизайн-токенов
|
||
run: |
|
||
(cd services/api && go generate ./...)
|
||
pnpm generate
|
||
- name: Проверка, что всё закоммичено
|
||
# status, а не diff: diff не видит новые неотслеживаемые файлы
|
||
run: |
|
||
changes="$(git status --porcelain -- services/api/internal/api/gen packages)"
|
||
if [ -n "$changes" ]; then echo "$changes"; git diff -- services/api/internal/api/gen packages; exit 1; fi
|
||
|
||
api:
|
||
runs-on: ubuntu-latest
|
||
defaults: { run: { working-directory: services/api } }
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions/setup-go@v5
|
||
with: { go-version: "${{ env.GO_VERSION }}", cache-dependency-path: services/api/go.sum }
|
||
- run: test -z "$(gofmt -l .)" || (gofmt -l . && exit 1)
|
||
- run: go vet ./...
|
||
- run: go test -race -coverprofile=coverage.out ./...
|
||
- run: go build ./cmd/...
|
||
|
||
recommender:
|
||
runs-on: ubuntu-latest
|
||
defaults: { run: { working-directory: services/recommender } }
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: astral-sh/setup-uv@v6
|
||
with: { version: "0.10.2", enable-cache: true, cache-dependency-glob: services/recommender/uv.lock }
|
||
- run: uv sync --frozen
|
||
- run: uv run ruff check .
|
||
- run: uv run ruff format --check .
|
||
- run: uv run mypy pipu_rec
|
||
- run: uv run pytest -q
|
||
|
||
ts:
|
||
name: ts (packages + web)
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: "${{ env.NODE_VERSION }}", cache: pnpm }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: pnpm i18n:check
|
||
- run: pnpm test:scripts
|
||
- run: pnpm typecheck
|
||
- run: pnpm test
|
||
- run: pnpm --filter @pipu/web build
|
||
|
||
docker:
|
||
name: docker (образы собираются — их сервер собирает сам при обновлении)
|
||
runs-on: ubuntu-latest
|
||
strategy:
|
||
matrix:
|
||
include:
|
||
- { name: api, dockerfile: services/api/Dockerfile, target: api }
|
||
- { name: storage-agent, dockerfile: services/api/Dockerfile, target: storage-agent }
|
||
- { name: recommender, dockerfile: services/recommender/Dockerfile, target: "" }
|
||
- { name: web, dockerfile: apps/web/Dockerfile, target: "" }
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: docker/setup-buildx-action@v3
|
||
- uses: docker/build-push-action@v6
|
||
with:
|
||
context: .
|
||
file: ${{ matrix.dockerfile }}
|
||
target: ${{ matrix.target }}
|
||
push: false
|
||
build-args: VERSION=ci
|
||
|
||
mobile:
|
||
name: mobile (Metro-бандл Android)
|
||
runs-on: ubuntu-latest
|
||
defaults: { run: { working-directory: apps/mobile } }
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: "${{ env.NODE_VERSION }}", cache: pnpm }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: npx expo-doctor
|
||
- run: npx expo export --platform android --output-dir dist
|