Статус: публичный пилот; проверка PR и DNS-деплой работают. Цель — обработать
заявки примерно 96 студентов в одной учебной DNS-зоне softdevtools.ru.
Репозиторий создан закрытым для подготовки, затем открыт для пилота. После
проверки инструкция будет выдана студентам для fork и PR. Решение принимает
владелец репозитория после проверки содержимого и защиты ветки.
Студент: публичный сайт на Pages + PR с YAML
→ проверка PR без секретов
→ ручная сверка автора и одобрение преподавателя
→ merge в main (защищённую перед доступом студентов)
→ повторная проверка и DNS Edit через Cloudflare API
→ отдельная проверка DNS, HTTP и HTTPS
Автор PR и содержимое его ветки недоверенные. ФИО и контактный email поступают
через отдельный закрытый канал. Публичная заявка не служит доказательством
личности, а поле с самостоятельно указанным github_id не принимается как
доказательство владения поддоменом.
Один файл в records/ описывает один CNAME на одно одноуровневое имя:
subdomain: ivan-ivanov
type: CNAME
target: ivan123.github.io
repository: https://github.com/ivan123/my-lab-site
В MVP разрешены только ASCII-метки из латинских букв, цифр и дефиса, без
дефиса по краям; только CNAME на username.github.io, DNS only
(proxied=false). Список зарезервированных имён задаётся преподавателем.
Не принимаются пользовательские A/AAAA/MX/TXT, wildcard, вложенные поддомены
и URL вместо DNS-имени. Для subdomain валидатор принимает только нижний
регистр и метку длиной до 47 символов: вместе с .softdevtools.ru полное имя
получается короче 64 символов, что требуется GitHub Pages для HTTPS-сертификата.
Регистр GitHub-логина в target может быть любым; перед созданием DNS-записи
цель приводится к нижнему регистру.
Предпочтительный формат студенческого имени — imya-familiya, например
ivan-ivanov.softdevtools.ru: имя и фамилия записываются латиницей в нижнем
регистре, через дефис. При совпадении можно предложить свободный вариант с
числовым суффиксом, например ivan-ivanov-2. Публиковать реальные имя и
фамилию в адресе необязательно: студент может согласовать с преподавателем
псевдоним. Валидатор проверяет технический формат, а соответствие выбранного
имени договорённости и автору PR сверяет преподаватель.
Сопоставление target, владельца репозитория сайта и автора PR требует
отдельной проверки. Для уже принятого имени право изменения нужно закрепить
доверенными метаданными, которые студент не может назначить себе сам.
Точный формат этих метаданных пока не выбран; до его появления изменения
и удаление ранее принятых заявок не разрешаются автоматически.
Проверка должна давать конкретную причину отказа. Минимум:
target; ссылка на публичный репозиторий
сайта имеет ожидаемую форму.records/. Workflow,
скрипты, конфигурация и уже принятые заявки недоступны для студенческой
правки в этом процессе.Сообщения об ошибке адресованы студенту и написаны по-русски: что не так с
заявкой, где именно (файл и строка) и что сделать, без внутренних деталей
валидатора. Формулировки живут в scripts/messages.py, правила — в
scripts/validate.py и scripts/validate_pr.py; проверка ничего не
исправляет автоматически и не ослабляется ради понятности: неверные имена и
содержимое по-прежнему отклоняются. В GitHub Actions те же замечания
печатаются аннотациями (::error file=…,line=…) для файлов из PR, а полный
список попадает в сводку шага (GITHUB_STEP_SUMMARY): аннотаций на шаг не
больше десяти, поэтому сводка дублирует их полностью. Для заявок из fork
аннотации создаёт доверенный job validate-student-request на событии
pull_request_target.
Проверка синтаксиса и структуры должна выполняться без сети и секретов. Сетевые проверки GitHub Pages, DNS и HTTPS выполняются отдельно, когда публикация уже началась. Проверка PR не ставит студенту итоговую оценку.
Деплой запускается из main после принятия PR. Он повторно
валидирует доверенное состояние, сверяет запись с Cloudflare и создаёт либо
идемпотентно подтверждает только запись, которой управляет этот проект.
Чужие и созданные вручную записи не меняются и не удаляются. Удаление по
исчезновению YAML и полная синхронизация зоны в MVP не предусмотрены.
Cloudflare API Token хранится как GitHub Actions Secret или Environment
Secret и ограничен правом DNS Edit для одной зоны. Токен не попадает в
workflow проверки PR. Безопасность секретного workflow зависит также от защиты
ветки и контроля изменений кода: хранение токена в Secrets само по себе не
защищает от вредоносного workflow после merge. В публичном пилоте только
владелец имеет право записи в основной репозиторий. Перед
доступом студентов обязательна защита main и проверка сценария с fork.
Workflow apply-dns.yml получает событие закрытого PR в main только при
изменении records/*.yaml и выполняет работу лишь для слитого PR. Он берёт
доверенное состояние основной ветки, а не явный SHA из события PR: в
pull_request_target actions/checkout@v7 блокирует прямой checkout кода
fork. Студенческая ветка может менять только данные заявки, поэтому её код не
запускается с секретом. Сам секрет не выдаётся PR.
Шаг записи включён переменной репозитория
CLOUDFLARE_DNS_DEPLOY_ENABLED=true для закрытого пилота. Скрипт
apply_dns.py по умолчанию
лишь читает DNS и выводит план; --apply создаёт отсутствующие CNAME. Он
помечает свои записи комментарием Managed by denrad/softdevtools-dns,
проверяет все имена на конфликты до первой записи и не присваивает чужие
записи даже при совпадении имени и цели. При ошибке API после частичной записи
повторный запуск пропускает уже созданные им записи.
Подробный проект читающего workflow, повторных запусков и его проверок — в плане проверки сайтов. Ниже зафиксирована минимальная модель результата.
Проверяющий процесс хранит отдельные результаты:
| Проверка | Успех | Пока ожидается |
|---|---|---|
dns_live |
публичный CNAME равен ожидаемому | DNS ещё не виден через резолвер |
site_live |
HTTP или HTTPS отдаёт ожидаемый отличительный текст | Pages ещё не направляет имя на сайт |
https_live |
обычный HTTPS-запрос проверяет сертификат и текст | сертификат ещё выпускается |
Команда curl -k может помочь диагностировать страницу при ещё невалидном
сертификате, но не даёт статус https_live=passed. HTTP 200 без проверки
содержимого также недостаточен. Статусы результата: passed, failed,
pending, not_checked. Повторная проверка возможна без нового PR; расписание
не должно трактовать временную задержку DNS или сертификата как ошибку
студента.
На занятии достаточно подтвердить заявку, DNS и доступность именно нужной страницы по HTTP либо HTTPS. Валидный HTTPS проверяется позже. Итоговое понимание цепочки оценивает преподаватель.
main, reviews и
обязательных проверок; проверить их на тестовом fork после открытия.
На текущем GitHub Free эти правила недоступны, пока репозиторий приватный;
пилот уже применяет DNS, но приём заявок студентов до защиты ветки не начинать.Справка: GitHub Pages и Custom domain, подтверждение домена, Cloudflare: лимиты DNS.