Yarn workspace + Lerna + GitHub Actions + S3 + CloudFront
ํ์ฌ ์ฐธ์ฌ ์ค์ธ ํ๋ก์ ํธ๋ Yarn workspace + Lerna ๊ธฐ๋ฐ ๋ชจ๋
ธ๋ ํฌ ๊ตฌ์กฐ๋ก ๊ด๋ฆฌ๋๊ณ ์์ผ๋ฉฐ,
GitHub Actions๋ฅผ ์ด์ฉํ CI/CD ์๋ํ ํ์ดํ๋ผ์ธ์ด ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
์ง์ ์ฒ์๋ถํฐ ์์ฑํ ์คํฌ๋ฆฝํธ๋ ์๋์ง๋ง,
์ ์ฒด์ ์ธ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๊ณ , ์ค๋ฌด์์ ๋ฐ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ฑฐ๋
ํ๊ฒฝ ๋ณ์ ์๋ํ, ์๋ฆผ ์กฐ๊ฑด ์ฒ๋ฆฌ ๋ฑ ์ผ๋ถ ๋ก์ง์ ํบ์๋ณด๊ณ ๊ฐ์ ยทํ์ฅํ์ต๋๋ค.
์ด ๊ธ์์๋ ์ด CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์กฐ์ ์๋ ๋ฐฉ์, ๊ทธ๋ฆฌ๊ณ ์ ๊ฐ ์ดํดํ ํฌ์ธํธ๋ฅผ ๊ณต์ ํ๋ ค ํฉ๋๋ค.
root
โโโ packages
โ โโโ admin
โ โโโ common
โ โโโ design-system
โ โโโ ...
โโโ .github
โ โโโ workflows
โ โโโ deploy.yml
Lerna์ --scope ์ต์ ์ ์ฌ์ฉํ์ฌ, ๋ณํฉ๋๋ release-* ๋ธ๋์น์ ๋ฐ๋ผ ํด๋น ํจํค์ง๋ง ๋น๋๋๋๋ก ๊ตฌ์ฑํ์ต๋๋ค.
run: yarn lerna run build:prod --scope=@fe/${{ steps.extract.outputs.PACKAGE_NAME }}
PACKAGE_NAME์ ๋ธ๋์น๋ช
์์ ์๋ ์ถ์ถ
release-{package_name} โ PACKAGE_NAME
GitHub Actions์์ ๋ธ๋์น๋ช ์ ๊ธฐ์ค์ผ๋ก production / stage ํ๊ฒฝ์ ํ๋จํ๊ณ , ๊ฐ ํ๊ฒฝ์ ๋ง๋ secret ๊ฐ์ .env ํ์ผ๋ก ์์ฑํฉ๋๋ค.
echo "PACKAGE_NAME=$(echo ${{ github.ref_name }} | cut -d '-' -f2)" >> $GITHUB_OUTPUT
if [[ ${{ github.ref_name }} == master ]]; then
echo "env=production" >> $GITHUB_OUTPUT
else
echo "env=stage" >> $GITHUB_OUTPUT
fi
run: aws s3 sync ${{ steps.extract.outputs.PACKAGE_NAME }}/dist s3://{PACKAGE_NAME}-prod
- run: aws cloudfront create-invalidation --paths "/*"
release-* ๋ธ๋์น๋ stage๋ก master ๋ณํฉ ์, production์ผ๋ก ๋ฐฐํฌ
๋ฐฐํฌ ํ CloudFront ์บ์ ๋ฌดํจํ๊น์ง ์๋ ์ฒ๋ฆฌํ์ฌ ์ฆ๊ฐ ๋ณ๊ฒฝ์ด ๋ฐ์๋๋๋ก ์ฒ๋ฆฌ
- if: failure()
uses: ./.github/actions/slack-notify
with:
slack_incoming_url: ${{ secrets.SLACK_INCOMING_URL }}
- if: success()
uses: ./.github/actions/slack-notify
with:
status: success
์ฑ๊ณต/์คํจ์ ๋ฐ๋ผ ์ฌ๋์ผ๋ก ์๋ฆผ์ ๋ณด๋
๋๋ค.
์คํจ ์์๋ ๋น๋ ๋ก๊ทธ๋ฅผ ํจ๊ป ํ์ธํ ์ ์๋๋ก ์ค์ ํ ์๋ ์์ต๋๋ค.
if [[ "$BRANCH_NAME" == release-* ]]; then
git push origin --delete $BRANCH_NAME
release-* ๋ธ๋์น๊ฐ master์ ๋ณํฉ๋๋ฉด ์๋์ผ๋ก ์ญ์ ๋์ด
๋ธ๋์น ์ ๋ฆฌ๋ฅผ ์๋์ผ๋ก ํ์ง ์์๋ ๋ฉ๋๋ค.
echo "PACKAGE_NAME=$(echo ${{ github.ref_name }} | cut -d '-' -f2)" >> $GITHUB_OUTPUT
ํญ์ release-*-*
ํํ์ ๋ธ๋์น๋ช
์ ๊ณ ์ํด์ผ CI/CD๊ฐ ๋์ํฉ๋๋ค.
๋ธ๋์น๋ช
์ด release๋ก ์์ํ๋ฉด stage ํ๊ฒฝ,master์ด๋ฉด prod ํ๊ฒฝ.
*-*
์ ์กฐํฉ์ ํจํค์ง๋ช
๊ทธ๋ ์ง๋ง ์ค์(?)๋ก ์คํ๊ฐ ์๊ธธ ์๋ ์๊ณ , ๋ค์ด๋ฐ ์ปจ๋ฒค์ ๋ณ๊ฒฝ์ ๊ณ ๋ คํ ๋ CI/CD๋ ์์ ์ด ํ์ํ๊ฒ ๋ฉ๋๋ค. ์ค์ ๋ก ์ ๋ฌด ์ค ๊ธํ ์ผ์ด ์์ด ํด๋น ์ปจ๋ฒค์ ๋ช ์ ๋ฐ๋ฅด์ง ์์ ๋ธ๋์น๋ฅผ ๋ฐฐํฌํ ์ ์ด ์์๊ณ ๋ฐฐํฌ๊ฐ ์คํจํด์ ๋นํฉํ๋ ์ ์ด ์์์ต๋๋ค.
๊ทธ๋ผ ์ด๋ป๊ฒ ?!
1. github PR Label ํ์ฉํ๊ธฐ
ํ์ฌ PROD-release
, DEV-release
๋ผ๋ ํ๊ทธ๋ฅผ ์ฐ๊ณ ์์ต๋๋ค.
ํ๋๋ master ๋ณํฉ์ฉ release๋ธ๋์น PR ํ๊ทธ
๋ค๋ฅธ ํ๋๋ develop ๋ณํฉ์ฉ relese ๋ธ๋์น PR ํ๊ทธ ์
๋๋ค.
git action์์๋ ์ด ๋ผ๋ฒจ ํ๊ทธ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค๊ณ ํ๋ ์ด๊ฑธ ๊ธฐ์ค์ผ๋ก ํ๊ฒฝ๋ณ์ ์ค์ ์ ํ๋ค๋ฉด ์ด๋ ๋ธ๋์น ์ปจ๋ฒค์
์์๋ ๋ฌธ์ ๊ฐ ์์ ๊ฒ ๊ฐ์ต๋๋ค!
2. lerna changed
ํจํค์ง๋ช
๊ฐ์ ๊ฒฝ์ฐ๋ lerna์์ ๋ณ๊ฒฝ์ ๊ฐ์งํ ์ ์์ด์ (lerna changed)
๊ผญ ๋ธ๋์น๋ช
์ ํจํค์ง๋ช
์ ๋ช
์ํ์ง ์์๋ ์์์ ๋ณ๊ฒฝ์ด ์๋ ํจํค์ง๋ฅผ ๋น๋ํ๊ฒ ํ ์ ์๋ค๊ณ ํฉ๋๋ค.
ํ์ฌ ๋ชจ๋
ธ๋ ํฌ ๊ตฌ์กฐ์์ CI/CD๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋๊ณ ๊ด๋ฆฌ๋๋์ง๋ฅผ ์กฐ๊ธ์ด๋๋ง ์ดํดํ ์ ์์์ต๋๋ค.
์ด๊ธฐ์๋ ์ด๋ ค์ ์ง๋ง ๋น๋, ๋ฐฐํฌ, ์บ์ ๋ฌดํจํ, slack ์๋ฆผ, ๋ธ๋์น ์ ๋ฆฌ๊น์ง์ ๊ณผ์ ์ ์จ์ ํ ์ดํดํ ์ ์์๊ณ ์์ฌ์ด ์ ๋ ๋ฐ๊ฒฌํ ์ ์์์ต๋๋ค. ์์ฌ์ด ์ ์ ์ง๊ธ๊น์ง ์ ์ง๋์ด์จ ์ปจ๋ฒค์
์ ๋ฐ๊ฟ ํ์๊ฐ ์์ด ํฐ ๋ฌธ์ ์์ผ๋, ์ถํ์ ์๊ฐ์ด ๋๋ค๋ฉด ๊ผญ ๊ฐ์ ํด๋ณด๊ณ ์ถ์ ๋ถ๋ถ์
๋๋ค :D