Jekyll Project에 CI 적용기
이 포스트는 MeuWorks 페이지에서도 확인할 수 있습니다.
문제
현재 당신이 보고 있는 MeuWorks의 사이트는, jekyll serve
기능을 이용해 작동하고 있었다. 그러나 이럴 경우, Jekyll의 프로세스가 죽으면 더 이상 사이트를 표시할 수 없다는 단점을 가지게 된다.
그래서 필자는 jekyll build
명령어를 이용해서 빌드된 사이트를 Nginx를 통해 바로 표시할 수 있게끔 방향을 틀었다.
근데 여기서 또다른 문제가 생겼다. 파일이 라이브로 업데이트 되지 않기 때문에 이 Jekyll 사이트에 포스트를 추가한 사람이 매번 Build 스크립트를 돌려주어야 한다는 것이다.
해결 전 두뇌 속 삽질
필자는 본 Jekyll 사이트의 소스 백업 목적으로 개설한 Git을 활용해보기로 했다.
Github, Gitlab 그리고 Bitbucket 같은 온라인 레포지터리 저장소들은, Webhook이라는 것을 지원한다.
본 사이트의 소스코드를 담고있는 1) Gitlab 저장소에 새로운 Commit이 Push되면, 2) Jekyll을 호스팅하는 서버에 이를 알리고 3) jekyll build
명령어를 이용하여 새로 서버를 빌드한다.
즉, 우리가 할 일은 그냥 _post 폴더에 게시글 작성하고 이를 깃에 추가하면 사이트가 자동으로 새로고침 되는 것이다!
구상도
해결 과정
1. Webhook 생성하기
Gitlab의 Jekyll 프로젝트에서 Webhook을 생성했다. 아래의 사진에도 나왔지만, Project - Settings - Intergration으로 가면 된다.
URL은 이 Webhook을 받아 처리해야할 서버로 연결되는 URL 주소다.
새로운 커밋이 Push 되었을 때, 이를 알려주는 역할을 수행하면 되므로 Trigger에 Push events를 체크한다. 이 설정에 따라 새로운 커밋이 올라오면 Gitlab이 Webhook의 URL에 요청을 보낼 것이다.
필요한 설정을 한 뒤, Add webhook을 눌러 설정을 저장한다.
2. Webhook 핸들링
Gitlab에서 보낸 Webhook을 받아서 처리하는 부분을 만들어야한다.
자신이 주로 사용하는 웹 프레임워크를 이용하면 금방 만들 수 있을 것이라 생각한다.
핸들링을 위해 서버가 갖추어야 할 최소 요구조건을 정리해보았다.
1. POST 요청을 받아야한다.
2. 헤더의 x-gitlab-token이 서버 내에 정의된 토큰값과 일치하는지 확인해야한다.
3. 정의된 토큰값과 일치하면, Git 저장소를 pull 할 수 있는 함수와 빌드 함수를 실행할 수 있어야 한다.
필자가 추천하는 프레임워크는 node.js다. 위 링크를 타고 들어가면 보이는 스니펫을 조금만 수정한다면, 바로 서버 하나를 만들어낼 수 있다.
MeuWorks의 킹갓엠페러충무공마제스티제네럴디벨롭먼트마스터이신 Syr이 node.js를 기반으로 서버를 쉽게 만들어주셨다. 간단하게나마 소스코드를 참고하고 싶다면, 여기를 참조하라.
3. Node.js 서버 포트포워딩 및 테스트
포트포워딩을 설정하기 이전에 Syr이 알려준 아이디어로, ‘어차피 같은 로컬 네트워크 안에 있으니, URL을 로컬 주소로 설정하면 되지 않겠냐’ 라는 의견을 줬다.
그 방법이 더 안전할 것이라고 생각해서, Gitlab의 URL을 로컬주소로 바꾸고 테스트를 해보았는데 오류가 발생했다.
Gitlab::HTTP::BlockedUrlError (URL 'http://10.0.1.102:3001/push' is blocked: Requests to the local network are not allowed):
lib/gitlab/proxy_http_connection_adapter.rb:17:in `rescue in connection'
lib/gitlab/proxy_http_connection_adapter.rb:14:in `connection'
...
(생략)
Requests to the local network are not allowed
즉, 로컬네트워크로 요청을 보내는 것이 허용되지 않았다. 라는 의미다.
그래서 그냥 포트포워딩을 이용해 Node.js가 사용하는 포트를 열어주기로 했다.
설정 하나를 건드릴 때 마다 재시작을 요구하는 멋진 공유기를 통해 다운타임을 만들고, 설정을 끝냈다!
이제 테스트를 진행하자.
테스트를 위해 Syr가 만들어준 Node.js 프로젝트를 수정했다.
서버를 띄우고, Webhook 요청이 들어오면 echo "Hi!"
를 실행하도록 프로젝트 내의 config.json 파일을 수정했다.
이제, Gitlab의 Intergration 설정에서 Webhook을 테스트해보자.
위에서 Add한 웹훅은, 새롭게 Webhook을 만드는 곳 아래에 리스팅된다.
오른쪽의 Test 버튼을 눌러 드롭다운 리스트를 열고, Push events를 눌러 테스트를 진행하자.
Hook이 성공적으로 작동됐다는 알림이 나왔다! 이제, 서버의 출력에 “Hi!”가 나왔는지 확인해보자.
Hi!
잘 작동된다!
4. Webhook 요청을 받았을 때, Jekyll 빌드 시키기
이제 Webhook을 받았을 때 실행되는 스크립트를 수정하고, 위의 Node.js 서버를 계속 구동시키면 우리가 원하던 구성을 만들 수 있다.
config.json 파일을 열어, 기존의 echo "Hi!"
를 지우고, Jekyll을 업데이트 하고 빌드 할 스크립트로 대체했다.
### UPDATE_JEYKLL.sh
#1. Jekyll 폴더로 이동해야 한다.
cd /home/****/*****/****
#2. Jekyll 폴더 내의 파일들을 Git 저장소에서 Pull 해 업데이트 해야한다.
git pull
#3. Build된 파일들은 다른 위치에 저장되어야한다.
JEKYLL_ENV=production bundle exec jekyll build --destination /home/****/*****/
그리고 서버는, nohup npm run start &
로 실행해서, 백그라운드에서 돌아가게끔 했다.
5. 실제로 잘 작동하는지 확인하기.
Git에 새로운 포스트(이 포스트)를 추가하고 추가 후 Push 한다면, MeuWorks 페이지의 모든 게시글에서 이 글을 확인할 수 있을 것이다.
이 글이 보인다면 성공!