05d413b37f
Прогон на push в dev/main дублировал проверку, уже сделанную на PR, и жёг по ~47 мин на нагруженном раннере. Оставляем только pull_request (main, dev): ветки в эти ветки попадают через PR, который и валидируется; релиз main триггерит отдельный release.yml. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
161 lines
8.0 KiB
YAML
161 lines
8.0 KiB
YAML
name: CI
|
||
|
||
on:
|
||
pull_request:
|
||
branches: [main, dev]
|
||
|
||
concurrency:
|
||
group: ${{ github.workflow }}-${{ github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
jobs:
|
||
lint:
|
||
name: Lint
|
||
runs-on: ubuntu-22.04
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
with: { version: '10' }
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: '20', cache: 'pnpm' }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: pnpm audit --audit-level=high
|
||
continue-on-error: true
|
||
|
||
typecheck:
|
||
name: Typecheck
|
||
runs-on: ubuntu-22.04
|
||
needs: lint
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
with: { version: '10' }
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: '20', cache: 'pnpm' }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: pnpm --filter @coopenomics/coopos-ship-reader build
|
||
- run: pnpm --filter @coopenomics/parser2 typecheck
|
||
|
||
unit:
|
||
name: Unit tests
|
||
runs-on: ubuntu-22.04
|
||
needs: typecheck
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
with: { version: '10' }
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: '20', cache: 'pnpm' }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: pnpm --filter @coopenomics/coopos-ship-reader build
|
||
- run: pnpm --filter @coopenomics/parser2 test:unit -- --reporter=verbose --coverage
|
||
- uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
fail_ci_if_error: false
|
||
|
||
integration:
|
||
name: Integration tests
|
||
runs-on: ubuntu-22.04
|
||
needs: unit
|
||
services:
|
||
redis:
|
||
image: redis:7-alpine
|
||
options: >-
|
||
--health-cmd "redis-cli ping"
|
||
--health-interval 5s
|
||
--health-timeout 3s
|
||
--health-retries 10
|
||
ports:
|
||
- 6379:6379
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
with: { version: '10' }
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: '20', cache: 'pnpm' }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: pnpm --filter @coopenomics/coopos-ship-reader build
|
||
# Parser2 build: нужен dist/deserialize.worker.cjs для Piscina worker pool
|
||
- run: pnpm --filter @coopenomics/parser2 build
|
||
# Запускаем nodeos вручную через docker run: образ dicoop/blockchain:v5.1.0-dev
|
||
# не имеет CMD по умолчанию, и GitHub Actions services: не поддерживает
|
||
# передачу команды контейнеру. Монтируем config.ini (SHiP на 8080) и genesis.json.
|
||
- name: Start blockchain node
|
||
run: |
|
||
# Раннер self-hosted и персистентный: упавший прогон оставляет контейнер
|
||
# с фиксированным именем blockchain, и следующий старт падает с exit 125
|
||
# (Conflict, name already in use). Сносим остаток перед стартом.
|
||
docker rm -f blockchain 2>/dev/null || true
|
||
# Конфиг кладём в контейнер через docker cp, а НЕ через bind-mount (-v).
|
||
# Раннер работает по схеме docker-in-docker (docker.sock хоста проброшен
|
||
# в job-контейнер), поэтому пути bind-mount резолвятся на ФС ХОСТА, а не
|
||
# внутри job-контейнера: ни mktemp, ни workspace хостовому демону не видны
|
||
# → монтируется ПУСТОЙ каталог (nodeos пишет туда protocol_features, но
|
||
# genesis.json/config.ini отсутствуют → 'genesis file does not exist').
|
||
# docker cp передаёт файлы tar-стримом по API и от путей хоста не зависит.
|
||
# /mnt/dev/config в образе нет (его создавал сам mount), а docker cp не
|
||
# создаёт родительские каталоги — поэтому config-dir = /mnt/cfg (родитель
|
||
# /mnt существует). protocol_features узел пишет туда же, в свежесозданный
|
||
# контейнер — никакого мусора между прогонами.
|
||
docker create --name blockchain \
|
||
dicoop/blockchain:v5.1.0-dev \
|
||
/bin/bash -c 'mkdir -p /mnt/data && exec /usr/local/bin/nodeos -d /mnt/data -p eosio --config-dir /mnt/cfg --genesis-json /mnt/cfg/genesis.json --disable-replay-opts'
|
||
docker cp "${GITHUB_WORKSPACE}/packages/parser2/test/integration/node-config" blockchain:/mnt/cfg
|
||
# Сеть в DinD: порт-маппинг -p публикует на ХОСТЕ, а шаги job'а крутятся
|
||
# внутри job-контейнера — его localhost хостовых портов не видит (поэтому
|
||
# localhost:8888 был недостижим). redis-сервис доступен по localhost лишь
|
||
# потому, что его сеть настраивает сам Gitea. Свою ноду подключаем в ту же
|
||
# сеть, что и job-контейнер, и адресуем по её IP на этой сети (надёжнее
|
||
# DNS — работает и на bridge); IP пробрасываем в env последующих шагов.
|
||
SELF=$(cat /etc/hostname)
|
||
NET=$(docker inspect "$SELF" --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{"\n"}}{{end}}' | grep -v '^bridge$' | head -1)
|
||
[ -z "$NET" ] && NET=bridge
|
||
docker network connect "$NET" blockchain
|
||
docker start blockchain
|
||
NODE_HOST=$(docker inspect blockchain --format "{{(index .NetworkSettings.Networks \"$NET\").IPAddress}}")
|
||
echo "Нода в сети '$NET' с IP $NODE_HOST"
|
||
echo "NODE_HOST=$NODE_HOST" >> "$GITHUB_ENV"
|
||
sleep 3
|
||
- name: Wait for Chain API
|
||
run: |
|
||
# Бюджет 120 попыток × (≤2с curl + 2с sleep) ≈ до 8 мин: на нагруженном
|
||
# раннере nodeos поднимается медленно (наблюдали >6 мин до get_info), а
|
||
# curl без --max-time подвисал на ещё-не-отвечающем порту и съедал бюджет.
|
||
for i in $(seq 1 120); do
|
||
if curl -sf --max-time 2 "http://${NODE_HOST}:8888/v1/chain/get_info" > /dev/null 2>&1; then
|
||
echo "Chain API ready after $i attempts"
|
||
exit 0
|
||
fi
|
||
echo " attempt $i/120..."
|
||
sleep 4
|
||
done
|
||
echo "ERROR: Chain API did not become ready. Container logs:"
|
||
docker logs blockchain | tail -100
|
||
exit 1
|
||
- run: pnpm --filter @coopenomics/parser2 test:integration
|
||
env:
|
||
# В Gitea/act job крутится в контейнере, а services: — контейнеры-соседи
|
||
# в той же сети, доступные ПО ИМЕНИ СЕРВИСА (redis), а не через localhost
|
||
# (localhost сработал бы на GitHub-хостед раннере, но не в DinD).
|
||
REDIS_URL: redis://redis:6379
|
||
CHAIN_URL: http://${{ env.NODE_HOST }}:8888
|
||
SHIP_URL: ws://${{ env.NODE_HOST }}:8080
|
||
- name: Show blockchain logs on failure
|
||
if: failure()
|
||
run: docker logs blockchain | tail -200
|
||
|
||
build:
|
||
name: Build
|
||
runs-on: ubuntu-22.04
|
||
needs: integration
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: pnpm/action-setup@v4
|
||
with: { version: '10' }
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: '20', cache: 'pnpm' }
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: pnpm --filter @coopenomics/coopos-ship-reader build
|
||
- run: pnpm --filter @coopenomics/parser2 build
|