Skip to content

Instantly share code, notes, and snippets.

@bluzky
Last active March 30, 2022 08:56
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bluzky/380995c41cd205170b7193b50d87f9c7 to your computer and use it in GitHub Desktop.
Save bluzky/380995c41cd205170b7193b50d87f9c7 to your computer and use it in GitHub Desktop.
Export your github pull request with Elixir
Mix.install([
{:tesla, "~> 1.4.3"},
{:csv, "~> 2.4"},
{:jason, "~> 1.3"}
])
defmodule GithubPR do
require Logger
def exec(repo, token) do
headers = [
:id,
:title,
:url,
:state,
:ticket,
:user,
:reviewer,
:created_at,
:updated_at,
:merged_at
]
stream_pr(repo, token)
|> CSV.encode(headers: headers)
|> Stream.into(File.stream!("pullrequest.csv", [:write, :utf8]))
|> Stream.run()
end
defp stream_pr(repo, token) do
per_page = 30
# update your filters
params = %{per_page: 30, state: "closed"}
Stream.resource(
fn -> %{page: 1} end,
fn
%{page: page} ->
params = Map.put(params, :page, page)
prs =
Tesla.get("https://api.github.com/repos/#{repo}/pulls",
query: params,
headers: [
{"Authorization", "token #{token}"},
{"Content-Type", "application/json; charset=utf-8"},
{"User-Agent", "Awesome-Octocat-App"}
]
)
|> parse_response()
|> Enum.map(&load_reviewer(&1, repo, token))
if prs == [] do
{:halt, nil}
else
{prs, %{page: page + 1}}
end
_ ->
{:halt, nil}
end,
fn _ -> nil end
)
end
defp parse_response(response) do
case response do
{:ok, %{body: body, status: status}} when status >= 200 and status < 300 ->
body
|> Jason.decode!()
|> Enum.map(&parse_pr/1)
_ ->
Logger.error(inspect(response))
end
end
defp parse_pr(item) do
%{
id: item["number"],
number: item["number"],
url: item["url"],
state: item["state"],
title: item["title"],
ticket: ticket_number(item["title"]) || ticket_number(item["head"]["label"]),
user: item["user"]["login"],
reviewer: Enum.map(item["requested_reviewers"], & &1["login"]) |> Enum.join(","),
created_at: item["created_at"],
updated_at: item["created_at"],
merged_at: item["merged_at"]
}
end
defp ticket_number(string) do
case Regex.run(~r/.*(os[\-\s]\d+|cu[\-\s][a-z0-9]+).*/, string) do
[_, match] -> match
_ -> nil
end
end
defp load_reviewer(pr, repo, token) do
response =
Tesla.get("https://api.github.com/repos/#{repo}/pulls/#{pr.number}/reviews",
headers: [
{"Authorization", "token #{token}"},
{"Content-Type", "application/json; charset=utf-8"},
{"User-Agent", "Awesome-Octocat-App"}
]
)
case response do
{:ok, %{body: body, status: status}} when status >= 200 and status < 300 ->
reviewers =
body
|> Jason.decode!()
|> Enum.map(& &1["user"]["login"])
|> Enum.uniq()
|> Enum.join(",")
%{pr | reviewer: reviewers}
_ ->
pr
end
end
end
GithubPR.exec("bluzky/tarams", "your_token")
@bluzky
Copy link
Author

bluzky commented Mar 30, 2022

Create your access token here https://github.com/settings/tokens

remember to check repo checkbox

@darknight1604
Copy link

darknight1604 commented Mar 30, 2022

Amazing script 💯
Its save for me thousand hours

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment