Skip to content

feat: add linear service#261

Merged
mbakgun merged 7 commits into
heymrun:mainfrom
eryue0220:feat/add-linear-service
Jun 28, 2026
Merged

feat: add linear service#261
mbakgun merged 7 commits into
heymrun:mainfrom
eryue0220:feat/add-linear-service

Conversation

@eryue0220

Copy link
Copy Markdown
Contributor

This pr is to add new linear service and e2e node.

@mbakgun

mbakgun commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Hi @eryue0220 🥇 Thanks for the work on this PR. The Linear integration is useful and the API key node path looks close to mergeable. I’d like a few OAuth fixes before we land it. 🚀

Could you please address these? 👑

  • Fix the OAuth token refresh request. The refresh call reuses the GraphQL client, which carries a default Content-Type: application/json, so the body goes out form-encoded while the header says JSON. Linear’s token endpoint expects application/x-www-form-urlencoded, so refresh will fail once a token expires. I reproduced this locally. The initial callback is fine since it uses a fresh client, so only the refresh path needs an explicit form content type or a separate token client.
  • Confirm Linear’s scope delimiter. The code uses space-separated scopes, while Linear’s docs appear to use comma-separated scopes such as read,write. Please verify this and update both the scope string and the test if needed.
  • Add a refresh-path test. That path has no coverage right now. Please verify the request headers and body, and that refreshed tokens are persisted back to the credential.
  • Close the LinearService client in the credential connection test path after test_connection(), matching the executor’s finally: service.close() pattern.
  • Make the docs consistent about Linear supporting both API key and OAuth, or split OAuth into a follow-up if we only want to ship API key support here.

Overall I’m happy with the direction 🙏 OAuth should either be corrected here or moved to a follow-up PR so the API key node can land cleanly. ⭐️

@eryue0220

Copy link
Copy Markdown
Contributor Author

Hi @eryue0220 🥇 Thanks for the work on this PR. The Linear integration is useful and the API key node path looks close to mergeable. I’d like a few OAuth fixes before we land it. 🚀

Could you please address these? 👑

  • Fix the OAuth token refresh request. The refresh call reuses the GraphQL client, which carries a default Content-Type: application/json, so the body goes out form-encoded while the header says JSON. Linear’s token endpoint expects application/x-www-form-urlencoded, so refresh will fail once a token expires. I reproduced this locally. The initial callback is fine since it uses a fresh client, so only the refresh path needs an explicit form content type or a separate token client.
  • Confirm Linear’s scope delimiter. The code uses space-separated scopes, while Linear’s docs appear to use comma-separated scopes such as read,write. Please verify this and update both the scope string and the test if needed.
  • Add a refresh-path test. That path has no coverage right now. Please verify the request headers and body, and that refreshed tokens are persisted back to the credential.
  • Close the LinearService client in the credential connection test path after test_connection(), matching the executor’s finally: service.close() pattern.
  • Make the docs consistent about Linear supporting both API key and OAuth, or split OAuth into a follow-up if we only want to ship API key support here.

Overall I’m happy with the direction 🙏 OAuth should either be corrected here or moved to a follow-up PR so the API key node can land cleanly. ⭐️

Thanks for your review, I've updated.

@mbakgun

mbakgun commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Thanks for the quick turnaround on this. The scope delimiter, the client close in the credential test path, and the docs cleanup all look good. I also appreciate you adding refresh-path coverage.

There is one important OAuth item that still needs another pass before we land this PR.

Linear's token endpoint requires form-encoded bodies, not JSON. Their OAuth docs say the token request parameters must be sent as a URL-encoded form submission with Content-Type: application/x-www-form-urlencoded.

The latest change switched both the callback and the refresh request from data={...} to json={...}. That makes the body and header consistent, but in the wrong format. Refresh will still fail when a token expires, and the callback path is now regressed too, since it was previously using a fresh client with data={...}.

Could you please update both token endpoint calls to use form encoding?

  • Use data={...}, not json={...}
  • Ensure Content-Type is application/x-www-form-urlencoded
  • For refresh, either override the GraphQL client's default JSON header on that call or use a separate token client
  • For the callback, reverting back to data={...} on the fresh client should be enough

Please also flip the tests accordingly. The current refresh and callback tests assert json is used and data is not, which locks in the wrong behavior. They should assert the form-encoded body, the form content type, and that refreshed tokens are persisted back to the credential.

Everything else looks good. Once the token requests are form-encoded and the tests verify that behavior, I think the Linear integration is ready to land as one complete PR.

Reference: https://linear.app/developers/oauth-2-0-authentication

@eryue0220

Copy link
Copy Markdown
Contributor Author

Thanks for the quick turnaround on this. The scope delimiter, the client close in the credential test path, and the docs cleanup all look good. I also appreciate you adding refresh-path coverage.

There is one important OAuth item that still needs another pass before we land this PR.

Linear's token endpoint requires form-encoded bodies, not JSON. Their OAuth docs say the token request parameters must be sent as a URL-encoded form submission with Content-Type: application/x-www-form-urlencoded.

The latest change switched both the callback and the refresh request from data={...} to json={...}. That makes the body and header consistent, but in the wrong format. Refresh will still fail when a token expires, and the callback path is now regressed too, since it was previously using a fresh client with data={...}.

Could you please update both token endpoint calls to use form encoding?

  • Use data={...}, not json={...}
  • Ensure Content-Type is application/x-www-form-urlencoded
  • For refresh, either override the GraphQL client's default JSON header on that call or use a separate token client
  • For the callback, reverting back to data={...} on the fresh client should be enough

Please also flip the tests accordingly. The current refresh and callback tests assert json is used and data is not, which locks in the wrong behavior. They should assert the form-encoded body, the form content type, and that refreshed tokens are persisted back to the credential.

Everything else looks good. Once the token requests are form-encoded and the tests verify that behavior, I think the Linear integration is ready to land as one complete PR.

Reference: https://linear.app/developers/oauth-2-0-authentication

Updated.

@mbakgun

mbakgun commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Thanks again for the quick fixes. The OAuth token flow looks good now. 👑

I noticed one remaining integration gap before we land this PR. When the Linear node is connected to an Agent as a tool, the Agent cannot fill the Linear parameters automatically. This behavior exists for the other tool-capable nodes, so Linear should support it too.

Could you please make the Linear tool fields available to AI autofill when the node is attached to an Agent? This should include the operation-specific fields such as team ID, project ID, issue ID, title, description, assignee, state, priority, comment fields, limit, cursor, and return all where applicable.

This also matches the node integration checklist in AGENTS.md: fields that can be configured on a tool attached to an Agent node should be available for AI autofill.

Please add or extend a frontend test if practical, similar to the existing coverage for other nodes. Once this is covered, I think the Linear integration is ready to land as one complete PR. ✅

Screenshot 2026-06-28 at 12 29 53 PM

@mbakgun mbakgun left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can merge this since this is gonna be included in #next version :)
We'll fix it locally , thank you so much for this amazing work !

We'll also fix (duplicated 083 alembic version)

` ^^^^^^^^^^^^^^^^^^^^^^^^
File "asyncpg/protocol/protocol.pyx", line 205, in bind_execute
asyncpg.exceptions.InvalidTextRepresentationError: invalid input value for enum credential_type: "linear"

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/Users/mbakgun/Projects/heym/heymrun/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
self.dialect.do_execute`

@mbakgun mbakgun merged commit eb912c4 into heymrun:main Jun 28, 2026
2 checks passed
@eryue0220

Copy link
Copy Markdown
Contributor Author

I think we can merge this since this is gonna be included in #next version :) We'll fix it locally , thank you so much for this amazing work !

We'll also fix (duplicated 083 alembic version)

` ^^^^^^^^^^^^^^^^^^^^^^^^ File "asyncpg/protocol/protocol.pyx", line 205, in bind_execute asyncpg.exceptions.InvalidTextRepresentationError: invalid input value for enum credential_type: "linear"

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "/Users/mbakgun/Projects/heym/heymrun/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context self.dialect.do_execute`

Thanks for your updated.

@eryue0220 eryue0220 deleted the feat/add-linear-service branch June 29, 2026 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants