Галоўная / Артыкулы / Центральны репазітарый настройкі для мікросэрвісаў: інтеграцыя та сінхронізацыя за адны каманды

Центральны репазітарый настройкі для мікросэрвісаў: інтеграцыя та сінхронізацыя за адны каманды

Створыце цэнтральны рэпазітарый налашчанняў з скрыптамі для наладкі, сінхронізацыі та ўтычных апдэйтаў, каб усія службы NestJS і React выкорыстоўвалі аднаковыя настройкі лінтавання, рэдагувальніка та Docker.

2452 слоў

Калі каманда запускае дзесятак мікросервісаў на базе Node.js, найцяжэйшым аспектам першага тыдня для новапрацаванага часто ёст не сам код, а сяродовышча: правильная версія Node, правілы ESLint і Prettier, правильныя значэння файла .env і налаштаванні Docker, якія будуць такімі ж, як у іншых. Кожны мікросервіс часта трохі адхіляецца ад стандарту, і старшыя інжынеры вынужданы выступаць у ролі службы падтрымкі. У этай статыце паказана, як выправіць гэта за дапамою аднароговага рэпазітарыя налаштаўванняй і калькі скрыптаў на Bash, якія за адну команду налаштавляюць машыну, копіююць спакульнае налаштаванні ў кожны мікросервіс і падтрымліваюць ўхоўненне іх у актуальным стане. Вы таксама пазнаёме, дзе скрыпты, якія ўжо напісаны, патрабуюць дадатковых захоўніх мераў, прытаму як толькі можна на іх паспалагацца.

Як поступова з’яўляецца адхіленне налаштаўванняй

Уявіце аптэктыўнага разрабоўца, які прыяўляецца да каманды, якая адпаведае за дванаццаць сервісаў. Першы дзень прыйдзецца пасвятаваць інсталляцыі Node і Docker, выкрэйсленню стылю ESLint для каманды, спадзяванню, якія зменныя патрабуюцца ў кожным файле .env, і запитам у чате, якая версія NestJS выкорыстоўваецца сервісамі. Пасля чаго auth-service перастае працаваць з-за памылкі CORS, вызванай адносна іншым локальным налаштаванням, а пазней першы pull request не праходзіць пераканальвання, таму што спяльная налаштаванні Prettier зменіліся месяц тыму назад, а локальная копія так і не была адкорэгавана.

Ніякая з гэтых проблем не ўзнемагаючая, але разам яны ствараюць вялікія затраты. Калі кожны сервіс мае своія, адносна іншыя правіла лінтавання, файлы Dockerfiles, структуру папак і налаштаванні рэдагара, гэта выражаецца ў втрачаных днях для новачакоў і втрачаных гадзінах ў кожны тыдзень для аптэктыўных інжынераў, якія адпаведзяюць на запытанні пра налаштавання.

Адна база дадзеных як аднаковы істочнік

Рашчынанне — это спецыяльны рэпазітарый, які тут называецца dev-environment-config, і ў яком знаходзіцца все, што патрэбна машыне для разработкі: шаблоны проектаў, правілы лінтингу і форматавання, настройкі VS Code, базовая конфігурацыя Docker, скрыпты для аўтаматызаціі і спяльная бібліятэка. Калі хтось яго апдэйтуе, кожная машына разработчыка автаматычна прыймае змяну наступны ранак.

Загальная структура выглядае так, пры чым центральны рэпазітарый задае данні кожнай службе:

dev-environment-config (Central Repo)
├── templates/          → Project scaffolding (NestJS, React)
├── shared/             → ESLint, Prettier, Git configs
├── vscode/             → Extensions & settings
├── docker/             → Base Docker configs
├── scripts/            → Automation (setup, sync, update)
├── common-lib/         → Shared NPM package
└── manifest.json       → Version tracking

         │  syncs to
         ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ user-svc │ │ auth-svc │ │ pay-svc  │  ... 12 services
│ .eslint  │ │ .eslint  │ │ .eslint  │
│ .vscode  │ │ .vscode  │ │ .vscode  │
│ Docker   │ │ Docker   │ │ Docker   │
└──────────┘ └──────────┘ └──────────┘

Стварэнне системы па шагах

Структура центральнага рэпазітарыя

Усередине рэпазітарыя кожная частка праблемы мае свой папаку. У шаблонах знаходзяцца готовыя стартавыя проекты NestJS і React, shared/ мае файлы для ESLint, Prettier, EditorConfig, правілы Git ignore і commitlint, vscode/ — настройкі рэдагара, а scripts/ — скрыпты для аўтаматызаціі.

dev-environment-config/
├── templates/
│   ├── nestjs-service/    # Complete NestJS starter
│   └── reactjs-service/   # Complete React starter
├── shared/
│   ├── .eslintrc.js
│   ├── .prettierrc
│   ├── .editorconfig
│   ├── .gitignore
│   └── commitlint.config.js
├── vscode/
│   ├── extensions.json
│   ├── settings.json
│   └── launch.json
├── scripts/
│   ├── setup-new-developer.sh
│   ├── sync-config.sh
│   ├── auto-update.sh
│   └── create-new-service.sh
├── common-lib/            # Shared NPM package
└── manifest.json          # Version tracker

Файл manifest.json являецца тым элементам, які дазваляюць адкаліцацыю. У ям запісваецца загальная версія, час і адказальнік за последнія змены, версіі для кожнай зоны налашоўкі і спіс служб, якія належаць да рабочага прастору.

{
  "version": "1.2.0",
  "lastUpdated": "2024-01-15T10:00:00Z",
  "updatedBy": "senior-dev",
  "configs": {
    "eslint": "3.2.0",
    "prettier": "2.1.0",
    "docker": "1.5.0"
  },
  "services": [
    "user-service",
    "auth-service",
    "payment-service"
  ]
}

Правілы простыя: будзь-яя змена у спакульнаных налашоўкіх падымае версію вышэйшага рангу. Скрыпт адкаліцацыі пазней пораўнюе версіі, каб выявіць, чы ўсё трэба синхронізаваць; таму, якщо забыць падняць версію, змены ня будуць пераданы. Перапытка CI, якая не праходзіць, калі файлы пад shared/ зменяюцца без падняцья версіі, являецца простым захавальным мерам.

Інтеграцыя за адной командай

Найбольшым прынтам являецца скрыпт запуску. Новы разработчык інсталюе VS Code, а потым запускае адную команду:

curl -sSL https://raw.githubusercontent.com/company/dev-environment-config/main/scripts/setup-new-developer.sh | bash

Прыгае дзесяць хвілін, і рабочая суперфіс готава. Перадача удаленага скрыпта безпасэчна ў bash є зручной, але вымагае абережнасці: скрыпт запускаецца з правамі пользователя і тым, што ў той момент знаходзится на гілцы. Для внутрашняго інструмента гэта зазвычай прыемна, але багато команд воліюць, каб людзі клонавалі репазітарый і запускалі скрыпт локальна, ў тым числі каб спачатку яго прачытаць.

Па суті скрыпт працюе за фіксаванай последовасцю:

#!/bin/bash
set -e

WORKSPACE_DIR="$HOME/company-workspace"
CONFIG_REPO="https://github.com/company/dev-environment-config.git"

echo "🚀 Setting up your development environment..."

# 1. Check & install prerequisites
check_and_install "git" "Git"
check_and_install "node" "Node.js" "nvm install 20"
check_and_install "docker" "Docker"

# 2. Create workspace & clone everything
mkdir -p "$WORKSPACE_DIR" && cd "$WORKSPACE_DIR"
git clone "$CONFIG_REPO"

# 3. Clone all service repos from manifest
SERVICES=$(cat dev-environment-config/manifest.json | \
  python3 -c "import sys,json; \
  [print(s) for s in json.load(sys.stdin)['services']]")

for service in $SERVICES; do
  git clone "https://github.com/company/${service}.git"
done

# 4. Install VS Code extensions
EXTENSIONS=$(cat dev-environment-config/vscode/extensions.json | \
  python3 -c "import sys,json; \
  [print(e) for e in json.load(sys.stdin)['recommendations']]")

for ext in $EXTENSIONS; do
  code --install-extension "$ext" --force
done

# 5. Sync shared configs to all services
bash dev-environment-config/scripts/sync-config.sh

# 6. Install dependencies everywhere
for service in $SERVICES; do
  cd "$service" && npm install && cp .env.example .env && cd ..
done

# 7. Set up daily auto-update cron (8 AM weekdays)
CRON="0 8 * * 1-5 cd $WORKSPACE_DIR && \
  bash dev-environment-config/scripts/auto-update.sh"
(crontab -l 2>/dev/null; echo "$CRON") | crontab -

echo "✅ Setup complete! Open VS Code: code $WORKSPACE_DIR"

Є калькі деталей, які варта адзначыць. Каманда set -e завершае выконанне праз першую неудачную каманду, што запобегае таму, каб напаловы настроены працоўны простор выглядаў завершаным. Памагальная каманда check_and_install не паказваецца і яе трэба напісаць па-разнаму для кожной аператыўной системы. Аналіз JSON за дапамой адразуванага Python-кода працюе, але скрыпт для апдэйта пазней выкарыстоўвае jq, таму стандартызацыя на адні інструмент скарочвае неабходныя умовы. Копіюванне файла .env.example дае безпечныя стандартныя значэння, але гэта працюе толькі якщо файлы-прыклады застаюцца цэлымі і не маюць рэальных секрэтных даных.

Сінхронізацыя спакульнага настроювання ў кожны сервіс

Скрыпт сінхронізацыі пераглядае всі сервісы і копіюе спакульныя файлы з точкай та настройкі VS Code ў кожны з іх, перазапісываючы тое, што ўжо там є.

#!/bin/bash
# sync-config.sh

CONFIG_ROOT="$(dirname "$SCRIPT_DIR")"
WORKSPACE_DIR="$(dirname "$CONFIG_ROOT")"

for service in $SERVICES; do
  SERVICE_DIR="$WORKSPACE_DIR/$service"

  # Copy shared configs
  cp -f "$CONFIG_ROOT/shared/.eslintrc.js" "$SERVICE_DIR/"
  cp -f "$CONFIG_ROOT/shared/.prettierrc" "$SERVICE_DIR/"
  cp -f "$CONFIG_ROOT/shared/.editorconfig" "$SERVICE_DIR/"
  cp -f "$CONFIG_ROOT/shared/.gitignore" "$SERVICE_DIR/"

  # Copy VS Code settings
  mkdir -p "$SERVICE_DIR/.vscode"
  cp -f "$CONFIG_ROOT/vscode/settings.json" "$SERVICE_DIR/.vscode/"
  cp -f "$CONFIG_ROOT/vscode/extensions.json" "$SERVICE_DIR/.vscode/"

  echo "✅ $service synced"
done

У гэтым фрагменте прыпускаецца, што SCRIPT_DIR і SERVICES уже з’явіліся, таму рэальны скрыпт павінен сам вылучыць іх (на прыклад, з $0 і маніфеста). Выклікі cp -f адбываюцца намеравана: перазапісваеўшы файлы, усуваецца ўсё нестандартнае. Недзея гэтага падходу — будь-які локальны змěн у гэтых файлах будзе втрачаны пад час наступнага запуску, таму персоналізацыя па кожнай службе павінна знаходзіцца ў окремых файлах, як будзе адмаўлена нижэй. Таксама разважыце, чы не трэба, каб файлы на кшталт .gitignore былі абавесны ў всіх местах, адколькі службы часта патрабуюць своіх сабэйных запісаў.

Кождадзённая автапаўнавальная задача

Гэта той элемент, який падтрымлівае сумеласць машын без таго, каб хтось памятаў пра нешто зрабіць. Кожны рабочы дзень о 8 ранку крон-задача запускае auto-update.sh:

#!/bin/bash
# auto-update.sh — Runs daily at 8 AM

cd "$CONFIG_ROOT"

# 1. Check for config updates
OLD_VERSION=$(cat manifest.json | jq -r '.version')
git pull origin main
NEW_VERSION=$(cat manifest.json | jq -r '.version')

if [ "$OLD_VERSION" != "$NEW_VERSION" ]; then
  echo "🆕 Config updated: $OLD_VERSION → $NEW_VERSION"
  bash "$SCRIPT_DIR/sync-config.sh"
fi

# 2. Pull latest code for all services
for service in $SERVICES; do
  cd "$WORKSPACE_DIR/$service"

  # Stash local changes safely
  git stash push -m "auto-update-$(date +%Y%m%d)" 2>/dev/null

  # Pull latest
  git pull origin $(git branch --show-current) --rebase

  # Update dependencies if package.json changed
  if git diff HEAD~1 --name-only | grep -q "package.json"; then
    npm install
  fi

  # Update shared library
  npm update @company/common-lib
done

# 3. Notify the developer
notify-send "Dev Environment" "✅ Updated to config v$NEW_VERSION"

Спрытвацець гэты скрап як пачатковую точку, а не каштое, што трэба разместіць без зменаў:

  • Змены захаваны, але ніколи не выкарыстоўваны, таму разработчык, які пакінуў роботу без збережэння змян на ноч, павінен знаты, як запусціць git stash pop; інакш заўважыцца, што робота зникла.
  • git diff HEAD~1 пераглядае толькі пасяльню змян. Якщо процес pull прыняў калькі пасяльні, змены ў package.json, якія былі здабыты ранейшай пасяльнёй, заўсёды працягваюцца; болей надзеяным є паўтарны перагляд змян праз пасяльню, якая была да pull.
  • Якщо пад час процесу rebase выйдзе на канфлікты, репазітарыю застаецца ў стане пад час rebase без нікаго, хто бы за ўсём стаўілі. Для задання, якое працюе без нагляду, болей безпечным є запуск git pull --ff-only і пры неудачы ігнораванне службы.
  • notify-send існуе толькі на Linux-десктопах, а cron не запускаецца на апараты, які знаходзяцца у стане сну о 8 ранку, таму корыстувальцы macOS можаць патрабаваць launchd або іншы спрыгчык.
  • Цэлы процес з’ўязвае дзіянне старшагінжынера з наступным ранкам кожнага разрабоўца:

    Senior Dev pushes config change
             │
             ▼
       GitHub Actions
             │
        ┌────┴────┐
        │ Slack   │ Notify team
        │ Publish │ common-lib to NPM
        └────┬────┘
             │
        Next 8 AM
             │
             ▼
      Every developer's cron runs
             │
        ┌────┴────────────────┐
        │ Pull config repo    │
        │ Sync shared configs │
        │ Pull service repos  │
        │ Update dependencies │
        │ Desktop notification│
        └─────────────────────┘
    

    Аб’еднаная бібліятэка заместо копіювання-выкладвання

    Захавальнікі, інтерцэптары, фільтры выключэнняяў і DTO-ы часта дуплікуюцца між сервісамі, а пасля становяцься несувязнымі. Їх пакаванне як прыватнага модуля npm, @company/common-lib, дазволяе кожнаму сервісу выкарыстоўваць аднае і тое ж импортаванне:

    // In any service, just import and use:
    import {
      AuthGuard,
      RolesGuard,
      ResponseInterceptor,
      LoggingInterceptor,
      HttpExceptionFilter,
      PaginationDto,
      McpService,        // Qwen MCP integration
    } from '@company/common-lib';
    
    @Controller('users')
    @UseGuards(AuthGuard, RolesGuard)
    @UseInterceptors(ResponseInterceptor)
    @UseFilters(HttpExceptionFilter)
    export class UserController {
      constructor(private mcpService: McpService) {}
    
      @Get()
      findAll(@Query() pagination: PaginationDto) {
        return this.userService.findAll(pagination);
      }
    
      @Post('analyze')
      async analyze(@Body() dto: AnalyzeDto) {
        return this.mcpService.callTool('text-analysis', {
          text: dto.text,
        });
      }
    }
    

    Кантроллер можа выкарыстоўваць спяльныя механізмы аутэнтыкацыі і контролю роляў, інтерсэптар адпаведзей і фільтр выключэнняя HTTP-адказаў, прыймаць спяльны DTO для пагінацыі і выкарыстоўваць обгортку McpService для інтэграцыі з Qwen MCP. Калі бібліятэка атрымуе новы механізм контролю чы ўраджэнне для фільтра выключэнняя адказаў, задача автападтверджэння пераносіць яе ў кожную службу.

    Зважайце, што команда npm update адпаведзае за дыапазон версій у кожным файле package.json; таму мажылівыя версій вышэйшага рангу не будуць автаматычна перанесеныя, што зазвычай і ўсё, чаго вы хочаце. Спяльныя бібліятэкі таксама ствараюць зв’язок межы службамі; стаття на тэму таго, калі следуе выкарыстоўваць спяльны код раскрывае, як выбраць, што належыць да аднай з служб.

    Стварэнне новых служб

    Раней стварэнне новага сервісу значыла дзень копіювання існуючага і выдалення таго, што не падходзіла. Скрыпт-генератор ператварае гэта на короткі інтэрактыўны запит:

    bash scripts/create-new-service.sh
    
    # Prompts:
    # Service name: order-service
    # Description: Handles order processing
    # Port: 3002
    # Type: nestjs
    
    # ✅ Done! Complete service with:
    # - src/common/ (filters, guards, interceptors, DTOs)
    # - Docker setup (Dockerfile + docker-compose)
    # - VS Code settings
    # - ESLint + Prettier
    # - Health check endpoint
    # - Swagger docs
    # - MCP integration
    # - Auto-update scripts
    

    Паколькі кожны новы сервіс ствараецца на аднам і тым жа шаблоне, ён пачынае свою роботу без дэвіянцяў.

    Што атрымлеўа команда

    Команда, якая адмаўіла такую наладку, запісала следзючыя эфекты:

    • Інтеграцыя за калікве хвілін: адна команда заменіла сторонку wiki з чатырохдзесятых крокаў, чым скорачыла час запуску кожнага сервіса з апошніх трох дзён да прыбліжна падаўносці панздзесят хвілін, а запыты пра наладку ў чате практычна зніклі.
    • Больш няма дэвіянцяў: сервісы таямна дэвіювалі (ESLint 8 у аднам, 7 у іншым, застарэлыя Dockerfiles); запланаваныя перазапісвы падтрымліваюць іх ідэнтычнасць.
  • Вялішы час працы: апоўну гадзіну ў дзень на падтрымку налашоўкі і выправленне толькі форматаванняя прыбуткаў CI, апоўну пяць гадзін у тыдзень — абратка да роботы над функцыямі.
  • Стабільныя сигналы якосці: тыя ж выправленні патэнаў і форматаванне при збережэнні, прымусовыя паведамлення пра змены ад Husky і автаматычна інсталаваныя расшырэнняя, таму пад час адзінакоў обсужваецца дизайн, а не прасветы між символамі.
  • Апдэйты без аанунсаў: новая правіла, базавыя зображэння Docker, выправленні расшырэнняя або бібліятэкая доходзяць да всіх наступнага дня.
  • Прыведамыя структуры: тые ж шаблоны src/common/, налашоўкі Docker і шляхы для перагледу стану ў кожнай службе.
  • Урокі для ўпроваджэння

    Пачніце з самага малогі корыстнага часткі

    Няма прычыны ствараць усё гэта адразу. Сінхронізацыя толькі налашоўкаў ESLint і Prettier дае ведамы рэзультат быстра. Канфігурацыя Docker, налашоўкі рэдагара, спаконаная бібліятэка і запланаваныя апдэйты могу быць даданы пасля таго, як каманда заўзяцца да гэтага падходу.

    Залішыце простор для локальных змян

    Спаконаная база не павінна быць строгім правілам. Сервіс, якому трэба дадатковая правіла, можа дадаць .eslintrc.local.js, які расшырюе спаконаную канфігурацыю; адтолькі што скрыпт сінхронізацыі ніколі не чапае гэты файл, змены застаюцца пасля кожнага запуску.

    Зробіце апдэйты ведамымі

    Упавяшчэнне на рабочым столе здаецца дробным элементам, але яно паведамляе разработчыкаў пра існаванне системы і пра тое, што ў чымсь змянілася. Тыхі апдэйты часта плутаюць людзей, калі ўсё іх артыкулы раптам пачынаюць сябе чыніць інача.

    Версіюйце все

    Без версіі маніфеста задача апдэта не можа з’ясаваць, чыгучы якія-небудзь змены, і будзе перасинхронізавацца ў кожны раз. Версіюванне таксама дае вам конкрэтны элемент для апіленаціі, калі змены ствараюць проблемы.

    Структура, якая лежыць у основе прыклада

    У настаўленні прыклада былі выкарыстаны NestJS і React (або ўсе два на TypeScript), Qwen, якій даўалася доступнасць через MCP, Docker і Docker Compose, Node.js 20 LTS, PostgreSQL 16, Redis 7, GitHub Actions, VS Code, а таксама Bash і cron для сінхронізацыі. Гэтыя версіі адпаведаюць настаўленню ў тым часе; пераканайцеся ў актуальных версіях LTS пры ўскладненні.

    Галоўныя выводы

    • Калі у вас больш за кальку служб і разработчыкаў, цэнтралізаваны рэпазітарый настаўлення быстра прадае сябе.
  • Ключовыя элементы — это рэпазітарый з настройкамі, шаблонамі та спяльнымі файламі, скрыпт налашчэння за адзіным камандам, скрыпт сінхронізацыі, запланаваны апдэйтар, спяльная бібліятэка npm і генератор служб.
  • Замена спяльных файлаў памагае усунуць адхыленні, таму з самага пачатку трэба стварыць спецыяльныя файлы для замены.
  • Аператыўныя дзеянні ў Git без нагляду — гэта самая рызыкаваная частка; краща вярнуць данні з режыму fast-forward, вярнуць схованыя данні та адкрыць нештатны стан, замест таго каб яго хаваць.
  • Рэзультат — разработчыкі можаць прасвятіць свой час на код продукту, а не на перабудову средавання іншых.