diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63de450..99152d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,3 +83,17 @@ jobs: - name: Run UI tests working-directory: apps/ui run: npm run test -- --run + + deployment: + name: Deployment Artifacts + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Validate docker compose + run: docker compose config -q + + - name: Build deployable images + run: docker compose build admin-api mcp-server ui diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 165f5c1..4b784d5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,22 +1,33 @@ name: Deploy on: - push: - branches: - - main + workflow_run: + workflows: + - CI + types: + - completed workflow_dispatch: concurrency: - group: deploy-${{ github.ref }} + group: deploy-${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch || github.ref }} cancel-in-progress: true jobs: deploy: + if: > + github.event_name == 'workflow_dispatch' || + ( + github.event_name == 'workflow_run' && + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.head_branch == 'main' + ) runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 + with: + ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }} - name: Configure SSH key run: | @@ -50,6 +61,7 @@ jobs: ssh "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" " set -e cd '${{ secrets.DEPLOY_PATH }}' + docker compose config -q docker compose up -d --build --remove-orphans " @@ -57,6 +69,16 @@ jobs: run: | ssh "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" " set -e - curl --fail --silent http://127.0.0.1:3001/health >/dev/null - curl --fail --silent http://127.0.0.1:3002/health >/dev/null + cd '${{ secrets.DEPLOY_PATH }}' + for attempt in \$(seq 1 30); do + if curl --fail --silent http://127.0.0.1:3000/ >/dev/null \ + && curl --fail --silent http://127.0.0.1:3001/health >/dev/null \ + && curl --fail --silent http://127.0.0.1:3002/health >/dev/null; then + exit 0 + fi + sleep 2 + done + echo 'deployment health verification failed' >&2 + docker compose ps >&2 + exit 1 " diff --git a/README.md b/README.md index 96d4320..789c6b9 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,14 @@ MCPaaS - это low-code платформа для публикации внеш Конфигурации операций должны импортироваться и экспортироваться в `YAML`, чтобы их можно было переносить между окружениями, хранить в git и редактировать вне UI. +## CI/CD статус + +В репозитории настроены: + +- `CI` для Rust, UI и deployment artifacts; +- `CD`, который запускается после успешного `CI` на `main` или вручную; +- containerized production-like deployment через `docker compose`. + ## Поддерживаемые протоколы В MVP платформа ориентируется на три основных протокольных сценария интеграции: diff --git a/TASKS.md b/TASKS.md index 8c9d070..8d46417 100644 --- a/TASKS.md +++ b/TASKS.md @@ -2,21 +2,21 @@ ## Current -### `feat/hardening` +### `feat/deployment-cd-polish` Status: completed DoD: -- демонстрационные сценарии воспроизводимы -- логирование и ошибки читаемы -- YAML roundtrip проверен -- publish/reload flow стабилен -- документация по запуску достаточна для повторения демо +- CI проверяет deployment artifacts +- CD запускается только после успешного CI на `main` или вручную +- compose не публикует внутренние сервисы шире, чем нужно +- deploy workflow проверяет health сервисов после запуска +- deployment documentation синхронизирована с фактическим pipeline ## Next -- `feat/deployment-cd-polish` +- `feat/ui-polish` ## Backlog diff --git a/docker-compose.yml b/docker-compose.yml index ff2dedf..4d8b228 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,7 +33,7 @@ services: volumes: - artifact_storage:${MCPAAS_STORAGE_ROOT:-/var/lib/rmcp/storage} ports: - - "3001:3001" + - "127.0.0.1:3001:3001" healthcheck: test: ["CMD", "curl", "--fail", "http://127.0.0.1:3001/health"] interval: 15s @@ -57,7 +57,7 @@ services: volumes: - artifact_storage:${MCPAAS_STORAGE_ROOT:-/var/lib/rmcp/storage} ports: - - "3002:3002" + - "127.0.0.1:3002:3002" healthcheck: test: ["CMD", "curl", "--fail", "http://127.0.0.1:3002/health"] interval: 15s @@ -70,7 +70,7 @@ services: dockerfile: apps/ui/Dockerfile restart: unless-stopped ports: - - "3000:3000" + - "127.0.0.1:3000:3000" healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/"] interval: 15s diff --git a/docs/deployment.md b/docs/deployment.md index 4f20aec..bbb0378 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -163,6 +163,7 @@ services: - поднимать `postgres`, `admin-api`, `mcp-server`, `ui`; - использовать env vars вместо hardcoded config; - иметь persistent storage для БД и artifacts; +- публиковать `ui`, `admin-api` и `mcp-server` только на loopback, если перед ними уже стоит reverse proxy; - не публиковать внутренние сервисы наружу без необходимости; - содержать healthchecks. @@ -190,7 +191,7 @@ CI должен выполнять: CD для MVP должен: -- запускаться только для `main`; +- запускаться только после успешного `CI` на `main` или вручную; - собирать production artifacts; - доставлять deployment files на целевой Linux host; - выполнять controlled restart; @@ -200,11 +201,11 @@ CD для MVP должен: 1. push в `main` 2. успешный `CI` -3. build images +3. build images или удаленная сборка на хосте 4. upload env и deployment files -5. `docker compose pull` +5. `docker compose config -q` 6. `docker compose up -d` -7. healthcheck verification +7. healthcheck verification для `ui`, `admin-api`, `mcp-server` Для MVP допустим deployment с удаленной сборкой на целевом Linux host через `ssh + rsync + docker compose up -d --build`, если не используется отдельный container registry.