Скрипт синхронизации arm-core/web с arm-web и проверка отставания в пайплайне переноса в контур (#94) #95
12
Makefile
12
Makefile
@ -7,7 +7,7 @@ CHANGE ?= slice-0-skeleton
|
|||||||
# Текущая версия модели данных — по ней рисуются диаграммы (make diagrams)
|
# Текущая версия модели данных — по ней рисуются диаграммы (make diagrams)
|
||||||
DBML ?= model/data-model-v5.18.dbml
|
DBML ?= model/data-model-v5.18.dbml
|
||||||
|
|
||||||
.PHONY: venv validate-contracts validate-openspec test-snapshot check diagrams
|
.PHONY: venv validate-contracts validate-openspec test-snapshot test-sync-web sync-web check diagrams
|
||||||
|
|
||||||
# Единственная зависимость скриптов проверки контракта — jsonschema
|
# Единственная зависимость скриптов проверки контракта — jsonschema
|
||||||
venv:
|
venv:
|
||||||
@ -26,7 +26,15 @@ validate-openspec:
|
|||||||
test-snapshot:
|
test-snapshot:
|
||||||
scripts/test_prepare_contour_snapshot.sh
|
scripts/test_prepare_contour_snapshot.sh
|
||||||
|
|
||||||
check: validate-contracts validate-openspec test-snapshot
|
# sync-web.sh на синтетических репозиториях: точка синхронизации, перенос набора, отказ при расхождении, пайплайн переноса
|
||||||
|
test-sync-web:
|
||||||
|
scripts/test_sync_web.sh
|
||||||
|
|
||||||
|
# Синхронизация arm-core/web с arm-web@test одной командой (worktree, issue, PR); SYNC_ARGS="--check" или "--dry-run"
|
||||||
|
sync-web:
|
||||||
|
scripts/sync-web.sh $(SYNC_ARGS)
|
||||||
|
|
||||||
|
check: validate-contracts validate-openspec test-snapshot test-sync-web
|
||||||
|
|
||||||
# Диаграммы model/diagrams/part01…09.{svg,png} из $(DBML); нужен npx (Node.js), зависимостей Python нет
|
# Диаграммы model/diagrams/part01…09.{svg,png} из $(DBML); нужен npx (Node.js), зависимостей Python нет
|
||||||
diagrams:
|
diagrams:
|
||||||
|
|||||||
@ -64,6 +64,13 @@ docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour
|
|||||||
|
|
||||||
Что делает скрипт (репозиторий-источник не меняется):
|
Что делает скрипт (репозиторий-источник не меняется):
|
||||||
|
|
||||||
|
0. Только arm-core: проверяет, не отстаёт ли встроенный фронт `web/` от `RSHB/arm-web@test` (`sync-web.sh --check`,
|
||||||
|
раздел 3.1). Если отстаёт — спрашивает «перенести как есть? [y/N]»: `y` — снимок делается, отставание записывается в
|
||||||
|
`SNAPSHOT.md`; `n` (или пустой ответ) — запускается синхронизация (worktree, issue, PR в arm-core) и перенос
|
||||||
|
останавливается с кодом 3 до merge PR и закрытия issue («закрывай»), затем снимок повторяется. Без терминала вопрос не
|
||||||
|
задаётся: нужен флаг `--web-as-is` первым аргументом, иначе код 3. Если `web/` правили напрямую в arm-core мимо arm-web
|
||||||
|
(точки синхронизации нет) — снимок не делается, разбирать вручную. Если `arm-web` рядом не найден — предупреждение,
|
||||||
|
снимок делается.
|
||||||
1. `git archive <ref>` → `/tmp/contour/<repo>/` — дерево коммита без `.git` и без игнорируемых файлов.
|
1. `git archive <ref>` → `/tmp/contour/<repo>/` — дерево коммита без `.git` и без игнорируемых файлов.
|
||||||
2. Удаляет `.claude/`, `.codegraph/`, `CLAUDE.md`, `openspec/config.yaml`, `docs/superpowers/` на любой глубине (в т.ч.
|
2. Удаляет `.claude/`, `.codegraph/`, `CLAUDE.md`, `openspec/config.yaml`, `docs/superpowers/` на любой глубине (в т.ч.
|
||||||
`web/` arm-core; опустевший `docs/` тоже), `Dockerfile` и `.dockerignore` — в корне.
|
`web/` arm-core; опустевший `docs/` тоже), `Dockerfile` и `.dockerignore` — в корне.
|
||||||
@ -76,7 +83,33 @@ docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour
|
|||||||
`git.aepif.ru`, на месте платформенные файлы (`raisa_config.yml`, `setup/`, `run_server.py`, `requirements.txt`,
|
`git.aepif.ru`, на месте платформенные файлы (`raisa_config.yml`, `setup/`, `run_server.py`, `requirements.txt`,
|
||||||
`.env.test`, `contracts/`). Любая проблема — код возврата 1 и список.
|
`.env.test`, `contracts/`). Любая проблема — код возврата 1 и список.
|
||||||
|
|
||||||
Тест скрипта — `make test-snapshot` (синтетический репозиторий с артефактами агента в корне и в `web/`).
|
Тест скрипта — `make test-snapshot` (синтетический репозиторий с артефактами агента в корне и в `web/`); проверка
|
||||||
|
отставания `web/` и остановка переноса — в `make test-sync-web`.
|
||||||
|
|
||||||
|
### 3.1. Синхронизация `arm-core/web` с `arm-web`: `scripts/sync-web.sh`
|
||||||
|
|
||||||
|
Фронт ведётся в двух местах: отдельный репозиторий `RSHB/arm-web` (ветка `test`, прототип и демо-стенд) и встроенный
|
||||||
|
`arm-core/web`, из которого собирается контур. Правила: `arm-core/web` напрямую не редактируется — все правки фронта идут в
|
||||||
|
arm-web и переносятся скриптом; состояние синхронизации не хранится — точкой считается коммит arm-web, у которого дерево
|
||||||
|
`src` совпадает с `web/src` в arm-core main (сравнение по хэшу дерева git).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make -C docs sync-web SYNC_ARGS=--check # 0 — синхронно; 10 — arm-core/web отстаёт (список коммитов); 20 — расхождение
|
||||||
|
make -C docs sync-web SYNC_ARGS=--dry-run # worktree .wt/web-sync-<sha7>/arm-core с перенесённым набором, без issue/PR
|
||||||
|
make -C docs sync-web # полный цикл: worktree, issue и PR в RSHB/arm-core, проверки, коммит, push
|
||||||
|
```
|
||||||
|
|
||||||
|
Полный цикл делает то же, что делалось вручную в arm-core #94 и #100: worktree по абсолютному пути на ветке
|
||||||
|
`feat/<issue>-web-sync-<sha7>` с `.bounded`; перенос набора синхронизации — всё дерево arm-web, кроме служебного
|
||||||
|
(`CLAUDE.md`, `.claude/`, `openspec/`, `docs/`, `scripts/`, `Makefile`, `ARCHITECTURE.md`, `.gitignore`, `package-lock.json`;
|
||||||
|
`README.md` входит в набор — решение владельца 10.10.2026); контроль `diff -rq` с деревом arm-web; проверки `vitest`,
|
||||||
|
`tsc --noEmit`, `biome check src` (предупреждений не больше, чем на main), `rsbuild build`; коммит и PR с диапазоном
|
||||||
|
коммитов arm-web и рулингами R-1/R-2. Любая красная проверка останавливает скрипт до коммита, worktree остаётся для разбора.
|
||||||
|
|
||||||
|
`node_modules` для проверок берётся из `WEB_NODE_MODULES` (по умолчанию `.wt/web-proto/arm-web/node_modules` — стенд демо),
|
||||||
|
иначе `npm install` в worktree. Скрипт ничего не мержит и не удаляет: ревью перенесённого кода против бэкенда, merge и
|
||||||
|
чеклист «закрывай» — за исполнителем. Код 20 (расхождение) означает прямые правки `web/` в arm-core: их нужно перенести в
|
||||||
|
arm-web или откатить, иначе автоперенос их затёр бы.
|
||||||
|
|
||||||
Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят `make check` без
|
Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят `make check` без
|
||||||
`docs` и `fixtures` (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5).
|
`docs` и `fixtures` (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5).
|
||||||
@ -204,7 +237,9 @@ git diff <коммит sync> HEAD -- . ':!SNAPSHOT.md' > /tmp/contour-arm-core.p
|
|||||||
1. Снаружи: нужные PR слиты в `main` трёх сервисов; `make check-full` зелёный в каждом; контракт в `docs/contracts` и копии
|
1. Снаружи: нужные PR слиты в `main` трёх сервисов; `make check-full` зелёный в каждом; контракт в `docs/contracts` и копии
|
||||||
`api/contracts` идентичны.
|
`api/contracts` идентичны.
|
||||||
2. Правки из контура (раздел 7) возвращены наружу и слиты.
|
2. Правки из контура (раздел 7) возвращены наружу и слиты.
|
||||||
3. `prepare-contour-snapshot.sh` по каждому сервису; скрипт завершился словами «снимок готов».
|
3. `prepare-contour-snapshot.sh` по каждому сервису; скрипт завершился словами «снимок готов». Для arm-core скрипт сам
|
||||||
|
проверяет отставание `web/` от arm-web (раздел 3.1): при остановке с кодом 3 — дождаться merge PR синхронизации и
|
||||||
|
«закрывай», затем повторить.
|
||||||
4. В контуре: клон, ветка, `rsync --delete`, просмотр `git status`, коммит `sync: <repo>@<hash> (<дата>)`, `make venv`,
|
4. В контуре: клон, ветка, `rsync --delete`, просмотр `git status`, коммит `sync: <repo>@<hash> (<дата>)`, `make venv`,
|
||||||
`make check` (пропуски — только из раздела 5), для arm-core `make web-check`, merge request по регламенту GitLab контура.
|
`make check` (пропуски — только из раздела 5), для arm-core `make web-check`, merge request по регламенту GitLab контура.
|
||||||
5. Порядок мержа при смене версии контракта: arm-core → tabular-parser → scan-gateway.
|
5. Порядок мержа при смене версии контракта: arm-core → tabular-parser → scan-gateway.
|
||||||
|
|||||||
@ -6,13 +6,22 @@
|
|||||||
# Nexus (как `setup/setup.sh` шаблона), убирает цель docker-build, заменяет ссылки на внешний Gitea, пишет SNAPSHOT.md с
|
# Nexus (как `setup/setup.sh` шаблона), убирает цель docker-build, заменяет ссылки на внешний Gitea, пишет SNAPSHOT.md с
|
||||||
# провенансом и проверяет результат. Репозиторий-источник не меняется.
|
# провенансом и проверяет результат. Репозиторий-источник не меняется.
|
||||||
#
|
#
|
||||||
# Запуск из workspace: docs/scripts/prepare-contour-snapshot.sh <каталог репозитория> <каталог вывода> [ref]
|
# Запуск из workspace: docs/scripts/prepare-contour-snapshot.sh [--web-as-is] <каталог репозитория> <каталог вывода> [ref]
|
||||||
# ref по умолчанию — origin/main (снимок всегда с сервера, не с рабочего дерева).
|
# ref по умолчанию — origin/main (снимок всегда с сервера, не с рабочего дерева).
|
||||||
# Пример: docs/scripts/prepare-contour-snapshot.sh tabular-parser /tmp/contour
|
# Пример: docs/scripts/prepare-contour-snapshot.sh tabular-parser /tmp/contour
|
||||||
# Результат: <каталог вывода>/<имя репозитория>/ — готовое дерево для rsync в клон репозитория контура.
|
# Результат: <каталог вывода>/<имя репозитория>/ — готовое дерево для rsync в клон репозитория контура.
|
||||||
|
#
|
||||||
|
# Для arm-core перед снимком проверяется, не отстаёт ли встроенный фронт web/ от RSHB/arm-web (sync-web.sh --check).
|
||||||
|
# Если отстаёт — вопрос «перенести как есть?»: «y» — снимок с отставанием (оно записывается в SNAPSHOT.md); «n» —
|
||||||
|
# запускается синхронизация (sync-web.sh: worktree, issue, PR) и перенос останавливается (код 3) до merge PR и закрытия
|
||||||
|
# issue. Без терминала вопрос не задаётся: нужен флаг --web-as-is, иначе код 3. Расхождение (прямые правки web/ в arm-core) —
|
||||||
|
# всегда стоп. arm-web ищется рядом с репозиторием (../arm-web) или в $ARM_WEB; если его нет — предупреждение, снимок делается.
|
||||||
|
# $SYNC_WEB_ARGS — дополнительные аргументы sync-web.sh (для теста: --dry-run --wt-root …).
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
usage() { echo "usage: $0 <repo-dir> <out-dir> [ref]" >&2; exit 2; }
|
usage() { echo "usage: $0 [--web-as-is] <repo-dir> <out-dir> [ref]" >&2; exit 2; }
|
||||||
|
WEB_AS_IS=0
|
||||||
|
if [ "${1:-}" = "--web-as-is" ]; then WEB_AS_IS=1; shift; fi
|
||||||
[ $# -ge 2 ] || usage
|
[ $# -ge 2 ] || usage
|
||||||
|
|
||||||
REPO=$(cd "$1" && pwd)
|
REPO=$(cd "$1" && pwd)
|
||||||
@ -31,6 +40,42 @@ if [ -e "$DEST" ]; then
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- 0. arm-core: встроенный фронт web/ не должен отставать от arm-web -----------------------------------------------
|
||||||
|
WEB_LAG=""
|
||||||
|
if [ "$NAME" = arm-core ]; then
|
||||||
|
SYNC_WEB="$(cd "$(dirname "$0")" && pwd)/sync-web.sh"
|
||||||
|
ARM_WEB_DIR=${ARM_WEB:-$(dirname "$REPO")/arm-web}
|
||||||
|
# shellcheck disable=SC2206
|
||||||
|
SYNC_ARGS=(--arm-core "$REPO" --arm-web "$ARM_WEB_DIR" --core-ref "$REF" ${SYNC_WEB_ARGS:-})
|
||||||
|
if [ ! -e "$ARM_WEB_DIR/.git" ]; then
|
||||||
|
echo "предупреждение: arm-web не найден ($ARM_WEB_DIR) — отставание web/ от arm-web не проверено" >&2
|
||||||
|
else
|
||||||
|
rc=0; "$SYNC_WEB" --check "${SYNC_ARGS[@]}" || rc=$?
|
||||||
|
case "$rc" in
|
||||||
|
0) ;;
|
||||||
|
10)
|
||||||
|
if [ "$WEB_AS_IS" = 1 ]; then
|
||||||
|
answer=y
|
||||||
|
elif [ -t 0 ] || [ -p /dev/stdin ] || [ -f /dev/stdin ]; then
|
||||||
|
read -r -p "web/ в arm-core отстаёт от arm-web. Перенести в контур как есть? [y/N] " answer || answer=n
|
||||||
|
else
|
||||||
|
answer=n
|
||||||
|
echo "нет терминала и нет --web-as-is: перенос как есть не подтверждён" >&2
|
||||||
|
fi
|
||||||
|
case "$answer" in
|
||||||
|
y|Y|д|Д) WEB_LAG="отстаёт от arm-web (перенесён как есть по решению оператора, см. sync-web.sh --check)" ;;
|
||||||
|
*)
|
||||||
|
echo "запускается синхронизация arm-core/web с arm-web (sync-web.sh)…" >&2
|
||||||
|
"$SYNC_WEB" "${SYNC_ARGS[@]}" || true
|
||||||
|
echo "перенос в контур остановлен до полного завершения синхронизации: merge PR и закрытие issue (чеклист «закрывай»), затем повторите снимок." >&2
|
||||||
|
exit 3 ;;
|
||||||
|
esac ;;
|
||||||
|
20) echo "ошибка: web/ в arm-core расходится с arm-web (прямые правки) — снимок не делается, разберитесь вручную" >&2; exit 1 ;;
|
||||||
|
*) echo "ошибка: sync-web.sh --check завершился с кодом $rc" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
git -C "$REPO" fetch -q origin
|
git -C "$REPO" fetch -q origin
|
||||||
HASH=$(git -C "$REPO" rev-parse "$REF")
|
HASH=$(git -C "$REPO" rev-parse "$REF")
|
||||||
DATE=$(git -C "$REPO" show -s --format=%cs "$REF")
|
DATE=$(git -C "$REPO" show -s --format=%cs "$REF")
|
||||||
@ -144,6 +189,9 @@ cat > "$DEST/SNAPSHOT.md" <<EOF
|
|||||||
|
|
||||||
Разработка ведётся снаружи; правки в контуре возвращаются в источник вручную (см. dev/contour-transfer-guide.md в docs).
|
Разработка ведётся снаружи; правки в контуре возвращаются в источник вручную (см. dev/contour-transfer-guide.md в docs).
|
||||||
EOF
|
EOF
|
||||||
|
if [ -n "$WEB_LAG" ]; then
|
||||||
|
printf '\nВстроенный фронт \`web/\` на момент снимка %s.\n' "$WEB_LAG" >> "$DEST/SNAPSHOT.md"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- 5. Проверки ----------------------------------------------------------------------------------------------------
|
# --- 5. Проверки ----------------------------------------------------------------------------------------------------
|
||||||
fail=0
|
fail=0
|
||||||
|
|||||||
218
scripts/sync-web.sh
Executable file
218
scripts/sync-web.sh
Executable file
@ -0,0 +1,218 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Синхронизация встроенного фронта arm-core/web с отдельным репозиторием фронта RSHB/arm-web (ветка test).
|
||||||
|
# Делает одной командой то, что делалось вручную в arm-core #94 и #100: worktree, issue, перенос набора файлов,
|
||||||
|
# проверки фронта, коммит, PR. Гайд: dev/contour-transfer-guide.md §3.1.
|
||||||
|
#
|
||||||
|
# Точка синхронизации не хранится: это коммит arm-web@<ref>, у которого хэш дерева `src` равен хэшу `web/src`
|
||||||
|
# в arm-core@<core-ref>. Если такого коммита нет — arm-core/web правили напрямую, мимо arm-web; перенос затёр бы
|
||||||
|
# эту работу, поэтому скрипт останавливается (код 20).
|
||||||
|
#
|
||||||
|
# Набор синхронизации — всё дерево arm-web, кроме служебного (контекст агента, спеки UI, Makefile и скрипты
|
||||||
|
# демо-стенда): CLAUDE.md, .claude/, openspec/, docs/, scripts/, Makefile, ARCHITECTURE.md, .gitignore, package-lock.json.
|
||||||
|
#
|
||||||
|
# Запуск из workspace: docs/scripts/sync-web.sh [--check] [--dry-run] [--ref <ref>] [--core-ref <ref>]
|
||||||
|
# [--arm-web <dir>] [--arm-core <dir>] [--wt-root <dir>]
|
||||||
|
# --check только сравнить: 0 — синхронно, 10 — arm-core/web отстаёт, 20 — расхождение (правки напрямую)
|
||||||
|
# --dry-run worktree, перенос и контроль идентичности без issue, PR, push и проверок npm (посмотреть, что перенесётся)
|
||||||
|
# --ref ветка arm-web, по умолчанию origin/test; --core-ref — база arm-core, по умолчанию origin/main
|
||||||
|
# WEB_NODE_MODULES — откуда взять node_modules для проверок (по умолчанию <wt-root>/web-proto/arm-web/node_modules);
|
||||||
|
# если каталога нет — npm install в worktree
|
||||||
|
# Скрипт пишет только в новый worktree arm-core на ветке фичи; ничего не мержит, не удаляет и не закрывает —
|
||||||
|
# закрытие после merge идёт обычным чеклистом «закрывай».
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
# Корень workspace — где рядом лежат arm-core и arm-web. Скрипт запускают и из docs/ (корень = ../..), и из worktree
|
||||||
|
# .wt/<задача>/docs (корень = ../../../..); внешний кандидат проверяется первым — там основные checkout'ы.
|
||||||
|
WS="$(cd "$HERE/../.." && pwd)"
|
||||||
|
for cand in "$HERE/../../../.." "$HERE/../.."; do
|
||||||
|
if [ -e "$cand/arm-core/.git" ] && [ -e "$cand/arm-web/.git" ]; then WS="$(cd "$cand" && pwd)"; break; fi
|
||||||
|
done
|
||||||
|
ARM_WEB="$WS/arm-web"
|
||||||
|
ARM_CORE="$WS/arm-core"
|
||||||
|
WT_ROOT="$WS/.wt"
|
||||||
|
REF=origin/test
|
||||||
|
CORE_REF=origin/main
|
||||||
|
MODE=sync
|
||||||
|
CHECK=0
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--check) CHECK=1 ;; # имеет приоритет над --dry-run независимо от порядка (пайплайн добавляет $SYNC_WEB_ARGS в конец)
|
||||||
|
--dry-run) MODE=dry ;;
|
||||||
|
--ref) REF=$2; shift ;;
|
||||||
|
--core-ref) CORE_REF=$2; shift ;;
|
||||||
|
--arm-web) ARM_WEB=$2; shift ;;
|
||||||
|
--arm-core) ARM_CORE=$2; shift ;;
|
||||||
|
--wt-root) WT_ROOT=$2; shift ;;
|
||||||
|
-h|--help) sed -n '2,24p' "$0"; exit 0 ;;
|
||||||
|
*) echo "sync-web: неизвестный аргумент $1" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
[ "$CHECK" = 0 ] || MODE=check
|
||||||
|
|
||||||
|
# Исключения набора синхронизации: pathspec для git diff и имена для diff -rq
|
||||||
|
EXCLUDE_NAMES=(CLAUDE.md .claude openspec docs scripts Makefile ARCHITECTURE.md .gitignore package-lock.json)
|
||||||
|
PATHSPEC=(.)
|
||||||
|
DIFF_EXCLUDES=(--exclude=node_modules --exclude=dist --exclude=.codegraph --exclude=.superpowers --exclude=.bounded)
|
||||||
|
for n in "${EXCLUDE_NAMES[@]}"; do PATHSPEC+=(":(exclude,top)$n"); DIFF_EXCLUDES+=("--exclude=$n"); done
|
||||||
|
|
||||||
|
die() { echo "sync-web: $1" >&2; exit "${2:-1}"; } # die <сообщение> [код]
|
||||||
|
[ -d "$ARM_WEB/.git" ] || [ -f "$ARM_WEB/.git" ] || die "arm-web не найден: $ARM_WEB (--arm-web <dir>)" 2
|
||||||
|
[ -d "$ARM_CORE/.git" ] || [ -f "$ARM_CORE/.git" ] || die "arm-core не найден: $ARM_CORE (--arm-core <dir>)" 2
|
||||||
|
ARM_WEB=$(cd "$ARM_WEB" && pwd); ARM_CORE=$(cd "$ARM_CORE" && pwd)
|
||||||
|
|
||||||
|
git -C "$ARM_WEB" fetch -q origin
|
||||||
|
git -C "$ARM_CORE" fetch -q origin
|
||||||
|
git -C "$ARM_WEB" rev-parse -q --verify "$REF^{commit}" >/dev/null || die "в arm-web нет $REF" 2
|
||||||
|
git -C "$ARM_CORE" rev-parse -q --verify "$CORE_REF^{commit}" >/dev/null || die "в arm-core нет $CORE_REF" 2
|
||||||
|
|
||||||
|
# --- 1. Точка синхронизации -------------------------------------------------------------------------------------------
|
||||||
|
CORE_SRC=$(git -C "$ARM_CORE" rev-parse -q --verify "$CORE_REF:web/src") || die "в arm-core@$CORE_REF нет web/src" 2
|
||||||
|
HEAD_SHA=$(git -C "$ARM_WEB" rev-parse "$REF")
|
||||||
|
HEAD7=${HEAD_SHA:0:7}
|
||||||
|
POINT=""
|
||||||
|
while IFS= read -r c; do
|
||||||
|
t=$(git -C "$ARM_WEB" rev-parse -q --verify "$c:src" 2>/dev/null || true)
|
||||||
|
if [ "$t" = "$CORE_SRC" ]; then POINT=$c; break; fi
|
||||||
|
done < <(git -C "$ARM_WEB" rev-list "$REF")
|
||||||
|
|
||||||
|
if [ -z "$POINT" ]; then
|
||||||
|
echo "sync-web: расхождение — ни у одного коммита arm-web@$REF дерево src не совпадает с arm-core@$CORE_REF:web/src." >&2
|
||||||
|
echo "arm-core/web правили напрямую, мимо arm-web; автоперенос затёр бы эти правки. Коммиты arm-core по web/:" >&2
|
||||||
|
git -C "$ARM_CORE" log --format=' %h %s' -10 "$CORE_REF" -- web/ >&2
|
||||||
|
echo "Разберитесь вручную: перенесите прямые правки в arm-web (или откатите их), затем повторите." >&2
|
||||||
|
exit 20
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$POINT" = "$HEAD_SHA" ]; then
|
||||||
|
echo "sync-web: arm-core@$CORE_REF web/ синхронен с arm-web@$REF ($HEAD7) — переносить нечего"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMITS=$(git -C "$ARM_WEB" log --format='%h %s' --no-merges "$POINT..$REF")
|
||||||
|
N_COMMITS=$(printf '%s\n' "$COMMITS" | grep -c . || true)
|
||||||
|
FILES=$(git -C "$ARM_WEB" diff --name-only "$POINT" "$REF" -- "${PATHSPEC[@]}")
|
||||||
|
N_FILES=$(printf '%s\n' "$FILES" | grep -c . || true)
|
||||||
|
|
||||||
|
echo "sync-web: arm-core@$CORE_REF web/ отстаёт от arm-web@$REF ($HEAD7)."
|
||||||
|
echo "точка синхронизации: arm-web ${POINT:0:7}; непереносённых коммитов: $N_COMMITS, файлов в наборе: $N_FILES"
|
||||||
|
printf '%s\n' "$COMMITS" | sed 's/^/ /'
|
||||||
|
[ "$MODE" != check ] || exit 10
|
||||||
|
|
||||||
|
# --- 2. Worktree -----------------------------------------------------------------------------------------------------
|
||||||
|
TMP_BRANCH="tmp/web-sync-$HEAD7"
|
||||||
|
WT="$WT_ROOT/web-sync-$HEAD7/arm-core"
|
||||||
|
[ ! -e "$WT" ] || die "worktree уже существует: $WT — завершите или удалите предыдущую синхронизацию" 2
|
||||||
|
git -C "$ARM_CORE" rev-parse -q --verify "$TMP_BRANCH" >/dev/null && die "ветка $TMP_BRANCH уже есть в arm-core" 2
|
||||||
|
mkdir -p "$(dirname "$WT")"
|
||||||
|
git -C "$ARM_CORE" worktree add -q -b "$TMP_BRANCH" "$WT" "$CORE_REF"
|
||||||
|
touch "$WT/.bounded"
|
||||||
|
echo "worktree: $WT ($TMP_BRANCH от $CORE_REF)"
|
||||||
|
|
||||||
|
# --- 3. Issue и ветка (не в dry-run) ---------------------------------------------------------------------------------
|
||||||
|
TEA=(tea --login home --repo RSHB/arm-core)
|
||||||
|
ISSUE=""
|
||||||
|
BRANCH="$TMP_BRANCH"
|
||||||
|
if [ "$MODE" = sync ]; then
|
||||||
|
TITLE="web: синхронизация встроенного фронта с arm-web@${REF#origin/} ($HEAD7)"
|
||||||
|
BODY="Встроенный фронт \`arm-core/web\` отстаёт от \`RSHB/arm-web@${REF#origin/}\` ($HEAD7); точка синхронизации — arm-web ${POINT:0:7}.
|
||||||
|
Непереносённые коммиты arm-web ($N_COMMITS):
|
||||||
|
$(printf '%s\n' "$COMMITS" | sed 's/^/- /')
|
||||||
|
|
||||||
|
Bounded-задача, выполнена \`docs/scripts/sync-web.sh\`: перенос набора синхронизации ($N_FILES файлов) в \`web/\`,
|
||||||
|
проверки vitest / tsc / biome / build, PR в main. Ревью перенесённого кода против бэкенда — за исполнителем."
|
||||||
|
ISSUE_URL=$("${TEA[@]}" issues create --title "$TITLE" --description "$BODY" | grep -o 'https://[^ ]*/issues/[0-9]*' | tail -1)
|
||||||
|
ISSUE=${ISSUE_URL##*/}
|
||||||
|
[ -n "$ISSUE" ] || die "не удалось создать issue через tea"
|
||||||
|
BRANCH="feat/$ISSUE-web-sync-$HEAD7"
|
||||||
|
git -C "$WT" branch -m "$TMP_BRANCH" "$BRANCH"
|
||||||
|
echo "issue: $ISSUE_URL; ветка: $BRANCH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 4. Перенос набора и контроль идентичности ------------------------------------------------------------------------
|
||||||
|
git -C "$ARM_WEB" diff --binary "$POINT" "$REF" -- "${PATHSPEC[@]}" | git -C "$WT" apply --directory=web
|
||||||
|
REF_TREE=$(mktemp -d); trap 'rm -rf "$REF_TREE"' EXIT
|
||||||
|
git -C "$ARM_WEB" archive "$REF" | tar -x -C "$REF_TREE"
|
||||||
|
if ! diff -rq "${DIFF_EXCLUDES[@]}" "$REF_TREE" "$WT/web" >/dev/null; then
|
||||||
|
echo "sync-web: после переноса web/ не совпадает с arm-web@$REF:" >&2
|
||||||
|
diff -rq "${DIFF_EXCLUDES[@]}" "$REF_TREE" "$WT/web" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "перенесено: $N_FILES файлов; web/ идентичен arm-web@$REF по набору синхронизации"
|
||||||
|
if [ "$MODE" = dry ]; then
|
||||||
|
echo "dry-run: issue, проверки, коммит и PR не выполнялись. Посмотреть: git -C $WT status; убрать:"
|
||||||
|
echo " git -C $ARM_CORE worktree remove --force $WT && git -C $ARM_CORE branch -D $TMP_BRANCH"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 5. Проверки фронта ---------------------------------------------------------------------------------------------
|
||||||
|
NM=${WEB_NODE_MODULES:-$WT_ROOT/web-proto/arm-web/node_modules}
|
||||||
|
if [ -d "$NM" ]; then
|
||||||
|
ln -s "$NM" "$WT/web/node_modules"
|
||||||
|
echo "node_modules: симлинк на $NM"
|
||||||
|
else
|
||||||
|
echo "node_modules: $NM нет — npm install в worktree"
|
||||||
|
(cd "$WT/web" && npm install --no-audit --no-fund >/dev/null)
|
||||||
|
fi
|
||||||
|
run_check() { # имя, команда... — печатает хвост вывода при ошибке и останавливает скрипт
|
||||||
|
local name=$1; shift
|
||||||
|
local log; log=$(mktemp)
|
||||||
|
if (cd "$WT/web" && "$@") >"$log" 2>&1; then rm -f "$log"; return 0; fi
|
||||||
|
echo "sync-web: проверка «$name» не прошла; worktree оставлен для разбора: $WT" >&2
|
||||||
|
tail -40 "$log" >&2; rm -f "$log"; exit 1
|
||||||
|
}
|
||||||
|
run_check vitest npx vitest run
|
||||||
|
TESTS=$(cd "$WT/web" && npx vitest run 2>&1 | grep -E '^\s*Tests\s' | sed 's/^ *//' || true)
|
||||||
|
run_check tsc npx tsc --noEmit
|
||||||
|
biome_warnings() { (cd "$WT/web" && npx biome check "$1" 2>&1 | grep -oE 'Found [0-9]+ warning' | grep -oE '[0-9]+') || echo 0; }
|
||||||
|
W_MAIN=$(biome_warnings "$ARM_CORE/web/src")
|
||||||
|
W_NEW=$(biome_warnings src)
|
||||||
|
[ "$W_NEW" -le "$W_MAIN" ] || { echo "sync-web: biome — предупреждений стало больше: $W_NEW против $W_MAIN на $CORE_REF; worktree: $WT" >&2; exit 1; }
|
||||||
|
run_check build npm run build
|
||||||
|
echo "проверки: $TESTS; tsc чисто; biome $W_NEW предупреждений (на $CORE_REF — $W_MAIN); build ок"
|
||||||
|
|
||||||
|
# --- 6. Коммит, push, PR -------------------------------------------------------------------------------------------
|
||||||
|
git -C "$WT" add -A web -- ':!web/node_modules' ':!web/dist'
|
||||||
|
git -C "$WT" -c commit.gpgsign=false commit -q -F - <<EOF
|
||||||
|
fix(web): синхронизация встроенного фронта с arm-web@${REF#origin/} ($HEAD7) (#$ISSUE)
|
||||||
|
|
||||||
|
Перенесён диапазон arm-web ${POINT:0:7}..$HEAD7 ($N_COMMITS коммитов, $N_FILES файлов набора
|
||||||
|
синхронизации) скриптом docs/scripts/sync-web.sh. После переноса web/ и
|
||||||
|
arm-web@${REF#origin/} идентичны по набору. Коммиты arm-web:
|
||||||
|
$(printf '%s\n' "$COMMITS" | sed 's/^/- /')
|
||||||
|
|
||||||
|
Co-Authored-By: sync-web.sh <noreply@aepif.ru>
|
||||||
|
EOF
|
||||||
|
COMMIT=$(git -C "$WT" rev-parse --short=7 HEAD)
|
||||||
|
git -C "$WT" push -q -u origin "$BRANCH"
|
||||||
|
PR_BODY="Закрывает #$ISSUE.
|
||||||
|
|
||||||
|
Встроенный фронт \`arm-core/web\` отставал от \`RSHB/arm-web@${REF#origin/}\` ($HEAD7). Диапазон arm-web ${POINT:0:7}..$HEAD7
|
||||||
|
перенесён скриптом \`docs/scripts/sync-web.sh\` без правок; после переноса \`web/\` и arm-web идентичны по набору синхронизации.
|
||||||
|
|
||||||
|
Коммиты arm-web ($N_COMMITS):
|
||||||
|
$(printf '%s\n' "$COMMITS" | sed 's/^/- /')
|
||||||
|
|
||||||
|
Файлы ($N_FILES):
|
||||||
|
$(printf '%s\n' "$FILES" | sed 's/^/- web\//')
|
||||||
|
|
||||||
|
Проверки в worktree: $TESTS; \`tsc --noEmit\` чисто; \`biome check src\` — $W_NEW предупреждений (на ${CORE_REF#origin/} — $W_MAIN); \`rsbuild build\` собирается.
|
||||||
|
|
||||||
|
## Rulings I made
|
||||||
|
- R-1 — служебные файлы arm-web (CLAUDE.md, .claude/, openspec/, docs/, scripts/, Makefile, ARCHITECTURE.md, .gitignore, lockfile) не переносятся: UI-спеки и демо-стенд живут в arm-web.
|
||||||
|
- R-2 — bounded-задача без OpenSpec change: перенос готового, проревьюенного в arm-web кода.
|
||||||
|
|
||||||
|
Ревью перенесённого кода против бэкенда — за исполнителем, находки с маркерами в комментариях к PR.
|
||||||
|
|
||||||
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)"
|
||||||
|
PR_URL=$("${TEA[@]}" pulls create --head "$BRANCH" --base "${CORE_REF#origin/}" --title "fix(web): синхронизация встроенного фронта с arm-web@${REF#origin/} ($HEAD7) (#$ISSUE)" \
|
||||||
|
--description "$PR_BODY" | grep -o 'https://[^ ]*/pulls/[0-9]*' | tail -1)
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "готово: коммит $COMMIT, ветка $BRANCH"
|
||||||
|
echo "issue: $ISSUE_URL"
|
||||||
|
echo "PR: ${PR_URL:-создать вручную: tea pulls create --head $BRANCH}"
|
||||||
|
echo "исполнителю: проверить перенесённый код против бэкенда (коммиты arm-web выше), затем — merge и «закрывай»."
|
||||||
|
echo "worktree $WT, симлинк web/node_modules и .bounded остаются до закрытия."
|
||||||
127
scripts/test_sync_web.sh
Executable file
127
scripts/test_sync_web.sh
Executable file
@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Тест sync-web.sh на синтетических репозиториях arm-web и arm-core (bare origin + клон), без tea, npm и сети.
|
||||||
|
# Сценарии: синхронно; arm-core отстаёт (--check и --dry-run); arm-core правили напрямую (отказ);
|
||||||
|
# пайплайн переноса в контур (prepare-contour-snapshot.sh спрашивает / останавливается / идёт «как есть»).
|
||||||
|
# Запуск: make test-sync-web (или напрямую из корня docs).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
SYNC="$HERE/sync-web.sh"
|
||||||
|
SNAPSHOT="$HERE/prepare-contour-snapshot.sh"
|
||||||
|
WORK=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$WORK"' EXIT
|
||||||
|
export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t
|
||||||
|
|
||||||
|
fail=0
|
||||||
|
check() { if [ "$1" = 0 ]; then echo "ok: $2"; else echo "FAIL: $2" >&2; fail=1; fi; }
|
||||||
|
|
||||||
|
put() { mkdir -p "$(dirname "$1")"; printf '%s\n' "${2:-x}" > "$1"; }
|
||||||
|
commit_push() { git -C "$1" add -A; git -C "$1" commit -qm "$2"; git -C "$1" push -q origin "HEAD:$3" 2>/dev/null; git -C "$1" fetch -q origin; }
|
||||||
|
|
||||||
|
# --- синтетический arm-web: ветка test ---------------------------------------------------------------------------
|
||||||
|
WEB="$WORK/arm-web"
|
||||||
|
git init -q --bare "$WORK/arm-web.git"
|
||||||
|
git clone -q "$WORK/arm-web.git" "$WEB" 2>/dev/null
|
||||||
|
git -C "$WEB" checkout -q -b test
|
||||||
|
put "$WEB/src/a.ts" "export const a = 1;"
|
||||||
|
put "$WEB/README.md" "arm-web v1"
|
||||||
|
put "$WEB/package.json" '{"name":"web"}'
|
||||||
|
for p in CLAUDE.md .claude/skills/s/SKILL.md openspec/config.yaml openspec/specs/ui/spec.md docs/superpowers/plans/p.md \
|
||||||
|
scripts/demo-prepare.sh Makefile ARCHITECTURE.md .gitignore; do put "$WEB/$p" "/Users/someone/arm-web"; done
|
||||||
|
commit_push "$WEB" "web v1" test
|
||||||
|
POINT=$(git -C "$WEB" rev-parse HEAD)
|
||||||
|
|
||||||
|
# --- синтетический arm-core: web/ = снимок arm-web v1 без служебных файлов, плюс платформенные файлы ----------------
|
||||||
|
CORE="$WORK/arm-core"
|
||||||
|
git init -q --bare "$WORK/arm-core.git"
|
||||||
|
git clone -q "$WORK/arm-core.git" "$CORE" 2>/dev/null
|
||||||
|
git -C "$CORE" checkout -q -b main
|
||||||
|
put "$CORE/web/src/a.ts" "export const a = 1;"
|
||||||
|
put "$CORE/web/README.md" "arm-web v1"
|
||||||
|
put "$CORE/web/package.json" '{"name":"web"}'
|
||||||
|
printf 'venv:\n\tuv venv api/.venv\n' > "$CORE/Makefile"
|
||||||
|
for p in raisa_config.yml setup/setup.sh setup/pip.conf api/run_server.py api/requirements.txt api/.env.test \
|
||||||
|
api/contracts/schema.json; do put "$CORE/$p"; done
|
||||||
|
commit_push "$CORE" "core v1" main
|
||||||
|
|
||||||
|
COMMON=(--arm-web "$WEB" --arm-core "$CORE" --wt-root "$WORK/wt")
|
||||||
|
|
||||||
|
# --- 1. синхронно ---------------------------------------------------------------------------------------------------
|
||||||
|
rc=0; "$SYNC" --check "${COMMON[@]}" >/dev/null || rc=$?
|
||||||
|
check "$([ "$rc" = 0 ] && echo 0 || echo 1)" "синхронно: --check возвращает 0 (rc=$rc)"
|
||||||
|
rc=0; out=$("$SYNC" --dry-run "${COMMON[@]}") || rc=$?
|
||||||
|
check "$([ "$rc" = 0 ] && [ ! -d "$WORK/wt" ] && echo 0 || echo 1)" "синхронно: --dry-run ничего не делает (rc=$rc)"
|
||||||
|
|
||||||
|
# --- arm-web уходит вперёд: правка src, новый файл, README; служебные файлы тоже меняются ---------------------------
|
||||||
|
put "$WEB/src/a.ts" "export const a = 2;"
|
||||||
|
put "$WEB/src/b.ts" "export const b = 1;"
|
||||||
|
put "$WEB/README.md" "arm-web v2"
|
||||||
|
put "$WEB/CLAUDE.md" "/Users/someone/arm-web v2"
|
||||||
|
put "$WEB/scripts/demo-prepare.sh" "v2"
|
||||||
|
commit_push "$WEB" "web v2" test
|
||||||
|
HEAD7=$(git -C "$WEB" rev-parse --short=7 HEAD)
|
||||||
|
|
||||||
|
# --- 2. отстаёт: --check ----------------------------------------------------------------------------------------------
|
||||||
|
rc=0; out=$("$SYNC" --check "${COMMON[@]}" 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 10 ] && echo 0 || echo 1)" "отстаёт: --check возвращает 10 (rc=$rc)"
|
||||||
|
check "$(grep -q "web v2" <<<"$out" && echo 0 || echo 1)" "отстаёт: --check перечисляет непереносённые коммиты"
|
||||||
|
check "$(grep -q "${POINT:0:7}" <<<"$out" && echo 0 || echo 1)" "отстаёт: --check называет точку синхронизации"
|
||||||
|
|
||||||
|
# --- 3. отстаёт: --dry-run переносит набор в worktree -------------------------------------------------------------------
|
||||||
|
rc=0; "$SYNC" --dry-run "${COMMON[@]}" >/dev/null || rc=$?
|
||||||
|
WT="$WORK/wt/web-sync-$HEAD7/arm-core"
|
||||||
|
check "$([ "$rc" = 0 ] && [ -d "$WT" ] && echo 0 || echo 1)" "dry-run: worktree $WT создан (rc=$rc)"
|
||||||
|
check "$([ "$(git -C "$WT" rev-parse --abbrev-ref HEAD)" = "tmp/web-sync-$HEAD7" ] && echo 0 || echo 1)" "dry-run: временная ветка tmp/web-sync-$HEAD7"
|
||||||
|
check "$([ -f "$WT/.bounded" ] && echo 0 || echo 1)" "dry-run: .bounded создан"
|
||||||
|
check "$([ "$(cat "$WT/web/src/a.ts")" = "export const a = 2;" ] && echo 0 || echo 1)" "dry-run: изменённый src/a.ts перенесён"
|
||||||
|
check "$([ -f "$WT/web/src/b.ts" ] && echo 0 || echo 1)" "dry-run: новый src/b.ts перенесён"
|
||||||
|
check "$([ "$(cat "$WT/web/README.md")" = "arm-web v2" ] && echo 0 || echo 1)" "dry-run: README перенесён"
|
||||||
|
check "$([ ! -e "$WT/web/CLAUDE.md" ] && [ ! -e "$WT/web/scripts" ] && echo 0 || echo 1)" "dry-run: служебные файлы arm-web не перенесены"
|
||||||
|
git -C "$WT" add -A web >/dev/null
|
||||||
|
TREE_WT=$(git -C "$WT" write-tree)
|
||||||
|
check "$([ "$(git -C "$WT" rev-parse "$TREE_WT:web/src")" = "$(git -C "$WEB" rev-parse test:src)" ] && echo 0 || echo 1)" "dry-run: дерево web/src совпадает с arm-web test:src"
|
||||||
|
git -C "$WT" reset -q
|
||||||
|
rc=0; "$SYNC" --dry-run "${COMMON[@]}" >/dev/null 2>&1 || rc=$?
|
||||||
|
check "$([ "$rc" != 0 ] && echo 0 || echo 1)" "dry-run повторно: отказ, worktree уже существует (rc=$rc)"
|
||||||
|
git -C "$CORE" worktree remove --force "$WT"; git -C "$CORE" branch -q -D "tmp/web-sync-$HEAD7"
|
||||||
|
|
||||||
|
# --- 4. пайплайн переноса: prepare-contour-snapshot.sh видит отставание ---------------------------------------------
|
||||||
|
export ARM_WEB="$WEB" SYNC_WEB_ARGS="--dry-run --wt-root $WORK/wt"
|
||||||
|
rc=0; out=$("$SNAPSHOT" "$CORE" "$WORK/out1" origin/main </dev/null 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 3 ] && echo 0 || echo 1)" "пайплайн без терминала: перенос остановлен, rc=3 (rc=$rc)"
|
||||||
|
check "$(grep -qi "остановлен" <<<"$out" && echo 0 || echo 1)" "пайплайн: сообщение «перенос остановлен до завершения синхронизации»"
|
||||||
|
check "$([ -d "$WT" ] && [ -f "$WT/web/src/b.ts" ] && echo 0 || echo 1)" "пайплайн: синхронизация запущена, worktree создан"
|
||||||
|
check "$([ ! -d "$WORK/out1/arm-core" ] && echo 0 || echo 1)" "пайплайн: снимок не создан"
|
||||||
|
git -C "$CORE" worktree remove --force "$WT"; git -C "$CORE" branch -q -D "tmp/web-sync-$HEAD7"
|
||||||
|
|
||||||
|
rc=0; out=$(printf 'y\n' | "$SNAPSHOT" "$CORE" "$WORK/out2" origin/main 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 0 ] && [ -f "$WORK/out2/arm-core/web/src/a.ts" ] && [ ! -e "$WORK/out2/arm-core/web/src/b.ts" ] && echo 0 || echo 1)" \
|
||||||
|
"пайплайн, ответ «y»: снимок как есть (rc=$rc)"
|
||||||
|
rc=0; out=$(printf 'n\n' | "$SNAPSHOT" "$CORE" "$WORK/out3" origin/main 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 3 ] && [ -d "$WT" ] && echo 0 || echo 1)" "пайплайн, ответ «n»: синхронизация запущена, перенос остановлен (rc=$rc)"
|
||||||
|
git -C "$CORE" worktree remove --force "$WT"; git -C "$CORE" branch -q -D "tmp/web-sync-$HEAD7"
|
||||||
|
|
||||||
|
rc=0; out=$("$SNAPSHOT" --web-as-is "$CORE" "$WORK/out4" origin/main </dev/null 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 0 ] && [ -f "$WORK/out4/arm-core/SNAPSHOT.md" ] && echo 0 || echo 1)" "пайплайн, --web-as-is: снимок без вопроса (rc=$rc)"
|
||||||
|
check "$(grep -q "отстаёт" "$WORK/out4/arm-core/SNAPSHOT.md" && echo 0 || echo 1)" "пайплайн, --web-as-is: отставание записано в SNAPSHOT.md"
|
||||||
|
unset SYNC_WEB_ARGS
|
||||||
|
|
||||||
|
# arm-web рядом нет (в тесте он есть как сосед $CORE, поэтому путь задаётся явно несуществующим)
|
||||||
|
export ARM_WEB="$WORK/no-such-arm-web"
|
||||||
|
rc=0; out=$("$SNAPSHOT" "$CORE" "$WORK/out5" origin/main </dev/null 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 0 ] && grep -q "arm-web не найден" <<<"$out" && echo 0 || echo 1)" "пайплайн без arm-web рядом: предупреждение, снимок сделан (rc=$rc)"
|
||||||
|
unset ARM_WEB
|
||||||
|
|
||||||
|
# --- 5. arm-core правили напрямую: точки синхронизации нет ----------------------------------------------------------
|
||||||
|
put "$CORE/web/src/a.ts" "export const a = 'direct';"
|
||||||
|
commit_push "$CORE" "core: прямая правка web" main
|
||||||
|
rc=0; out=$("$SYNC" --check "${COMMON[@]}" 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" = 20 ] && echo 0 || echo 1)" "прямая правка arm-core: --check возвращает 20 (rc=$rc)"
|
||||||
|
check "$(grep -q "прямая правка web" <<<"$out" && echo 0 || echo 1)" "прямая правка arm-core: названы коммиты arm-core по web/"
|
||||||
|
export ARM_WEB="$WEB"
|
||||||
|
rc=0; out=$("$SNAPSHOT" "$CORE" "$WORK/out6" origin/main </dev/null 2>&1) || rc=$?
|
||||||
|
check "$([ "$rc" != 0 ] && [ ! -d "$WORK/out6/arm-core" ] && echo 0 || echo 1)" "пайплайн при расхождении: снимок не делается (rc=$rc)"
|
||||||
|
unset ARM_WEB
|
||||||
|
|
||||||
|
[ "$fail" = 0 ] || exit 1
|
||||||
|
echo "ok: sync-web.sh — точка синхронизации, перенос набора, отказ при расхождении, пайплайн переноса"
|
||||||
Loading…
x
Reference in New Issue
Block a user