Skip to content
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

Add Linear.app adapter #336

Merged
merged 2 commits into from
Apr 26, 2022
Merged

Add Linear.app adapter #336

merged 2 commits into from
Apr 26, 2022

Conversation

mtarnovan
Copy link
Contributor

Adds a simple, DOM based Linear adapter.

The selectors are fragile (because Linear minimizes their CSS so we can't use their CSS classes) and will require updating if Linear adds more languages.

I had a few issues locally:

  1. after running any tasks that create dist/ the path is picked up by yarn test which produces a lot of confusing test failures
  2. (this is only an issue if one doesn't want to install Rosetta) the build system uses some notifiers that come with pre-built x86 executables for terminal-notifier. Those will crash on arm64 (Apple M1). Since terminal-notifier seems unmaintained, as a (very) dirty work-around one can compile terminal-notifier to get an arm64 executable (for example via brew) and use that binary instead:
brew install terminal-notifier
ln -sf `which terminal-notifier` node_modules/node-notifier/node_modules/node-notifier/vendor/mac.noindex/terminal-notifier.app/Contents/MacOS/terminal-notifier
ln -sf `which terminal-notifier` node_modules/webpack-build-notifier/node_modules/node-notifier/vendor/mac.noindex/terminal-notifier.app/Contents/MacOS/terminal-notifier

In lieu of a better fix, maybe we should add this to the README?

@mtarnovan
Copy link
Contributor Author

Note that we could also use Linear's SDK to fetch ticket info, but I gave it a try and it felt slow, so I think it's worth the tradeoff of using selectors even if might need updating from time to time.

Copy link
Member

@klappradla klappradla left a comment

Choose a reason for hiding this comment

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

Hey @mtarnovan 👋

Thanks a ton for your interest in this project and for jumping on board with a contribution 💚

I'm a bit hesitant about integrating this adapter though: I've never heard of the tracker software and we're not using it internally. This combined with the fact that the adapter's implementation is - as you said - very fragile and likely to break on any updates the team does to their software (imagine for instance they switch from <span> with title attribute to normal <label> and <input> tags), makes it quite hard to maintain for us.

And having an adapter which is very likely to break fully unnoticed is a bit of a pain to maintain for us.

I'll think about it again and hopefully have the time some day this week to also try it with the software.

Thanks a ton 💙

expect(result).toEqual([]);
});

it("extracts the ticket from the issue page", async () => {
Copy link
Member

Choose a reason for hiding this comment

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

Are there also other views where one would highlight a ticket? E.g. a sprint or list view?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are such views, but since the markup is so obfuscated I'm not sure it's worth the effort...


if (!id) return [];

const ticket = {
Copy link
Member

Choose a reason for hiding this comment

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

Is there also a description field in a somewhat commit-message-body-usable format?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we use the API (see my other comment) then yes, otherwise, probably not very reliably.

Comment on lines 41 to 47
GitHub,
GitLab,
Jira,
Notion,
Tara,
Trello,
Linear,
Copy link
Member

Choose a reason for hiding this comment

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

Let's stick with alphabetic ordering 🤷 Even though it's not "fair".

if (url.hostname !== "linear.app") return [];

const { id, issueType } = match("/:team/:issueType/:id/:slug", url.pathname);
const title = $text('[title="Edit issue title"]', document);
Copy link
Member

Choose a reason for hiding this comment

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

This is indeed a bit fragile 🧱

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The markup looks like this:

Screenshot 2022-03-07 at 17 01 01

So I don't see a way around this other that the one I already mentioned: use the official SDK which is a client for a Graphql API (but as I said I played around with it seems a bit slow, I don't want to wait seconds to grab a branch command 🙃). Ofc using an API client would be much more reliable and maintainable, so if that's your preference I could explore that alternative.

@mtarnovan
Copy link
Contributor Author

Hey @klappradla,

Thanks for taking the time to review.

I've never heard of the tracker software

We switched from JIRA to Linear and so far we like it (although it is missing some more advanced features)

very fragile and likely to break on any updates

Understood. I can work on an alternative implementation using the official SDK then, it should be more reliable (albeit slower...).

Best,
Mihai

@klappradla
Copy link
Member

Hey @mtarnovan 👋

I thought about this PR again over the holiday. It would indeed be great if TicketyTick would support a more diverse set of trackers, even tools which bitcrowd isn't using internally. If you and your team are actively using the tool, we can be sure that breaking changes on the Linear.app side are detected quite fast.

So my suggestion would be: do a quick spike on a) trying to get the ticket's description field somehow and b) base the fetching on the API rather than the DOM. If both don't work out, I'd also be fine with merging the current approach from this PR.

Another note on fetching via the API: take a look at the notion.so and Jira adapters: it can make sense to use the internal API the SPAs are using, rather than a public API the tools offer. When building the notion.so adapter, I just opened the network tab in the developer tools to see what request the app does. As the client is already authenticated, we can just do the same requests in the extension 🤷

@mtarnovan
Copy link
Contributor Author

Hey Max 👋

I thought about this PR again over the holiday. It would indeed be great if TicketyTick would support a more diverse set of trackers, even tools which bitcrowd isn't using internally. If you and your team are actively using the tool, we can be sure that breaking changes on the Linear.app side are detected quite fast.

We are probably going to stick with Linear for the foreseeable future, so yes, we can be the canary in the coal mine :-)
I actually replaced the release extension with a dev build from this PR and have been using that at work in the last few days (we don't use the description field in commits anyway since it feels redundant)

So my suggestion would be: do a quick spike on a) trying to get the ticket's description field somehow and b) base the fetching on the API rather than the DOM. If both don't work out, I'd also be fine with merging the current approach from this PR.

Happy to give that a try when time permits.

Another note on fetching via the API: take a look at the notion.so and Jira adapters: it can make sense to use the internal API the SPAs are using, rather than a public API the tools offer. When building the notion.so adapter, I just opened the network tab in the developer tools to see what request the app does. As the client is already authenticated, we can just do the same requests in the extension 🤷

From my research Linear uses the same GraphQL API internally and externally (they provide an SDK that wraps it). They provide a global function loadLinearClient that loads an already authenticated client. My first implementation was using that, but it felt slow so I threw it out (as I mentioned above for us the description field is not at all important, since Linear has a Github integration that already takes care of that for us by adding the description to the PR automatically; so I prefered keeping the code fast and simple by not accessing any APIs)

I'll try what you're suggesting, but I'm pretty sure it will not work: their internal APIs are authenticated with Oauth bearer tokens, not with session cookies (like I assume notion.so does).

To summarize:

  • the Linear adapter will probably have the limitation of not working on "index" views (sprint, board, roadmaps etc) since the markup makes it very difficult to reliably iterate over individual tickets from those pages; for us this is not important at all, but ofc I can't speak for other users of tickety-tick
  • I'll work on your suggestions to integrate the API and get the description field too

Thanks again,
Mihai

Copy link
Member

@klappradla klappradla left a comment

Choose a reason for hiding this comment

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

Thanks for the updates @mtarnovan 🙏

If this has been working for you with a local build in the last weeks, let's give this a try for everyone 🌊 ⛵

@mtarnovan
Copy link
Contributor Author

@klappradla nice!

Please ping me when you release this to the extension stores so I can replace the locally build extension. I'll keep an eye on breakages and will try to fix them asap.

@klappradla klappradla merged commit b6d5d32 into bitcrowd:main Apr 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants