이번 포스팅은 쇼핑몰 컨셉이다. 빰빠빠. 빰빠빰. 빠라 빠라바라 빠밤밤.
이런!
github action이 한 두개가 아니라고요? action을 돌릴 때마다 너무 느려 답답하다고요? 그런 당신을 위해 준비했습니다!
dependency, build caching하는 방법, 절찬리 공개 중!
자, 지금부터 제가 소개할것은 그리 대단한것은 아니지만 엄청난 걸 소개해드리려고 합니다!
actions/cache 액션을 사용해서 캐싱하는 방법입니다. 자, 아래의 코드를 보시죠!
name: Caching with npm
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Install Dependencies
run: npm install
- name: Build
run: npm build
- name: Test
run: npm test
key
갑작스러운 코드에 놀라지마시고 key에 주목해주세요! 캐시를 저장할 때 생성되는 키입니다. 캐싱된 데이터를 찾을 때 이 key를 사용합니다. 실행 context에서 가져온 package-lock.json 파일을 해싱해서 키로 저장합니다. 만약 key가 그대로면 캐싱된 파일을 찾아서 사용하고, key가 바뀌었다면 변경사항이 있다고 판단해 다시 install 합니다. 👍
runner.os
runner.os에는 운영체제가 들어갑니다. ubuntu를 쓰고 있으니 Linux가 들어가겠군요.
restore key
만약 key로 못찾았다면 restore key에 매치되는 또 다른 키를 찾아 사용합니다. 사용되는 순서는 위에서 아래부터입니다.
인생은 실전!
이제 캐싱한 dependency를 다른 job에서 사용해보겠습니다. main 브랜치에 Pull Request를 날릴 때마다 실행되는 workflow.yml 파일입니다.
자 하나하나 파헤쳐 볼까요?
name: Pull Request CI
on:
pull_request:
branches:
- main
env:
CACHED_DEPENDENCY_PATHS: ${{ github.workspace }}/node_modules
CACHED_BUILD_PATHS: ${{ github.workspace }}/.next
BUILD_CACHE_KEY: ${{ github.sha }}
jobs:
job_install_dependencies:
name: Install Dependencies
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out current commit (${{ github.sha }})
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v1
- name: Compute dependency cache key
id: compute_lockfile_hash
run: echo "::set-output name=hash::${{ hashFiles('package-lock.json') }}"
- name: Check dependency cache
uses: actions/cache@v2
id: cache_dependencies
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ steps.compute_lockfile_hash.outputs.hash }}
- name: Install dependencies
# use '.', not '[]' with hyphenated variables
# https://github.com/nektos/act/issues/104#issuecomment-592892249
if: steps.cache_dependencies.outputs.cache-hit == ''
run: npm install
outputs:
dependency_cache_key: ${{ steps.compute_lockfile_hash.outputs.hash }}
job_build:
name: Build
needs: job_install_dependencies
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out current commit (${{ github.sha }})
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v1
- name: Check dependency cache
uses: actions/cache@v2
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}
- name: Check build cache
uses: actions/cache@v2
id: cache_built_packages
with:
path: ${{ env.CACHED_BUILD_PATHS }}
key: ${{ env.BUILD_CACHE_KEY }}
- name: Build packages
if: steps.cache_built_packages.outputs.cache-hit == ''
run: npm run build
outputs:
dependency_cache_key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}
job_audit:
name: Audit
needs: job_build
# ... 생략
job_size_check:
name: Size Check
needs: job_build
timeout-minutes: 15
runs-on: ubuntu-latest
if: ${{ github.head_ref }}
steps:
- name: Check out current commit (${{ github.sha }})
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v1
- name: Check dependency cache
uses: actions/cache@v2
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ needs.job_build.outputs.dependency_cache_key }}
- name: Check build cache
uses: actions/cache@v2
with:
path: ${{ env.CACHED_BUILD_PATHS }}
key: ${{ env.BUILD_CACHE_KEY }}
- name: Check bundle sizes
uses: andresz1/size-limit-action@v1.4.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
skip_step: build
env path
- CACHED_DEPENDENCY_PATHS: install dependency가 위치한 경로입니다.
- CACHED_BUILD_PATHS: build 폴더가 위치한 경로입니다.
- BUILD_CACHE_KEY: github commit hash code 입니다.
env:
CACHED_DEPENDENCY_PATHS: ${{ github.workspace }}/node_modules
CACHED_BUILD_PATHS: ${{ github.workspace }}/.next
BUILD_CACHE_KEY: ${{ github.sha }}
install dependency
install job을 추가해줍니다. job_install_dependencies는 다른 job에서도 쓰일 이름이니 최대한 직관적으로 적어주세요.
Compute dependency cache key 스텝에서는 위에서 말한 대로 package-lock.json 파일을 해시하여 hash라는 이름으로 output을 저장합니다.
Check dependency cache 스텝에서는 actions/cache를 사용해 캐시된 dependency가 있는지 체크합니다. key: ${{ steps.compute_lockfile_hash.outputs.hash }}를 보니 step id인 compute_lockfile_hash의 outputs.hash 키로 확인하고 있군요.
그 다음 cache-hit가 false라면 npm install을 합니다. 만약 cache-hit가 true라면 install 하지 않겠지요?
jobs:
job_install_dependencies:
name: Install Dependencies
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out current commit (${{ github.sha }})
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v1
- name: Compute dependency cache key
id: compute_lockfile_hash
run: echo "::set-output name=hash::${{ hashFiles('package-lock.json') }}"
- name: Check dependency cache
uses: actions/cache@v2
id: cache_dependencies
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ steps.compute_lockfile_hash.outputs.hash }}
- name: Install dependencies
# 하이픈 변수에는 '[]'가 아니라 '.'을 사용하세요
# https://github.com/nektos/act/issues/104#issuecomment-592892249
if: steps.cache_dependencies.outputs.cache-hit == ''
run: npm install
outputs:
dependency_cache_key: ${{ steps.compute_lockfile_hash.outputs.hash }}
아니 이럴수가! 정말 실행되지 않았군요. 놀랍게도 install이 23초 밖에 안걸렸습니다!
build
job_build:
name: Build
needs: job_install_dependencies
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out current commit (${{ github.sha }})
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v1
- name: Check dependency cache
uses: actions/cache@v2
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}
- name: Check build cache
uses: actions/cache@v2
id: cache_built_packages
with:
path: ${{ env.CACHED_BUILD_PATHS }}
key: ${{ env.BUILD_CACHE_KEY }}
- name: Build packages
if: steps.cache_built_packages.outputs.cache-hit == ''
run: npm run build
outputs:
dependency_cache_key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}
- needs: job_install_dependencies : 위의 job name이 기억나시나요? 앞의 job이 선행되어야 한다는 걸 뜻합니다! 아래처럼 직렬로 실행될지 병렬로 실행될 지 알 수 있습니다.
- Check dependency cache: install job의 output인 dependency key로 캐싱된 파일을 찾습니다.
- Check build cache: env 에서 정한 build cache key를 사용해 cache된 파일을 찾습니다.
- cache-hit가 true면 캐싱 파일을 사용하고 false면 build 합니다.
- outputs: 다음 job에서는 install의 output을 모르기 때문에 build job에서 한 번 더 dependency_cache_key를 output으로 저장합니다.
do something
이제는 캐시된 dependency와 build 파일을 갖다쓰기만 하면 됩니다. needs로 job_build 가 선행되어야 함을 알려줍시다. 그리고 dependency key와 build key로 캐시 파일을 체크하고 그 다음 원하는 액션을 실행시켜주시면 됩니다!
job_size_check:
name: Size Check
needs: job_build
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- name: Check out current commit (${{ github.sha }})
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v1
- name: Check dependency cache
uses: actions/cache@v2
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ needs.job_build.outputs.dependency_cache_key }}
- name: Check build cache
uses: actions/cache@v2
with:
path: ${{ env.CACHED_BUILD_PATHS }}
key: ${{ env.BUILD_CACHE_KEY }}
- name: Check bundle sizes
uses: andresz1/size-limit-action@v1.4.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
skip_step: build
자, 잘 붙었습니다! 당신도 이제 팀에서 멋진 CI 꾼이 될 수 있습니다!
"이 포스팅을 통해 action을 손쉽고 빠르게 사용할 수 있게 되었어요!"
지금 당장 github action cache를 사용해보세요!
사용을 원하시는 분들은 아래 링크를 참고해주세요.
- https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows
- https://github.com/actions/cache
- sentry workflow 참고
캄사합니다! 😉
'개발 이야기 > 실무 Recipe' 카테고리의 다른 글
여러 개의 docker-compose 파일 사용하기 | multiple docker-compose files (0) | 2021.03.18 |
---|---|
Zapier로 Google Form과 Slack 연동하기 | 구글 폼 응답 올 때마다 슬랙 알림 오게 하는 방법 (0) | 2021.03.06 |
git으로 함께 일하기 | merge 전략, PR, 커밋 컨벤션 (0) | 2021.02.24 |
[GraphQL] Connection, Edge, Node (0) | 2021.02.07 |
[실무레시피] 자바스크립트로 바코드 이미지 생성하기 | JsBarcode, bwip-js (0) | 2021.02.01 |