iac/apps/projects/CONFIGURATION.md

134 lines
11 KiB
Markdown
Raw 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.

# Конфигурация проекта projects-frontend
Документ описывает, как конфигурируется микрофронтенд `projects-frontend`: переменные сборки, способы запуска, параметры Docker/nginx, Helm-чарта и CI.
## Способы конфигурирования
`projects-frontend` — это клиентский микрофронтенд (React 17 + MobX, сборка Webpack 5, Module Federation). У приложения **нет runtime-конфигурации и файла `.env`**: всё поведение, зависящее от окружения, определяется **на этапе сборки** одной переменной `BUILD_ENV`.
Разбор выполняется в `configWebpack/config/build.config.ts` (`extractBuildOptions`): значение `process.env.BUILD_ENV` (одно из `local` / `stage` / `prod` / `preprod` / `contour`, по умолчанию `prod`) определяет режим сборки (`development`/`production`) и «endpoint». Полученный `endPoint` через `DefinePlugin` (`configWebpack/buildPlugins.ts`) подставляется в бандл как глобальная константа `__ENDPOINT__`:
```js
new DefinePlugin({ __ENDPOINT__: JSON.stringify(endPoint) })
```
Константа `__ENDPOINT__` используется в рантайме бандла для выбора:
- карты хостов API — `src/shared/api/http-service.ts` (`const endpoint = (__ENDPOINT__ as TypeEnvironment) || "prod"`) поверх `src/shared/api/hosts.ts`;
- URL удалённого модуля timeline — `src/widgets/remote-timeline/ui/timelineProxy.tsx`;
- локального провайдера разработки — `src/app/bootstrap.tsx` (`__ENDPOINT__ === "local" ? <LocalDevProvider /> : <div />`).
Отдельного конфиг-файла (yaml/env) у приложения нет.
## Переменные сборки и запуска
| Переменная | Где используется | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `BUILD_ENV` | `webpack.config.ts`, `configWebpack/config/build.config.ts`, `Dockerfile` (build-arg) | `prod` | Целевое окружение сборки: `local`/`stage`/`prod`/`preprod`/`contour`. Определяет режим (`development`/`production`), карту хостов и URL удалённых модулей |
| `NPM_NEXUS_TOKEN` | `.npmrc`, `Dockerfile` (build-arg) | — | Токен доступа к приватному npm-реестру Nexus (`https://nexus.infra.sarex.io/repository/npm/`) для установки пакетов `@sarex-team/*` |
| `PORT` | `webpack.config.ts` | `9001` | Порт dev-сервера Webpack |
Версия Node фиксирована в `.nvmrc``v16.0.0`. Приватный реестр и авторизация заданы в `.npmrc`:
```
@sarex-team:registry=https://nexus.infra.sarex.io/repository/npm/
//nexus.infra.sarex.io/repository/npm/:_authToken=${NPM_NEXUS_TOKEN}
```
### npm-скрипты (`package.json`)
| Команда | Действие |
| --- | --- |
| `npm run dev` | Локальная разработка: `BUILD_ENV=local webpack serve --config webpack.config.ts` |
| `npm run build-module` | Сборка модуля: `webpack --config webpack.config.ts` (окружение — из `BUILD_ENV`) |
| `npm run build:start` | Раздача собранного бандла: `serve -s ./dist -l 9001` |
| `npm run lint` | Форматирование Prettier: `npx prettier --write .` |
## Сборка Webpack и Module Federation
Точка входа — `src/app/index.ts` (`webpack.config.ts`). Для всех окружений, кроме `local`, добавляется `ModuleFederationPlugin`:
- `name`: `srx_projects`;
- `filename`: `module/remoteEntry.js`;
- `exposes`: `./ProjectsPage``./src/app/App.tsx`;
- `shared` (singleton, `requiredVersion: false`): `react`, `react-dom`, `@material-ui/core`, `@sarex-team/sdk-js`.
Плагины (`configWebpack/buildPlugins.ts`): `HtmlWebpackPlugin`, `DefinePlugin`. В режиме `local` дополнительно `ProgressPlugin`, `ForkTsCheckerWebpackPlugin`, `ReactRefreshWebpackPlugin`; вне `local``MiniCssExtractPlugin` (хеши в именах файлов).
### Dev-сервер (`configWebpack/buildDevServer.ts`)
HTTPS, порт `9001`, `historyApiFallback`, `hot`. Прокси на stage-окружение с `pathRewrite`:
| Префикс | Target |
| --- | --- |
| `/sarex-backend` | `https://stage.sarex.io` |
| `/sarex-gateway` | `https://stage-api.sarex.io/gateway` |
| `/sarex-documentations` | `https://stage-api.sarex.io/documentations` |
| `/sarex-api` | `https://stage-api.sarex.io` |
Заголовки CORS dev-сервера разрешают любой origin, методы `GET, POST, PUT, DELETE, PATCH, OPTIONS` и заголовки `X-Requested-With, content-type, Authorization`.
## Docker
Многоступенчатая сборка (`Dockerfile`):
1. **Стадия сборки** (`node:16`): установка зависимостей (`npm i` с `NPM_NEXUS_TOKEN`), `npm run lint`, `BUILD_ENV=$BUILD_ENV npm run build-module``dist`.
2. **Стадия раздачи** (`nginx:1.19.6`): копирование `dist` в `/dist` и `nginx/nginx.conf` в `/etc/nginx/nginx.conf`.
Build-args: `BUILD_ENV`, `NPM_NEXUS_TOKEN`.
### nginx (`nginx/nginx.conf`)
Статика раздаётся с `root /dist` на порту `80`. Особенности:
- `location = /ping` → возвращает `200 {"result": "ok"}` (используется как liveness/readiness-проба);
- `location = /module/remoteEntry.js``Cache-Control: no-store, no-cache, must-revalidate…`, `expires off` (точка входа Module Federation не кешируется);
- `gzip on`, логи в `stdout`/`stderr`.
## Helm-чарт (`.helm`)
Чарт `projects-frontend` (`Chart.yaml`, `type: application`, `version: 0.1.0`, `appVersion: 1.16.0`) разворачивает статику как `Deployment` + `Service` (`templates/static.yaml`) и публикует её через Istio `VirtualService` (`templates/mesh-config.yaml`).
Значения задаются в `values-<env>.yaml` (блок `static`):
| Параметр | `stage` | `preprod` | `production` |
| --- | --- | --- | --- |
| `static.host` | `stage-modules.sarex.io` | `modules.preprod.sarex.io` | `modules.sarex.io` |
| `static.replicas` | `1` | `2` | `2` |
| `static.path` | `/projects/static/` | `/projects/static/` | `/projects/static/` |
| `static.image` | `sarex/projects-frontend-static:latest` | то же | то же |
| `static.port` / `static.service_port` | `80` / `80` | `80` / `80` | `80` / `80` |
| `static.requests` | `memory: 100Mi`, `cpu: 100m` | то же | то же |
| `imagePullSecrets` | `dockerhub` | `dockerhub` | `dockerhub` |
Общее для всех окружений: `static.name: projects-frontend-static`, `static.service_name: projects-frontend-static-service`, `static.version: stable`. Пробы `livenessProbe`/`readinessProbe` бьют в `/ping` (`templates/static.yaml`).
`VirtualService` (`templates/mesh-config.yaml`): хост `static.host`, шлюз `gateway/modules-gateway`, матч по префиксу `static.path` (`/projects/static/`) с `rewrite` на `/`. Политика CORS: `allowOrigins` по регулярке `(https://.*\.sarex\.io)|(https://localhost:.*)`, `allowMethods: [GET, POST, PUT, PATCH, HEAD, DELETE]`, `allowHeaders: [Authorization, Content-Type]`, `maxAge: 24h`.
## CI/CD (`.gitlab-ci.yml`)
Пайплайн подключает общие шаблоны из `generic/common-ci` (`universal-pipeline-*`, `common-security-scan`, `common-build`) и переключает окружение по ветке/тегу через `workflow.rules`:
| Условие | STAND | Namespace | `BUILD_ENV` |
| --- | --- | --- | --- |
| ветка `master` | `preprod` | `projects-preprod` | `preprod` |
| ветка `stage` | `stage` | `projects-stage` | `stage` |
| тег (`CI_COMMIT_TAG`) | `prod` | `projects-prod` | `prod` |
Ключевые переменные пайплайна (общие для всех окружений): `RELEASE_NAME`/`CHART_NAME` = `projects-frontend`, `IMAGE_PATH` = `static.image`, `HELM_SET_ARGS` = `--set static.image=${IMAGE_NAME}`, `BUILD_ARGS` = `--build-arg BUILD_ENV=<env> --build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN}`, `DOCKERFILE_PATH` = `Dockerfile`. Флаги этапов: `ENABLE_LINTER` (`false`), `ENABLE_BUILD_CHART`, `ENABLE_BUILD_IMAGE`, `ENABLE_STATE_UPDATE`, `ENABLE_DEPLOY` (`true`). `CHART_VERSION` задаётся как `0.0.1-<env>`. Стадии: `linter → test → unittest → prebuild-secscan → build → state-update → deploy`.
## Замечания и потенциальные проблемы
- **Нет runtime-конфигурации.** Всё, что зависит от окружения, «зашивается» в бандл на этапе сборки через `BUILD_ENV`/`__ENDPOINT__`. Пересборка под другое окружение обязательна — переопределить хосты в рантайме нельзя.
- **Значение по умолчанию `BUILD_ENV=prod`.** Если переменная не задана при сборке, собирается production-вариант (`build.config.ts`, `webpack.config.ts`, `http-service.ts`). Для локальной разработки нужно явно `BUILD_ENV=local` (скрипт `npm run dev` это делает).
- **Окружение `contour` неполно сконфигурировано.** Оно перечислено в `build.config.ts` и типах, но в `src/shared/api/hosts.ts` карта хостов для `contour` отсутствует, а URL удалённого модуля timeline для `contour` пуст (`timelineProxy.tsx`). Сборка с `BUILD_ENV=contour` не сможет разрешить хосты API.
- **README не совпадает с `package.json`.** В `README.md` указаны `nvm use 16.0.0` и `npm run start:local`, однако скрипта `start:local` в `package.json` нет — локальный запуск выполняется командой `npm run dev`. `.nvmrc` фиксирует `v16.0.0`.
- **Версии чарта расходятся.** В `Chart.yaml``version: 0.1.0` / `appVersion: 1.16.0`, тогда как в CI `CHART_VERSION` задаётся как `0.0.1-<env>`. Значения не синхронизированы.
- **Приватный реестр.** Установка зависимостей требует валидный `NPM_NEXUS_TOKEN` (`.npmrc`); без него `npm i` (в т.ч. в Docker-сборке) завершится ошибкой авторизации.
## Минимальный набор для локального запуска
1. `nvm use` (Node `v16.0.0` из `.nvmrc`).
2. Экспортировать `NPM_NEXUS_TOKEN` (доступ к Nexus) и выполнить `npm i`.
3. `npm run dev` — соберёт с `BUILD_ENV=local` и поднимет HTTPS dev-сервер на `https://localhost:9001` (запросы к backend проксируются на stage через `/sarex-backend`, `/sarex-gateway`, `/sarex-documentations`, `/sarex-api`).