fix: cyrillic fonts, dev certs, page head, and ru-text typography (#67)

🤖 PR generated for branch `fix/cyrillic-fonts-dev-certs-and-page-head`.

### Changes Summary
- **Fonts**: Add Cyrillic glyph subsets for Lato, EB Garamond, and Fira
Code.
- **Dev**: Support remote Root CA and encrypted dev CA key in
`.env.dev`.
- **UI & Kits**: Add size variant to `Breadcrumbs` component and enlarge
`PageHead` breadcrumbs with tuned collapse scroll threshold.
- **ESLint**: Add `no-hanging-particles` i18n & markdown typography rule
with auto-fixer.
- **Content & i18n**: Apply `ru-text` editorial and typography polish
(em dashes, number ranges, «ё» restoration, non-breaking spaces) across
`services/www` and `services/docs`.
This commit is contained in:
deytenit authored and GitHub committed 2026-10-25 15:21:09 +03:00
1 parent c6487dc258
commit b3638f4d63
111 files changed
+2350 -1512

No files matched your search

@@ -1,10 +1,10 @@
---
title: Разработка действий
description: Создавайте, переопределяйте и тестируйте действия движка в commons или proprietaries.
description: Создавайте, переопределяйте и тестируйте действия движка в commons или proprietaries.
weight: 22
---
**Контекст:** вся автоматизация устроена в виде [действий](/apex/glossary#action) — по одному Python-модулю на каждое действие, диспетчеризуемых по пути к файлу. Общий код находится в каталоге [commons](/apex/glossary#commons) `actions/` («commons» — общий репозиторий), а специфика конкретного узла — в его `proprietaries/actions/`. Оба дерева используют единый контракт, а запускатель добавляет оба каталога в `sys.path`. Поэтому локальное действие импортирует `engine.*` точно так же, как и действие из commons.
**Контекст:** вся автоматизация устроена в виде [действий](/apex/glossary#action) — по одному Python-модулю на каждое действие, диспетчеризуемых по пути к файлу. Общий код находится в каталоге [commons](/apex/glossary#commons) `actions/` («commons» — общий репозиторий), а специфика конкретного узла — в его `proprietaries/actions/`. Оба дерева используют единый контракт, а запускатель добавляет оба каталога в `sys.path`. Поэтому локальное действие импортирует `engine.*` точно так же, как и действие из commons.
## Минимальное действие {#minimal}
@@ -29,14 +29,14 @@ def run(ctx, args):
ctx.log.success("Конфигурация развёрнута.")
```
Путь к файлу задаёт имя действия: модуль выше вызывается как `apex utils/example`. Верните `0` или `None` при успехе, целое число — для конкретного кода выхода, либо выбросьте `SystemExit(code)`. [Соглашение о кодах выхода](/apex/concepts/actions-and-overlay#exit-codes): `64` — ошибка использования, `65` — ошибка данных, `66` — отсутствие входных данных, `1` — общая ошибка.
Путь к файлу задаёт имя действия: модуль выше вызывается как `apex utils/example`. Верните `0` или `None` при успехе, целое число — для конкретного кода выхода, либо выбросьте `SystemExit(code)`. [Соглашение о кодах выхода](/apex/concepts/actions-and-overlay#exit-codes): `64` — ошибка использования, `65` — ошибка данных, `66` — отсутствие входных данных, `1` — общая ошибка.
## Соглашения для фоновых действий {#unattended}
## Соглашения для фоновых действий {#unattended}
Действия, которые запускаются по cron без надзора оператора, следуют двум правилам, чтобы сбои отправляли оповещение, а не исчезали бесследно:
Действия, которые запускаются по cron без надзора оператора, следуют двум правилам, чтобы сбои отправляли оповещение, а не исчезали бесследно:
- **Оберните тело** в `try/except Exception` и отправьте `ctx.notify.error(...)` перед тем как выбросить `SystemExit(1)` — это Python-аналог перехвата `ERR` в shell.
- **Привяжите код выхода к итоговому уведомлению**: методы `ctx.notify.*` возвращают `False`, если доставить сообщение не удалось. Запуск, чьё статусное сообщение не дошло, всё равно должен завершиться с кодом 1.
- **Оберните тело** в `try/except Exception` и отправьте `ctx.notify.error(...)` перед тем как выбросить `SystemExit(1)` — это Python-аналог перехвата `ERR` в shell.
- **Привяжите код выхода к итоговому уведомлению**: методы `ctx.notify.*` возвращают `False`, если доставить сообщение не удалось. Запуск, чьё статусное сообщение не дошло, всё равно должен завершиться с кодом 1.
```python
try:
@@ -54,7 +54,7 @@ def run(ctx, args):
## Переопределение, обёртывание, отключение {#override}
Проприетарный файл с тем же относительным путём, что и действие из commons, полностью перекрывает его. Внутри переопределяющего модуля вызов `ctx.commons.run(args)` обращается к исходной реализации из commons — по паттерну обёртки:
Проприетарный файл с тем же относительным путём, что и действие из commons, полностью перекрывает его. Внутри переопределяющего модуля вызов `ctx.commons.run(args)` обращается к исходной реализации из commons — по паттерну обёртки:
```python {filename="proprietaries/actions/sync/packages.py"}
from engine.descriptor import Meta, Arg
@@ -67,23 +67,23 @@ def run(ctx, args):
return ctx.commons.run(args) # делегирование реализации из commons
```
Чтобы отключить действие на конкретном узле, укажите `DISABLED = "reason"` на верхнем уровне модуля. Диспетчер отклонит запуск такого действия с кодом выхода 1, а в общем списке появится отметка `[DISABLED: reason]`.
Чтобы отключить действие на конкретном узле, укажите `DISABLED = "reason"` на верхнем уровне модуля. Диспетчер отклонит запуск такого действия с кодом выхода 1, а в общем списке появится отметка `[DISABLED: reason]`.
## Тестирование {#testing}
Набор тестов commons построен на стандартном модуле `unittest`:
Набор тестов commons построен на стандартном модуле `unittest`:
```bash
./tests/run.sh # python3 -m unittest discover -s tests -p 'test_*.py' -v
```
Изменения в&nbsp;движке должны сохранять тесты зелёными. Быстрая smoke-проверка для&nbsp;любого действия (как из&nbsp;commons, так и&nbsp;проприетарного)&nbsp;— запуск со&nbsp;справкой: команда `apex <name> --help` должна завершаться с&nbsp;кодом&nbsp;0. Это подтверждает, что модуль синтаксически корректен, объект `METADATA` сформирован без&nbsp;ошибок, а&nbsp;механизм обнаружения находит действие.
Изменения в движке должны сохранять тесты зелёными. Быстрая smoke-проверка для любого действия (как из commons, так и проприетарного) — запуск со справкой: команда `apex <name> --help` должна завершаться с кодом 0. Это подтверждает, что модуль синтаксически корректен, объект `METADATA` сформирован без ошибок, а механизм обнаружения находит действие.
Хук pre-commit в&nbsp;commons (скрипт `init.sh` подключает его через `core.hooksPath`) запускает `apex utils/lint-docker-compose --hook` для&nbsp;подготовленных (staged) compose-файлов, поэтому ошибки в&nbsp;композициях отлавливаются ещё на&nbsp;этапе коммита.
Хук pre-commit в commons (скрипт `init.sh` подключает его через `core.hooksPath`) запускает `apex utils/lint-docker-compose --hook` для подготовленных (staged) compose-файлов, поэтому ошибки в композициях отлавливаются ещё на этапе коммита.
---
**См.&nbsp;также:**
**См. также:**
- [Concept: Actions and the overlay](/apex/concepts/actions-and-overlay)
- [Concept: The execution context](/apex/concepts/execution-context)