treeposture

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package treeposture отвечает на ОДИН вопрос: лежит ли модуль в дереве платформы — и приводит координаты, записанные от корня платформы, к той посадке, в которой идёт прогон.

ЗДЕСЬ НЕТ `testing` — И ЭТО НЕСУЩЕЕ. Тот же вопрос задаёт не только проба: приборы модуля (отпечаток сетки замера, писатель отчётов) читают свои каталоги по координатам, записанным от корня платформы, и в самостоятельном клоне ошибаются ровно так же. Пакет с `testing` в импорте прод-код звать не вправе — он утащил бы испытательную оснастку в поставляемый двоичный. Поэтому чистая часть живёт здесь, а третий исход для пробы (`Require*`) — в обёртке `internal/testsupport/platformtree`, которая эту часть и зовёт.

───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ

Модуль живёт в двух посадках. В монорепо рядом с ним лежат манифесты остальных модулей платформы, каталог контрактов и зонтичный чарт стенда; в самостоятельном клоне у арендатора их нет и не будет — они в поставку модуля не входят BY CONSTRUCTION.

Проба, судящая такое дерево, в клоне не «красная»: у неё не создано условие. Красное у КАЖДОГО, кто склонирует, вердиктом о продукте не является — это «проверка НЕ ИСПОЛНЯЛАСЬ», третий исход (`testing.md` §«Чтение вердикта»), который не вычитается из вердикта и не зачитывается в успех.

───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ЭТО НЕ МАСКА — И ЧЕМ ЭТО ДЕРЖИТСЯ

Пропуск, который проба назначает себе сама, был бы ровно тем механизмом, который корпус запрещает: его нельзя отличить от «проба сломалась, и её заглушили». Здесь пропуск назначает НЕ проба, а ПРЕДПОСЫЛКА, и предпосылка эта — свойство дерева, проверяемое на месте:

дерево платформы ЕСТЬ  → Require возвращает корень, проба идёт целиком;
дерева платформы НЕТ   → пропуск с НАЗВАННОЙ причиной и координатой.

Отсюда несущее свойство: **в монорепо пропуск невозможен**. Не «его там не бывает», а невозможен — детектор отвечает «есть», и ветвь пропуска не достижима ни для одной пробы. Держит это гейт-сосед (`platformtree_gate_test.go`): он спрашивает детектор о ТОМ дереве, в котором идёт прогон, и падает, если в монорепо тот ответил «нет». Тогда «сколько проб пропущено» перестаёт быть вопросом доверия: их ноль, и это следует из одного утверждения, а не из переписи по каждой пробе.

Пометка ИСТЕКАЕТ САМА в обратную сторону: приедет каталог контрактов в поставку модуля — детектор в клоне ответит «есть», и помеченные пробы начнут исполняться там, где раньше пропускались. Снимать пометки для этого не нужно.

───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ПРИЗНАК — СОСЕДНИЕ МОДУЛИ, А НЕ ИМЯ КАТАЛОГА

Имя каталога у арендатора выбирает тот, кто клонировал. Признаком служит то, ради чего дерево и нужно: каталог `services/` с манифестами модулей рядом с нашим. Он есть в монорепо и отсутствует в поставке — то есть ровно та величина, которую пробы и спрашивают.

ЧЕГО ЗДЕСЬ НЕТ. Пакет не решает, ЧТО пробе читать, и не заменяет резолв канона модели: тот резолвится в ОБЕИХ посадках (модуль везёт свою побайтовую копию) и пометки не требует. Здесь только «есть ли рядом остальная платформа».

Index

Constants

This section is empty.

Variables

View Source
var ErrModuleRootUnknown = errors.New("корень модуля не установлен")

ErrModuleRootUnknown — корень модуля не установлен: судить не о чем.

View Source
var ErrNoPlatformTree = errors.New("дерева платформы рядом с модулем нет")

ErrNoPlatformTree — дерева платформы рядом с модулем нет.

Отдельный признак, а не общий отказ: «платформы рядом нет» и «пробу не удалось запустить» — разные исходы, и первый есть свойство поставки, а не поломка.

Functions

func CorpusRoot

func CorpusRoot(start string) (root, prefix string, err error)

CorpusRoot — КОРЕНЬ ДЕРЕВА, которое проба обходит, и ПРИСТАВКА, под которой в нём лежат файлы этого модуля.

───────────────────────────────────────────────────────────────────────────── ЗАЧЕМ ОТДЕЛЬНО ОТ PathOf

`PathOf` отвечает про ОДИН путь. Есть другой род проб: они не читают названный файл, а ОБХОДЯТ состав дерева и судят его целиком — «композиция одна, тонких вызывающих двое», «у каждой записи ведомости есть предмет», «литерал не является источником чтения». Такой пробе нужны две величины сразу: от какого корня брать состав и с какой приставки начинаются её собственные файлы в этом составе.

В монорепо это корень платформы и `services/iam`; в самостоятельном клоне — корень модуля и ПУСТАЯ приставка: модуль там сам себе дерево, и файлы лежат без неё.

───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ЭТО НЕ ПРОПУСК

Пропускать такие пробы в клоне было бы ЛОЖЬЮ в другую сторону: их предмет — собственная композиция модуля — в поставку ВХОДИТ, и судить его есть чем. Пропуск здесь означал бы «условие не создано» там, где оно создано.

Пропуск остаётся законным ровно для тех проб, чей предмет лежит ВНЕ модуля (манифесты соседей, каталог контрактов, зонтичный чарт) — для них `Require` и `RequirePath`, и они возвращают ErrNoPlatformTree честно.

func ModuleDirIn

func ModuleDirIn(root, moduleRoot string) (string, error)

ModuleDirIn — каталог модуля В НАЗВАННОМ дереве.

Существует ради вызывающих, которые прежде складывали этот путь литералом `services/iam`: литерал верен ровно для одной посадки, а в другой указывает в несуществующий подкаталог клона. Здесь он ВЫВОДИТСЯ, поэтому верен в обеих.

func ModuleDirInPlatform

func ModuleDirInPlatform() string

ModuleDirInPlatform — та же координата для гейта, который её сверяет.

func ModuleRootFrom

func ModuleRootFrom(start string) (string, error)

ModuleRootFrom поднимается от start до БЛИЖАЙШЕГО каталога с `go.mod`.

Маркер — `go.mod`, а не число уровней и не имя каталога: имя у арендатора выбирает тот, кто клонировал, а число уровней верно ровно для одной посадки.

func PathOf

func PathOf(start, rel string) (string, error)

PathOf — путь, записанный ОТ КОРНЯ ДЕРЕВА ПЛАТФОРМЫ, приведённый к посадке, в которой идёт прогон.

───────────────────────────────────────────────────────────────────────────── ЗАЧЕМ

Пробы модуля называют свои файлы координатами монорепо: `services/iam/internal/migrations`, `services/iam/docs/…`. В монорепо это верно. В самостоятельном клоне модуль САМ является корнем, поэтому тот же путь указывает в несуществующий подкаталог — и проба отказывает «нет файла» там, где файл ЕСТЬ и лежит на уровень выше по этому же дереву.

Замер, ради которого функция написана: в клоне так отказывали 66 проб, читая то, что с модулем ЕДЕТ (миграции, посев, документы, собственные исходники).

───────────────────────────────────────────────────────────────────────────── ТРИ ИСХОДА, И ТРЕТИЙ НЕСУЩИЙ

дерево платформы есть        → путь как написан, от его корня;
клон, путь ВНУТРИ модуля     → приставка модуля снимается, путь от корня клона;
клон, путь ВНЕ модуля        → ErrNoPlatformTree: названного в поставку не
                               входит, и это «условие не создано», а не «нет файла».

Третий исход — то, ради чего у функции есть ошибка. Каталог контрактов, манифест соседнего модуля, зонтичный чарт стенда у арендатора отсутствуют BY CONSTRUCTION; вернуть для них «путь, которого нет» значило бы превратить свойство поставки в находку о продукте.

func PathUnder

func PathUnder(root, rel string) (string, error)

PathUnder — координата, записанная от корня платформы, приведённая к НАЗВАННОМУ корню.

───────────────────────────────────────────────────────────────────────────── ЧЕМ ОТЛИЧАЕТСЯ ОТ PathOf

`PathOf` сам ищет корень подъёмом от рабочего каталога. Здесь корень УЖЕ ДАН — его спросили у git (`rev-parse --show-toplevel`) либо получили аргументом. Такие вызывающие есть, и это приборы модуля: отпечаток сетки замера, писатель отчётов, сверщик состава. Они читают свои каталоги по координатам вида `services/iam/...` и складывают их с корнем — то есть верны ровно для монорепо.

В самостоятельном клоне корень репозитория И ЕСТЬ корень модуля, поэтому сложенный путь указывает в несуществующий подкаталог `<клон>/services/iam/…`, а прибор отказывает «нет файла» там, где файл есть уровнем выше.

───────────────────────────────────────────────────────────────────────────── ПОСАДКА ОПОЗНАЁТСЯ ПО САМОМУ КОРНЮ, А НЕ ПО РАБОЧЕМУ КАТАЛОГУ

Признак — лежит ли модуль в `services/` этого корня. Спрашивать рабочий каталог здесь нельзя: вызывающий мог получить корень откуда угодно, и два разных ответа об одном дереве разошлись бы молча.

Третий исход сохранён: путь ВНЕ модуля в клоне даёт ErrNoPlatformTree, а не «нет файла». Названного в поставку не входит by construction, и подменять свойство поставки находкой о продукте нельзя.

func PrefixUnder

func PrefixUnder(root string) string

PrefixUnder — приставка модуля в составе, отсчитываемом от НАЗВАННОГО корня.

`"services/iam"` в дереве платформы и ПУСТАЯ в самостоятельном клоне. Нужна обходчикам состава: они сравнивают записи с координатами, и склеенная не с той приставкой не совпадёт ни с одной — молча.

func RootFrom

func RootFrom(start string) (string, error)

RootFrom — корень дерева платформы для модуля, найденного от start.

Возвращает ErrNoPlatformTree, если модуль стоит самостоятельным клоном. Подъём ограничен деревом: за пределы каталога, содержащего модуль, резолв не выходит — иначе нашлось бы ЧУЖОЕ дерево, и вердикт был бы о нём.

func Under

func Under(prefix, rel string) string

Under — координата файла модуля в составе, приведённая к приставке.

`Under("services/iam", "internal/x")` -> `services/iam/internal/x`; `Under("", "internal/x")` -> `internal/x`.

Существует ради вызывающих, которые иначе склеили бы приставку конкатенацией и получили ведущий слеш в клоне — путь, который не совпадёт ни с одной записью состава, причём МОЛЧА: обход просто не найдёт ничего, и «ноль находок» стало бы неотличимо от «ноль прочитанного».

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL