Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.

Probot으로 GitHub App 만들기

ProbotGitHub App을 쉽게 만들 수 있는 프레임워크다. 기존에 사용하던 GitHub Service는 2018년 10월 1일부로 더는 지원하지 않기 때문에 앞으로 GitHub에서 기능을 확장하거나 통합하려면 GitHub App을 사용해야 한다.

Probot 로고

Probot은 Node.js로 만들어진 프레임워크인데 알게 된 지는 좀 되었지만 몇 달 전부터 사용을 해보고 있다. 사용해 보니 GitHub App을 쉽게 만들 수 있게 인터페이스나 도구가 잘 갖추어져 있다. 만들기는 쉬운데 뭘 만들지가 더 어렵다.

Probot으로 만든 앱 목록을 보면 GitHub App으로 어떤 기능을 구현할 수 있는지 알 수 있고 전부 오픈소스이므로 비슷한 기능을 개발할 때 참고해서 사용할 수 있다.

Stale이 동작한 댓글

Stalemocha에서처럼 이슈에 일정 시간 동안 활동이 없으면 더는 활동이 없으면 닫겠다고 알린 뒤에 해당 시간이 지나면 이슈를 닫는다.

Lock Threads가 잠근 댓글

Henry Zhu가 An Issue with Issues에서 이미 닫힌 이슈에 사람들이 글을 계속 남겨서 관리 부담이 커지는 것을 막기 위해서 Babel에서 Lock Threads를 이용해서 이슈를 잠갔다.

Probot으로 GitHub App 만들기

최초 앱 구조를 만들기 쉽도록 create-probot-app을 제공하고 있다.

$ npx create-probot-app ping-app
npx: 227개의 패키지를 4.522초만에 설치했습니다.
Let's create a Probot app!
? App name: ping-app
? Description of app: An example app
? Author's full name: Outsider
? Author's email address: 
? Homepage:
? GitHub user or org name: outsideris
? Repository name: ping-app
created file: /Users/outsider/example/ping-app/.env.example
created file: /Users/outsider/example/ping-app/.gitignore
created file: /Users/outsider/example/ping-app/.travis.yml
created file: /Users/outsider/example/ping-app/CODE_OF_CONDUCT.md
created file: /Users/outsider/example/ping-app/CONTRIBUTING.md
created file: /Users/outsider/example/ping-app/LICENSE
created file: /Users/outsider/example/ping-app/README.md
created file: /Users/outsider/example/ping-app/index.js
created file: /Users/outsider/example/ping-app/package.json
created file: /Users/outsider/example/ping-app/.github/CODEOWNERS
created file: /Users/outsider/example/ping-app/test/index.test.js
created file: /Users/outsider/example/ping-app/test/fixtures/issues.opened.json
Finished scaffolding files!

Installing Node dependencies!

npm notice created a lockfile as package-lock.json. You should commit this file.
added 995 packages from 533 contributors in 31.587s
[+] no known vulnerabilities found [22357 packages audited]


Done! Enjoy building your Probot app!

위 명령어로 필요한 모든 파일을 만들어주고 필요한 npm 모듈도 설치해 준다.

GitHub App은 보통 개발자가 앱을 GitHub에 등록하고 이 앱을 저장소에 설치하면 해당 저장소에서 이벤트를 받아서 Probot이 처리하게 된다. 서버를 공개적으로 배포했다면 상관없지만, 로컬에서 개발할 때는 GitHub이 로컬 Probot 서버에 웹 훅을 바로 보낼 수 없으므로 프락시 서버를 두어야 한다. Probot 팀에서는 smee.io라는 서비스를 만들어서 제공하고 있다. 이를 사용하면 GitHub의 웹 훅을 smee.io가 대신 받아서 로컬 서버에 보내주기 때문에 개발을 편하게 할 수 있다.

앞에서 만들어진 .env.example 파일을 .env 파일로 복사한다. 이 내용은 아래와 같다.

# The ID of your GitHub App
APP_ID=
WEBHOOK_SECRET=development

# Use `trace` to get verbose logging or `info` to show less
LOG_LEVEL=debug

# Go to https://smee.io/new set this to the URL that you are redirected to.
WEBHOOK_PROXY_URL=

smee.io에서 "Start a new channel"을 누르면 아래처럼 새로운 프락시 URL을 만들어 준다.

smee.io에서 새로 만든 채널

위의 .env 파일의 WEBHOOK_PROXY_URLsmee.io의 URL을 지정한다.

WEBHOOK_PROXY_URL=https://smee.io/Sc5IsuyKfj06PeqM

Developer settings 아래 Register new GitHub App에서 새로운 GitHub 앱을 등록할 수 있다.

GitHub App 등록화면

앱의 이름을 지정하고 Webhook URL에 위의 smee.io URL을 입력한다.. Webhook secret에는 .envWEBHOOK_SECRET에 있는 development를 입력한다.

GitHub App의 권한 설정

하단 Permissions 부분에서는 사용할 권한을 지정한다. 이는 나중에 앱을 설치할 때 설치하는 사람에게 어떤 권한을 쓰는지 알려주게 된다. 예를 들어 이슈 내용을 가져올 것이면 Issues를 "Read-only"로 지정하면 되고 앱이 댓글도 남기려면 "Read & write"로 지정하면 된다.

GitHub App의 이벤트 구독 설정

지정한 권한에 따라 웹 훅을 받을 이벤트를 체크한다. 여기선 예제로 Issues 이벤트만 받도록 지정했다. 마지막으로 아직 테스트 중이므로 "Only on this account"를 선택해서 내 계정에서만 사용할 수 있게 지정했다.

등록한 앱의 ID 확인과 키 생성

앱을 등록하고 나면 Basic information 중간에서 등록된 앱 ID를 볼 수 있다. 이 ID를 .env 파일의 APP_ID=에 지정한다. Generate a private key를 클릭하면 ping-example-app.2018-07-29.private-key.pem와 같은 키 파일이 다운로드되는데 이를 프로젝트 루트 위치로 이동시킨다.

GitHub 앱 설치

등록한 앱을 GitHub 저장소에 설치해야 사용할 수 있다.

GitHub 앱 설치화면

현재는 내 계정에서만 설치할 수 있으므로 앱 설정 화면에서 설치할 수 있다.

GitHub 앱 설치화면

사용할 저장소를 지정한 뒤에 설치한다.

Probot 서버 테스트

앞에서 만들어진 index.js의 내용은 다음과 같다.

/**
 * This is the entry point for your Probot App.
 * @param {import('probot').Application} app - Probot's Application class.
 */
module.exports = app => {
  // Your code here
  app.log('Yay, the app was loaded!')

  app.on('issues.opened', async context => {
    app.log('hello');
    const issueComment = context.issue({ body: 'Thanks for opening this issue!' })
    return context.github.issues.createComment(issueComment)
  })

  // For more information on building apps:
  // https://probot.github.io/docs/

  // To get your app running against GitHub, see:
  // https://probot.github.io/docs/development/
}

app.on('issues.opened', async context => {})부분이 GitHub의 이벤트를 받는 부분이다. 이슈가 열렸을 때 발생하는 이벤트인 issues.opened가 웹 훅으로 오면 이 함수가 실행된다. 여러 이벤트를 받을 때는 app.on(['issues.opened', 'issues.closed'], callback)처럼 받으면 된다. 이벤트 이름은 GitHub 문서에서 확인할 수 있는데 이벤트 이름과 종류를 조합해서 사용하면 된다.

그리고 context.github.issues.createComment는 댓글을 남기는 함수이다. 즉, 이슈가 만들었지만 앱이 Thanks for opening this issue!라는 댓글을 남기게 된다. 여기서 context.github@octokit/rest의 객체이므로 GitHub API에 필요한 부분은 Octokit 문서를 확인하면 된다.

$ npm start

> ping-app@1.0.0 start /Users/outsider/Dropbox/projects/temp/ping-app
> probot run ./index.js

13:15:03.322Z  INFO probot: Yay, the app was loaded!
13:15:03.439Z  INFO probot: Forwarding https://smee.io/Sc5IsuyKfj06PeqM to http://localhost:3000/
13:15:03.442Z  INFO probot: Listening on http://localhost:3000
13:15:04.239Z  INFO probot: Connected https://smee.io/Sc5IsuyKfj06PeqM
13:15:04.546Z DEBUG github: GitHub request: GET /app/installations - 200 OK (installation=undefined)
  params: {
    "per_page": 100,
    "baseUrl": "https://api.github.com",
    "request": {
      "timeout": 0
    }
  }
13:15:05.101Z DEBUG github: GitHub request: POST /installations/:installation_id/access_tokens - 201 Created (installation=264944)
  params: {
    "installation_id": "264944",
    "baseUrl": "https://api.github.com",
    "request": {
      "timeout": 0
    }
  }
13:15:06.194Z DEBUG github: GitHub request: GET /installation/repositories - 200 OK (installation=264944)
  params: {
    "per_page": 100,
    "baseUrl": "https://api.github.com",
    "request": {
      "timeout": 0
    }
  }

위처럼 npm start로 서버를 시작하고 GitHub에서 새로운 이슈를 만들면 smee.io를 통해 아래처럼 웹 훅을 받게 된다.

13:15:47.256Z DEBUG probot: Webhook received
  event: {
    "event": "issues.opened",
    "id": "816ee850-9331-11e8-847b-59be5276fdff",
    "installation": 264944,
    "repository": "outsideris/cla-checker"
  }
13:15:47.265Z  INFO probot: hello
13:15:47.922Z DEBUG github: GitHub request: POST /repos/:owner/:repo/issues/:number/comments - 201 Created (id=816ee850-9331-11e8-847b-59be5276fdff, installation=264944)
  params: {
    "number": 17,
    "owner": "outsideris",
    "repo": "cla-checker",
    "body": "Thanks for opening this issue!",
    "baseUrl": "https://api.github.com",
    "request": {
      "timeout": 0
    }
  }
13:15:47.925Z  INFO http: POST / 200 - 670.04 ms (id=70fc935d-fab6-4af4-8f83-20f4de2a7e2d)
13:15:47.929Z  INFO probot: POST http://localhost:3000/ - 200

만든 probot이 댓글을 남긴 이슈

ping-example-app에 아이콘을 올리지 않아서 내 아이콘이 사용되었지만 새로 만든 이슈에 제대로 달린 것을 볼 수 있다.

smee.io에 저장된 웹훅 페이로드

smee.io를 보면 전달된 웹 훅이 다 기록되어 있고 이를 재전송할 수 있다. GitHub과 연동해서 만들어야 하므로 이슈를 등록했다가 오류가 있으면 이슈를 다시 등록해서 테스트해야 하므로 smee.io의 이런 기능은 개발할 때 무척 편리하다.

설치과정이 좀 복잡했지만, 내용은 아주 어렵지 않다. 특히 인터페이스가 잘 되어 있어서 아주 쉽게 GitHub에서 필요한 부분을 자동화할 수 있다.

2018/07/29 22:34 2018/07/29 22:34

기술 뉴스 #106 : 18-07-15

웹개발 관련

  • Here are examples of everything new in ECMAScript 2016, 2017, and 2018 : ECMAScript에 새로운 기능이 계속 추가되는 상황이라 새로 추가된 걸 모르거나 한번 알았다가도 손에 익기 전에 까먹는 경우도 많은데 이 글에 ECMAScript 2016, 2017, 2018 별로 추가된 기능과 사용법이 한 번에 잘 정리되어 있어서 확인하기 좋다.(영어)
  • 배민찬은 Vue를 어떻게 사용하나요? : 배민찬 서비스에서 jQuery를 사용하던 레거시에 Vue를 도입한 과정을 설명한 글이다. 반응형 웹이 아니라 믹스인과 확장을 이용해서 공통부분을 재사용하고 DOM 접근이 필요한 곳에는 디렉티브를 만들어서 적용한 과정이 잘 나와 있다.(한국어)
  • Progressive Web Apps : PWA를 만드는 방법을 설명한 글이다. PWA의 특징을 설명하고 기본이 되는 Service Woker, manifest 작성 방법 등이 나와 있다.(한국어)
  • A Real-World WebAssembly Benchmark : 브라우저에서 PDF 문서를 볼 수 있는 PSPDFKit의 SDK를 Web Assembly로 구현하고 벤치마크를 통해 각 브라우저에서 Web Assembly와 JavaScript 구현체와의 성능 비교를 했다. Firefox를 제외하고는 아직 Web Assembly가 아주 빠르진 않은데 각 브라우저가 Web Assembly에 대한 개선 계획을 어떻게 잡고 있는지까지 정리되어 있다.(영어)
  • 산업별 자바스크립트 사용 현황 : JavaScript 사용에 대한 설문은 꽤 많지만, 업계별 사용을 정리한 JavaScript Usage by Industry를 번역한 글이다. 마케팅, IT, 정부, 교육 등 산업별로 어떤 도구와 프레임워크를 사용하고 다른 언어는 어떤 걸 사용하는지 정리한 글인데 다른 업계에서 일해본 적은 없지만 업계별 특징이 나온다는 점이 재미있다.(한국어)

그 밖의 프로그래밍 관련

  • Goodbye Microservices: From 100s of problem children to 1 superstar : Segment에서 2015년에 마이크로서비스 아키텍처를 도입했다가 다시 Monolith로 돌아간 과정을 설명한 글이다. 어떤 문제 때문에 2015년에 MSA를 도입했고 처음에는 잘 동작했고 저장소도 100여 개로 분리했지만, 시간이 지나면서 운영상의 부담이 너무 커져서 다시 단일 저장소로 합치고 기존에 있던 문제를 해결한 과정이 아주 잘 나와 있다. MSA냐 Monolith냐의 문제보다 어떤 이유로 MSA가 좋다고 생각했고 어떤 이유로 Monolith가 좋다고 생각했는지가 잘 나와 있다.(영어)
  • 커맨드라인 JSON 프로세서 jq : 개발하다 보면 파일이나 API를 통해서 JSON을 많이 다루게 되는데 이 때 편리한 jq의 사용방법을 정리한 글이다. jq를 익혀두면 JSON 데이터를 쉽게 확인하거나 조작할 수 있어서 아주 유용한데 처음 사용할 때는 문법이나 사용방법이 어색할 수 있다. 이 글에서 jq의 동작 방식이 자세하게 나와 있다.(한국어)
  • Python 3.7의 새로운 기능들 : Cool New Features in Python 3.7의 번역 글로 최근에 나온 Python 3.7의 기능을 정리한 글이다. 편리한 breakpoint(), 데이터 클리스, 타이핑 등 추가 기능의 사용법과 배경이 잘 나와 있다.(한국어)
  • Compiler in JavaScript using ANTLR : MongoDB의 Compass를 지원하면서 다른 언어로 작성한 쿼리를 컴파일하는 작업을 바탕으로 ANTLR로 JavaScript를 Python으로 컴파일 하는 과정을 설명한다. AST나 컴파일러에 대한 개념을 설명하고 이때 사용할 수 있는 도구나 개념들을 소개한 뒤에 ANTLR로 어떻게 JavaScript 코드를 UAST로 만들어서 Python으로 변환하는지를 자세히 보여주고 있다.(영어)
  • 도커(Docker) 컨테이너 로케일 설정 : Debian이나 Ubuntu로 Docker를 사용할 때 기본 로케일 설정이 POSIX라서 한글 입력이 안 되는 문제를 해결하기 위해 LC_ALL=C.UTF-8로 설정하거나 로케일을 설치해서 한글을 입력할 수 있게 하는 방법을 설명한다.(한국어)

볼만한 링크

  • 8년째 같은 제품을 만들고 있습니다 : Ridibooks의 CTO인 남현우 님이 8년간 Ridibooks를 만들면서 오래 가는 제품을 만들려면 어떻게 해야 할지에 대한 생각을 정리한 발표자료다. 개발에서 흔히 하듯이 제품개발도 컴포넌트로 만들어서 조립해야 한다는 이야기인데 그 생각을 풀어가는 과정에 많은 고민이 담겨있어서 재미있게 봤다.(한국어)
  • 스타트업에서 전화응대 고객센터 간단히 구축하기 : LG U+ 인터넷 전화의 REST API를 이용해서 고객 전화가 올 때 사용자로 등록되어 있으면 슬랙에 사용자 정보를 보여주도록 한 과정을 설명하고 있다. 고객대응을 직접 해본 적은 없어서 이런 생각을 해본 적은 없는데 C/S 담당자가 일일이 어드민에서 조회해 보지 않고도 편하게 정보를 확인하고 기록할 수 있는 좋은 방법인 것 같다.(한국어)

IT 업계 뉴스

  • [python-committers] Transfer of power : Python 언어를 만든 귀도 반 로섬이 Python의 의사 결정에서 물러나기로 했다.(영어)
  • Postmortem for Malicious Packages Published on July 12th, 2018 : 지난 12일 ESLint 메인테이너 중 한 명의 계정이 해킹당하면서 eslint-scope@3.7.2eslint-config-eslint@5.0.2가 npm 레지스트리에 배포되었다. 이 버전을 설치하면 pastebin.com에서 코드를 받아서 실행하면서 사용자의 .npmrc를 공격자에게 보내도록 해 사용자의 npm 토큰을 탈취할 수 있게 되었다. 위 두 버전은 현재 npm 레지스트리에서 제거되었고 위 버전을 설치한 적이 있다면 토큰을 탈취당했을 수 있으므로 주의해야 한다.(영어)

프로젝트

  • termtosvg : 터미널을 SVG 애니메니션으로 녹화하는 Python 도구.
  • vim.wasm : WebAssembly로 Vim을 웹 브라우저에 포팅한 프로젝트.
  • Badgen : README 파일 등에서 주로 사용하는 상태 배지를 URL에 색과 텍스트를 지정하면 만들어주는 서비스.

버전 업데이트

2018/07/15 23:50 2018/07/15 23:50