blob: e52b4527176efa68d2b3ea8343b7aef0d100552b [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
# Linear
## Summary
This plugin collects data from [Linear](https://linear.app) through its
[GraphQL API](https://linear.app/developers/graphql) and maps it into DevLake's
standardized `ticket` domain, so Linear issues appear in DevLake dashboards
(throughput, lead/cycle time, sprint burndown, etc.).
The selectable **scope** is a Linear **Team**, which maps to a domain `Board`.
## Supported data
| Linear entity | Tool-layer table | Domain-layer table |
|-----------------|-----------------------------------|--------------------------------------------|
| Team | `_tool_linear_teams` (scope) | `boards` |
| User | `_tool_linear_accounts` | `accounts` |
| Workflow state | `_tool_linear_workflow_states` | (drives issue status mapping) |
| Issue | `_tool_linear_issues` | `issues`, `board_issues` |
| Label | `_tool_linear_issue_labels` | `issue_labels` |
| Comment | `_tool_linear_comments` | `issue_comments` |
| Cycle | `_tool_linear_cycles` | `sprints`, `board_sprints`, `sprint_issues`|
| Issue history | `_tool_linear_issue_history` | `issue_changelogs` |
### Field mapping highlights
- **Status** — derived deterministically from Linear's `WorkflowState.type`
(no manual mapping needed, unlike Jira):
- `backlog`, `unstarted` → `TODO`
- `started` → `IN_PROGRESS`
- `completed`, `canceled` → `DONE`
- **Priority** — Linear's integer priority maps to a label: `0` No priority,
`1` Urgent, `2` High, `3` Medium, `4` Low.
- **Type** — Linear has no native issue type, so issues default to `REQUIREMENT`.
- **Lead time** — `completedAt − createdAt` (Linear provides `startedAt`/`completedAt`
natively; the history changelog captures every status transition).
- **Story points** — Linear's `estimate`.
## Authentication
The plugin uses a Linear **personal API key**, passed verbatim in the
`Authorization` header (no `Bearer` prefix). Create one under
**Settings → Security & access → Personal API keys** in Linear.
## Configuration
Create a connection:
```
curl 'http://localhost:8080/api/plugins/linear/connections' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "linear",
"endpoint": "https://api.linear.app/graphql",
"token": "<YOUR_LINEAR_API_KEY>",
"rateLimitPerHour": 1500
}'
```
Add a team scope (the team id is the Linear team UUID):
```
curl 'http://localhost:8080/api/plugins/linear/connections/<CONNECTION_ID>/scopes' \
--header 'Content-Type: application/json' \
--data-raw '{
"data": [{ "connectionId": <CONNECTION_ID>, "teamId": "<TEAM_ID>", "name": "Engineering" }]
}'
```
## Collecting data
```
curl 'http://localhost:8080/api/pipelines' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "linear pipeline",
"plan": [[{
"plugin": "linear",
"options": { "connectionId": <CONNECTION_ID>, "teamId": "<TEAM_ID>" }
}]]
}'
```
## Rate limiting
Linear enforces a per-API-key request budget (1,500 requests/hour) plus a
complexity budget. The collector paces requests against the configured
`rateLimitPerHour` (default 1500). Issues are collected incrementally using
`updatedAt` ordering so re-runs only fetch changes.
## Limitations / roadmap
- Authentication is personal API key only; OAuth2 is a planned follow-up.
- Issue type defaults to `REQUIREMENT`; label-based type mapping via the scope
config is a planned follow-up.
- config-ui integration (connection form + team picker) and the website
documentation page are planned follow-ups; for now connections and scopes are
managed via the API calls shown above.