96 lines
9.2 KiB
Markdown
96 lines
9.2 KiB
Markdown
# Конфигурация проекта document-link (document-link-frontend)
|
||
|
||
Документ описывает способы конфигурирования и все переменные окружения сервиса публичных ссылок на документы.
|
||
|
||
## Что это за сервис
|
||
|
||
`document-link-frontend` — микрофронтенд на **Next.js 13** (App Router, `src/app`), отдающий публичную страницу-карточку документа по ссылке вида `https://document-link.<env>.sarex.io/<uuid>`. По `uuid` фронтенд запрашивает метаданные документа у сервиса `documentations` и показывает название, автора, версию, размер, срок действия ссылки и кнопку скачивания (см. `ENDPOINTS.md`). Собственного бэкенда у сервиса нет — это чистый фронтенд, поэтому файлы вида `openapi.yaml` для него неприменимы.
|
||
|
||
## Способы конфигурирования
|
||
|
||
В отличие от бэкенд-сервисов, у фронтенда **нет разбора переменных окружения в коде**. На текущий момент:
|
||
|
||
- Базовый хост API выбирается в рантайме по `window.location.hostname` в `src/app/[uuid]/components/modal.tsx` (жёстко заданный `switch`), а не из переменной окружения;
|
||
- JWT для авторизации запроса **зашит в коде** (константа `fixedToken` в том же файле) — временное решение;
|
||
- Обращений к `process.env` / `NEXT_PUBLIC_*` в `src/` нет.
|
||
|
||
При этом конфигурационная поверхность **объявлена в инфраструктуре** (Helm-чарт репозитория и CI) в виде переменных `NEXT_PUBLIC_*` — их предполагается использовать вместо хардкода. Ниже описаны и код, и инфраструктурные объявления.
|
||
|
||
Источники переменных по способам запуска:
|
||
|
||
| Способ запуска | Откуда берутся значения |
|
||
| --- | --- |
|
||
| Локально (`npm run dev`) | Значения зашиты в коде; `apiBaseUrl` для `localhost` → `stage-api.sarex.io` |
|
||
| Локально (Docker / `docker-compose`) | `Dockerfile` (`node:18-alpine`, `next build`, `ENTRYPOINT npm start`, порт `3000`); `docker-compose.yaml` пробрасывает `8000:3000` |
|
||
| Kubernetes — репозиторный чарт | `.helm/values.yaml`: блок `services.frontend.envs` и `secretEnvs` (см. ниже) |
|
||
| Kubernetes — infra (этот репозиторий) | `apps/document-link/base` (kustomize) и `apps/document-link/{brusnika-stage,brusnika-prod}` (FluxCD `HelmRelease` поверх `universal-chart`) |
|
||
| CI/CD (GitLab) | `.gitlab-ci.yml`: `generic/common-ci` (`universal-pipeline`, ref `apps-business`), `SERVICE_NAME=document-link` |
|
||
|
||
## Переменные приложения
|
||
|
||
Объявлены в `.helm/values.yaml` исходного репозитория. **Важно:** текущий код фронтенда их не читает (см. раздел «Замечания»).
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `NEXT_PUBLIC_API_BASE_URL` | string | `stage-api.sarex.io` (stage), `api.sarex.io` (production) | Базовый хост API (сервис `documentations`), без схемы |
|
||
| `NEXT_PUBLIC_API_TOKEN` | string (secret) | — | JWT сервисного аккаунта для `Authorization: Bearer <jwt>`. Берётся из секрета `documentations-publiclink-jwt-secret` (ключ `jwt`) |
|
||
|
||
## Базовые хосты API по окружениям
|
||
|
||
Логика `src/app/[uuid]/components/modal.tsx` (`switch` по `window.location.hostname`):
|
||
|
||
| Hostname фронтенда | `apiBaseUrl` |
|
||
| --- | --- |
|
||
| `localhost` | `stage-api.sarex.io` |
|
||
| `document-link.stage.sarex.io` | `stage-api.sarex.io` |
|
||
| `document-link.sarex.io` | `api.sarex.io` |
|
||
| прочее | не определён (ошибка в консоль, fallback `stage-api.sarex.io`) |
|
||
|
||
## Сборка и контейнер
|
||
|
||
| Параметр | Значение | Где задано |
|
||
| --- | --- | --- |
|
||
| Базовый образ | `node:18-alpine` | `Dockerfile` |
|
||
| Команда сборки | `npm i` → `npm run build` (`next build`) | `Dockerfile` |
|
||
| Entrypoint | `npm start` (`next start`) | `Dockerfile` |
|
||
| Порт приложения | `3000` | `Dockerfile` (`EXPOSE 3000`), `.helm/values.yaml` (`port._default: 3000`) |
|
||
| Образ (registry) | `cr.yandex/crp3ccidau046kdj8g9q/document-link-frontend` | `.helm/values.yaml`, infra `HelmRelease` |
|
||
|
||
## Деплой (infra: `apps/document-link`)
|
||
|
||
| Оверлей | Механизм | Особенности |
|
||
| --- | --- | --- |
|
||
| `base` | kustomize (`Deployment` + `Service` + `Namespace`) | namespace `document-link` c `istio-injection: enabled`; `Deployment/frontend` |
|
||
| `brusnika-stage` | FluxCD `HelmRelease` → `universal-chart` `0.1.7` | `replicaCount`: stage `1`; probes выключены |
|
||
| `brusnika-prod` | FluxCD `HelmRelease` → `universal-chart` `0.1.7` | `replicaCount`: preprod/production `3`; probes выключены |
|
||
| `yc-k8s-test` | kustomize (`../base`) | тестовый контур |
|
||
|
||
Порты сервиса: в `universal-chart` — `service.port 8080` → `targetPort 3000` (`portName: http`); в `base/service.yaml` — `port 80` → `targetPort 80`.
|
||
|
||
## Переменные в CI (`.gitlab-ci.yml`)
|
||
|
||
Пайплайн подключает общие шаблоны `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`, ref `apps-business`). Ключевые переменные: `SERVICE_NAME=document-link`, `DOCKERFILE_PATH=./Dockerfile`, `CI_TRIGGER_SOURCE=app`. Окружение переключается по ветке/тегу:
|
||
|
||
| Условие | STAND | Namespace | Chart |
|
||
| --- | --- | --- | --- |
|
||
| `merge_request_event` | — | — | `ENABLE_BUILD_IMAGE=false` (только проверки) |
|
||
| ветка `stage` | `stage` | `documentations` | `document-link` `0.1.7`, `--build-arg ENV=stage` |
|
||
| ветка `master` | `preprod` | `document-link-preprod` | `document-link` `0.1.7`, `--build-arg ENV=preprod` |
|
||
| тег (`CI_COMMIT_TAG`) | `production` | `document-link-prod` | `document-link` `0.1.7`, `--build-arg ENV=prod` |
|
||
|
||
`HELM_SET_ARGS` пробрасывает в `universal-chart` образ (`services.frontend.image.name.<env>`), `global.env`, а также `commitSha`/`gitlabUri`/`gitlabJobUrl`/`owner`.
|
||
|
||
## Замечания и потенциальные проблемы
|
||
|
||
- **Env-переменные не используются кодом.** `NEXT_PUBLIC_API_BASE_URL` и `NEXT_PUBLIC_API_TOKEN` объявлены в `.helm/values.yaml`, но `src/` их не читает: базовый хост берётся из `switch` по `hostname`, а токен зашит константой `fixedToken`. Для корректной работы на разных стендах логику стоит перевести на `process.env.NEXT_PUBLIC_*` (и тогда `.env.example` станет рабочим шаблоном).
|
||
- **Зашитый JWT.** Константа `fixedToken` в `modal.tsx` — секрет в исходниках и с ограниченным сроком действия (`exp`). Должен приходить из секрета `documentations-publiclink-jwt-secret` через `NEXT_PUBLIC_API_TOKEN`.
|
||
- **Неизвестный hostname.** При домене, не входящем в `switch`, `apiBaseUrl` не задаётся явно (используется дефолт `stage-api.sarex.io`) — для новых стендов список нужно расширять.
|
||
- **Расхождение портов.** Приложение слушает `3000` (Dockerfile/helm `targetPort`), но `apps/document-link/base/deployment.yaml` объявляет `containerPort: 80`, а `base/service.yaml` — `port/targetPort 80`. В `universal-chart` (`HelmRelease`) — корректный `targetPort 3000`. Kustomize-`base` стоит выровнять на `3000`.
|
||
- **Многоступенчатый Dockerfile закомментирован.** Финальный `runner`-stage отключён — образ запускается из `builder` с полным `node_modules`; для прод-образа стоит включить slim-runner.
|
||
|
||
## Минимальный набор для запуска
|
||
|
||
- Локально: `npm i && npm run dev`, открыть `http://localhost:3000/<uuid>` (API — `stage-api.sarex.io`).
|
||
- Docker: `docker compose up` (порт `8000` → контейнер `3000`).
|
||
- В кластере фактически требуется рабочий JWT для сервиса `documentations` (сейчас — `fixedToken`; целевое — секрет `documentations-publiclink-jwt-secret`).
|