nodejs 환경에서 깃허브 API를 사용할 일이 있어서 여러 문서를 참고하여 활용해 보았다.
문서에 있는 코드들의 결과 값들을 위주로 정리해 두었다.
공식 문서를 보면서 하나하나 쳐 보면서 결과 값을 확인하는게 제일 좋지만 귀찮거나 급하신 분들께서 구글링을 하다가 내 글을 발견하고 많은 도움을 얻으신다면 좋겠다.
Github API 공식 Docs
이게 결국 정답인건데 요청하는 코드를 직접 짜는 것보다.. 더 편리한 방법을 찾기 위해 찾아보았다.
NPM github-api
이걸 직접 써보기 전까지는 여기 모든 기능이 있을 줄 알았는데, 생각보다 잘 되지 않아서(아마 버전 문제인 듯) 추가적으로 다른 모듈들을 사용해볼 수밖에 없었다.
githubjs 사이트에서 확인하면 알 수 있듯이, 인증 방식에는 세 가지가 있다.
1. No Auth
2. PW Auth
3. Token Auth
셋 중에서 No Auth는 잘 되고, PW Auth는 이상하게 되고, Token Auth는 시도해보지 않았기 때문에 No Auth로 시도한 코드를 쓰려 한다.
var GitHub = require('github-api');
var noAuth = new GitHub();
var seojinseojin = noAuth.getUser('seojinseojin');
seojinseojin.listStarredRepos(function(err, repos) {
repos.forEach((repo) => {
console.log(`" ${repo.name} " by "${repo.owner.login}"`)
})
});
이렇게 하면 Seojinseojin이라는 유저가 좋아요를 누른 레포지토리들을 확인할 수 있다.
json 배열 형식으로 나오며, 배열 요소 하나는 객체로 이뤄졌는데 다음과 같은 형식이다.
{
id: 54997288,
node_id: 'MDEwOlJlcG9zaXRvcnk1NDk5NzI4OA==',
name: 'd3js',
full_name: 'colorfest/d3js',
private: false,
owner: {
login: 'colorfest',
id: 6611620,
node_id: 'MDQ6VXNlcjY2MTE2MjA=',
avatar_url: 'https://avatars.githubusercontent.com/u/6611620?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/colorfest',
html_url: 'https://github.com/colorfest',
followers_url: 'https://api.github.com/users/colorfest/followers',
following_url: 'https://api.github.com/users/colorfest/following{/other_user}',
gists_url: 'https://api.github.com/users/colorfest/gists{/gist_id}',
starred_url: 'https://api.github.com/users/colorfest/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/colorfest/subscriptions',
organizations_url: 'https://api.github.com/users/colorfest/orgs',
repos_url: 'https://api.github.com/users/colorfest/repos',
events_url: 'https://api.github.com/users/colorfest/events{/privacy}',
received_events_url: 'https://api.github.com/users/colorfest/received_events',
type: 'User',
site_admin: false
},
html_url: 'https://github.com/colorfest/d3js',
description: 'd3.js tutorial series by Accio Code for beginners to intermediate',
fork: false,
url: 'https://api.github.com/repos/colorfest/d3js',
forks_url: 'https://api.github.com/repos/colorfest/d3js/forks',
keys_url: 'https://api.github.com/repos/colorfest/d3js/keys{/key_id}',
collaborators_url: 'https://api.github.com/repos/colorfest/d3js/collaborators{/collaborator}',
teams_url: 'https://api.github.com/repos/colorfest/d3js/teams',
hooks_url: 'https://api.github.com/repos/colorfest/d3js/hooks',
issue_events_url: 'https://api.github.com/repos/colorfest/d3js/issues/events{/number}',
events_url: 'https://api.github.com/repos/colorfest/d3js/events',
assignees_url: 'https://api.github.com/repos/colorfest/d3js/assignees{/user}',
branches_url: 'https://api.github.com/repos/colorfest/d3js/branches{/branch}',
tags_url: 'https://api.github.com/repos/colorfest/d3js/tags',
blobs_url: 'https://api.github.com/repos/colorfest/d3js/git/blobs{/sha}',
git_tags_url: 'https://api.github.com/repos/colorfest/d3js/git/tags{/sha}',
git_refs_url: 'https://api.github.com/repos/colorfest/d3js/git/refs{/sha}',
trees_url: 'https://api.github.com/repos/colorfest/d3js/git/trees{/sha}',
statuses_url: 'https://api.github.com/repos/colorfest/d3js/statuses/{sha}',
languages_url: 'https://api.github.com/repos/colorfest/d3js/languages',
stargazers_url: 'https://api.github.com/repos/colorfest/d3js/stargazers',
contributors_url: 'https://api.github.com/repos/colorfest/d3js/contributors',
subscribers_url: 'https://api.github.com/repos/colorfest/d3js/subscribers',
subscription_url: 'https://api.github.com/repos/colorfest/d3js/subscription',
commits_url: 'https://api.github.com/repos/colorfest/d3js/commits{/sha}',
git_commits_url: 'https://api.github.com/repos/colorfest/d3js/git/commits{/sha}',
comments_url: 'https://api.github.com/repos/colorfest/d3js/comments{/number}',
issue_comment_url: 'https://api.github.com/repos/colorfest/d3js/issues/comments{/number}',
contents_url: 'https://api.github.com/repos/colorfest/d3js/contents/{+path}',
compare_url: 'https://api.github.com/repos/colorfest/d3js/compare/{base}...{head}',
merges_url: 'https://api.github.com/repos/colorfest/d3js/merges',
archive_url: 'https://api.github.com/repos/colorfest/d3js/{archive_format}{/ref}',
downloads_url: 'https://api.github.com/repos/colorfest/d3js/downloads',
issues_url: 'https://api.github.com/repos/colorfest/d3js/issues{/number}',
pulls_url: 'https://api.github.com/repos/colorfest/d3js/pulls{/number}',
milestones_url: 'https://api.github.com/repos/colorfest/d3js/milestones{/number}',
notifications_url: 'https://api.github.com/repos/colorfest/d3js/notifications{?since,all,participating}',
labels_url: 'https://api.github.com/repos/colorfest/d3js/labels{/name}',
releases_url: 'https://api.github.com/repos/colorfest/d3js/releases{/id}',
deployments_url: 'https://api.github.com/repos/colorfest/d3js/deployments',
created_at: '2016-03-29T17:43:21Z',
updated_at: '2021-02-14T11:06:29Z',
pushed_at: '2017-05-21T22:26:50Z',
git_url: 'git://github.com/colorfest/d3js.git',
ssh_url: 'git@github.com:colorfest/d3js.git',
clone_url: 'https://github.com/colorfest/d3js.git',
svn_url: 'https://github.com/colorfest/d3js',
homepage: '',
size: 24,
stargazers_count: 50,
watchers_count: 50,
language: 'JavaScript',
has_issues: true,
has_projects: true,
has_downloads: true,
has_wiki: true,
has_pages: false,
forks_count: 53,
mirror_url: null,
archived: false,
disabled: false,
open_issues_count: 1,
license: {
key: 'mit',
name: 'MIT License',
spdx_id: 'MIT',
url: 'https://api.github.com/licenses/mit',
node_id: 'MDc6TGljZW5zZTEz'
},
forks: 53,
open_issues: 1,
watchers: 50,
default_branch: 'master'
}
정말 많은 정보들을 가져온다.
내가 하고 싶었던 건 해당 유저의 레포를 보는건데, 아쉽게도 noAuth.getUser().getRepos()를 하면 없는 함수라고 나와서 나에게 상처를 주었기 때문에 다른 방법을 찾아보게 되었다.
내가 찾는 기능들은 여기 다 있었다.
const ghrepos = require("ghrepos");
const authOptions = { use: "seojinseojin", token: process.env.PAT }
ghrepos.listUser(authOptions, "seojinseojin", (err, repolist) => {
// console.log(repolist)
repolist.forEach((repo) => {
console.log(repo);
})
})
seojinseojin이라는 유저의 모든 레포지토리를 출력한다.
{
id: 244069909,
node_id: 'MDEwOlJlcG9zaXRvcnkyNDQwNjk5MDk=',
name: 'python_web-scrapping_practice',
full_name: 'SeojinSeojin/python_web-scrapping_practice',
private: false,
owner: {
login: 'SeojinSeojin',
id: 48249505,
node_id: 'MDQ6VXNlcjQ4MjQ5NTA1',
avatar_url: 'https://avatars.githubusercontent.com/u/48249505?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/SeojinSeojin',
html_url: 'https://github.com/SeojinSeojin',
followers_url: 'https://api.github.com/users/SeojinSeojin/followers',
following_url: 'https://api.github.com/users/SeojinSeojin/following{/other_user}',
gists_url: 'https://api.github.com/users/SeojinSeojin/gists{/gist_id}',
starred_url: 'https://api.github.com/users/SeojinSeojin/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/SeojinSeojin/subscriptions',
organizations_url: 'https://api.github.com/users/SeojinSeojin/orgs',
repos_url: 'https://api.github.com/users/SeojinSeojin/repos',
events_url: 'https://api.github.com/users/SeojinSeojin/events{/privacy}',
received_events_url: 'https://api.github.com/users/SeojinSeojin/received_events',
type: 'User',
site_admin: false
},
html_url: 'https://github.com/SeojinSeojin/python_web-scrapping_practice',
description: '웹 스크래핑 연습',
fork: false,
url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice',
forks_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/forks',
keys_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/keys{/key_id}',
collaborators_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/collaborators{/collaborator}',
teams_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/teams',
hooks_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/hooks',
issue_events_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/issues/events{/number}',
events_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/events',
assignees_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/assignees{/user}',
branches_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/branches{/branch}',
tags_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/tags',
blobs_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/blobs{/sha}',
git_tags_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/tags{/sha}',
git_refs_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/refs{/sha}',
trees_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/trees{/sha}',
statuses_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/statuses/{sha}',
languages_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/languages',
stargazers_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/stargazers',
contributors_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/contributors',
subscribers_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/subscribers',
subscription_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/subscription',
commits_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/commits{/sha}',
git_commits_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/commits{/sha}',
comments_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/comments{/number}',
issue_comment_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/issues/comments{/number}',
contents_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/contents/{+path}',
compare_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/compare/{base}...{head}',
merges_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/merges',
archive_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/{archive_format}{/ref}',
downloads_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/downloads',
issues_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/issues{/number}',
pulls_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/pulls{/number}',
milestones_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/milestones{/number}',
notifications_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/notifications{?since,all,participating}',
labels_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/labels{/name}',
releases_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/releases{/id}',
deployments_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/deployments',
created_at: '2020-03-01T01:49:51Z',
updated_at: '2021-02-19T15:43:06Z',
pushed_at: '2020-07-13T13:26:54Z',
git_url: 'git://github.com/SeojinSeojin/python_web-scrapping_practice.git',
ssh_url: 'git@github.com:SeojinSeojin/python_web-scrapping_practice.git',
clone_url: 'https://github.com/SeojinSeojin/python_web-scrapping_practice.git',
svn_url: 'https://github.com/SeojinSeojin/python_web-scrapping_practice',
homepage: '',
size: 20,
stargazers_count: 0,
watchers_count: 0,
language: 'Python',
has_issues: true,
has_projects: true,
has_downloads: true,
has_wiki: true,
has_pages: false,
forks_count: 0,
mirror_url: null,
archived: false,
disabled: false,
open_issues_count: 0,
license: null,
forks: 0,
open_issues: 0,
watchers: 0,
default_branch: 'master',
permissions: { admin: true, push: true, pull: true }
}
배열 형식으로 출력되고, 다 쓰기엔 너무 많아서 하나의 repo는 무슨 정보들을 갖고 있는지 보면 위의 형식과 같이 출력된다.
정말 많은 정보들이 출력되는데.. 그 중 가장 감동적인건 language_url이었다.
어느 언어가 얼마나 쓰였는지 알려주는데, 이걸 찾으려고 github api를 사용한거라 정말 감격스러웠다.
ghrepos.listCommits(authOptions, 'seojinseojin', 'node-js_practice', function(err, refData) {
console.log(refData)
})
seojinseojin의 레포지토리 중 node-js_practice에 있는 모든 커밋들을 출력했을 때,
각 커밋들은 다음과 같은 JSON형식으로 출력된다.
{
sha: '832e32ccc0f49ad9bf288581e447d2c020677388',
node_id: 'MDY6Q29tbWl0MjgyODI4NTI0OjgzMmUzMmNjYzBmNDlhZDliZjI4ODU4MWU0NDdkMmMwMjA2NzczODg=',
commit: {
author: [Object],
committer: [Object],
message: 'github api - with noauth',
tree: [Object],
url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/git/commits/832e32ccc0f49ad9bf288581e447d2c020677388',
comment_count: 0,
verification: [Object]
},
url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/commits/832e32ccc0f49ad9bf288581e447d2c020677388',
html_url: 'https://github.com/SeojinSeojin/node-js_practice/commit/832e32ccc0f49ad9bf288581e447d2c020677388',
comments_url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/commits/832e32ccc0f49ad9bf288581e447d2c020677388/comments',
author: {
login: 'SeojinSeojin',
id: 48249505,
node_id: 'MDQ6VXNlcjQ4MjQ5NTA1',
avatar_url: 'https://avatars.githubusercontent.com/u/48249505?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/SeojinSeojin',
html_url: 'https://github.com/SeojinSeojin',
followers_url: 'https://api.github.com/users/SeojinSeojin/followers',
following_url: 'https://api.github.com/users/SeojinSeojin/following{/other_user}',
gists_url: 'https://api.github.com/users/SeojinSeojin/gists{/gist_id}',
starred_url: 'https://api.github.com/users/SeojinSeojin/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/SeojinSeojin/subscriptions',
organizations_url: 'https://api.github.com/users/SeojinSeojin/orgs',
repos_url: 'https://api.github.com/users/SeojinSeojin/repos',
events_url: 'https://api.github.com/users/SeojinSeojin/events{/privacy}',
received_events_url: 'https://api.github.com/users/SeojinSeojin/received_events',
type: 'User',
site_admin: false
},
committer: {
login: 'SeojinSeojin',
id: 48249505,
node_id: 'MDQ6VXNlcjQ4MjQ5NTA1',
avatar_url: 'https://avatars.githubusercontent.com/u/48249505?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/SeojinSeojin',
html_url: 'https://github.com/SeojinSeojin',
followers_url: 'https://api.github.com/users/SeojinSeojin/followers',
following_url: 'https://api.github.com/users/SeojinSeojin/following{/other_user}',
gists_url: 'https://api.github.com/users/SeojinSeojin/gists{/gist_id}',
starred_url: 'https://api.github.com/users/SeojinSeojin/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/SeojinSeojin/subscriptions',
organizations_url: 'https://api.github.com/users/SeojinSeojin/orgs',
repos_url: 'https://api.github.com/users/SeojinSeojin/repos',
events_url: 'https://api.github.com/users/SeojinSeojin/events{/privacy}',
received_events_url: 'https://api.github.com/users/SeojinSeojin/received_events',
type: 'User',
site_admin: false
},
parents: [ [Object] ]
}
object 형식인 committer은
{
name: 'SeojinSeojin',
email: '1106laura@naver.com',
date: '2021-02-22T14:56:15Z'
}
tree는
{
sha: '3168f6305d238ada53ed978b130bc66403efd9fe',
url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/git/trees/3168f6305d238ada53ed978b130bc66403efd9fe'
}
위의 정보들을 위의 형식으로 보여준다.
커밋 자체에 대한 출력보다는 committer, author의 정보를 더 많이 출력해주는 느낌이었다.
사실 내가 얻고 싶던 건 그 커밋을 이루고 있는 언어들의 양이었는데.. 그런 정보는 없어서 정말 슬프다.
listCommits()를 위의 listUser()와 엮어서 쓴다면 해당 유저의 레포지토리에 있는 모든 커밋들을 출력할 수 있다.
ghrepos.listUser(authOptions, "seojinseojin", (err, repolist) => {
repolist.forEach((repo) => {
ghrepos.listCommits(authOptions, "seojinseojin", repo.name, (err, refData) => {
console.log(`\nRepository : ${repo.name} by ${repo.owner.login}`)
refData.forEach((ref) => {
console.log(`${ref.commit.author.date}\n${ref.commit.committer.name} committed : ${ref.commit.message}`)
})
})
})
})
이 외에도 좋은 API들이 많으니.. 꼭 사용해보시길 바란다!!