[@ant] feat(boot): dicoop/bootcoop образ для sideboot в соседних репо

Цель: в соседних репозиториях (parser2, blockchain-protocol и т.д.)
для тестов и отладки нужно поднимать только цепь + контракты, без
mono-инфры (mongo/postgres/desktop). Решение — два контейнера в их
compose: dicoop/blockchain (нода) + dicoop/bootcoop (one-shot bootstrap).

Что добавлено:
- components/boot/Dockerfile — multi-stage от dicoop/contracts:<tag>
  (контракты flat-layout в /contracts) + dicoop/mono-base:<tag>
  (runtime с pnpm/node + workspace). ENTRYPOINT = pnpm run boot:remote.
  CONTRACTS_DIR=/contracts выставлен по умолчанию.
- .github/workflows/build-bootstrap.yaml — push в dev/testnet/main
  билдит и пушит dicoop/bootcoop:<branch> + :latest для main +
  :<branch>-<short-sha> для пинов. Telegram нотификации.
- components/boot/README.md — раздел про sideboot с готовым compose
  snippet'ом, переменными окружения и опциональными INSTALL_*_DATA.

Версионирование dicoop/bootcoop:<tag> совпадает с dicoop/contracts:<tag>
(multi-stage из того же тега) — контракты и bootstrap синхронны.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
coopops
2026-05-01 09:02:21 +00:00
parent 3cc86331bf
commit b0bbe05c56
3 changed files with 227 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
name: Build bootstrap container
# Сборка и публикация docker-образа `dicoop/bootcoop` — bootstrap-артефакта
# для развёртывания контрактов на удалённой ноде. Образ содержит CLI
# (`pnpm run boot:remote`) и `/contracts` от dicoop/contracts (multi-stage).
# Используется как one-shot job в стороннем docker-compose рядом с
# `dicoop/blockchain` — никакой mono-инфры (mongo/postgres/desktop) не нужно.
#
# Триггер — push в dev/testnet/main. Тег `dicoop/bootcoop` совпадает с
# веткой и подтягивает соответствующий тег `dicoop/contracts` (так
# контракты и bootstrap всегда синхронны).
#
# Зависимости в hub:
# dicoop/contracts:<branch> — пакет wasm/abi (build-contracts.yaml)
# dicoop/mono-base:<branch> — runtime с pnpm/node + workspace (build-containers.yaml)
#
# Секреты:
# DOCKERHUB_USERNAME / DOCKERHUB_TOKEN
# TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID
on:
push:
branches: [dev, testnet, main]
paths:
- 'components/boot/**'
- '.github/workflows/build-bootstrap.yaml'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Determine docker tags
run: |
case "${{ github.ref_name }}" in
main)
echo "DOCKER_TAG=main" >> $GITHUB_ENV
echo "EXTRA_TAG=latest" >> $GITHUB_ENV
;;
testnet)
echo "DOCKER_TAG=testnet" >> $GITHUB_ENV
echo "EXTRA_TAG=" >> $GITHUB_ENV
;;
dev)
echo "DOCKER_TAG=dev" >> $GITHUB_ENV
echo "EXTRA_TAG=" >> $GITHUB_ENV
;;
*)
echo "Unsupported branch ${{ github.ref_name }}" >&2
exit 1
;;
esac
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Pull source images
run: |
docker pull dicoop/contracts:${{ env.DOCKER_TAG }}
docker pull dicoop/mono-base:${{ env.DOCKER_TAG }}
- name: Build and push image
run: |
IMAGE="dicoop/bootcoop"
docker build \
--build-arg CONTRACTS_TAG=${{ env.DOCKER_TAG }} \
--build-arg MONO_BASE_TAG=${{ env.DOCKER_TAG }} \
--label "org.opencontainers.image.revision=${{ github.sha }}" \
--label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-f components/boot/Dockerfile \
-t "$IMAGE:${{ env.DOCKER_TAG }}" \
.
docker push "$IMAGE:${{ env.DOCKER_TAG }}"
if [ -n "${{ env.EXTRA_TAG }}" ]; then
docker tag "$IMAGE:${{ env.DOCKER_TAG }}" "$IMAGE:${{ env.EXTRA_TAG }}"
docker push "$IMAGE:${{ env.EXTRA_TAG }}"
fi
SHORT_SHA="${GITHUB_SHA::7}"
docker tag "$IMAGE:${{ env.DOCKER_TAG }}" "$IMAGE:${{ env.DOCKER_TAG }}-$SHORT_SHA"
docker push "$IMAGE:${{ env.DOCKER_TAG }}-$SHORT_SHA"
- name: Telegram notify success
if: ${{ success() }}
run: |
curl -s -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage \
-d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} \
-d text="✅ [GITHUB MONO] dicoop/bootcoop:${{ env.DOCKER_TAG }} (sha=${GITHUB_SHA::7})"
- name: Telegram notify failure
if: ${{ failure() }}
run: |
curl -s -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage \
-d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} \
-d text="❌ [GITHUB MONO] Ошибка сборки dicoop/bootcoop на ${{ github.ref_name }} (sha=${GITHUB_SHA::7})"
+54
View File
@@ -0,0 +1,54 @@
# Образ-bootstrap для удалённой ноды.
#
# Назначение: one-shot job в чужом docker-compose рядом с уже
# запущенным `node`-сервисом (dicoop/blockchain). Bootstrap
# дожидается готовности RPC, после чего вкатывает на ноду все
# системные и кооперативные контракты, активирует протокол-фичи,
# создаёт системный токен и инициализирует system/emission/powerup.
#
# Контракты НЕ собираются здесь — они тянутся multi-stage из
# готового артефакта `dicoop/contracts:<tag>` (см. workflow
# build-contracts.yaml) и кладутся в /contracts. CLI находит их
# через CONTRACTS_DIR.
#
# Окружение:
# CHAIN_URL — endpoint удалённой ноды (например http://node:8888)
# CONTRACTS_DIR=/contracts (выставлено по умолчанию)
# RPC_WAIT_TIMEOUT_MS — сколько ждать RPC (default 120000)
# EOSIO_PUB_KEY / EOSIO_PRV_KEY — ключи системного аккаунта eosio
# INSTALL_INITIAL_DATA=1 — опционально доставить mono-данные (нужны MONGO_URI/POSTGRES_*)
# INSTALL_EXTRA_DATA=1 — то же + расширенный совет
#
# Применение в стороннем compose:
# services:
# node:
# image: dicoop/blockchain:latest
# ports: ["8888:8888"]
# bootcoop:
# image: dicoop/bootcoop:dev
# depends_on: [node]
# environment:
# CHAIN_URL: http://node:8888
# EOSIO_PUB_KEY: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
# EOSIO_PRV_KEY: 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
# restart: "no"
ARG CONTRACTS_TAG=latest
ARG MONO_BASE_TAG=latest
FROM dicoop/contracts:${CONTRACTS_TAG} AS contracts
FROM dicoop/mono-base:${MONO_BASE_TAG} AS runtime
# Контракты из готового артефакта в flat-layout
# (configs/contracts.ts читает из CONTRACTS_DIR).
COPY --from=contracts /contracts /contracts
ENV CONTRACTS_DIR=/contracts
WORKDIR /app/components/boot
# По умолчанию sideboot режим — против внешней ноды, без docker-управления.
# Переопределить можно: docker run dicoop/bootcoop:dev pnpm run boot:remote
# или подменив CMD/entrypoint в compose.
ENTRYPOINT ["pnpm", "run"]
CMD ["boot:remote"]
+71
View File
@@ -51,6 +51,77 @@ pnpm install --filter @coopenomics/boot
Подробное описание переменных — в файле `.env-example`.
## Запуск bootstrap'а в стороннем проекте (sideboot)
Для проектов, которым нужна **только цепь + контракты** (без mongo/pg/mono-инфры),
есть готовый docker-образ `dicoop/bootcoop:<branch>`. Он one-shot job'ом
накатывает на удалённую ноду все системные и кооперативные контракты,
активирует протокол-фичи, создаёт системный токен.
Минимальный `docker-compose.yaml` для стороннего репозитория:
```yaml
services:
node:
image: dicoop/blockchain:latest
ports:
- "8888:8888"
- "9876:9876"
volumes:
- ./blockchain-data:/mnt/dev/data
command: >
/bin/bash -c "/usr/local/bin/nodeos -d /mnt/dev/data
--config-dir /mnt/dev/config
--genesis-json /mnt/dev/config/genesis.json"
bootcoop:
image: dicoop/bootcoop:dev # или :testnet / :main / :latest
depends_on: [node]
restart: "no"
environment:
CHAIN_URL: http://node:8888
EOSIO_PUB_KEY: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
EOSIO_PRV_KEY: 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
RPC_WAIT_TIMEOUT_MS: "180000"
```
Запуск:
```bash
docker compose up -d node
docker compose up bootcoop # one-shot, выходит после успеха
```
Bootcoop ждёт `${CHAIN_URL}/v1/chain/get_info`, затем катит контракты на ноду.
По выходу с кодом 0 — цепь готова к работе.
### Версионирование
`dicoop/bootcoop:<tag>` всегда multi-stage'ится из `dicoop/contracts:<tag>` с
тем же `<tag>` (dev/testnet/main). Контракты и bootstrap синхронны по sha
коммита mono-репо — no skew.
Точный пин по коммиту: `dicoop/bootcoop:dev-<short-sha>` (тегается каждой сборкой).
### Дополнительные данные (опционально)
Если в стороннем проекте всё же нужны mono-данные (voskhod, ant, совет) —
выставить флаги, и поднять рядом mongo + postgres:
```yaml
environment:
CHAIN_URL: http://node:8888
MONGO_URI: mongodb://mongo:27017/cooperative-x
POSTGRES_HOST: postgres
POSTGRES_USERNAME: postgres
POSTGRES_PASSWORD: postgres!23!23
POSTGRES_DATABASE: voskhod
INSTALL_INITIAL_DATA: "1" # voskhod + ant + совет
INSTALL_EXTRA_DATA: "1" # + расширенный совет (5 пайщиков)
```
Без этих флагов запускается чистый chain-only сценарий.
## Тестирование
Перед запуском тестов необходима работающая инфраструктура (см. `docker-compose.yaml` в корне проекта):