Skip to content

Export Linear issues including assignees, comments, labels, linked issues/PRs and projects to GitHub issues.

License

Notifications You must be signed in to change notification settings

portone-io/byelinear

 
 

Repository files navigation

Introduction

Linear에 존재하는 issue를 Github issue로 migration하기 위해 같은 용도인 byelinear를 fork하여 custom하게 수정한 repository입니다.

변경점

  • 06c4404: Linear API Key를 Bearer prefix 없이 Authorization header에 설정하도록 변경
  • e295061: 현재는 지원하지 않는 Linear GraphQL object를 쿼리하지 않도록 수정
  • 1aa8638: assignee 및 author 설정을 위해 Linear email -> Github username map 등록
  • b8eabaa: 특정 team의 issue만 가져올 수 있도록 argument로 team name 추가 및 query 필터 수정
  • 2e2d0b6: Linear의 label 정보는 가져오지 않도록 관련 코드 삭제
  • 24c164a: Github issue 제목에서 Linear identifier(ex. SRE-17)는 제외하도록 수정
  • 4e7ef07: Slack 등 integration에 의해 생성된 comment에 User 정보가 없어 생기는 버그 수정
  • 8346cab: Linear의 project 이름에 해당하는 Github project를 찾고 없으면 생성하는 것이 아닌 추가할 issue를 추가할 Github project 명을 직접 입력하도록 argument 추가
  • 37b4e94: Github API가 rate limit을 초과하였을 때 header에 있는 다음 호출 가능 시간을 print하도록 수정
  • 41e8329: Linear issue를 업로드하기 전 issue number의 오름차순으로 리스트를 sorting하도록 수정
  • 278ce0e: Linear identifier number와 github issue number를 맞추기 위해 삭제된 issue가 있는 경우 빈 issue를 생성 및 즉시 삭제하도록 수정

사용법

# Linear에 있는 issue들을 Local로 export하기
$ BYELINEAR_TEAM_NAME={Linear Team Name} LINEAR_API_KEY={Linear API Key} go run . from-linear
# Test용도로 특정 number의 issue만 export하기
$ BYELINEAR_ISSUE_NUMBER={Linear Issue number} BYELINEAR_TEAM_NAME={Linear Team Name} LINEAR_API_KEY={Linear API Key} go run . from-linear

# Local에 export된 Linear issue를 Github에 import하기
# Github PAT needs to be granted (repo, read:org, read:project) scopes
$ BYELINEAR_ORG={Github Organization Name} BYELINEAR_REPO={Github Repository Name} BYELINEAR_PROJECT_NAME={Github Project Name} GITHUB_TOKEN={Github Personal Access Token} go run . to-github

주의 사항

  • assignee 및 issue, comment 작성자가 github의 username으로 대체되길 원할 경우, 1aa8638룰 참고하여 map을 수정합니다.
  • 이미지나 첨부파일 등의 경우 Linear authorization이 필요한 private link로 제공되기때문에 import할 경우 보이지 않게됩니다. Core chapter issue의 경우 Linear issue 내 download link를 jq를 이용해 모두 추출하여 다운받은 뒤 수작업으로 edit하여 첨부하는 식으로 대체하였습니다.
# id 와 함께 url 추출
$ jq '[.identifier, ((.description, .comments.nodes[].body) | match("https://uploads.linear.app/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; "g").string)] | select(length >= 2)' SRE-*.json

# url 만 추출
$ jq '.description, .comments.nodes[].body | match("https://uploads.linear.app/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; "g").string' -r SRE-*.json

# curl로 파일 다운로드
$ curl -X GET {url} --header 'Authorization: {Linear API Key}' > {파일명.확장자}

byelinear

ci daily license

byelinear exports Linear issues including assignees, comments, labels, linked issues/PRs and projects to GitHub issues.

While we enjoyed Linear's slick UI and superior featureset, we ultimately decided that we wanted our issues on the same platform with the rest of our development. GitHub issues aren't perfect but they work well enough for us and are more tightly integrated with GitHub. So we wrote this for our internal migration from Linear issues to GitHub issues.

byelinear uses the Linear GraphQL API and the GitHub V3 and V4 APIs.

Install

$ go install oss.terrastruct.com/byelinear@latest
$ byelinear --help
usage:
        byelinear [ from-linear | to-github ]

Use from-linear to export issues from linear and to-github to export issues to github.
See docs and environment variable configuration at https://oss.terrastruct.com/byelinear

See configuration to setup the required environment variables. Then see the example below for how to run and what the logs look like.

Configuration

# Location of corpus for issues fetched from Linear.
# Defaults to linear-corpus in the current directory.
export BYELINEAR_CORPUS=

# Use to fetch and export only a single issue by the linear issue number. Useful for testing.
export BYELINEAR_ISSUE_NUMBER=

# org/repo into which to import issues.
# Required when running to-github.
export BYELINEAR_ORG=terrastruct
export BYELINEAR_REPO=byelinear

# Secrets required when importing/exporting with private repos/issues.
export GITHUB_TOKEN=
export LINEAR_API_KEY=

Caveats

Issues order

byelinear fetches Linear issues in reverse so that the most recent issue is created last and thus shows up first in GitHub issues.

Resumption

from-linear

If you have thousands of issues and hit a rate limit or something goes wrong, know that byelinear from-linear stores all fetched issues on the disk in ./linear-corpus/<issue-identifier>.json. You can ctrl+c and resume later and byelinear from-linear will know to start from the last fetched issue based on ./linear-corpus/state.json.

You can change the corpus directory with $BYELINEAR_CORPUS.

to-github

If something goes wrong when exporting to github and you ctrl+c, you can resume but you might end up with an incomplete but also duplicate issue. To avoid this, first check your repo to see the last created issue and ensure the state in the comment/linear matches the github state. Mainly labels, projects and comments. Make any changes you need to to make it match. Then go into ./linear-corpus/state.json and ensure "exported_to_json":true.

Now you can restart.

In fact I now realize you might also end up with duplicate issues if say the request to add your issue to a project fails. Or to create a comment. to-github's retry loop is around recreating the issue again and redoing everything instead of around every individual API request.

In the future to-github should be improved to allow seamless resumption by storing state about each successfully completed operation in the state.json instead of just the issue as a whole.

For now, it's best that once you start, you let it export every issue to GitHub.

Projects

byelinear gets everything right except for projects and state as there are limitations in GitHub's project API. There is no way to add a new project state/column programatically so it tries to map incoming states to GitHub default states as best as possible.

e.g. In Review from Linear becomes In Progress on GitHub. Cancelled becomes Done.

As well, GitHub's projects API does not allow for control over workflow automations like automatically setting an issue to In Progress when a PR is opened for it. You'll have to manually go into the projects settings and enable the workflows there.

Example

The following example fetches issue TER-1396 from linear and then exports it to GitHub. Empty $BYELINEAR_ISSUE_NUMBER to fetch all issues.

$ BYELINEAR_ISSUE_NUMBER=1396 LINEAR_API_KEY=lin_api_... go run . from-linear
2022/09/15 12:44:09 fetching 1396
2022/09/15 12:44:10 fetched 1396
$ BYELINEAR_ISSUE_NUMBER=1396 GITHUB_TOKEN=ghp_... BYELINEAR_ORG=terrastruct BYELINEAR_REPO=byelinear-test go run . to-github
2022/09/15 12:44:49 TER-1396: exporting
2022/09/15 12:44:49 TER-1396: ensuring label: backend
2022/09/15 12:44:49 TER-1396: ensuring label: easy
2022/09/15 12:44:49 TER-1396: ensuring label: blocked
2022/09/15 12:44:50 TER-1396: ensuring label: dsl
2022/09/15 12:44:50 TER-1396: creating
2022/09/15 12:44:51 TER-1396: creating comment 0
2022/09/15 12:44:52 TER-1396: creating comment 1
2022/09/15 12:44:52 TER-1396: ensuring project: D2
2022/09/15 12:44:54 TER-1396: exported: https://github.com/terrastruct/byelinear-test/issues/3

Before

linear

After

github

Related

About

Export Linear issues including assignees, comments, labels, linked issues/PRs and projects to GitHub issues.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 98.7%
  • Shell 1.3%