@rt-tools/agent-kit 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/checks/check-file-size.mjs +19 -4
- package/assets/checks/check-state-next.mjs +10 -2
- package/assets/checks/rt-kit-checks.config.mjs +16 -2
- package/assets/defaults/project.sh +9 -1
- package/assets/defaults/turn-map.md +8 -6
- package/assets/hooks/browser-guard-device-id.sh +3 -1
- package/assets/hooks/browser-guard-no-asking.sh +3 -1
- package/assets/hooks/browser-guard-no-other-drivers.sh +5 -3
- package/assets/hooks/browser-guard-require-select.sh +4 -2
- package/assets/hooks/claim-guard.sh +3 -1
- package/assets/hooks/conscience-guard.sh +3 -1
- package/assets/hooks/dev-server-guard.sh +5 -3
- package/assets/hooks/dispatch.sh +69 -0
- package/assets/hooks/docs-guard.sh +6 -4
- package/assets/hooks/exam-guard.sh +5 -3
- package/assets/hooks/git-guard-delivery.sh +37 -5
- package/assets/hooks/git-guard-main.sh +6 -4
- package/assets/hooks/git-guard-push-tests.sh +6 -4
- package/assets/hooks/grill-gate.sh +4 -2
- package/assets/hooks/handoff-entry-guard.sh +4 -2
- package/assets/hooks/handoff-write.sh +27 -6
- package/assets/hooks/hook-input.sh +54 -0
- package/assets/hooks/lint-after-edit.sh +5 -3
- package/assets/hooks/postmortem-guard.sh +3 -1
- package/assets/hooks/proposal-guard.sh +3 -1
- package/assets/hooks/prose-style-guard.sh +5 -3
- package/assets/hooks/qa-dataid-guard.sh +4 -2
- package/assets/hooks/rerun-guard.sh +5 -3
- package/assets/hooks/reuse-first-guard.sh +5 -3
- package/assets/hooks/rule-article.sh +99 -0
- package/assets/hooks/skill-gate-rearm.sh +3 -1
- package/assets/hooks/skill-gate.sh +23 -2
- package/assets/hooks/skill-loaded.sh +3 -1
- package/assets/hooks/sql-guard-request.sh +2 -1
- package/assets/hooks/sql-guard.sh +4 -2
- package/assets/hooks/task-flow-guard.sh +6 -4
- package/assets/hooks/turn-exit-guard.sh +42 -17
- package/assets/hooks/waiting-turn-guard.sh +3 -1
- package/assets/hooks/window-fill-guard.sh +6 -4
- package/assets/laws/work-conduct.md +5 -9
- package/assets/patterns/dependencies-upgrade.md +1 -1
- package/assets/patterns/doc-style-write.md +3 -3
- package/assets/patterns/git-workflow-commit.azure.md +2 -202
- package/assets/patterns/git-workflow-commit.github.md +2 -258
- package/assets/patterns/git-workflow-commit.gitlab.md +1 -217
- package/assets/patterns/git-workflow-docker.md +3 -3
- package/assets/patterns/git-workflow-merge.md +3 -2
- package/assets/patterns/git-workflow-migration.md +3 -3
- package/assets/patterns/git-workflow-pr.azure.md +224 -0
- package/assets/patterns/git-workflow-pr.github.md +280 -0
- package/assets/patterns/git-workflow-pr.gitlab.md +240 -0
- package/assets/patterns/git-workflow-restart.md +3 -3
- package/assets/patterns/git-workflow-secrets.md +3 -3
- package/assets/patterns/task-flow-archive.md +193 -0
- package/assets/patterns/task-flow-close.md +3 -173
- package/assets/patterns/task-flow-handoff.md +4 -4
- package/assets/pitfalls/doc-style.md +80 -0
- package/assets/pitfalls/git-workflow.azure.md +50 -0
- package/assets/pitfalls/git-workflow.github.md +78 -0
- package/assets/pitfalls/git-workflow.gitlab.md +49 -0
- package/assets/pitfalls/spec-driven.md +36 -0
- package/assets/pitfalls/styling-bem.md +45 -0
- package/assets/pitfalls/task-flow.md +62 -0
- package/assets/pitfalls/testing.md +70 -0
- package/assets/rules/deploy-flow.azure.md +106 -0
- package/assets/rules/deploy-flow.github.md +113 -0
- package/assets/rules/deploy-flow.gitlab.md +108 -0
- package/assets/rules/doc-style.md +25 -76
- package/assets/rules/git-workflow.azure.md +6 -92
- package/assets/rules/git-workflow.github.md +14 -127
- package/assets/rules/git-workflow.gitlab.md +6 -93
- package/assets/rules/spec-driven.md +39 -30
- package/assets/rules/styling-bem.md +20 -39
- package/assets/rules/task-flow.md +17 -199
- package/assets/rules/testing.md +3 -64
- package/assets/rules/turn-conduct.md +206 -0
- package/assets/rules/typescript-conventions.md +15 -0
- package/assets/skills/agent-kit.md +35 -12
- package/assets/templates/pitfalls.md +10 -0
- package/assets/templates/rule.md +5 -3
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +1 -42
- package/bin/agent-kit.js.map +1 -1
- package/lib/assets.d.ts.map +1 -1
- package/lib/assets.js +6 -1
- package/lib/assets.js.map +1 -1
- package/lib/cascade.d.ts.map +1 -1
- package/lib/cascade.js +19 -1
- package/lib/cascade.js.map +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +1 -0
- package/lib/commands.js.map +1 -1
- package/lib/config.d.ts +16 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +8 -0
- package/lib/config.js.map +1 -1
- package/lib/hooks-map.d.ts +13 -0
- package/lib/hooks-map.d.ts.map +1 -1
- package/lib/hooks-map.js +33 -1
- package/lib/hooks-map.js.map +1 -1
- package/lib/ship.d.ts +1 -2
- package/lib/ship.d.ts.map +1 -1
- package/lib/ship.js +0 -54
- package/lib/ship.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.12.0.tgz +0 -0
- package/assets/commands/agent-kit-digest.md +0 -89
- package/assets/commands/rules-review.md +0 -98
- package/assets/patterns/cargo-triage-mark.md +0 -119
- package/assets/rules/cargo-triage.md +0 -126
- package/lib/cargo-state.d.ts +0 -62
- package/lib/cargo-state.d.ts.map +0 -1
- package/lib/cargo-state.js +0 -118
- package/lib/cargo-state.js.map +0 -1
- package/rt-tools-agent-kit-0.11.0.tgz +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Оформление — холодная часть
|
|
2
|
+
|
|
3
|
+
Ловушки: грабли, на которые уже наступали. Грузится не вместе с правилом, а по
|
|
4
|
+
требованию — при обычном решении она не нужна.
|
|
5
|
+
|
|
6
|
+
Правило — `styling-bem`; статьи, которыми держится закон, стоят там.
|
|
7
|
+
|
|
8
|
+
## Ловушки
|
|
9
|
+
|
|
10
|
+
- **`rtElem` без предка с `rtBlock` роняет отрисовку в рантайме** — сборка и линт молчат.
|
|
11
|
+
- **Спроецированный узел блока-предка не имеет.** `rtElem` берёт имя блока инъекцией от
|
|
12
|
+
ближайшего предка **по месту объявления шаблона**, а не по месту вставки: элемент, который
|
|
13
|
+
экран объявляет у себя и отдаёт в проекцию чужого компонента, ищет `rtBlock` в своём шаблоне
|
|
14
|
+
и не находит. Отрисовка падает в рантайме, сборка и линт зелёные. Класс на такой узел
|
|
15
|
+
вешается правилом по селектору кита в общем слое раскладки, а не директивой.
|
|
16
|
+
- **Элемент с `backdrop-filter` или своим `z-index` замыкает потомков в свой слой.** Липкая
|
|
17
|
+
шапка с размытием — самый частый случай: номер слоя у того, что лежит внутри неё,
|
|
18
|
+
сравнивается не с соседями по странице, а только с соседями внутри шапки, и нижняя панель
|
|
19
|
+
накрывает открытую шторку вместе с её кнопкой. Проверяется это `elementFromPoint` в центре
|
|
20
|
+
кнопки: сборка, линт и скриншот показывают тут целую страницу.
|
|
21
|
+
- **До узла, вынесенного к `<body>`, стили компонента не достают.** Превью и заглушку переноса
|
|
22
|
+
кладёт туда библиотека, а правила компонента заскоуплены атрибутом: файл выглядит рабочим и
|
|
23
|
+
не красит ничего. Такие правила объявляются в общем слое приложения. Ни сборка, ни линт, ни
|
|
24
|
+
проверка «класс без правила» этого не видят: класса такого в шаблоне нет вовсе, и пролежать
|
|
25
|
+
это может несколько задач подряд.
|
|
26
|
+
- **Имя токена не сверяется ничем.** Ссылка на несуществующий токен собирается, проходит
|
|
27
|
+
stylelint и проверку класса без правила, а свойство молча берёт наследованное значение:
|
|
28
|
+
правило выглядит написанным и не красит ничего. Ловится это только замером в браузере, а
|
|
29
|
+
имена берутся из объявлений кита, а не по догадке о том, как токен должен был бы называться.
|
|
30
|
+
- **`rtBlock` на `<ng-container>` класса не ставит вовсе:** узел это комментарий, и имя блока
|
|
31
|
+
он только объявляет потомкам. Класс блока экрана вешает хост через `host: { class: … }`.
|
|
32
|
+
- **`justify-content: center` во flex-контейнере с `overflow-x` уводит первые элементы за
|
|
33
|
+
нулевой скролл** — доскроллить до них невозможно. В прокручиваемых лентах —
|
|
34
|
+
`justify-content: safe center`.
|
|
35
|
+
- **`scrollbar-gutter: stable` на корне не заводить:** резерв под полосу прокрутки сужает
|
|
36
|
+
содержащий блок для `position: fixed`, и попап, выровненный по правому краю, встаёт на
|
|
37
|
+
ширину резерва левее своей кнопки.
|
|
38
|
+
- **`& + :host` невалиден:** изнутри компонента до соседнего хоста не дотянуться. Разделитель
|
|
39
|
+
между повторяющимися хостами — `:host(:not(:first-of-type))`.
|
|
40
|
+
- **`[attr.aria-disabled]` визуального состояния не даёт:** браузер стилизует `:disabled`, но
|
|
41
|
+
атрибуты `aria-*` — нет. К каждому `aria-disabled` заводится правило `[aria-disabled='true']`.
|
|
42
|
+
- **Гарнитуру с `body` элементы формы не наследуют:** браузер задаёт `button`, `input`,
|
|
43
|
+
`select` и `textarea` свой шрифт. Наследование включено глобально — сбрасывать его нельзя.
|
|
44
|
+
- **Комментарии-выключатели stylelint не ставятся.** Селекторы объединяются вложенностью.
|
|
45
|
+
- **При переносе стилей новых объявлений не появляется** — только перемещение существующих.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Ведение работы — холодная часть
|
|
2
|
+
|
|
3
|
+
Ловушки и поведение по разборам происшествий. Грузится не вместе с правилом, а по требованию:
|
|
4
|
+
при обычном решении она не нужна — она нужна тому, кто разбирает промах или спорит с гардом.
|
|
5
|
+
|
|
6
|
+
Правило — `task-flow`; статьи, которыми держится закон, стоят там.
|
|
7
|
+
|
|
8
|
+
## Ловушки
|
|
9
|
+
|
|
10
|
+
- **Папка называется именем ветки, один в один.** Хук запуска ищет её по
|
|
11
|
+
`git branch --show-current`, и папка, названная иначе, не находится ничем: работа идёт с
|
|
12
|
+
пустым контекстом, а владельца просят пересказать то, что уже записано.
|
|
13
|
+
- **Разбор просьбы задним числом не переписывается.** Пересказ незаметно подгоняется под уже
|
|
14
|
+
сделанное, и сверять результат становится не с чем. Решение, изменённое по ходу, дописывается
|
|
15
|
+
в ход работы, а не правится в разборе.
|
|
16
|
+
- **Договорённость о продукте не кладётся в папку задачи.** Папка умирает с мержем, а
|
|
17
|
+
договорённость обязана его пережить: её сценарии получают номера в общей нумерации домена,
|
|
18
|
+
и на них ссылаются заголовки тестов. Обратное тоже верно — ход работы не кладётся в
|
|
19
|
+
`proposed/`: спек, в котором завелись шаги, снова становится планом и умирает после мержа.
|
|
20
|
+
- **У меню нет строки «вопрос не тот».** Меню годится для выбора значения из закрытого набора;
|
|
21
|
+
пока постановка вопроса не подтверждена, отвергнуть её владельцу нечем — он выбирает из
|
|
22
|
+
вариантов, выведенных из неверной посылки. Настройки владельца, требующие меню, требование
|
|
23
|
+
не снимают: тогда к каждому вопросу добавляется свободный вариант, и он же — единственное
|
|
24
|
+
место, где вопрос отвергается целиком. Три вопроса ушли одним меню, у одного постановка была
|
|
25
|
+
ложной, и сказать «вопрос не тот» было нечем. Выбор слова, имени и термина узким вопросом не
|
|
26
|
+
является никогда.
|
|
27
|
+
- **Субагент вопросов владельцу не задаёт.** Ни роли, ни конвейер до него не достучатся —
|
|
28
|
+
они возвращают текст главному агенту. Поэтому разбор ведёт главный агент, а роли стоят по
|
|
29
|
+
обе стороны от него.
|
|
30
|
+
- **Если дефект чинится правкой одного общего числа, спроси владельца, тем ли способом ты его
|
|
31
|
+
чинишь.** Замер показывает, что дефект ушёл, — но не то, что причину вылечили. В одной
|
|
32
|
+
задаче так ушли две правки подряд: сначала подняли общее число у соседнего узла, потом
|
|
33
|
+
перенесли узел в другое место разметки. Обе владелец отверг, а нужный способ назвал сам.
|
|
34
|
+
Спрашивают до правки, а не показывают замер после.
|
|
35
|
+
- **Путь, предложенный человеку, судится числом его шагов и тем, чем ему для этого надо
|
|
36
|
+
владеть.** Со стороны кода вариант выглядит дешёвым — «меньше путей», «строку запуска не
|
|
37
|
+
трогаем», — а человеку он стоит захода на сервер. Однажды рекомендуемым вариантом так стояла
|
|
38
|
+
выдача токена, за которой владельцу надо было идти по ssh в работающий контейнер; отбивал
|
|
39
|
+
этот вариант он сам. Цена называется со стороны того, кто пойдёт: сколько шагов и что ему для
|
|
40
|
+
них нужно. Пересказ действующего порядка без такой оценки владелец читает как одобрение.
|
|
41
|
+
- **Эпик по теме читается до того, как решается раскладка.** Замысел эпика держит решения,
|
|
42
|
+
которые пережили десяток задач, и разведка по коду их не находит: снятое решение следа в
|
|
43
|
+
дереве не оставляет. Домен, заведённый генератором и снесённый через полчаса, стоял в замысле
|
|
44
|
+
прямым запретом — но замысел открыли уже после того, как он был заведён во второй раз.
|
|
45
|
+
- **Работа, которая разбирает чужую папку задачи, разбирает и свою — одним коммитом.** Свою
|
|
46
|
+
папку она заводит наравне со всеми: исключения из этого требования нет. Круг, которым
|
|
47
|
+
исключение оправдывали, закрывается не отказом от папки, а порядком разбора: последний
|
|
48
|
+
коммит снимает обе, и после работы неубранного не остаётся. Однажды такой разбор оставил
|
|
49
|
+
свою папку, и на неё пришлось заводить третью задачу — лечится это порядком, а не правом
|
|
50
|
+
работать без замысла на диске. Как разобрать две папки — паттерн `task-flow-archive`.
|
|
51
|
+
- **Слово для нового понятия берётся из `docs/GLOSSARY.md` или заводится там же.** Третий файл
|
|
52
|
+
папки задачи называется `progress.md`, а не `journal.md`, ровно поэтому: журнал в этом
|
|
53
|
+
дереве один, и он другой.
|
|
54
|
+
- **Черновик папки задачи называется тем же коротким именем, что и будущая ветка.** Команда
|
|
55
|
+
заведения ищет черновик по нему и, не найдя, молча собирает папку с образца: работа при этом
|
|
56
|
+
идёт дальше, а разбор просьбы остаётся лежать в брошенном каталоге, и следующий заход
|
|
57
|
+
расспрашивает владельца заново. Имя черновику дают словами просьбы, а ветке — терминологией
|
|
58
|
+
договорённости; те же слова, да не те же.
|
|
59
|
+
|
|
60
|
+
## Поведение исполнителя — по разборам происшествий
|
|
61
|
+
|
|
62
|
+
Переезжает из правила следующей задачей эпика.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Проверка — холодная часть
|
|
2
|
+
|
|
3
|
+
Ловушки: грабли, на которые уже наступали. Грузится не вместе с правилом, а по
|
|
4
|
+
требованию — при обычном решении она не нужна.
|
|
5
|
+
|
|
6
|
+
Правило — `testing`; статьи, которыми держится закон, стоят там.
|
|
7
|
+
|
|
8
|
+
## Ловушки
|
|
9
|
+
|
|
10
|
+
- **Зелёный `nx test <проект>` не значит, что хоть один файл исполнялся.** Либа без своего
|
|
11
|
+
`vitest.config.mts` не запускает ничего — так тесты домена броней не запускались ни разу.
|
|
12
|
+
Либа с конфигом, но без единого `*.spec.ts`, проходит зелёной из-за `passWithNoTests: true`,
|
|
13
|
+
который обычно стоит в каждом конфиге дерева, и на глаз эти два случая неотличимы: в обоих
|
|
14
|
+
прогон успешен. Доля либ без единого теста меряется пересчётом ниже — в дереве, где его
|
|
15
|
+
завели впервые, она вышла почти в две трети. Перед правкой в
|
|
16
|
+
незнакомой либе проверяется, есть ли в ней хоть один `*.spec.ts`; если нет — первый
|
|
17
|
+
заводится этой же правкой, а не откладывается: откладывать здесь не с чего, долг уже
|
|
18
|
+
накоплен. Пересчёт: `for d in $(find libs -name vitest.config.mts -exec dirname {} \;); do
|
|
19
|
+
[ -z "$(find "$d" -name '*.spec.ts')" ] && echo "$d"; done | wc -l`.
|
|
20
|
+
- **Зелёная сводка покрытия не значит, что тесты проходят.** Сверка читает заголовки тестов и
|
|
21
|
+
сопоставляет их со сценариями спека; исполняется ли тест и чем он кончается — она не знает
|
|
22
|
+
вовсе, и падающий тест значится в ней покрытием. Три сценария одной панели падали и до правки
|
|
23
|
+
экрана, а нашлось это только прогоном. Перед правкой экрана его сквозные тесты гоняются один
|
|
24
|
+
раз до первой строки кода: иначе чужое падение читается как своя регрессия, а своё — как
|
|
25
|
+
чужое.
|
|
26
|
+
- **«Executable doesn't exist» — состояние машины, а не дефект правки.** Установлен только
|
|
27
|
+
chromium, `firefox` и `webkit` падают всегда: гонять `--project=chromium`, узкий экран —
|
|
28
|
+
`--project=mobile-chrome`. Та же ошибка приходит после смены версии Playwright: браузер
|
|
29
|
+
ставится под конкретную версию, и после подъёма нужен повторный
|
|
30
|
+
`npx playwright install chromium`. Девять тестов так и упали, и это выглядело регрессией
|
|
31
|
+
обновления.
|
|
32
|
+
- **Первому прогону сразу после установки браузера верить нельзя.** Два падения сквозного
|
|
33
|
+
набора не повторились ни при отдельном прогоне тех же тестов, ни при втором полном. Такой
|
|
34
|
+
прогон повторяют, а выводы делают по второму.
|
|
35
|
+
- Сквозная спека, которой нужен вход, без учётных данных в окружении пропускается молча — в
|
|
36
|
+
отчёте она значится `skipped`, и прогон выглядит успешным. Имена переменных — при дереве.
|
|
37
|
+
- **Справочник флоу вторых сценариев не заводит.** В `docs/E2E_<ДОМЕН>_FLOWS.md` кладут то,
|
|
38
|
+
чего в спеке домена нет и быть не должно: `qa-dataid` элементов, состояния разметки, ловушки
|
|
39
|
+
стенда. Обещанное поведение остаётся сценарием в `scenarios.md`: если списать его во второе
|
|
40
|
+
место, копии разойдутся молча — `npm run check:specs` этого не увидит.
|
|
41
|
+
- `npx nx serve` проверкой не считается: это шаг из правила `browser-verification`, а не тест.
|
|
42
|
+
- **Кадр, зависящий от загрузки машины, проверяет машину, а не вёрстку.** Ожидание отсчётом
|
|
43
|
+
времени этим и кончается: на свободной машине набор зелен целиком, на занятой падает, и какой
|
|
44
|
+
именно кадр не успел — дело случая. Лечится ожиданием события, а не удлинением отсчёта: шрифты
|
|
45
|
+
подняты, картинки нарисованы, движение остановлено, положение узла не менялось два кадра
|
|
46
|
+
подряд. Пока ожидание идёт по времени, «проверено снимками» означает «машина была свободна», и
|
|
47
|
+
перезапуск, давший зелёное, этого не отменяет, а прячет. Восемь кадров расходились с эталоном
|
|
48
|
+
на 0,15–0,74 % в задании конвейера и проходили на той же машине вне его.
|
|
49
|
+
- **Стенд, поднятый предыдущим шагом, останавливается перед съёмкой.** Оставленный работать, он
|
|
50
|
+
соревнуется за машину с тем, что снимают, и делает исход прогона зависящим от того, чем занят
|
|
51
|
+
сосед. Нагрузка, которую задание создаёт себе само — соседняя витрина, только что законченная
|
|
52
|
+
сборка, — ничем не отличается от чужой.
|
|
53
|
+
- **Свой стенд снимается перед тем, как звать набор.** Прогон переиспользует поднятое на его
|
|
54
|
+
портах, и стенд, оставленный для замера, отдаёт ему чужую сборку с чужими данными. Красное при
|
|
55
|
+
этом приходит не строкой про занятый порт, а десятком спек про экраны — то есть выглядит
|
|
56
|
+
дефектом правки: за один заход так покраснели сначала шесть новых тестов, потом гейт пуша, и
|
|
57
|
+
оба раза причиной был свой же стенд. Разобранный занятый порт эту сторону не закрывает: он про
|
|
58
|
+
чужой стенд, а этот — про свой.
|
|
59
|
+
- **Разбор упавшего кадра начинается с чисел, а не с картинки расхождения.** Доля площади
|
|
60
|
+
говорит, сколько разошлось, и молчит о том, что именно: сдвиг всего кадра на пиксель,
|
|
61
|
+
переставленные строки и рябь на сглаженных уголках выглядят на картинке одинаково — «стало
|
|
62
|
+
другим». Читаются координаты разошедшихся точек и величина расхождения по каналу: сдвинутые
|
|
63
|
+
границы блоков — это раскладка, разошедшийся текст при неподвижных границах — это данные,
|
|
64
|
+
единица-две по каналу на кривых краях — это цвет. Три расхождения одного набора разобрались
|
|
65
|
+
ровно так, и ни одно из трёх не оказалось дефектом экрана.
|
|
66
|
+
- **Ожидаемое значение теста не берётся из кода, который тест проверяет.** Вывезенное из
|
|
67
|
+
проверяемой либы, оно делает тест зелёным при любом значении: «колесо показывает пять строк»
|
|
68
|
+
сходится и тогда, когда строк стало три. Ожидаемое пишется числом в самой спеке рядом с
|
|
69
|
+
проверкой, а общий модуль сквозных спек держит приёмы — открыть, дождаться, снять со
|
|
70
|
+
страницы, — но не то, что от страницы ожидается.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-flow
|
|
3
|
+
kind: rule
|
|
4
|
+
law: delivery
|
|
5
|
+
description: Правило под «Закон о поставке» для дерева в Azure DevOps — та его часть, что про выкатку. Брать, когда правка едет на прод: слияние в главную ветку, конвейер, образы и их метки, чистка реестра, описание прода, цепочка миграций хранилища. Называет признак режима в образе, выкатку по sha коммита, глубину отката и сверку прода с главной веткой. Готовый код — в паттернах git-workflow-migration, git-workflow-restart, git-workflow-docker и git-workflow-secrets. Не брать на заведение задачи, ветки, коммит и заявку — это правило git-workflow.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Выкатка — как это устроено здесь
|
|
9
|
+
|
|
10
|
+
Правило под закон `docs/constitution/delivery.md` — та его часть, что про прод. Закон
|
|
11
|
+
говорит, что должно быть верно; здесь — каким приёмом это держится в дереве, лежащем
|
|
12
|
+
в Azure DevOps. Работа с очередью, ветка, коммит и заявка — правило `git-workflow` под тем же
|
|
13
|
+
законом.
|
|
14
|
+
|
|
15
|
+
## Как это называется здесь
|
|
16
|
+
|
|
17
|
+
| В законе | Здесь |
|
|
18
|
+
| -------------------------------- | -------------------------------------------------------- |
|
|
19
|
+
| попадание правки в главную ветку | слияние PR; оно же запускает выкатку — `azure-pipelines.yml` |
|
|
20
|
+
| образ того коммита | `IMAGE_TAG=<sha>` в командах `docker compose` на сервере |
|
|
21
|
+
| изменение хранилища | миграция в `prisma/migrations/<метка>_<имя>/` |
|
|
22
|
+
|
|
23
|
+
## Где это лежит
|
|
24
|
+
|
|
25
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
26
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
27
|
+
же дереве, которое держит код иначе.
|
|
28
|
+
|
|
29
|
+
## Ход
|
|
30
|
+
|
|
31
|
+
Ход выкатки: что уезжает на прод, чем помечен образ и что делается со старыми.
|
|
32
|
+
|
|
33
|
+
```mermaid
|
|
34
|
+
flowchart TD
|
|
35
|
+
A[Слияние в главную ветку] --> B{Правка задела код}
|
|
36
|
+
B -->|Нет| C[Шаги сборки пропускаются по признаку состава правки]
|
|
37
|
+
B -->|Да| D[Образ собирается и метится sha того коммита]
|
|
38
|
+
D --> E{Хранилище меняется этой правкой}
|
|
39
|
+
E -->|Да| F[Цепочка миграций прогнана с пустого хранилища до слияния]
|
|
40
|
+
E -->|Нет| G[Образ выкатывается по sha, а не по метке «последний»]
|
|
41
|
+
F --> G
|
|
42
|
+
G --> H[Старые образы снимаются, три последних sha остаются глубиной отката]
|
|
43
|
+
H --> I{Прод отвечает тем, что выкачено}
|
|
44
|
+
I -->|Нет| J[Разбор выкатки: перезапуск идёт по sha, а не по последней метке]
|
|
45
|
+
I -->|Да| K[Сверка очереди работ читает последний прогон главной ветки]
|
|
46
|
+
C --> K
|
|
47
|
+
J --> K
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Как закон применяется здесь
|
|
51
|
+
|
|
52
|
+
- **Конвейер судит по составу правки, а не гоняет всё подряд.** Шаги, которым нечего проверять,
|
|
53
|
+
пропускаются по признаку, посчитанному от главной ветки: ветка, не тронувшая ни строки кода,
|
|
54
|
+
не поднимает стенда, не снимает кадров и не собирает образов. Признак объявляется переменной
|
|
55
|
+
задания и считается один раз, а не переспрашивается в каждом условии. Пропущенный шаг виден в
|
|
56
|
+
прогоне пропущенным — молча выпавший читается как пройденный.
|
|
57
|
+
- **Слияние в главную ветку выкатывает прод.** Фильтры путей конвейера покрывают документы
|
|
58
|
+
отдельно, поэтому переменные окружения, секреты и записи имён ставятся до слияния, а не
|
|
59
|
+
после.
|
|
60
|
+
- **Признак режима объявлен в образе, а не только в составе прода.** Значение, заданное
|
|
61
|
+
составом, действует лишь на контейнер, поднятый этим составом; ручной прогон того же образа
|
|
62
|
+
идёт с пустым значением, а пусто здесь означает локалхост — со всеми отладочными
|
|
63
|
+
умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
|
|
64
|
+
- **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
|
|
65
|
+
от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
|
|
66
|
+
- **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
|
|
67
|
+
висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
|
|
68
|
+
сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
|
|
69
|
+
через две выкатки, откатывается уже некуда.
|
|
70
|
+
- **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
|
|
71
|
+
бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
|
|
72
|
+
копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
|
|
73
|
+
- **Правка конвейера прогоняется до слияния ручным запуском.** Конвейер запускается на любой
|
|
74
|
+
ветке, а задание выкатки прибито условием к главной: прогон ради проверки доходит до сборок и
|
|
75
|
+
там кончается. Прогон команд задания на своей машине его не покрывает: он проверяет команды,
|
|
76
|
+
а не файл конвейера, — верность самого файла читается только по списку прогонов после пуша.
|
|
77
|
+
- **PR проверяется до слияния тем же конвейером, что и главная ветка.** Проверки и сборки
|
|
78
|
+
образов идут на конвейере проверки PR, выкатка — нет: её держит условие по главной ветке у
|
|
79
|
+
своего задания, а образ PR в реестр не уезжает.
|
|
80
|
+
- **Расхождение прода с главной веткой видно сверкой очереди работ.** Рабочий элемент уходит из
|
|
81
|
+
очереди слиянием, но слияние — ещё не прод: отказавшая выкатка не трогает ни элемент, ни его
|
|
82
|
+
состояние, и заметить её неоткуда. Сверка спрашивает последний прогон главной ветки и судит
|
|
83
|
+
только завершённый: идущий ещё может кончиться выкаткой.
|
|
84
|
+
- **Цепочка миграций прогоняется с пустого хранилища до слияния.** Порядок применения
|
|
85
|
+
лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
|
|
86
|
+
ветки, начатой раньше, встаёт перед той, от которой зависит.
|
|
87
|
+
- **Расхождение миграций со схемой меряется на теневом хранилище, а не на том, где работает
|
|
88
|
+
тот, кто пушит.** Оно законно несёт след любой недоделанной ветки, и сверка с ним держала бы
|
|
89
|
+
чужую правку. Гейт и выкатка зовут одну и ту же проверку — иначе «сошлось» станет значить в
|
|
90
|
+
двух местах разное.
|
|
91
|
+
|
|
92
|
+
## Чего из закона здесь нет
|
|
93
|
+
|
|
94
|
+
Состояние прода машине не видно: сверка очереди работ спрашивает последний прогон главной
|
|
95
|
+
ветки и судит по нему, а отвечает ли прод той сборкой, которую он выкатил, не спрашивает
|
|
96
|
+
никто. Держится это тем, кто выкатывал.
|
|
97
|
+
|
|
98
|
+
Полноту чистки реестра не считает ничто: сценарий оставляет три последних sha, и промах в
|
|
99
|
+
его отборе виден только тогда, когда диск сервера кончился.
|
|
100
|
+
|
|
101
|
+
## Паттерны
|
|
102
|
+
|
|
103
|
+
- `git-workflow-migration` — правка схемы хранилища и её миграций.
|
|
104
|
+
- `git-workflow-restart` — ручной перезапуск прода.
|
|
105
|
+
- `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
|
|
106
|
+
- `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-flow
|
|
3
|
+
kind: rule
|
|
4
|
+
law: delivery
|
|
5
|
+
description: Правило под «Закон о поставке» для дерева на GitHub — та его часть, что про выкатку. Брать, когда правка едет на прод: мерж в главную ветку, конвейер, образы и их метки, чистка реестра, описание прода, цепочка миграций хранилища. Называет признак режима в образе, выкатку по sha коммита, глубину отката и сверку прода с главной веткой. Готовый код — в паттернах git-workflow-migration, git-workflow-restart, git-workflow-docker и git-workflow-secrets. Не брать на заведение задачи, ветки, коммит и заявку — это правило git-workflow.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Выкатка — как это устроено здесь
|
|
9
|
+
|
|
10
|
+
Правило под закон `docs/constitution/delivery.md` — та его часть, что про прод. Закон
|
|
11
|
+
говорит, что должно быть верно; здесь — каким приёмом это держится в дереве, лежащем
|
|
12
|
+
на GitHub. Работа с очередью, ветка, коммит и заявка — правило `git-workflow` под тем же
|
|
13
|
+
законом.
|
|
14
|
+
|
|
15
|
+
## Как это называется здесь
|
|
16
|
+
|
|
17
|
+
| В законе | Здесь |
|
|
18
|
+
| -------------------------------- | -------------------------------------------------------- |
|
|
19
|
+
| попадание правки в главную ветку | мерж PR; он же запускает выкатку — `.github/workflows/deploy.yml` |
|
|
20
|
+
| образ того коммита | `IMAGE_TAG=<sha>` в командах `docker compose` на сервере |
|
|
21
|
+
| изменение хранилища | миграция в `prisma/migrations/<метка>_<имя>/` |
|
|
22
|
+
|
|
23
|
+
## Где это лежит
|
|
24
|
+
|
|
25
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
26
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
27
|
+
же дереве, которое держит код иначе.
|
|
28
|
+
|
|
29
|
+
## Ход
|
|
30
|
+
|
|
31
|
+
Ход выкатки: что уезжает на прод, чем помечен образ и что делается со старыми.
|
|
32
|
+
|
|
33
|
+
```mermaid
|
|
34
|
+
flowchart TD
|
|
35
|
+
A[Мерж в главную ветку] --> B{Правка задела код}
|
|
36
|
+
B -->|Нет| C[Шаги сборки пропускаются по признаку состава правки]
|
|
37
|
+
B -->|Да| D[Образ собирается и метится sha того коммита]
|
|
38
|
+
D --> E{Хранилище меняется этой правкой}
|
|
39
|
+
E -->|Да| F[Цепочка миграций прогнана с пустого хранилища до слияния]
|
|
40
|
+
E -->|Нет| G[Образ выкатывается по sha, а не по метке «последний»]
|
|
41
|
+
F --> G
|
|
42
|
+
G --> H[Старые образы снимаются, три последних sha остаются глубиной отката]
|
|
43
|
+
H --> I{Прод отвечает тем, что выкачено}
|
|
44
|
+
I -->|Нет| J[Разбор выкатки: перезапуск идёт по sha, а не по последней метке]
|
|
45
|
+
I -->|Да| K[Сверка очереди работ читает последний прогон главной ветки]
|
|
46
|
+
C --> K
|
|
47
|
+
J --> K
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Как закон применяется здесь
|
|
51
|
+
|
|
52
|
+
- **Конвейер судит по составу правки, а не гоняет всё подряд.** Шаги, которым нечего проверять,
|
|
53
|
+
пропускаются по признаку, посчитанному от главной ветки: ветка, не тронувшая ни строки кода,
|
|
54
|
+
не поднимает стенда, не снимает кадров и не собирает образов. Признак считается один раз и
|
|
55
|
+
объявляется выводом шага, а не переспрашивается в каждом условии. Пропущенный шаг виден в
|
|
56
|
+
прогоне пропущенным — молча выпавший читается как пройденный.
|
|
57
|
+
- **Мерж в главную ветку выкатывает прод.** Исключения по путям покрывают только документы,
|
|
58
|
+
поэтому переменные окружения, секреты и записи имён ставятся до мержа, а не после.
|
|
59
|
+
- **Признак режима объявлен в образе, а не только в составе прода.** Значение, заданное
|
|
60
|
+
составом, действует лишь на контейнер, поднятый этим составом; ручной прогон того же образа
|
|
61
|
+
идёт с пустым значением, а пусто здесь означает локалхост — со всеми отладочными
|
|
62
|
+
умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
|
|
63
|
+
- **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
|
|
64
|
+
от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
|
|
65
|
+
- **Убирает за собой и та машина, которая образы собирает.** Отбор у обеих один — своё имя
|
|
66
|
+
реестра, три последних sha, поднятые контейнеры остаются, — и зовётся он одним сценарием:
|
|
67
|
+
разойдясь, две чистки начали бы оставлять разное, а заметить это нечем. Отличаются они
|
|
68
|
+
хвостом: сервер снимает следом висячие слои и кэш сборки, машина сборки оставляет их себе,
|
|
69
|
+
иначе каждая сборка идёт как первая. Чистка на сборке не ждёт мержа: образ ветки занимает
|
|
70
|
+
столько же места, в реестр не уезжает вовсе и точкой отката не бывает.
|
|
71
|
+
- **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
|
|
72
|
+
висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
|
|
73
|
+
сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
|
|
74
|
+
через две выкатки, откатывается уже некуда.
|
|
75
|
+
- **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
|
|
76
|
+
бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
|
|
77
|
+
копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
|
|
78
|
+
- **Правка конвейера прогоняется до мержа ручным запуском.** `workflow_dispatch` у выкатки
|
|
79
|
+
запускает её на любой ветке, а сама выкатка прибита условием к главной: прогон ради проверки
|
|
80
|
+
доходит до сборок и там кончается. Триггер регистрируется по главной ветке, поэтому правку,
|
|
81
|
+
которая его заводит или переносит, ручной запуск не покрывает. Прогон команд задания на своей
|
|
82
|
+
машине не покрывает её тоже: он проверяет команды, а не файл конвейера, — верность самого
|
|
83
|
+
файла читается только по списку прогонов после пуша.
|
|
84
|
+
- **PR проверяется до мержа тем же конвейером, что и главная ветка.** Проверки и сборки
|
|
85
|
+
образов идут на событии `pull_request`, выкатка — нет: её держит условие по главной ветке у
|
|
86
|
+
своего задания, а образ PR в реестр не уезжает.
|
|
87
|
+
- **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
|
|
88
|
+
мержем, но мерж — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её колонку, и
|
|
89
|
+
заметить её неоткуда. Сверка спрашивает последний прогон главной ветки и судит только
|
|
90
|
+
завершённый: идущий ещё может кончиться выкаткой.
|
|
91
|
+
- **Цепочка миграций прогоняется с пустого хранилища до мержа.** Порядок применения
|
|
92
|
+
лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
|
|
93
|
+
ветки, начатой раньше, встаёт перед той, от которой зависит.
|
|
94
|
+
- **Расхождение миграций со схемой меряется на теневом хранилище, а не на том, где работает
|
|
95
|
+
тот, кто пушит.** Оно законно несёт след любой недоделанной ветки, и сверка с ним держала бы
|
|
96
|
+
чужую правку. Гейт и выкатка зовут одну и ту же проверку — иначе «сошлось» станет значить в
|
|
97
|
+
двух местах разное.
|
|
98
|
+
|
|
99
|
+
## Чего из закона здесь нет
|
|
100
|
+
|
|
101
|
+
Состояние прода машине не видно: сверка очереди работ спрашивает последний прогон главной
|
|
102
|
+
ветки и судит по нему, а отвечает ли прод той сборкой, которую он выкатил, не спрашивает
|
|
103
|
+
никто. Держится это тем, кто выкатывал.
|
|
104
|
+
|
|
105
|
+
Полноту чистки реестра не считает ничто: сценарий оставляет три последних sha, и промах в
|
|
106
|
+
его отборе виден только тогда, когда диск сервера кончился.
|
|
107
|
+
|
|
108
|
+
## Паттерны
|
|
109
|
+
|
|
110
|
+
- `git-workflow-migration` — правка схемы хранилища и её миграций.
|
|
111
|
+
- `git-workflow-restart` — ручной перезапуск прода.
|
|
112
|
+
- `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
|
|
113
|
+
- `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-flow
|
|
3
|
+
kind: rule
|
|
4
|
+
law: delivery
|
|
5
|
+
description: Правило под «Закон о поставке» для дерева на GitLab — та его часть, что про выкатку. Брать, когда правка едет на прод: слияние в главную ветку, конвейер, образы и их метки, чистка реестра, описание прода, цепочка миграций хранилища. Называет признак режима в образе, выкатку по sha коммита, глубину отката и сверку прода с главной веткой. Готовый код — в паттернах git-workflow-migration, git-workflow-restart, git-workflow-docker и git-workflow-secrets. Не брать на заведение задачи, ветки, коммит и заявку — это правило git-workflow.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Выкатка — как это устроено здесь
|
|
9
|
+
|
|
10
|
+
Правило под закон `docs/constitution/delivery.md` — та его часть, что про прод. Закон
|
|
11
|
+
говорит, что должно быть верно; здесь — каким приёмом это держится в дереве, лежащем
|
|
12
|
+
на GitLab. Работа с очередью, ветка, коммит и заявка — правило `git-workflow` под тем же
|
|
13
|
+
законом.
|
|
14
|
+
|
|
15
|
+
## Как это называется здесь
|
|
16
|
+
|
|
17
|
+
| В законе | Здесь |
|
|
18
|
+
| -------------------------------- | -------------------------------------------------------- |
|
|
19
|
+
| попадание правки в главную ветку | слияние MR; оно же запускает выкатку — `.gitlab-ci.yml` |
|
|
20
|
+
| образ того коммита | `IMAGE_TAG=<sha>` в командах `docker compose` на сервере |
|
|
21
|
+
| изменение хранилища | миграция в `prisma/migrations/<метка>_<имя>/` |
|
|
22
|
+
|
|
23
|
+
## Где это лежит
|
|
24
|
+
|
|
25
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
26
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
27
|
+
же дереве, которое держит код иначе.
|
|
28
|
+
|
|
29
|
+
## Ход
|
|
30
|
+
|
|
31
|
+
Ход выкатки: что уезжает на прод, чем помечен образ и что делается со старыми.
|
|
32
|
+
|
|
33
|
+
```mermaid
|
|
34
|
+
flowchart TD
|
|
35
|
+
A[Слияние в главную ветку] --> B{Правка задела код}
|
|
36
|
+
B -->|Нет| C[Шаги сборки пропускаются по признаку состава правки]
|
|
37
|
+
B -->|Да| D[Образ собирается и метится sha того коммита]
|
|
38
|
+
D --> E{Хранилище меняется этой правкой}
|
|
39
|
+
E -->|Да| F[Цепочка миграций прогнана с пустого хранилища до слияния]
|
|
40
|
+
E -->|Нет| G[Образ выкатывается по sha, а не по метке «последний»]
|
|
41
|
+
F --> G
|
|
42
|
+
G --> H[Старые образы снимаются, три последних sha остаются глубиной отката]
|
|
43
|
+
H --> I{Прод отвечает тем, что выкачено}
|
|
44
|
+
I -->|Нет| J[Разбор выкатки: перезапуск идёт по sha, а не по последней метке]
|
|
45
|
+
I -->|Да| K[Сверка очереди работ читает последний прогон главной ветки]
|
|
46
|
+
C --> K
|
|
47
|
+
J --> K
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Как закон применяется здесь
|
|
51
|
+
|
|
52
|
+
- **Конвейер судит по составу правки, а не гоняет всё подряд.** Шаги, которым нечего проверять,
|
|
53
|
+
пропускаются по признаку, посчитанному от главной ветки: ветка, не тронувшая ни строки кода,
|
|
54
|
+
не поднимает стенда, не снимает кадров и не собирает образов. Правила `rules:changes` считают
|
|
55
|
+
это сами, но по путям, а не по составу правки — совпадение пути ещё не значит, что задета
|
|
56
|
+
сборка, поэтому признак объявляется явно и один раз. Пропущенный шаг виден в прогоне
|
|
57
|
+
пропущенным — молча выпавший читается как пройденный.
|
|
58
|
+
- **Слияние в главную ветку выкатывает прод.** Правила `only`/`rules` конвейера покрывают
|
|
59
|
+
документы отдельно, поэтому переменные окружения, секреты и записи имён ставятся до слияния,
|
|
60
|
+
а не после.
|
|
61
|
+
- **Признак режима объявлен в образе, а не только в составе прода.** Значение, заданное
|
|
62
|
+
составом, действует лишь на контейнер, поднятый этим составом; ручной прогон того же образа
|
|
63
|
+
идёт с пустым значением, а пусто здесь означает локалхост — со всеми отладочными
|
|
64
|
+
умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
|
|
65
|
+
- **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
|
|
66
|
+
от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
|
|
67
|
+
- **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
|
|
68
|
+
висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
|
|
69
|
+
сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
|
|
70
|
+
через две выкатки, откатывается уже некуда.
|
|
71
|
+
- **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
|
|
72
|
+
бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
|
|
73
|
+
копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
|
|
74
|
+
- **Правка конвейера прогоняется до слияния ручным запуском.** Конвейер запускается на любой
|
|
75
|
+
ветке, а задание выкатки прибито правилом к главной: прогон ради проверки доходит до сборок и
|
|
76
|
+
там кончается. Прогон команд задания на своей машине его не покрывает: он проверяет команды,
|
|
77
|
+
а не файл конвейера, — верность самого файла читается только по списку конвейеров после
|
|
78
|
+
пуша, и синтаксис отдельно судит проверка `.gitlab-ci.yml` в проекте.
|
|
79
|
+
- **PR проверяется до слияния тем же конвейером, что и главная ветка.** Проверки и сборки
|
|
80
|
+
образов идут на конвейере запроса слияния, выкатка — нет: её держит правило по главной ветке
|
|
81
|
+
у своего задания, а образ PR в реестр не уезжает.
|
|
82
|
+
- **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
|
|
83
|
+
слиянием, но слияние — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её список, и
|
|
84
|
+
заметить её неоткуда. Сверка спрашивает последний конвейер главной ветки и судит только
|
|
85
|
+
завершённый: идущий ещё может кончиться выкаткой.
|
|
86
|
+
- **Цепочка миграций прогоняется с пустого хранилища до слияния.** Порядок применения
|
|
87
|
+
лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
|
|
88
|
+
ветки, начатой раньше, встаёт перед той, от которой зависит.
|
|
89
|
+
- **Расхождение миграций со схемой меряется на теневом хранилище, а не на том, где работает
|
|
90
|
+
тот, кто пушит.** Оно законно несёт след любой недоделанной ветки, и сверка с ним держала бы
|
|
91
|
+
чужую правку. Гейт и выкатка зовут одну и ту же проверку — иначе «сошлось» станет значить в
|
|
92
|
+
двух местах разное.
|
|
93
|
+
|
|
94
|
+
## Чего из закона здесь нет
|
|
95
|
+
|
|
96
|
+
Состояние прода машине не видно: сверка очереди работ спрашивает последний прогон главной
|
|
97
|
+
ветки и судит по нему, а отвечает ли прод той сборкой, которую он выкатил, не спрашивает
|
|
98
|
+
никто. Держится это тем, кто выкатывал.
|
|
99
|
+
|
|
100
|
+
Полноту чистки реестра не считает ничто: сценарий оставляет три последних sha, и промах в
|
|
101
|
+
его отборе виден только тогда, когда диск сервера кончился.
|
|
102
|
+
|
|
103
|
+
## Паттерны
|
|
104
|
+
|
|
105
|
+
- `git-workflow-migration` — правка схемы хранилища и её миграций.
|
|
106
|
+
- `git-workflow-restart` — ручной перезапуск прода.
|
|
107
|
+
- `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
|
|
108
|
+
- `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
|