iac/apps/prescriptions/CONFIGURATION.md

128 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Конфигурация проекта prescriptions-frontend
Документ описывает способы конфигурирования микрофронтенда `prescriptions-frontend` (Module Federation `srx_prescriptions`, экспонирует `./PrescriptionsPage`), его переменные сборки/CI и параметры деплоя.
## Способы конфигурирования
В отличие от backend-сервисов, у фронтенда **нет рантайм-конфигурации через `.env`**: собранный бандл — статические файлы, которые раздаёт nginx. Всё поведение задаётся **на этапе сборки** одной переменной — `BUILD_ENV`.
- `env.js` читает `process.env.BUILD_ENV` и валидирует его против списка `local`/`stage`/`prod`/`contour`/`preprod` (иначе — ошибка сборки `set BUILD_ENV one of ...`);
- `webpack.config.js` через `DefinePlugin` внедряет глобальные константы `BUILD_ENV` и `STORYBOOK` в бандл;
- `build.config.js` по `BUILD_ENV` выбирает режим сборки (`mode`/`devtool`);
- `module/api/hosts.ts` и `module/api/module-hosts.ts` содержат карты хостов по окружениям; SDK (`@sarex-team/sdk-js`) на рантайме выбирает нужный хост по глобальной константе `BUILD_ENV` (по умолчанию `prod`).
Отдельного конфиг-файла (yaml/toml) у приложения нет.
### Значения `BUILD_ENV`
| `BUILD_ENV` | `mode` | `devtool` | Назначение |
| --- | --- | --- | --- |
| `local` | `development` | `eval-source-map` | Локальная разработка (dev-server, storybook), `httpService``original` |
| `stage` | `development` | `eval-source-map` | Стенд stage |
| `preprod` | `production` | `source-map` | Предпрод |
| `prod` | `production` | `source-map` | Прод |
| `contour` | `production` | `source-map` | Изолированный контур (относительные пути хостов) |
## Переменные сборки и CI
| Переменная | Где используется | Назначение |
| --- | --- | --- |
| `BUILD_ENV` | `env.js`, `webpack.config.js`, `Dockerfile` (ARG), `.gitlab-ci.yml` (`--build-arg`) | Целевое окружение сборки. Обязательна |
| `NPM_TOKEN` | `.npmrc`, `Dockerfile` (ARG), `.gitlab-ci.yml` (`--build-arg`) | Токен доступа к приватному npm-реестру `nexus.infra.sarex.io` |
| `STORYBOOK` | `webpack.config.js` (`DefinePlugin`), `module/pages/index.tsx` | Флаг сборки под Storybook (`"true"`/`"false"`) |
Cypress-тесты берут учётные данные из `cypress.env.json` (пример — `cypress.env-example.json`): `SRX_LOGIN`, `SRX_PASSWORD`.
Версия Node для разработки — `v20.16.0` (`.nvmrc`).
## Хосты по окружениям
Базовые API-хосты подставляются из `module/api/hosts.ts` по `BUILD_ENV` (детальная разбивка по сервисам — в `ENDPOINTS.md`):
| Окружение | Базовый API | Пример (`documentations`) |
| --- | --- | --- |
| `local` / `stage` | `https://stage-api.sarex.io` | `https://stage-api.sarex.io/documentations/api/v1` |
| `preprod` | `https://api.preprod.sarex.io` | `https://api.preprod.sarex.io/documentations/api/v1` |
| `prod` | `https://api.sarex.io` | `https://api.sarex.io/documentations/api/v1` |
| `contour` | относительные пути | `/documentations/api/v1` |
Удалённый модуль (Module Federation) `documentations` подключается по `module/api/module-hosts.ts` (`remoteEntry.js`).
## Запуск и скрипты (`package.json`)
| Команда | Назначение |
| --- | --- |
| `npm run serve-module` | Dev-server (`webpack.dev.js`, порт `9001`, https, proxy `/api`, `/admin` на `appUrl`), `BUILD_ENV=local` |
| `npm run storybook` | Storybook (порт `9000`, https), `BUILD_ENV=local` |
| `npm run start` / `test:dev` | Параллельный запуск serve-module + storybook (+ cypress в `test:dev`) |
| `npm run build-module` | Продакшн-сборка модуля (`webpack --config webpack.config.js`) |
| `npm run build-storybook` | Сборка статики Storybook |
| `npm run cypress:open` | Запуск e2e-тестов Cypress |
| `npm run lint` / `lint:ts` | Prettier / проверка типов `tsc --noEmit` |
## Сборка образа (`Dockerfile`)
Двухстадийная сборка:
1. `node:15` — установка зависимостей (`npm i --legacy-peer-deps` с `NPM_TOKEN`), `npm run lint`, `BUILD_ENV=$BUILD_ENV npm run build-module``/app/dist`;
2. `nginx:mainline-alpine-otel` — копирование `dist` в `/dist` и конфига `nginx/nginx.conf`.
Build-args: `BUILD_ENV`, `NPM_TOKEN`.
nginx (`nginx/nginx.conf`) раздаёт статику из `/dist`, отдаёт `/ping``{"result": "ok"}` (healthcheck) и запрещает кеширование `/module/remoteEntry.js` (`Cache-Control: no-store`).
## CI/CD (`.gitlab-ci.yml`)
Пайплайн подключает общие шаблоны `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`, ref `apps-business`). `SERVICE_NAME=prescriptions-frontend`. Окружение переключается по ветке/тегу (`workflow.rules`):
| Условие | STAND | NAMESPACE | BUILD_ENV | CHART_VERSION |
| --- | --- | --- | --- | --- |
| ветка `stage` | `stage` | `proc` | `stage` | `1.0.0-stage` |
| ветка `master` | `preprod` | `prescriptions-preprod` | `preprod` | `1.0.0-preprod` |
| тег (`CI_COMMIT_TAG`) | `production` | `prescriptions-prod` | `prod` | `1.0.0-prod` |
| merge request | — | — | — | сборка образа отключена (`ENABLE_BUILD_IMAGE=false`) |
Деплой параметризуется через `HELM_SET_ARGS` (образ, `global.env`, `commitSha`, `gitlabUri`, `gitlabJobUrl`, `owner`).
## Helm-чарт проекта (`.helm`)
`Chart.yaml`: зависимость `universal-chart` (`oci://cr.yandex/.../charts`, версия `0.1.7`).
`values.yaml` (`universal-chart.services.frontend`):
- `deployment.name = prescription-frontend`, `replicaCount = 1`, `port = 80`, `revisionHistoryLimit = 10` (prod — `15`);
- `image.name = cr.yandex/crp3ccidau046kdj8g9q/prescription-frontend`, `pullPolicy = IfNotPresent`;
- `service.name = prescriptions-frontend-service`, `type = ClusterIP`, `port/targetPort = 80`;
- `imagePullSecrets = dockerhub`;
- probes (`liveness`/`readiness`) на `/ping:80` заданы, но **выключены** (`enabled: false`);
- `envs: []`, `secretEnvs: []` — переменных окружения контейнеру не передаётся;
- ресурсы: `requests` `memory 100Mi`, `cpu 100m`.
## Инфраструктура (`iac/apps/prescriptions`)
Разворачивается через Kustomize. Состав каталога:
| Путь | Назначение |
| --- | --- |
| `base/namespace.yaml` | Namespace `prescriptions` с `istio-injection: enabled` |
| `base/deployment.yaml` | Deployment `frontend`, образ `cr.yandex/.../prescriptions-frontend:production_...`, порт `80`, `requests` `cpu 25m`/`memory 100Mi`, `imagePullSecrets: regcred` |
| `base/service.yaml` | Service `frontend-service`, `ClusterIP`, порт `80` |
| `base/kustomization.yaml` | Сборка base (namespace + deployment + service) |
| `yc-k8s-test/` | Оверлей поверх `../base` (патч `replicas.yaml` закомментирован) |
| `brusnika-prod/`, `brusnika-stage/` | Оверлеи (см. замечание ниже) |
## Замечания и потенциальные проблемы
- **Оверлеи `brusnika-prod` / `brusnika-stage`** сейчас содержат `HelmRelease` бэкенда `measurements` (namespace `measurements`, образ `documentations`), не относящийся к prescriptions — похоже на копипаст-заготовку, которую нужно заменить на конфигурацию prescriptions-frontend либо удалить.
- **Два способа описания деплоя**: helm-чарт в репозитории фронтенда (`.helm`, `universal-chart`) и Kustomize-манифесты в инфраструктуре (`iac/apps/prescriptions`) описывают один и тот же сервис по-разному — стоит зафиксировать единый источник истины.
- **Несогласованные имена**: `SERVICE_NAME=prescriptions-frontend` (мн. ч.), а `deployment.name`/`image.name` в `.helm``prescription-frontend` (ед. ч.). В инфра-манифестах deployment называется просто `frontend`.
- **Версии Node расходятся**: разработка — `v20.16.0` (`.nvmrc`), сборка образа — `node:15` (`Dockerfile`).
- **Мёртвая конфигурация**: экспорт `hosts` в `networking.config.js` (внедрение `__<service>_host`) и `module/Env` (`IEnv`, `process.env as IEnv`) в коде модуля не используются; `dotenv-webpack` присутствует в devDependencies, но не подключён в `webpack.config.js`. `networking.config.js` реально используется только в `webpack.dev.js` (прокси dev-сервера).
## Минимальный набор для сборки
- `BUILD_ENV` — одно из `local`/`stage`/`preprod`/`prod`/`contour` (обязательно);
- `NPM_TOKEN` — для установки приватных пакетов `@sarex-team/*` из nexus;
- (опционально) `STORYBOOK=true` — при сборке/запуске Storybook;
- (для e2e) `SRX_LOGIN`, `SRX_PASSWORD` в `cypress.env.json`.