🔵 Linear : https://linear.app/ 🐦 Tinybird : https://tinybird.co/
This project performs an initial ETL process to seed Tinybird with data from Linear. Once the initial data is loaded, a webhook is set up to handle real-time updates, ensuring Tinybird stays in sync with Linear.
This project provides two main functionalities:
- ETL Process: Extracts historical data from Linear API and loads it into Tinybird.
- Webhook Handler: Receives real-time data updates from Linear via webhooks and sends them to Tinybird.
linear-tinybird/
├── src/
│ ├── app/
│ │ └── main.py # Webhook handler (FastAPI app)
│ ├── etl/
│ │ └── main.py # ETL script for historical data
│ └── utils/
│ ├── config_query.py # Schemas and GraphQL queries
│ └── helper.py # Utility functions
├── vercel.json # Vercel deployment configuration
└── requirements.txt # Project dependencies- Python 3.8+
- Linear account with API access
- Tinybird account
- Clone the repository:
git clone https://github.com/yourusername/linear-tinybird-etl.git cd linear-tinybird-etl - Create a virtual environment:
python -m venv venv source venv/bin/activate - Install dependencies:
pip install -r requirements.txt
- Create a
.envfile in the root directory. Refer to.env.examplefor the required variables.
To extract data from Linear and load it into Tinybird:
cd src
python etl/main.py Linear_Issue # Extract issues
python etl/main.py Linear_Project # Extract projects
python etl/main.py Linear_User # Extract usersBy default, the ETL process will extract all data from Linear.
You can limit the number of records with the --limit flag:
python etl/main.py Linear_Issue --limit 100Once the ETL process is complete, you can check the datasource in Tinybird.
The data is sent to Tinybird with the following datasource naming convention:
Linear_Issuefor issuesLinear_Projectfor projectsLinear_Userfor users
You can create pipes in Tinybird to analyze this data and build dashboards.
Done!
Now, we can set up the webhook to handle real-time updates from Linear.
The webhook handler is designed to be deployed on Vercel. The vercel.json file configures the deployment to use the FastAPI application in src/app/main.py.
-
Ensure the vercel.json is set up correctly.
-
Important: Set the environment variables in your Vercel project settings > Environment Variables.
1. LINEAR_WEBHOOK_SECRET=
2. TINYBIRD_API_KEY=
3. TINYBIRD_REGION=
-
Deploy the webhook handler to Vercel:
vercel
This will deploy the webhook handler to Vercel and provide you the deployed app url.
-
Copy the url. Optionally, you can get the url by opening Vercel and clicking on the deployed app. E.g:
https://your-app.vercel.app/webhookRemember to include the
/webhookpath! -
Configure your Linear webhook:
- Go to Linear workspace settings
- Navigate to Settings > API
- Create a new webhook with your Vercel URL:
https://your-app.vercel.app/webhook - Set the webhook secret. (must match LINEAR_WEBHOOK_SECRET in your Vercel app environment variables)
- Tick to select the events you want to receive (Issues, Projects, etc.)
-
Test the webhook by creating or updating an issue in Linear.
-
Done! Open Tinybird and you should see the data being streamed in.
To run the webhook handler locally:
cd src
uvicorn app.main:app --reloadYou can use a tool like ngrok to expose your local server to the internet for webhook testing.
Note: It wont work if you dont expose the local server to the internet, since webhooks require a publicly accessible url to deliver the payload. Without exposing the local server to the internet, Linear cannot send webhook events to it.
To run the webhook handler locally using Docker, you can use Docker Compose. This will build the Docker image and start the container:
docker compose up --build--build: This flag forces a rebuild of the Docker image. Use this if you've made changes to the code orDockerfile.
To stop the running container, use:
docker compose downThe webhook handler is implemented using FastAPI and verifies Linear's HMAC signatures to ensure authenticity.
Linear use HMAC signatures rather than sending the secret directly in the headers. This is a more secure approach since the actual secret is never transmitted over the network.
Steps:
- Implemented proper signature verification using HMAC SHA-256
- Used the raw request body to calculate the signature
- Compared it with the signature Linear sent in the Linear-Signature header
This approach ensures that:
- The webhook is genuinely from Linear
- The payload hasn't been tampered with during transmission
Future enhancement considerations:
- Adding more detailed logging for different event types
- Implementing error handling for malformed payloads
- Adding a timeout mechanism for webhook processing