Как программно создать заявку (Issue) на GitHub с картинками и вложениями из 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Интеграция систем 1С с внешними сервисами управления задачами, такими как GitHub, является востребованной задачей для автоматизации технической поддержки и баг-трекинга. Однако при реализации этой функции разработчики часто сталкиваются с тем, что стандартный REST API GitHub для создания заявок (Issues) принимает только текстовую информацию в формате Markdown. Прямого метода для загрузки бинарных данных (картинок или файлов) непосредственно в тело заявки через публичный API не существует.

В этой статье мы разберем, как обойти это ограничение, используя возможности платформы 1С для работы с HTTP-запросами, и реализуем надежную схему публикации заявок с вложениями.

Анализ проблемы и выбор архитектуры решения

Рассмотрим стандартный механизм работы GitHub. Когда пользователь вручную прикрепляет скриншот к тикету в браузере, GitHub использует внутренний недокументированный API, который взаимодействует с облачным хранилищем. Попытка повторить этот процесс из кода 1С крайне трудозатратна, так как требует эмуляции сессии браузера и обработки CSRF-токенов.

Вместо этого мы проанализируем и внедрим легальный программный путь, состоящий из двух этапов:

  1. Загрузка файла в специальный репозиторий (или папку основного репозитория) с использованием Repository Contents API.
  2. Создание заявки, в тексте которой содержится ссылка на загруженный файл в формате Markdown.

Шаг 1: Подготовка файла и авторизация

Для взаимодействия с GitHub нам потребуется персональный токен доступа (PAT) с правами contents:write и issues:write. В 1С для авторизации мы будем использовать заголовок Authorization со значением Bearer.

Выясним, как подготовить файл для передачи. GitHub API требует, чтобы содержимое файла было закодировано в Base64. Разберем пример формирования заголовков и преобразования данных в 1С:


// Подготовка данных файла
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
СтрокаBase64 = Base64Строка(ДвоичныеДанныеФайла);
// Удаление лишних символов переноса строки, которые может добавить Base64Строка
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ВК, "");

// Формирование заголовков запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступа);
Заголовки.Вставить("Accept", "application/vnd.github+json");
Заголовки.Вставить("Content-Type", "application/json");

Шаг 2: Загрузка изображения в репозиторий

Для загрузки файла мы используем метод PUT /repos/{owner}/{repo}/contents/{path}. Важно понимать, что путь к файлу должен быть уникальным, чтобы избежать конфликтов. Рекомендуется использовать временные папки или добавлять метку времени (GUID) к имени файла.

Рассмотрим структуру JSON-тела запроса для загрузки:


СтруктураТела = Новый Структура;
СтруктураТела.Вставить("message", "Upload attachment for issue");
СтруктураТела.Вставить("content", СтрокаBase64);
СтруктураТела.Вставить("branch", "main"); // Укажите вашу ветку

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураТела);
ТелоЗапроса = ЗаписьJSON.Закрыть();

После отправки этого запроса через HTTPСоединение, GitHub вернет ответ, содержащий параметр download_url. Это прямая ссылка на файл, которую мы будем использовать в дальнейшем. Однако для корректного отображения картинок в теле заявки лучше формировать ссылку самостоятельно, используя домен raw.githubusercontent.com.

Шаг 3: Формирование текста заявки с использованием Markdown

Теперь, когда у нас есть ссылка на файл, мы можем создать саму заявку. Текст описания (body) должен быть сформирован с учетом синтаксиса Markdown. Разберем ситуацию: если мы загрузили картинку, нам нужно обернуть ссылку в тег ![Описание](ссылка). Если это документ (например, лог-файл), достаточно обычной ссылки.

Проанализируем пример формирования текста заявки:


СсылкаНаФайл = "https://raw.githubusercontent.com/Пользователь/Репозиторий/main/assets/image_2023.png";
ТекстОписания = "Обнаружена ошибка при проведении документа. " + Символы.ПС;
ТекстОписания = ТекстОписания + "Скриншот ошибки: " + Символы.ПС;
ТекстОписания = ТекстОписания + "![Скриншот](" + СсылкаНаФайл + ")";

СтруктураIssue = Новый Структура;
СтруктураIssue.Вставить("title", "Ошибка проведения документа №123");
СтруктураIssue.Вставить("body", ТекстОписания);

Шаг 4: Итоговая отправка заявки

Завершающим этапом является отправка POST-запроса к ресурсу /repos/{owner}/{repo}/issues. Обратите внимание на кодировку: при работе с 1С обязательно убедитесь, что JSON передается в кодировке UTF-8 без BOM, иначе API может вернуть ошибку валидации данных.

Посмотрим на пример кода для выполнения итогового запроса:


ЗапросIssue = Новый HTTPЗапрос("/repos/" + Владелец + "/" + ИмяРепозитория + "/issues", Заголовки);
ЗапросIssue.УстановитьТелоИзСтроки(ТелоJSONIssue, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Соединение = Новый HTTPСоединение("api.github.com", 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL());
Ответ = Соединение.ОтправитьДляОбработки(ЗапросIssue);

Если Ответ.КодСостояния = 201 Тогда
    Сообщить("Заявка успешно создана!");
Иначе
    Сообщить("Ошибка: " + Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;

Важные технические нюансы

При реализации данного алгоритма следует учитывать несколько критически важных моментов:

  1. Лимиты API: GitHub ограничивает количество запросов в час. Используйте авторизацию через токен, чтобы увеличить эти лимиты.
  2. Очистка репозитория: Если вы часто прикрепляете файлы, ваш репозиторий будет расти в объеме. Подумайте о периодической очистке папки с временными вложениями через тот же API (метод DELETE для содержимого).
  3. Безопасность: Никогда не храните токены доступа в открытом коде. Используйте защищенные константы или параметры сеанса.
  4. Альтернативные хостинги: Если политика безопасности компании позволяет, вы можете упростить схему, предварительно загружая изображения на сторонние хостинги с простым API (например, Imgur или собственное S3-хранилище), передавая в GitHub только готовую ссылку.

Подведем итог: несмотря на отсутствие прямой функции «прикрепить файл» в API заявок GitHub, связка Repository Contents API и разметки Markdown позволяет полностью автоматизировать процесс создания информативных тикетов с вложениями напрямую из 1С.

← На главную