본문 바로가기
JAVA

[Java] Github API 통신

by 햄과함께 2020. 12. 11.
320x100

참고 : github-api.kohsuke.org/


의존성 추가

mvnrepository.com/artifact/org.kohsuke/github-api

버전은 일단 제일 최신 버전! 1.117을 클릭

난 gradle을 쓰기 때문에 gradle 클릭. 내용을 복사한다.

dependencies {
	// add
	compile group: 'org.kohsuke', name: 'github-api', version: '1.117'
}

build.gradle 파일, dependencies 블록에 붙여넣는다.


통신 확인

package javaStudy;

import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubBuilder;

import java.io.IOException;

public class GithubApi {

    public void connectGithub(String token) throws IOException {
        GitHub github = new GitHubBuilder().withOAuthToken(token).build();
        github.checkApiUrlValidity();
    }
}

일단 문서를 보며 인증을 하는 코드를 먼저 테스트해보자.

package javaStudy;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.fail;

class GithubApiTest {

    GithubApi githubApi = new GithubApi();

    @Test
    void test() {
        String token = "<Persional Access Token>"; // 생성한 토큰
        try {
            githubApi.connectGithub(token);
        } catch (Exception e) {
            fail();
        }
    }

}

테스트 코드는 위와 같이 작성했다. Exception이 발생하면 인증실패라 인식, 테스트 실패라고 판단했다.

<Persional Access Token>에는 깃허브에서 직접 생성한 토큰을 넣는다.

깃허브 사이트에서 우측 상단 Settings 클릭.

좌측하단에 Developer settings 클릭.

Persional access token > Generate new token.

흠흠. 대충 읽어보니 repo에 대한 권한만 있으면 될 것 같으니 일단 repo만 체크하고 생성했다.

하다가 권한때문에 안되면 그 때 다시 확인해보자.

 

생성된 토큰을 복사하여 token 변수에 세팅한 뒤 테스트를 실행해본다.

성공!

잘못된 토큰을 넣으면 AssertionFailedError가 발생하여 테스트가 실패한다.

코드를 짜면서 중간중간 테스트를 실행하면서 성공하고 있는지 확인해줬다.


이제 과제를 하면서 깃허브 통신을 해보자.

요구사항은 특정 레포의 이슈들을 탐색하면서 참석자들의 참석율을 계산한다.

하나의 이슈에 댓글을 남긴 경우 참석했다고 가정한다.

 

// main/java/javaStudy/GithubApi.java

package javaStudy;

import org.apache.commons.lang3.tuple.Pair;
import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHIssueState;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubBuilder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;

public class GithubApi {

    public List<Pair<String, Double>> getParticipationRates(String token, String repoName) throws IOException {
        GitHub github = new GitHubBuilder().withOAuthToken(token).build();
        github.checkApiUrlValidity();

        GHRepository repo = github.getRepository(repoName);
        List<GHIssue> issues = repo.getIssues(GHIssueState.ALL);

        // key = name, value = cnt
        Map<String, Integer> memberCnts = new HashMap<>();
        for (GHIssue issue : issues) {
            // get participants name
            List<String> participantNames = issue.getComments().stream().map(comment -> {
                try {
                    return comment.getUser().getName();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }).distinct().collect(toList());

            participantNames.forEach(name -> memberCnts.merge(name, 1, Integer::sum));
        }

        int issueCnt = issues.size();
        List<Pair<String, Double>> participationRate = new ArrayList<>();
        for (String key : memberCnts.keySet()) {
            participationRate.add(Pair.of(key, (double)memberCnts.get(key) / issueCnt * 100));
        }
        return participationRate;
    }
}

사용한 함수는 다음과 같다.

GitHubBuilder.withOAuthToken(String oauthToken) oauthToken 세팅한 GithubBuilder 생성
GHRepository.getRepository(String name) name으로 레포 조회
GHRepository.getIssues(GHIssueState state) state(OPEN, CLOSED, ALL) 조건을 만족하는 이슈들 조회
GHIssue.getComments() 이슈 comment 정보들 조회
GHIssueComment.getUser() comment 작성한 User 정보 조회
GHPerson.getName() User의 이름 조회

로직 작성하면서 stream 내부에서 comment의 유저정보, 이름을 가져오게 작성하였는데 반드시 예외처리해야 하는 checked Exception인 IOException을 throw 할수도 있는 함수들이라 에러가 발생했다.

그래서 IOException을 catch 하는 경우 unchecked exception인 RuntimeException으로 예외를 변경하여 throw 하게했다.

// test/javaStudy/GithubApiTest.java

package javaStudy;

import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.fail;

class GithubApiTest {

    GithubApi githubApi = new GithubApi();

    @Test
    void githubConnectTest() {
        String token = "<token>";
        String repoName = "fpdjsns/Tetris";

        List<Pair<String, Double>> rates = new ArrayList<>();
        try {
            rates = githubApi.getParticipationRates(token, repoName);
        } catch (Exception e) {
            fail();
        }

        rates.forEach(rate -> System.out.println(rate.getLeft() + ": " + rate.getRight()));
    }

}

확인은 먼저 내 레포로!

테스트는 성공했고 결과는 withham 이 27.77777777777778 의 확률로 코멘트를 달았다라고 한다.

나 혼자하는 레포이기에 참석자는 항상 나뿐이다.

Open, Closed 레포는 총 18개이고 이들 중 덧글이 달린 이슈는 총 5개이다.

하나의 이슈에는 덧글이 2개 달려있는데 둘 다 내가 단 것이기 때문에 하나의 이슈에 동일인물이 2개 이상의 덧글을 단 경우 한 명으로 체크되는지도 확인가능하다.

이제 계산 타임!  5 / 18 * 100  

27.777777777777778

계산기 결과와 테스트 결과가 약간 다른데 어디에서 반올림 하냐의 차이이다. -> 오차로 보겠다.

결과가 같으므로 과제를 해결하기 위해 테스트 코드에서 repoName을  whiteship/live-study 으로 바꿔서 테스트를 다시 돌린다.

결과 나오는데 시간이 좀 걸린다.

결과 중 내 것만 가져와봤다. 허헣. 다시 열심히 하자..!


참고용 소스코드 : github.com/fpdjsns/study/tree/main/java/reference/githubApi

320x100

'JAVA' 카테고리의 다른 글

[Java] 이진검색트리(BST) 구현  (0) 2020.12.19
[Java] 클래스, 객체  (0) 2020.12.19
[Java] 연결리스트(Linked List), Stack, Queue 구현  (0) 2020.12.12
[Java] 선택문, 반복문  (0) 2020.12.10
[Java] JUnit5 테스트  (1) 2020.12.10

댓글