์ด๊ฑฐ ๋ณด์ญ์์ค!!! ์ ๊ฐ ๋ฉ์ง ๊ฒ์ ํด๋์ต๋๋ค!!!
ํฌํฌ ๋ฟ๋ฏโ๐ป์ด๋ฐ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํด๋ณธ ๊ฒ ์ฒ์์ด๋ผ ๋ง์ด ํค๋งธ๋ค. ๋๊ฐ์ ์ด๋ณด์๋ค์ด ์ดํดํ๊ธฐ ์ฝ๊ฒ ์์ฑํด๋ณด๊ฒ ๋ค.
๐๐ปโ๏ธ Github Actions๋?
CI/CD ํด์ด๋ค. Jenkins, CircleCI, TravisCI ๋ฑ์ ๋ค๋ฅธ ํด๋ค๋ ์์ง๋ง Github Actions์ ๊ฒฝ์ฐ Github์์ ์ ๊ณตํ๋ CI/CD ํด์ด๋ผ๋ ๊ฒ ํฐ ์ด์ ์ด๋ค.
๐ฉ๐ป๐ป ์ ์ฉ ๋ฐฉ๋ฒ
- ํ๋ก์ ํธ ์ต์๋จ์
.github
ํด๋ ์์ฑ - ๊ทธ ์์
workflows
ํด๋ ์์ฑ - ๊ฐ๋ณ workflow ํ์ผ ์์ฑ. ํ์ฅ์๋
.yml
์ ์ฌ์ฉํ๋ค. ํ์ผ๋ช ์ ์์ ๋กญ๊ฒ ์ง์ผ๋ฉด ๋๋ค.
๋๋ CI ๋ผ๋ ์ด๋ฆ์ workflow๋ฅผ ์์ฑํ๋ค. ํ์ผ๋ช ์ ci.yml๋ก ์ง์๋ค. workflow๋ ๋ง๊ทธ๋๋ก ์ผ๋ จ์ ๋์๋ค์ ์๋ฏธํ๋ค. ํน์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ์๋์ผ๋ก ์คํํ ์์ ๋ค์ ๋์ดํด๋๋ฉด, Github Actions๊ฐ ์ด๋ฅผ ์คํํด์ฃผ๋ ๊ฒ์ด๋ผ๊ณ ์ดํดํ๋ค.
Github์ด ์ ๊ณตํ๋ ํ ํ๋ฆฟ ํ์ฉํ๊ธฐ
Github์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ํ ํ๋ฆฟ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ฐฑ์ง ์ํ์์ ์ ์ผ๋ ค๋ฉด ๋ฌด์ฒ์ด๋ ๋ง๋งํ๋ค. Github ๋ ํฌ์งํ ๋ฆฌ์์ Actions ํญ์ ํด๋ฆญํ๋ฉด, ์ ๊ณต๋๋ ์ฌ๋ฌ ๊ฐ์ง ํ ํ๋ฆฟ์ ํ์ธํ ์ ์๋ค. ์๋ ํ๋ฉด์ set up a workflow yourself ๋ฅผ ํด๋ฆญํ๋ฉด ๊ฐ์ฅ ๊ธฐ๋ณธ ํ ํ๋ฆฟ์ด ๋์จ๋ค.
์ ํ๋ฉด์์ ์์ฑ์ ์์ํด๋ณด์.
workflow๋ฅผ ์ด๋ฃจ๋ ๊ฐ๋ณ ์์๋ค ์ดํดํ๊ธฐ
- name: workflow์ ์ด๋ฆ์ ์๋ฏธํ๋ค. ์๋ฌด๋ ๊ฒ๋ ์ง์ด๋ ์๊ด์๋ค.
- on: ํด๋น workflow๋ฅผ ํธ๋ฆฌ๊ฑฐํ ์ด๋ฒคํธ๋ฅผ ๋ช ์ํ๋ค. ex) main ๋ธ๋์น์ pull request๊ฐ ๋ฐ์ํ์ ๋ ์ผ๋ จ์ ์์ ๋ค์ ์ํํ๋ค.
- jobs: ํ workflow๋ ์ฌ๋ฌ ๊ฐ์ job์ ๊ฐ์ง ์ ์๋ค. ๊ฐ๋ณ job์ ์ฌ๋ฌ ๊ฐ์ step๋ค๋ก ์ด๋ค์ง๋ค. job์ ํ์์ step๋ค์ ์์ฑํ๋ฉด ๋๋ค. step๋ค์ ์ฐจ๋ก๋๋ก ์คํ๋๊ณ , job๋ค์ ๋ณ๋ ฌ์ ์ผ๋ก ์คํ๋๋ค. ์ด๋ ๊ฐ๋ณ step์ action์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. action์ workflow์์์ ๊ฐ์ฅ ์์ ๋จ์๋ค.
์ดํดํ๊ธฐ ์ฝ๊ฒ ์ค์ ์ฝ๋์ ํ์๋ฅผ ํด๋ดค๋ค. ๋ฏผํธ์ ์ฌ๊ฐํ์ด ๊ฐ๋ณ job์ด๊ณ , ํํฌ์ ์ฌ๊ฐํ์ด ๊ฐ๋ณ step์ด๋ค. ๋ฏผํธ์ ์ฌ๊ฐํ ๋ด์ ํํฌ์ ์ฌ๊ฐํ์ด ์ฌ๋ฌ ๊ฐ ์๋ค.
์ ๋ฐ์ ์ธ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๋ค๋ฉด, ์ด์ ๋ ์ด๋ค ์์ ๋ค์ ํ ์ง๋ฅผ ์์ฑํด์ผ ํ๋ค. (๊ฐ step์ ์์ฑํด์ผ ํ๋ค.)
action ์์ฑํ๊ธฐ
CI๋ฅผ ์ฒ์ ์ ํ๋ ์ด๋ณด์ ์ ์ฅ์์ ๊ฐ๋ณ ๋จ๊ณ๋ฅผ ๊น์ด ์ดํดํ๊ธด ์ด๋ ต๋ค๊ณ ์๊ฐํ๋ค. ์ง๊ทนํ ์ด๋ณด์ ์์ค์์ ์๊ฒ ์์๋ณด์.
action(๊ฐ๋ณ step)์ ์์ฑํ๋ ๋ฐฉ๋ฒ์๋ ํฌ๊ฒ ๋ ๊ฐ์ง๊ฐ ์๋ค. ์ฒซ์งธ๋ ์ด๋ฏธ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์์ฑํด๋์ ๊ฑธ ๊ทธ๋๋ก ๊ฐ์ ธ๋ค ์ฐ๋ ๊ฒ์ด๊ณ , ๋๋ฒ์งธ๋ ์ง์ ์์ฑํ๋ ๊ฒ์ด๋ค. ์ ์์ ๊ฒฝ์ฐ uses ํค์๋๋ก ์ฌ์ฉํ๊ณ ์ ํ๋ action๋ช ์ ๋ช ์ํ๋ค. ํ์์ ๊ฒฝ์ฐ run ํค์๋๋ก ์คํํ๊ณ ์ ํ๋ CLI ๋ช ๋ น์ด๋ฅผ ์์ฑํ๋ค.
action์ ์ธ ์ข ๋ฅ๋ก ๋๋ ์ ์๊ฐํด๋ณด๊ฒ ๋ค. ๊ฐ๋ณ action์ ์์ธํ ์ดํดํ ํ์๋ ์๋ค.
- ํ์ action
- ๊ฐ์ฅ ์ต๊ทผ commit์ checkout ํ๊ธฐ
uses: actions/checkout@v3
- node ์ธํ
ํ๊ธฐ
uses: actions/setup-node@v1
- ์์กด์ฑ ์ค์นํ๊ธฐ
run: yarn install
- ๊ฐ์ฅ ์ต๊ทผ commit์ checkout ํ๊ธฐ
- ์ถ๊ฐํ๋ฉด ์ข์ action
- ์์กด์ฑ ์บ์ฑํ๊ธฐ
uses: actions/cache@v3
: CI๋ฅผ ํ ๋๋ง๋ค ์์กด์ฑ์ ์๋กญ๊ฒ ์ค์นํ๋ ๊ฒ์ ๋นํจ์จ์ ์ด๋ค. ์ด์ CI์ ์์กด์ฑ์ด ๋์ผํ ๊ฒฝ์ฐ ์บ์ฑ๋ ๊ฐ์ ์ฌ์ฉํ๋ค.
- ์์กด์ฑ ์บ์ฑํ๊ธฐ
- ์ค์ CI action
- lint
- test: ๋ณ๊ฒฝ๋ ์ฝ๋์ ๋ํ ํ ์คํธ
- build
์๋ง ๋ค๋ค ๋์ฒ๋ผ 3๋ฒ์ ํด๋นํ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ณ ์ถ์ด์ Github Actions๋ฅผ ๊ตฌ๊ธ๋ง ํ์ํ ๋ฐ, ๋ญ ํ๋์ง ๋ชจ๋ฅด๊ฒ ๋ ์ฌ๋ฌ ์ฝ๋๋ค์ด ์ถ๊ฐ๋์ด ์์ด์ ์ ์์ด ๋นํฉํ์ ๊ฒ์ด๋ค๐ ์ ๋ถ๋ฅ๋ฅผ ์ฐธ๊ณ ํ๋ค๋ฉด ๊ตฌ๊ธ๋ง ํด์ ๋์จ ์ฝ๋ ์ค ํ์ํ ๊ฒ์ ์ทจ์ฌ์ ํ ํ๋๋ฐ ๋์์ด ๋ ๊ฒ์ด๋ค.
((์ฌ์ค))
์ฌ์ค ๋ด๊ฐ ๊ฐ์ฅ ์๋ฌธ์ด์๋ ๊ฑด ๋์ฒด CI์ ๋ญ ์ถ๊ฐํด์ผํ๋๊ฐ? ์๋ค. ํ๋ก์ ํธ ๋ผ๋๋ถํฐ ์ก๊ณ ์๋ ๋จ๊ณ๋ผ ์์ง ํ ์คํธ ์ฝ๋๊ฐ ์๋๋ฐ?
๊ทธ๋์ ๋ฌด์ฒ ์์ฌํ๊ฒ ์ฒซ ์ง๋ฌธ์ ์ฌ๋ ธ๋๋ฐ ํ์๋ถ๋ค์ด ๋๋ ์น์ ํ๊ฒ ๋ตํด์ฃผ์ จ๋ค ๐ฅบ ๊ฐ๋
๊ฐ๋ ์ ๋ฐ๋ ํธ
๐ ๋ด๊ฐ ์์ฑํ workflow
name: CI
on: # main ๋ธ๋์น์ push ํน์ PR์ด ๋ฐ์ํ์ ๋ ์๋ ๊ธฐ์ ํ ์์
๋ค์ ์ํํ๋ค.
push:
branches: ['main']
pull_request:
branches: ['main']
env: # jobs์์ ์ฌ์ฉ๋ ์ ์๋ ์ ์ญ ์์๊ฐ์ ์ ์ธํ๋ ๊ฒ์ด๋ผ๊ณ ์ดํดํ๋ฉด ๋๋ค.
CACHED_DEPENDENCY_PATHS: ${{ github.workspace }}/.yarn/unplugged
DEFAULT_NODE_VERSION: '16'
jobs:
job_continuous_integration: # job์ ์ด๋ฆ
runs-on: ubuntu-latest # ubuntu ํ๊ฒฝ์์ ์คํํ ๊ฒ์์ ๋ช
์
steps:
- name: Checkout current commit # action์ name์ ๋ง๋๋ก ์ง์ด๋ ๋๋ค.
uses: actions/checkout@v3 # ์ต๊ทผ commit์ checkout
- name: Set up Node
uses: actions/setup-node@v1 # node setup
with:
node-version: ${{ env.DEFAULT_NODE_VERSION }}
- name: Compute dependency cache key # ์บ์ฑ key๋ฅผ ๊ณ์ฐํ๋ค.
id: compute_lockfile_hash
run: echo "::set-output name=hash::${{ hashFiles('yarn.lock') }}"
- name: Check dependency cache # key์ ๋ํ ์บ์๊ฐ์ด ์๋์ง ํ์ธํ๋ค.
uses: actions/cache@v3
id: cache_dependencies
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ steps.compute_lockfile_hash.outputs.hash }}
- name: Install dependencies # ์ผ์นํ๋ ์บ์๊ฐ์ด ์์ ๊ฒฝ์ฐ ์์กด์ฑ์ ์๋ก ์ค์นํ๋ค.
if: steps.cache_dependencies.outputs.cache-hit == ''
run: yarn install
- name: Check lint # lint๋ฅผ ์งํํ๋ค.
run: yarn lint
outputs:
dependency_cache_key: ${{ steps.compute_lockfile_hash.outputs.hash }}
์ฃผ์์ ๋งค์ฐ๋งค์ฐ ์์ธํ ๋ฌ์๋๋ค. ์ฐธ๊ณ ๊ฐ ๋์ผ๋ฉด ์ข๊ฒ ๋ค!
โ ์ ์๋๋๋ ์ง ํ์ธํ๊ธฐ
๊ทน ์์ฌ์ด์ธ ๋๋ ๋ด๊ฐ ์์ฑํ ์ํฌํ๋ก์ฐ๊ฐ ์ ๋๋ก ์๋ ์๋๋ฉด ์ด์ฉ์ง๊ฐ ๋ฌด์ฒ์ด๋ ๊ฑฑ์ ๋๋ค ^_^ ๊ทธ๋ ์ง๋ง ์๋ฌด๋ฆฌ ๊ตฌ๊ธ๋ง์ ํด๋ ์ ์๋ํ๋์ง์ ๋ํ ๋ฐฉ๋ฒ์ ๋์ค์ง ์์๋ค... ๋๊ฐ์ ์ฌ๋๋ค์ ์ํด ํน์ ๋ชฐ๋ผ ์ถ๊ฐํ๋ ๋ด์ฉ
๊ฒฐ๋ก ๋ถํฐ ์ด์ผ๊ธฐํ์๋ฉด, ๋ ํผ์งํ ๋ฆฌ์ push๋ฅผ ํ๊ณ , main ๋ธ๋์น์ PR์ ๋ ๋ฆฌ๋ฉด ๋๋ค. ๊ทธ ํ Actions ํญ์ ํ์ธํด๋ณด๋ฉด ๋ด ์ํฌํ๋ก์ฐ๊ฐ ์ ์๋ํ๋์ง ํ์ธํ ์ ์๋ค. ์๋ ์ฌ์ง ์ฒ๋ผ ๋ง์ด๋ค.
workflow ์์ฒด์ ๋ฌธ์ ๊ฐ ์์ผ๋ฉด Startup failure
๊ฐ ๋ฌ๋ค. (๋๋ ์ค์๋ก ์ค๊ดํธ ํ๋๋ฅผ ๋นผ๋จน์์๋ค.) workflow์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง ๋ด ์ฝ๋๊ฐ CI๋ฅผ ํต๊ณผํ์ง ๋ชปํ์ ๊ฒฝ์ฐ, ์ผ์ชฝ์ X ์์ด์ฝ์ด ๋ฌ๋ค. ํด๋ฆญํด๋ณด๋ฉด ์๋ ์ฌ์ง์ฒ๋ผ ์ CI๋ฅผ ํต๊ณผํ์ง ๋ชปํ๋์ง, ๊ฐ step์ ์ผ๋ง์ ์๊ฐ์ด ์์๋์๋์ง๋ ํ์ธํ ์ ์๋ค.
+) ๋ก์ปฌ์์ Github Actions๋ฅผ ํ ์คํธํด๋ณผ ์ ์๋ ํด๋ ์กด์ฌํ๋ค.
์ฌ์ฉํด๋ดค์๋๋ฐ, ๋์ปค์ ๋ฌธ์ ๊ฐ ์๋๊ฑด์ง yarn ๋ช ๋ น์ด๊ฐ ์คํ์ด ์๋๋ค. yarn ๋ช ๋ น์ด ์ด์ ๊น์ง ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋ค. ์ฌ์ฉ๋ฒ์ด ๊ทธ๋ฆฌ ์ด๋ ต์ง ์์ผ๋ ํ์ํ์ ๋ถ๋ค์ ํ ๋ฒ ์๋ํด๋ณด์๊ธธ!
References
github action cache ํ๊ธฐ
React Native CI/CD using GitHub Actions - LogRocket Blog
Github Action์ ๋ํ ์๊ฐ์ ์ฌ์ฉ๋ฒ
๋งค.์ฐ.๋ฟ.๋ฏ. ๋๋ ์ฌ๋ฐ๋น