# Как вносить изменения Основной репозиторий — на [GitLab](https://gitlab.com/space-education-development/soniks/network/soniks-network). Merge-request'ы отправляются туда, не в апстрим SatNOGS и не на GitHub. Полный текст руководства по вкладу, унаследованный от Libre Space Foundation (включая Developer's Certificate of Origin и требование подписывать коммиты), — в `CONTRIBUTING.md` в корне репозитория. ## Рабочий цикл 1. Ветка от актуальной основной ветки. 2. Изменения атомарными коммитами: одно логическое изменение — один коммит. 3. Локально прогнать проверки: ```bash tox -e ruff tox -e deps,pytest tox -e docs npm run lint npm test ``` 4. Merge request с описанием мотивации, а не только содержания диффа. 5. Отработать замечания ревью. ### Хуки до коммита Необязательно, но экономит круг по CI: те же проверки, но только по файлам в индексе. ```bash pip install pre-commit pre-commit install ``` Набор описан в `.pre-commit-config.yaml`: `ruff check --fix`, `ruff format`, `eslint` и `stylelint`. Версия `ruff` в хуке совпадает с версией в `tox.ini` — разъехавшиеся версии форматтера и дают «у меня проходило»: хук переформатирует файл по-своему, CI просит обратно. CI от хуков не зависит и гоняет тот же набор целиком. ## Стиль кода Правила фиксируются `ruff.toml` и проверяются `tox -e ruff`: | Правило | Значение | |---|---| | Длина строки | 88 | | Отступ | 4 пробела | | Кавычки | двойные | | Импорты | сортировка `I`: стандартная библиотека → сторонние → локальные `network.*` | | Docstring'и | стиль Google | Форматирование применяется командой `tox -e ruff-format`. ## Обязательные соглашения **Миграции.** Существующие файлы в `network/*/migrations/` не редактируются. Изменения схемы — только новыми миграциями через `makemigrations`. **Бэкфиллы.** `RunPython`, который проходит по `Observation`, пишется батчами: таблица на проде — миллионы строк, а `web` не отвечает, пока идут миграции. ```python def fill(apps, schema_editor): Observation = apps.get_model("base", "Observation") batch = [] for observation in Observation.objects.filter(field__isnull=True).iterator( chunk_size=5000 ): observation.field = compute(observation) batch.append(observation) if len(batch) >= 5000: Observation.objects.bulk_update(batch, ["field"]) batch.clear() if batch: Observation.objects.bulk_update(batch, ["field"]) ``` Образец того, как не надо, — `0048_observation_snapshot`: два безусловных `UPDATE` по всей таблице. Она уже выпущена, редактировать её нельзя (см. выше), и в CHANGELOG к `1.10.0` из-за неё стоит отдельное предупреждение «заложить время на миграции». Squash миграций `base` не делаем: стенды и станции обновляются вразнобой, а squash ломает любую базу, которая остановилась на миграции внутри схлопнутого отрезка. **Секреты.** Ничего не хардкодится. Только `config("VAR_NAME", default="")` через `python-decouple`, значение попадает в `.env`, а новая переменная — в `env-dist` и в [](../configuration.md). **Решённые вопросы.** Прежде чем предлагать очевидное улучшение, загляните в [](decisions.md): там записано, что уже пробовали и почему отказались. **Размещение кода.** HTML-представления — в `network/base/views/<домен>.py`, эндпоинты API — в `network/api/views.py` классами DRF. См. [](architecture.md). **Локализация.** Весь текст, видимый пользователю, — через `gettext_lazy`. Комментарии и docstring'и — на английском. **Сгенерированные файлы.** Руками не правятся: * `requirements.txt`, `requirements-dev.txt`, `constraints.txt` — генерируются `./contrib/refresh-requirements.sh` из `setup.cfg`; * `soniks-network-api-client/` — генерируется openapi-generator в CI; * `network/_version.py` — versioneer. ## Декодеры телеметрии Декодеры (`.ksy` Kaitai Struct) живут в отдельном репозитории [soniks-decoders](https://gitlab.com/space-education-development/soniks/network/soniks-decoders), подключённом как submodule `soniks-decoders/`; пакет `satnogs-decoders` с PyPI больше не используется. Сгенерированный Python в репозитории не хранится: в образе `.ksy` компилируются стадией `decoders` Dockerfile, для разработки без Docker — `cd soniks-decoders && ./contrib/docker-ksc.sh`. Новый декодер: MR в soniks-decoders (ветка `soniks`), затем в этом репозитории передвинуть пин и закоммитить: ```bash git submodule update --remote soniks-decoders git add soniks-decoders ``` ## Документация Документация живёт в `docs/`, пишется на русском в MyST-Markdown, собирается с `-W` (любое предупреждение Sphinx — ошибка сборки). ```bash tox -e docs # или pip install -r docs/requirements.txt && make -C docs html ``` Новая страница обязана попасть в какой-нибудь `toctree` в `docs/index.md` — иначе сборка упадёт. Ссылки между страницами — относительные, синтаксисом MyST: `[](../tle.md)` подставит заголовок целевой страницы. Зависимости сборки — только в `docs/requirements.txt`, в `setup.cfg` они не входят. Изменение поведения без изменения документации — незаконченное изменение. Особенно это касается новых настроек, задач Celery, management-команд и эндпоинтов API: для них есть готовые места в [](../configuration.md), [](../tasks.md), [](../commands.md) и [](../api/endpoints.md).