Перейти к содержанию

Интеграция Jira и n8n: создание issue, webhooks, JQL-поиск и защита от дублей

Обновлено: 2026-05-30

AI summary: Problem/Solution-гайд по Jira и n8n: как создавать и обновлять Jira issues из внешних событий без дублей, неверных transitions и потери контекста для инженерной команды.
Готовый blueprint для внедрения

Импортируйте JSON в n8n, замените credentials, URL API, project/list IDs, поля и лимиты под вашу инфраструктуру.

Проблема: Jira требует строгих project key, issue type, transitions и custom fields. Если отправлять в неё сырые события из CRM, мониторинга или формы, команда получает дубли, неправильные статусы и задачи без воспроизводимого контекста.

Решение: Используйте n8n как issue router: валидируйте project и issue type, собирайте summary/description, ищите дубль через JQL/external_id и применяйте transitions только по разрешённым правилам.

Схема интеграции Jira и n8n для issue automation, JQL-поиска и дедупликации
Схема показывает проверку mapping, поиск дубля через JQL и создание или обновление issue.

Проблема: почему простая интеграция создаёт дубли и ручной хаос

Jira часто принимает события из мониторинга, поддержки, релизов и клиентских форм. Но простой HTTP Request к create issue не решает главную задачу: инженеру нужен воспроизводимый контекст, severity, environment, owner, ссылка на исходное событие и история повторов.

Без JQL-поиска и external_id один инцидент может создать десятки issues. Без контроля transitions автоматизация переводит задачу в статус, который недоступен для текущего workflow. Поэтому integration layer должен быть строгим и предсказуемым.

Архитектура workflow для n8n

БлокЗадачаProduction-проверка
Webhook issue eventпринимает incident, bug report или support escalationsource, entity_id, severity
Validate Jira mappingпроверяет project key, issue type и fieldsнет случайного project
Build issue payloadсобирает summary, description и labelsADF/plain text, environment, source_url
Find duplicate via JQLищет issue по external_id/labelsдо create issue
Create/update issueсоздаёт issue или добавляет commentallowed transitions
Respond and alertвозвращает статус и ссылкуissue_key, DLQ, owner

Для инцидентов лучше обновлять existing issue и добавлять комментарий с новым событием, чем создавать отдельный issue на каждый alert.

Контракт входных данных

{
  "source": "monitoring",
  "event_type": "api_error_rate_high",
  "entity_id": "incident-2026-05-30-1042",
  "project_key": "OPS",
  "issue_type": "Bug",
  "summary": "Высокий процент ошибок API оплаты",
  "description": "5xx > 8% за 10 минут на payment API",
  "severity": "critical",
  "environment": "production",
  "service": "payment-api",
  "source_url": "https://monitoring.example.ru/incidents/1042"
}

project_key и issue_type должны приходить из allowlist, а не из произвольной формы. Это защищает Jira от задач в неправильном проекте.

Code Node: нормализация, mapping и guard-условия

const src = $json.body ?? $json;
const allowedProjects = ['OPS', 'WEB', 'CRM'];
const projectKey = String(src.project_key ?? 'OPS').trim().toUpperCase();
if (!allowedProjects.includes(projectKey)) throw new Error(`Project is not allowed: ${projectKey}`);
const issueType = String(src.issue_type ?? 'Task').trim();
const allowedTypes = ['Bug', 'Task', 'Incident'];
if (!allowedTypes.includes(issueType)) throw new Error(`Issue type is not allowed: ${issueType}`);
const entityId = String(src.entity_id ?? '').trim();
if (!entityId) throw new Error('No entity_id for Jira issue');
const severity = String(src.severity ?? 'medium').toLowerCase();
const externalId = `jira-router:${src.source ?? 'external'}:${entityId}`;
const summary = String(src.summary ?? src.title ?? 'External event').trim().slice(0, 180);
const description = [String(src.description ?? '').trim(), '', `Source: ${src.source ?? 'external'}`, `Entity: ${entityId}`, `Service: ${src.service ?? 'n/a'}`, `Environment: ${src.environment ?? 'n/a'}`, `URL: ${src.source_url ?? ''}`].join('\n');
const jql = `project = ${projectKey} AND labels = "external-sync" AND text ~ "${externalId}" ORDER BY created DESC`;
return [{ json: { external_id: externalId, jql, issue: { fields: { project: { key: projectKey }, issuetype: { name: issueType }, summary, description, labels: ['external-sync', `severity-${severity}`] } }, comment: `Repeated event for ${externalId}`, allowed_transition: severity === 'critical' ? 'Escalate' : 'Triage' }}];
Почему JQL-поиск нужен до create issue

Jira не знает ваш внешний incident_id. Если не искать существующий issue по external_id, повтор webhook создаст новый ticket и размажет историю инцидента по нескольким задачам.

Готовый workflow JSON: скачать и импортировать

Скачать готовый workflow JSON Скачать тестовый payload

{
  "name": "Nodbot - Jira issue router with JQL dedupe",
  "nodes": [
    {
      "name": "Webhook issue input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять событие"
    },
    {
      "name": "Validate and build Jira issue",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить mapping и собрать payload"
    },
    {
      "name": "Find duplicate via JQL",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Найти существующий issue"
    },
    {
      "name": "Create or update issue",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Создать issue или comment"
    },
    {
      "name": "Apply safe transition",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Выполнить разрешённый transition"
    },
    {
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть issue key"
    }
  ],
  "connections": "Webhook issue input → Validate and build Jira issue → Find duplicate via JQL → Create or update issue → Apply safe transition → Respond"
}

Пошаговая настройка связки

  1. Опишите allowlist project_key и issue_type.
  2. Создайте labels/custom fields для external_id, severity и source.
  3. Импортируйте workflow JSON и замените Jira base URL, email/API token или OAuth.
  4. Настройте JQL-поиск дублей до create issue.
  5. Проверьте transitions на тестовом project workflow.

Тесты перед production

curl -X POST "https://YOUR-N8N-DOMAIN/webhook/integration-jira-n8n-issue-router" \
  -H "Content-Type: application/json" \
  --data @integration-jira-n8n-issue-router-payload.json
  1. Повтор entity_id добавляет комментарий к existing issue.
  2. Недопустимый project_key останавливается до API-запроса.
  3. Critical severity попадает в правильный label/transition.
  4. JQL не ломается на специальных символах во внешнем ID.
  5. Ошибка Jira API уходит в DLQ с payload без токенов.

Production-риски

  • Project key приходит из формы. Пользователь может создать issue не в том проекте.
  • Нет JQL-дедупликации. Один инцидент создаёт много tickets.
  • Transitions вызываются без проверки. Jira вернёт ошибку или переведёт задачу не туда.
  • Описание без контекста. Инженер не видит service, environment и source_url.
  • Секреты в comment. Stack trace может содержать токены.
Карточка результата Jira issue router с issue key, severity и JQL dedupe
Пример результата: инцидент привязан к одному Jira issue и содержит полный контекст.

Критерии готовности

  1. Project key и issue type проходят allowlist.
  2. JQL-поиск дублей выполняется до create issue.
  3. Summary короткий, а description содержит source_url, service и environment.
  4. Transitions выполняются только по разрешённым правилам.
  5. Ошибки Jira API логируются и попадают в alert/DLQ.
Нужна Jira-автоматизация без дублей?

Nodbot настроит Jira + n8n: issue router, JQL-дедупликацию, transitions, labels/custom fields, Slack-алерты и безопасный DLQ.

Обсудить Jira-интеграцию