Как вносить изменения

Полный документ — CONTRIBUTING.md в корне репозитория (руководство Libre Space Foundation, основанное на правилах ядра Linux). Здесь — выжимка того, что проверяет CI и на чём чаще всего спотыкаются.

Подпись коммита обязательна

Каждый коммит должен нести трейлер Signed-off-by: — это Developer Certificate of Origin. Джоба sign_off в GitLab CI падает без него, и слияние блокируется.

git commit -s -m "Add USP deframer threshold parameter"

Флаг -s добавляет трейлер автоматически из user.name и user.email. Забыли — поправьте, не создавая нового коммита:

git commit --amend -s --no-edit

Атомарные коммиты

Одно логическое изменение — один коммит, полный и работоспособный. Проект должен собираться и запускаться после каждого коммита серии: кто-то будет искать регрессию через git bisect.

Правка в нескольких файлах ради одного изменения — это один коммит. Исправление бага и новая возможность — минимум два.

Разумное разбиение для нового декодера: .grc вместе со строкой в CMakeLists.txt, затем регистрация режима в диспетчере, затем документация.

Сообщение коммита

  • заголовок отделён от тела пустой строкой;

  • заголовок не длиннее 50 символов, с заглавной буквы, без точки в конце;

  • заголовок в повелительном наклонении: «Add», «Fix», «Remove» — не «Added», не «Fixes»;

  • тело переносится по 72 символам и объясняет что и зачем, а не как.

Fix decimation floor for low baudrates

satnogs.find_decimation() returns 2 at 400 baud, and the audio path
divides by decimation // 2, which then yields zero and aborts the
flowgraph at startup.

Signed-off-by: Имя Фамилия <адрес@пример.рф>

Что нельзя коммитить

Бинарные файлы. Попав в историю Git, они из неё уже не удаляются.

Сгенерированные .py флоуграфов. generic/*.py и satellites/*.py создаёт grcc при сборке; они перечислены в .gitignore. Источник правды — .grc.

Собранную документацию. docs/_build/ тоже в .gitignore.

Документация — часть изменения

Изменили поведение — правьте соответствующую страницу docs/ в том же наборе коммитов. Что чему соответствует — таблица в 6. Обновить документацию.

Собрать локально перед отправкой:

pip install -r docs/requirements.txt
make -C docs html

Сборка идёт с -W: любое предупреждение Sphinx считается ошибкой, ровно как в CI. Битая ссылка внутри документации остановит сборку.

Проверка перед отправкой

Первые три команды не требуют ни GNU Radio, ни SDR — их же прогоняет CI:

python3 tests/test_flowgraphs.py        # инварианты .grc
python3 tests/test_dispatcher.py        # контракт аргументов диспетчера
flake8 flowgraph_dispatcher tests       # настройки в setup.cfg
cd build && cmake .. && make            # все флоуграфы генерируются
make -C ../docs html                    # документация собирается
git log --format='%s' origin/soniks..HEAD | awk 'length > 50'   # длинные заголовки
git log --format='%(trailers:key=Signed-off-by)' origin/soniks..HEAD  # подписи на месте

Тесты — простые скрипты на assert без pytest: tests/grc.py читает .grc через PyYAML и импортирует диспетчер по пути. Добавили режим или параметр — тесты должны остаться зелёными; если они падают, расхождение реально.

Merge request

Ветка разработки этого форка — soniks. Merge request создаётся в GitLab; описание должно быть самодостаточным — читающий не обязан искать контекст в чате.

CI прогонит sign_off, lint, test, flowgraphs (все .grc через grcc в образе станции плюс tests/e2e_check.py — GNU Radio там уже есть), сборку документации и её публикацию. Все проверки должны пройти. Debian-пакет в CI не собирается — см. Известные расхождения.

Пайплайн идёт на собственном раннере «SONIKS Dev Stand», публичные раннеры не используются. Тег раннера и версии образов вынесены в variables: наверху .gitlab-ci.yml — сменился раннер или образ, правится одно значение. Джобы задают image:, поэтому раннер должен быть с исполнителем Docker.

Структура .gitlab-ci.yml повторяет soniks-client-new: те же имена переменных, default: tags: [$GITLAB_CI_RUNNER_TAG], interruptible: true и собственная джоба sign_off вместо кросс-проектного include шаблонов Libre Space Foundation — форк вне namespace LSF их не подтягивает. Версия линтера закреплена намеренно: незакреплённая роняет джобу без единой правки кода.