Linear 连接器
通过 Tajo 将您的 Linear 工作区连接到 Brevo,实现面向客户的 Issue 跟踪、产品更新通知和开发里程碑活动。
概览
| 属性 | 值 |
|---|---|
| 平台 | Linear |
| 类别 | 自定义 |
| 设置复杂度 | 简单 |
| 官方集成 | 否 |
| 同步数据 | Issue、项目、用户、事件 |
| API 类型 | GraphQL API |
| 认证方式 | OAuth 2.0 / 个人 API 密钥 |
| 基础 URL | https://api.linear.app/graphql |
功能
- Issue 事件同步 - 将 Issue 创建、更新和完成事件转发到 Brevo 联系人时间线
- 项目里程碑跟踪 - 当项目达到关键里程碑时触发 Brevo 活动
- 客户 Issue 关联 - 将 Linear Issue 与 Brevo 联系人关联,提供支持可见性
- 基于标签的细分 - 将 Linear 标签映射到 Brevo 联系人属性
- 周期分析 - 同步冲刺/周期完成数据,用于团队绩效报告
- Webhook 驱动自动化 - 通过 Linear Webhook 实现实时事件转发
前提条件
开始之前,请确保您已具备:
- 具有管理员权限的 Linear 工作区
- 已配置个人 API 密钥或 OAuth 应用
- 具有 API 访问权限的 Brevo 账户
- 具有有效订阅的 Tajo 账户
认证
Linear 支持个人 API 密钥和 OAuth 2.0。
选项 1:个人 API 密钥
- 前往 Linear > 设置 > API > 个人 API 密钥
- 点击创建密钥
- 命名为”Tajo Integration”
- 复制生成的密钥(以
lin_api_开头)
curl -X POST https://api.linear.app/graphql \ -H "Authorization: $LINEAR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "{ viewer { id name email } }"}'选项 2:OAuth 2.0
适用于服务多个工作区的集成:
- 在 linear.app/settings/api/applications 创建 OAuth 应用
- 配置重定向 URI:
https://app.tajo.io/callbacks/linear - 请求范围:
read、write、issues:create、comments:create
GraphQL API
Linear 专用 GraphQL API。所有查询和变更均通过单一端点进行:https://api.linear.app/graphql。Tajo 自动处理所有 GraphQL 查询构建。
连接到 Tajo
# Using Personal API Keytajo connectors install linear \ --api-key $LINEAR_API_KEY
# Using OAuthtajo connectors install linear \ --client-id $LINEAR_CLIENT_ID \ --client-secret $LINEAR_CLIENT_SECRET配置
基础设置
connectors: linear: enabled: true
sync: issues: true projects: true cycles: true users: true
teams: - key: "ENG" sync_to_list: 38 - key: "SUPPORT" sync_to_list: 39
issue_states: - Backlog - Todo - "In Progress" - Done - Canceled字段映射
将 Linear 用户和 Issue 数据映射到 Brevo 属性:
field_mapping: # User fields id: LINEAR_USER_ID email: email name: FIRSTNAME
# Issue metrics mapped to contact events last_issue_identifier: LAST_LINEAR_ISSUE last_issue_state: LAST_ISSUE_STATUS last_issue_priority: LAST_ISSUE_PRIORITY total_issues: LINEAR_ISSUE_COUNT
# Project data current_project: ACTIVE_PROJECT team_key: LINEAR_TEAM事件映射
event_mapping: Issue.create: ISSUE_CREATED Issue.update: ISSUE_UPDATED Issue.remove: ISSUE_DELETED Comment.create: COMMENT_ADDED Project.update: PROJECT_UPDATED Cycle.update: CYCLE_UPDATEDAPI 端点
Linear 使用单一 GraphQL 端点。Tajo 使用的主要查询和变更:
| 操作 | 类型 | 用途 |
|---|---|---|
issues | 查询 | 列出和过滤 Issue |
issue | 查询 | 按 ID 获取单个 Issue |
projects | 查询 | 列出所有项目 |
cycles | 查询 | 列出周期(冲刺) |
teams | 查询 | 列出工作区团队 |
users | 查询 | 列出工作区成员 |
viewer | 查询 | 获取已认证用户信息 |
issueCreate | 变更 | 创建新 Issue |
issueUpdate | 变更 | 更新现有 Issue |
commentCreate | 变更 | 向 Issue 添加评论 |
webhookCreate | 变更 | 注册 Webhook |
GraphQL 查询示例
query GetIssues($filter: IssueFilter, $first: Int, $after: String) { issues(filter: $filter, first: $first, after: $after) { nodes { id identifier title state { name } priority assignee { email name } labels { nodes { name } } createdAt updatedAt } pageInfo { hasNextPage endCursor } }}代码示例
初始化连接器
import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({ apiKey: process.env.TAJO_API_KEY, brevoApiKey: process.env.BREVO_API_KEY});
await tajo.connectors.connect('linear', { apiKey: process.env.LINEAR_API_KEY});同步 Issue
await tajo.connectors.sync('linear', { type: 'incremental', resources: ['issues'], teams: ['ENG', 'SUPPORT'], since: '2024-01-01'});
const status = await tajo.connectors.status('linear');console.log(status);// {// connected: true,// lastSync: '2024-03-15T18:00:00Z',// issuesTracked: 3200,// projectsMonitored: 8,// usersLinked: 45// }处理 Linear Webhook
app.post('/webhooks/linear', async (req, res) => { const event = req.body;
// Verify webhook signature const signature = req.get('Linear-Signature'); if (!verifyLinearSignature(req.body, signature)) { return res.status(401).send('Unauthorized'); }
await tajo.connectors.handleWebhook('linear', { type: event.type, action: event.action, payload: { issueId: event.data?.id, identifier: event.data?.identifier, title: event.data?.title, state: event.data?.state?.name, assigneeEmail: event.data?.assignee?.email } });
res.status(200).send('OK');});从 Brevo 事件创建 Issue
// Create a Linear issue when a Brevo contact submits a requesttajo.events.on('contact.event', async (event) => { if (event.name === 'FEATURE_REQUEST') { await tajo.connectors.create('linear', { teamId: 'ENG', title: `Feature Request: ${event.data.subject}`, description: event.data.description, priority: 3, labelIds: ['feature-request'] }); }});速率限制
Linear 对其 GraphQL API 实施速率限制:
| 限制类型 | 值 |
|---|---|
| 请求速率 | 每 API 密钥每小时 1,500 个请求 |
| 查询复杂度 | 每请求 10,000 复杂度点 |
| 分页 | 每页最多 250 个节点(默认 50) |
| Webhook | 无限制传入事件 |
复杂度预算
Linear 使用基于复杂度的速率限制系统。简单查询消耗的点数更少。Tajo 通过只请求必要字段和使用高效分页来优化查询以最小化复杂度。
超出限制时,Linear 返回 429 Too Many Requests 并附带 Retry-After 头部。
故障排除
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 401 Unauthorized | API 密钥无效或已撤销 | 在 Linear 设置中生成新 API 密钥 |
| 查询错误 | GraphQL 语法无效 | 使用 Linear 的 API 资源管理器验证查询 |
| Issue 缺失 | 团队访问受限 | 确保 API 密钥所有者有访问目标团队的权限 |
| Webhook 未触发 | URL 不正确或已禁用 | 在 Linear 设置 > API > Webhooks 中检查 Webhook 状态 |
| 分页不完整 | 缺少 after 游标 | 确保分页循环直到 hasNextPage 为 false |
调试模式
connectors: linear: debug: true log_level: verbose log_queries: true测试连接
tajo connectors test linear# ✓ GraphQL API connection successful# ✓ Workspace access verified# ✓ Team list readable# ✓ Issue query operational# ✓ Webhook registration available最佳实践
- 使用 Webhook 实现实时 - 注册 Webhook 而非轮询 Issue 变更
- 按团队过滤 - 只同步相关团队的 Issue 以减少 API 使用
- 优化 GraphQL 查询 - 只请求所需字段以保持在复杂度限制内
- 将标签映射到细分 - 使用 Linear 标签驱动 Brevo 联系人细分
- 处理分页 - 始终检查
hasNextPage并使用endCursor获取完整数据 - 验证 Webhook 签名 - 始终验证
Linear-Signature头部
安全
- API 密钥认证 - 限定到工作区的个人密钥
- OAuth 2.0 - 多工作区集成的安全授权流程
- 仅 HTTPS - 所有 API 通信通过 TLS 1.2+ 加密
- Webhook 签名 - 基于 HMAC 的签名验证
- 加密存储 - API 密钥在 Tajo 中静态加密
- SOC 2 合规 - Linear 平台通过 SOC 2 Type II 认证