[@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:
@@ -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})"
|
||||
@@ -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"]
|
||||
@@ -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` в корне проекта):
|
||||
|
||||
Reference in New Issue
Block a user