Hakyll 로 블로그를 돌리게 되면 컨텐츠를 등록할 때마다 다음 절차를 실행해야 합니다.
매 번 이렇게 하기에는 성가신 작업입니다.
이렇게 하면 나머지는 자동으로 했으면 좋겠습니다. 이럴 때 Github Action 을 쓰면 됩니다. 이 전에는 Travis Ci, Circle Ci 등을 이용했다고 하는데, 2019년 말에 Github 자체에도 push, pull 등의 이벤트가 발생하면 자동으로 실행되는 기능이 생겼습니다.
이렇게 실행되는 작업을 workflow 라 부릅니다. workflow 는 여러 개 액션들의 조합으로 이루어집니다.
workflow 를 실행하는 머신을 runner 라고 부르는데, 클라우드 호스트라고 생각하면 됩니다. workflow 실행은 호스트를 준비하는 것으로부터 시작합니다. 매 번 이렇게 호스트를 올리는게 비효율적인 것 같긴 한데, Github 의 runner 관리 입장에서 보면 효율적인 설계일 수도 있겠습니다.
처음 workflow 를 실행할 때는 40분 가까이 걸렸고, 캐싱을 사용하면서부터 3분정도의 시간이 걸립니다. workflow 로그를 보면, 아직도 하스켈 설치에 1분, 캐싱에서 파일을 풀어서 설치하는데 1분정도가 걸립니다. todo: 하스켈 설치 폴더도 캐싱 작업을 걸어두면 더 빨라질 것 같다.
(workflow 문법: Workflow syntax for GitHub Actions)
name: Haskell CI
on:
push:
branches: [ master ]
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-haskell@v1
with:
ghc-version: '8.8.3'
cabal-version: '3.2.0'
- name: Cache
uses: actions/cache@v1
env:
cache-name: cache-cabal
with:
path: ~/.cabal
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}- - name: Install dependencies
run: |
cabal update
cabal install --only-dependencies - name: Build
run: cabal build
- name: Build Site
run: cabal exec lionhairdino build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
publish_dir: _site
publish_branch: master
External_repository: lionhairdino/lionhairdino.github.io
사이트 소스와 공개된 사이트를 위해 두 개의 저장소를 만듭니다.
sitSource 저장소에 workflow 를 걸어 두는데, 작업 말미에 결과를 lionhairdino.github.io 저장소에 커밋하려면 보안을 위해 ssh 키 쌍을 등록해 둬야 합니다. (peaceiris/actions-gh-pages 액션을 보면 workflow 를 걸어 둔 저장소와 같은 저장소로 커밋할 때는 github_token 을 쓰고, 다른 저장소에 커밋할 때는 deploy_key 를 씁니다. peaceiris / actions-gh-pages)
siteSource 에 public 키를, lionhairdino.github.io 에 private 키를 등록합니다.
VS Code를 이용한다면 Settings -> Extensions -> Git -> Post Commit Command를 push로 선택하면 됩니다. 아마도 다른 툴들도 비슷한 post 액션 설정이 있을겁니다.
2021.04.29 추가
Caching dependencies to speed up workflows
cache
액션은 현재 실행되는 workflow
를 가진 branch
에서 key
또는 restore-keys
가 일치하는 캐시를 찾습니다. 현재 branch
에서 일치하는 캐시가 없을 때는 부모 branch
와 upstream branch
에서 찾습니다.
key
로 못찾으면 사용할 restore key
목록을 지정할 수 있습니다. 자세한 이름에서 덜 자세한 이름 순서로 지정해서 매칭을 시도합니다.
복원키 지정
restore-keys: |
npm-foobar-${{ hashFiles('package-lock.json') }}
npm-foobar- npm-
npm-foobar-XXX
복원키는 npm-foobar-XXX
로 시작하는 모든 키와 매치하고,
npm-foobar-
복원키는 npm -foor-
로 시작하는 모든 키,
npm-
복원키는 npm-
로 시작하는 모든 키와 매치됩니다.
여려개가 매치되면 가장 최근에 생성한 캐시를 선택합니다.
캐시는 7일동안 접근이 없으면 지워집니다. 캐시 개수의 제한은 없고, 전체 캐시를 위한 용량은 5GB로 제한됩니다. 용량이 꽉차면 오래된 것부터 자동으로 지웁니다evicting.
출력 매개 변수 cache-hit
로 key
와 정확히 일치한 캐시가 있는지 여부를 알 수 있습니다. key
와 정확히 일치하는 캐시를 찾으면 true
, 아니면 false
캐시 액션의 위치는 체크 아웃 바로 다음이 적당한 듯 합니다.
- uses: actions/checkout@v2
- name: Cache
uses: actions/cache@v2
캐싱을 제대로 써먹지 못할 때가 많아, install dependency 에서 30분 이상 소요되어 아예 GHC를 설치할 필요없이 Hakyll 바이너리를 올려서 사이트를 생성하게 바꾸었습니다.
name: Haskell CI
on:
push:
branches: [ master ]
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: decompress lionhardino
run: gzip -d ~/work/*****/*****/hakyllBinary.gz
- name: Build Site
run: ~/work/*****/*****/hakyllBinary build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
publish_dir: _site
publish_branch: master
External_repository: lionhairdino/lionhairdino.github.io
hakyll 바이너리를 만들면 120MB쯤 되는데, github가 100MB가 넘어가는 파일은 받지 않기 때문에 압축을 해서 올리고 실행할 때 풉니다. 이렇게 하니, GHC를 설치할 필요도, 의존 파일들을 설치할 필요도, 캐싱할 필요도 없어 액션 실행 시간이 13초로 줄었습니다. 음, 처음부터 왜 이렇게 셋팅하지 않았나 싶은데, 아마도 막연히 바이너리를 돌리는 게 까다로울 거란 생각을 했었나 봅니다.
2021.05.24 추가
UPX를 이용해 하킬 바이너리를 압축하니 용량이 120MB가 넘던 파일이 24MB로 줄어들었습니다. 굳이 압축해서 올렸다 압축을 푸는 번거로움을 없앨 수 있게 되었습니다. 위 코드에서
- name: decompress lionhardino
run: gzip -d ~/work/*****/*****/hakyllBinary.gz
이제 이 부분을 삭제해도 됩니다.
https://dixonary.co.uk/blog/haskell/small 하스켈로 만든 바이너리가 너무 클 때 참고할만한 블로그입니다.