Интеграция Linear и n8n: issues, webhooks и безопасный routing ¶
Обновлено: 2026-05-30
Импортируйте JSON в n8n, замените credentials, URL API, project/list IDs, поля и лимиты под вашу инфраструктуру.
Проблема: Linear удобен для инженерной команды, но не любит “сырые” события из форм, CRM и мониторинга: без team mapping, labels и дедупликации issues быстро становятся мусором.
Решение: Используйте n8n как issue router для Linear: валидируйте team и project, собирайте GraphQL mutation, ищите existing issue по external_id и обновляйте comment/labels вместо создания дубля.
Проблема: почему простая интеграция создаёт дубли и ручной хаос ¶
Linear обычно внедряют там, где команде важна скорость: баги из поддержки, feature request из CRM, инциденты из мониторинга, product feedback из формы. Если каждый источник создаёт issue напрямую, backlog загрязняется задачами без owner, priority и воспроизводимого контекста.
Надёжная настройка Linear и n8n должна решать не только “создать issue”. Нужно контролировать team_id, project_id, priority, labels, source_url, actor, environment и повторные события. Это снижает ручной triage и помогает инженерной команде доверять автоматизации.
Архитектура workflow для n8n ¶
| Блок | Задача | Production-проверка |
|---|---|---|
| Webhook product event | принимает bug, feature request или incident | source, entity_id, event_type |
| Validate Linear mapping | проверяет team_id, project_id и priority | allowlist команд и проектов |
| Build GraphQL payload | собирает mutation для Linear API | title, description, labels, assignee |
| Find existing issue | ищет issue по external_id | до создания нового issue |
| Create/update issue | создаёт issue или добавляет comment | без потери labels и priority |
| Respond / notify | возвращает issue identifier | alert на API-ошибки |
Для Linear важно заранее договориться, какие внешние события становятся issue, а какие только комментарием к существующему issue. Иначе backlog заполняется повторными “сигналами”, а не задачами.
Контракт входных данных ¶
{
"source": "support",
"event_type": "bug_report",
"entity_id": "case-9102",
"title": "Ошибка оплаты при повторной попытке",
"description": "Пользователь получает 500 после retry платежа",
"team_key": "PAY",
"project_key": "checkout-stability",
"priority": "urgent",
"labels": [
"bug",
"payment",
"customer-report"
],
"source_url": "https://support.example.ru/cases/9102",
"customer_impact": "Платёж не завершается у 12 клиентов"
}team_key и priority должны проходить allowlist. Нельзя отдавать пользователю формы право создавать задачи в любой engineering team.
Code Node: нормализация, mapping и guard-условия ¶
const src = $json.body ?? $json;
const teams = { PAY: 'linear-team-payments', WEB: 'linear-team-web' };
const priorities = { urgent: 1, high: 2, medium: 3, low: 4 };
const teamKey = String(src.team_key ?? 'WEB').trim().toUpperCase();
if (!teams[teamKey]) throw new Error(`Linear team is not allowed: ${teamKey}`);
const entityId = String(src.entity_id ?? '').trim();
if (!entityId) throw new Error('No entity_id for Linear issue');
const priorityKey = String(src.priority ?? 'medium').toLowerCase();
const externalId = `linear-router:${src.source ?? 'external'}:${entityId}`;
const labels = Array.isArray(src.labels) ? src.labels.map(String).slice(0, 8) : [];
const title = String(src.title ?? 'External issue').trim().slice(0, 180);
const description = [String(src.description ?? '').trim(), '', `External ID: ${externalId}`, `Source: ${src.source ?? 'external'}`, `Impact: ${src.customer_impact ?? 'n/a'}`, `URL: ${src.source_url ?? ''}`].join('
');
return [{ json: {
external_id: externalId,
find_query: externalId,
mutation: {
teamId: teams[teamKey],
title,
description,
priority: priorities[priorityKey] ?? 3,
labels,
projectKey: src.project_key ?? null
},
comment: `Повторное событие для ${externalId}`
}}];
Почему Linear GraphQL лучше закрывать шаблоном
GraphQL mutation гибкая, но ломкая для ручных правок. Шаблон в Code Node фиксирует обязательные поля, mapping команд и формат description, чтобы разные источники не создавали разные структуры issues.
Готовый workflow JSON: скачать и импортировать ¶
Скачать готовый workflow JSON Скачать тестовый payload
{
"name": "Nodbot - Linear issue router with GraphQL dedupe",
"nodes": [
{
"name": "Webhook Linear event",
"type": "n8n-nodes-base.webhook",
"purpose": "Принять событие"
},
{
"name": "Validate Linear mapping",
"type": "n8n-nodes-base.code",
"purpose": "Проверить team/project/priority"
},
{
"name": "Find existing Linear issue",
"type": "n8n-nodes-base.httpRequest",
"purpose": "Найти issue по external_id"
},
{
"name": "Create or update Linear issue",
"type": "n8n-nodes-base.httpRequest",
"purpose": "Создать issue или comment"
},
{
"name": "Notify owner",
"type": "n8n-nodes-base.httpRequest",
"purpose": "Сообщить ссылку на issue"
},
{
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"purpose": "Вернуть identifier"
}
],
"connections": "Webhook Linear event → Validate Linear mapping → Find existing Linear issue → Create or update Linear issue → Notify owner → Respond"
}
Пошаговая настройка связки ¶
- Опишите mapping team_key → Linear team ID и project_key → project.
- Создайте labels для источников и severity.
- Импортируйте workflow JSON и замените Linear API token.
- Настройте поиск existing issue по external_id до create mutation.
- Проверьте тестовые события с разным priority и повторным entity_id.
Тесты перед production ¶
curl -X POST "https://YOUR-N8N-DOMAIN/webhook/integration-linear-n8n-issue-router" \
-H "Content-Type: application/json" \
--data @integration-linear-n8n-issue-router-payload.json- Повторный payload не создаёт дубль и возвращает тот же output key.
- Некорректный mapping останавливается до запроса к внешнему API.
- Пустые необязательные поля не ломают workflow.
- Ошибка API уходит в alert или DLQ с безопасным payload.
- Execution data не содержит секретов, токенов и лишних персональных данных.
Production-риски ¶
- team_id задаётся из внешнего payload. Событие может попасть в неправильную команду.
- Каждый alert создаёт issue. Инцидент размазывается по backlog вместо одного issue с комментариями.
- Priority не нормализован. Срочные клиентские ошибки становятся обычными задачами.
- GraphQL error игнорируется. Workflow отвечает 200, но issue не создан.
- Нет ссылки на источник. Инженер не может открыть case, alert или CRM-сущность.
Полезные ссылки и смежные материалы ¶
- Linear API and Webhooks
- Linear GraphQL API
- n8n Webhook node
- GitHub automation
- Webhook idempotency to Postgres
Критерии готовности ¶
- team_key и project_key проходят allowlist.
- external_id сохраняется в issue description или custom workflow-поле.
- Повтор entity_id добавляет comment, а не создаёт duplicate issue.
- GraphQL errors попадают в alert и не маскируются под successful run.
- Issue содержит source_url, impact и понятный priority.
Nodbot настроит Linear + n8n: GraphQL mutation, team mapping, дедупликацию, labels, source links и алерты для engineering workflow.
Обсудить Linear-интеграцию