-
Couldn't load subscription status.
- Fork 1
Fix Linear Webhooks Example and Add Standalone Version #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Linear Webhooks Example | ||
|
|
||
| This example demonstrates how to set up a webhook endpoint to receive events from Linear using the Codegen framework. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Python 3.13 or later | ||
| - [Modal](https://modal.com/) account | ||
| - Linear account with API access | ||
|
|
||
| ## Setup | ||
|
|
||
| 1. Install the required dependencies: | ||
|
|
||
| ```bash | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| Or using uv: | ||
|
|
||
| ```bash | ||
| uv pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| 2. Create a `.env` file with your Linear credentials: | ||
|
|
||
| ``` | ||
| LINEAR_ACCESS_TOKEN="your_linear_access_token" | ||
| LINEAR_SIGNING_SECRET="your_linear_signing_secret" | ||
| LINEAR_TEAM_ID="your_linear_team_id" | ||
| ``` | ||
|
|
||
| You can find your Linear Team ID in your Linear workspace settings → Teams → Select your team → The Team ID will be in the URL (e.g., `https://linear.app/your-workspace/team/team-id/settings`). | ||
|
|
||
| ## Running the Example | ||
|
|
||
| ### Local Development | ||
|
|
||
| For local development and testing, you can run the example using Modal: | ||
|
|
||
| ```bash | ||
| modal serve webhooks.py | ||
| ``` | ||
|
|
||
| This will start a local server that you can use for testing. | ||
|
|
||
| ### Deployment | ||
|
|
||
| To deploy the example to Modal: | ||
|
|
||
| ```bash | ||
| modal deploy webhooks.py | ||
| ``` | ||
|
|
||
| After deployment, Modal will provide a URL that you can use as your webhook endpoint in Linear. | ||
|
|
||
| ## Setting Up the Linear Webhook | ||
|
|
||
| 1. Go to your Linear workspace settings → API → Webhooks → Create webhook | ||
| 2. Enter the Modal URL provided after deployment | ||
| 3. Select the events you want to receive (e.g., Issue created, Issue updated) | ||
| 4. Save the webhook | ||
|
|
||
| ## How It Works | ||
|
|
||
| The example sets up a webhook endpoint that listens for Linear events. When an event is received, it prints the event data to the console. You can extend this example to perform custom actions based on the event data. | ||
|
|
||
| The key components are: | ||
|
|
||
| - `CodegenApp`: Handles the webhook events | ||
| - `@app.linear.event("Issue")`: Decorator that registers a handler for Issue events | ||
| - `app.linear.subscribe_all_handlers()`: Subscribes to all registered handlers | ||
| - `app.linear.unsubscribe_all_handlers()`: Unsubscribes from all handlers when the app is shut down | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| If you encounter any issues, check the following: | ||
|
|
||
| - Make sure your Linear credentials are correct | ||
| - Verify that the webhook URL is accessible from the internet | ||
| - Check the Modal logs for any errors | ||
|
|
||
| ## Further Reading | ||
|
|
||
| - [Linear API Documentation](https://developers.linear.app/docs/) | ||
| - [Modal Documentation](https://modal.com/docs/) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| codegen>=0.22.2 | ||
| modal>=0.73.25 | ||
| fastapi[standard] | ||
| python-dotenv |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| """ | ||
| Standalone version of the Linear webhooks example that can be run without Modal. | ||
| This is useful for local development and testing. | ||
| """ | ||
|
|
||
| import os | ||
| from dotenv import load_dotenv | ||
| from fastapi import FastAPI, Request | ||
| import uvicorn | ||
| from codegen.extensions.events.codegen_app import CodegenApp | ||
|
|
||
| # Load environment variables from .env file | ||
| load_dotenv() | ||
|
|
||
| # Create the CodegenApp instance | ||
| app = CodegenApp(name="linear-webhook-standalone") | ||
|
|
||
| # Get the FastAPI app from the CodegenApp | ||
| fastapi_app = app.app | ||
|
|
||
| @fastapi_app.get("/") | ||
| async def root(): | ||
| return {"message": "Linear Webhook Server is running"} | ||
|
|
||
| @fastapi_app.post("/linear/webhook") | ||
| async def linear_webhook(request: Request): | ||
| """Handle incoming Linear webhook events.""" | ||
| payload = await request.json() | ||
| print(f"Received Linear webhook event: {payload}") | ||
| return {"status": "success"} | ||
|
|
||
| def main(): | ||
| """Run the FastAPI application.""" | ||
| # Check if required environment variables are set | ||
| required_vars = ["LINEAR_ACCESS_TOKEN", "LINEAR_SIGNING_SECRET", "LINEAR_TEAM_ID"] | ||
| missing_vars = [var for var in required_vars if not os.getenv(var)] | ||
|
|
||
| if missing_vars: | ||
| print(f"Error: Missing required environment variables: {', '.join(missing_vars)}") | ||
| print("Please set these variables in your .env file or environment.") | ||
| return | ||
|
|
||
| print("Starting Linear webhook server...") | ||
| print(f"LINEAR_TEAM_ID: {os.getenv('LINEAR_TEAM_ID')}") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Printing sensitive information such as Suggested Change: # print(f"LINEAR_TEAM_ID: {os.getenv('LINEAR_TEAM_ID')}") |
||
|
|
||
| # Run the FastAPI application | ||
| uvicorn.run(fastapi_app, host="0.0.0.0", port=8000) | ||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,9 @@ | ||
| import modal.running_app | ||
| from codegen.extensions.events.app import CodegenApp | ||
| from codegen.extensions.events.codegen_app import CodegenApp | ||
| import modal | ||
|
|
||
| image = modal.Image.debian_slim(python_version="3.13").apt_install("git").pip_install("fastapi[standard]", "codegen>=v0.22.2") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of a specific Python version ( Recommendation: Consider using a version range or a more commonly supported version of Python to ensure long-term compatibility and ease of maintenance. |
||
| app = CodegenApp(name="test-linear", modal_api_key="", image=image) | ||
| app = CodegenApp(name="test-linear") | ||
|
|
||
| # Here is an example implementation of setting up an endpoint for receiving webhook events from Linear. | ||
| # The @app.linear.event() decorator takes care of subscribing to the webhook and also unsubscribing when the deployment spun | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling for missing environment variables could be improved. Currently, the function simply returns without terminating the program, which could lead to further execution without the necessary configurations. Consider using
sys.exit(1)to exit the program with a non-zero status code, indicating an error condition.Suggested Change: