Применимость: Cloud. Названия пунктов и доступность функций зависят от версии, плана и типа проекта. Проверяйте изменения на тестовом окружении. Описанные рабочие процедуры — предлагаемый подход, а не гарантии поставщика.
Задача: отчёт заканчивается после первой страницы
Интеграция получает HTTP 200, записывает найденные задачи в файл и сообщает об успехе. Однако читатель замечает, что часть ожидаемых ключей отсутствует. В учебном сценарии команда поддержки готовит реестр из тестового проекта DEMO. Нужно выгрузить весь согласованный набор, а не только первые несколько записей. Успех HTTP-запроса здесь подтверждает получение ответа, но не полноту отчёта.
Разделите работу на три результата: согласованная область поиска, завершённый обход страниц и проверенный выходной файл. До пилота составьте небольшой список ожидаемых ключей вручную. Возьмите обезличенные тестовые задачи, которые не будут редактировать во время сверки. Это предлагаемый порядок внедрения интеграции, а не рассказ о выполненном клиентском проекте. Не используйте содержимое рабочего проекта как открытые тестовые данные.
Применимость и предварительные условия
Далее используется Jira Cloud REST API v3 и enhanced search POST /rest/api/3/search/jql. У Cloud нет фиксированной версии установки. Старый /rest/api/3/search отмечен Atlassian как устаревающий и удаляемый; его схему со startAt нельзя механически переносить на новый поиск. Для Data Center проверьте отдельную документацию своей версии.
Подготовьте согласованную учётную запись интеграции и разрешённый способ авторизации. Результат ограничен правами просмотра проекта и уровней безопасности задач. Для разового скрипта Basic auth использует email и API-токен, а не пароль аккаунта; для интеграционного приложения оцените рекомендованный OAuth. Адрес API и разрешения настройте по выбранному способу доступа. Секреты храните вне кода и журналов. Не расширяйте права до администратора только ради совпадения числа строк с чужим отчётом.
Шаг 1. Зафиксируйте JQL и ожидаемый набор
Создайте пять тестовых задач в DEMO и запишите их ключи и внутренние ID в закрытый контрольный список. Дополнительно подготовьте одну задачу в другом проекте как отрицательный пример. Если проверяете уровни безопасности, используйте ещё одну безвредную задачу, недоступную учётной записи интеграции. Согласуйте ожидаемый результат именно для её прав.
Для первого запуска используйте project = DEMO ORDER BY key ASC. Замените DEMO на свой тестовый проект. Не начинайте с широкого запроса на весь сайт или подвижной выборки вроде «изменено за последние минуты». Зафиксируйте текст JQL, набор полей и условия пилота. В пользовательском интерфейсе сверяйте поиск тем же аккаунтом либо отдельно объясняйте разницу прав; результат администратора не является эталоном для обычного пользователя.
Шаг 2. Выполните первую страницу и продолжение
В настроенном REST-клиенте отправьте POST на путь /rest/api/3/search/jql с Content-Type: application/json и Accept: application/json. Для пилота запросите только key и задайте maxResults = 2, чтобы маленький набор потребовал несколько запросов. Первое тело показано ниже; авторизация в него не включается.
Из ответа передавайте nextPageToken следующему запросу без изменений, сохраняя JQL и поля. Не вычисляйте курсор из номера страницы и не заменяйте его startAt. Проверяйте признак завершения isLast; если ответ не финальный, но продолжения нет, считайте запуск неполным. Короткая страница сама по себе не является надёжным сигналом остановки.
{
"jql": "project = DEMO ORDER BY key ASC",
"fields": [
"key"
],
"maxResults": 2
}Шаг 3. Сделайте завершение явным в коде
Ниже пример функции на Python 3, которая собирает ID и ключи и возвращает результат только после финального ответа. fetch_page — функция вашего HTTP-клиента: она должна выполнить описанный POST, вернуть разобранный JSON и выбросить исключение при сетевой ошибке или неуспешном HTTP-статусе. Пример не содержит транспорта и сам по себе не подключается к Jira. Авторизацию, проверку TLS и таймаут задайте в клиенте.
Лимит страниц и остановка при повторном ID — защитные решения этого учебного примера, а не требование Atlassian. При нарушении условий результат нужно исследовать, а не молча объявлять полным. Для больших объёмов отдельно спроектируйте потоковую запись во временный файл: список в памяти предназначен для небольшого пилота. Размер 2 выбран для демонстрации; рабочий размер подберите по нагрузке и ограничениям операции.
def collect_pages(fetch_page, jql, max_pages=1000):
rows, ids, cursors = [], set(), set()
cursor = None
for _ in range(max_pages):
body = {"jql": jql, "fields": ["key"], "maxResults": 2}
if cursor is not None:
body["nextPageToken"] = cursor
data = fetch_page(body) # raises on HTTP/transport errors
issues = data.get("issues")
if not isinstance(issues, list):
raise ValueError("Missing issues list")
for issue in issues:
issue_id = str(issue["id"])
if issue_id in ids:
raise ValueError("Duplicate issue ID; review the run")
ids.add(issue_id)
rows.append({"id": issue_id, "key": issue["key"]})
if data.get("isLast") is True:
return rows
next_cursor = data.get("nextPageToken")
if not isinstance(next_cursor, str) or not next_cursor:
raise ValueError("No continuation token before final page")
if next_cursor in cursors:
raise ValueError("Repeated continuation token")
cursors.add(next_cursor)
cursor = next_cursor
raise ValueError("Page limit reached; result is incomplete")Шаг 4. Проверьте полноту до сохранения отчёта
Для пяти доступных задач и запрошенного размера 2 ожидайте переходов между несколькими страницами. Сравните итоговое множество ID и ключей с контрольным списком, а не только общее количество. Убедитесь, что нет повторов и задачи из чужого проекта. Недоступная по согласованной модели задача также не должна оказаться в выгрузке. Отдельно выполните запрос с заведомо пустой выборкой и проверьте корректное завершение.
Проверьте на локальных фикстурах ошибки протокола: ответ без issues, не финальный ответ без курсора, повторяющийся курсор и повторный ID. Смоделируйте сбой HTTP-клиента на второй странице. Ни один такой запуск не должен подменять предыдущий принятый отчёт. Сохраняйте новый файл сначала под временным именем и заменяйте рабочий только после полной сверки. Эти проверки не подтверждают работоспособность конкретной авторизации или права в вашей Jira.
Шаг 5. Отделите обход страниц от актуальности поиска
Даже правильная пагинация не гарантирует, что недавно изменённая задача уже отразилась в поиске. Atlassian описывает отсутствие read-after-write consistency по умолчанию. Поэтому отсутствие только что созданной или изменённой позиции нельзя сразу исправлять увеличением числа страниц. Сначала проверьте саму задачу, JQL и задержку отражения изменения.
Для известного небольшого набора недавно изменённых задач документация предлагает reconcileIssues: параметр принимает до 50 ID и обеспечивает более сильную согласованность только для указанных задач, если они соответствуют поиску. Это не способ превратить весь экспорт в неизменяемый снимок сайта. Для важного отчёта согласуйте период спокойных данных и повторную сверку контрольного набора. Не обещайте полноту исторического среза, если во время выгрузки менялись состав выборки и права.
Ошибки и безопасная диагностика
При HTTP 400 проверьте JQL и схему запроса; при 401 — выбранную авторизацию. Если ожидаемая задача отсутствует при успешном ответе, проверьте её доступность и принадлежность выборке. Обработку 429 и временных серверных ошибок вынесите в транспорт с ограниченным числом попыток. Не возвращайте пустой словарь из обработчика исключения: так ошибка превратится в видимость нормального пустого отчёта.
В рабочем журнале достаточно записывать идентификатор запуска, число полученных страниц и уникальных ID, состояние завершения и безопасный код ошибки. Не печатайте Authorization, API-токен, весь ответ сервера или полные описания задач. При повторном запуске начинайте новый обход с неизменным согласованным запросом; сохранённый курсор не считайте долговечным механизмом восстановления без отдельной проверки контракта API.
Откат и передача в сопровождение
Эта процедура читает задачи и не изменяет их. При сбое остановите расписание выгрузки и сохраните последний принятый отчёт. Не удаляйте задачи и не меняйте права ради восстановления экспорта. Если новая версия клиента дала неполный результат, верните предыдущую согласованную версию и выполните пилот заново. Возврат к удаляемому endpoint не следует считать устойчивым планом отката.
Передайте владельцу интеграции JQL, правила доступа, контрольные примеры, лимиты запуска и порядок проверки выходного файла. Укажите, какие поля разрешено экспортировать и кто получает результат. Добавьте отдельный сигнал о незавершённом обходе. Критерий готовности — проверенная выдача для согласованной аудитории и явный отказ при частичном результате; количество успешных HTTP-запросов само по себе этот критерий не заменяет.
Официальная документация
Применить это к вашей системе
Обсудим контекст, ограничения и безопасный порядок изменений.
Обсудить задачу