Интеграция систем 1С с внешними сервисами управления задачами, такими как GitHub, является востребованной задачей для автоматизации технической поддержки и баг-трекинга. Однако при реализации этой функции разработчики часто сталкиваются с тем, что стандартный REST API GitHub для создания заявок (Issues) принимает только текстовую информацию в формате Markdown. Прямого метода для загрузки бинарных данных (картинок или файлов) непосредственно в тело заявки через публичный API не существует.
В этой статье мы разберем, как обойти это ограничение, используя возможности платформы 1С для работы с HTTP-запросами, и реализуем надежную схему публикации заявок с вложениями.
Рассмотрим стандартный механизм работы GitHub. Когда пользователь вручную прикрепляет скриншот к тикету в браузере, GitHub использует внутренний недокументированный API, который взаимодействует с облачным хранилищем. Попытка повторить этот процесс из кода 1С крайне трудозатратна, так как требует эмуляции сессии браузера и обработки CSRF-токенов.
Вместо этого мы проанализируем и внедрим легальный программный путь, состоящий из двух этапов:
Для взаимодействия с 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");
Для загрузки файла мы используем метод 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.
Теперь, когда у нас есть ссылка на файл, мы можем создать саму заявку. Текст описания (body) должен быть сформирован с учетом синтаксиса Markdown. Разберем ситуацию: если мы загрузили картинку, нам нужно обернуть ссылку в тег . Если это документ (например, лог-файл), достаточно обычной ссылки.
Проанализируем пример формирования текста заявки:
СсылкаНаФайл = "https://raw.githubusercontent.com/Пользователь/Репозиторий/main/assets/image_2023.png";
ТекстОписания = "Обнаружена ошибка при проведении документа. " + Символы.ПС;
ТекстОписания = ТекстОписания + "Скриншот ошибки: " + Символы.ПС;
ТекстОписания = ТекстОписания + "";
СтруктураIssue = Новый Структура;
СтруктураIssue.Вставить("title", "Ошибка проведения документа №123");
СтруктураIssue.Вставить("body", ТекстОписания);
Завершающим этапом является отправка 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 Тогда
Сообщить("Заявка успешно создана!");
Иначе
Сообщить("Ошибка: " + Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;
При реализации данного алгоритма следует учитывать несколько критически важных моментов:
Подведем итог: несмотря на отсутствие прямой функции «прикрепить файл» в API заявок GitHub, связка Repository Contents API и разметки Markdown позволяет полностью автоматизировать процесс создания информативных тикетов с вложениями напрямую из 1С.