github actions을 사용하면 CI/CD파이프라인을 매우 쉽게 구축할 수 있다.
이번에 dev 환경에서 새로운 기술을 익히는 프로젝트를 해보면서 실제 운영서버에 배포는 하지 않지만 CI라도 구축해보고자 하였고, github actions를 통해 쉽게 해낼 수 있었습니다. 이 포스팅에서는 github actions를 이용해 CI를 구축한 방법을 기록할 것입니다. 또한 CD도 같은 방법으로 하면 되니 추후에 CI/CD파이프라인을 구축할 일이 있을 때에 github actions를 이용하면 문제없이 할 수 있겠다는 생각을 했습니다.
workflows 추가
github repository에 들어가면 actions탭이 있습니다. 거기에서는 여러 workflows templates를 제공해주고 있습니다. 하지만 저는 로컬에서 직접 workflows를 만들어서 리모트에 푸시하는 방법으로 진행해보겠습니다.
프로젝트 폴더 루트 디렉터리에 .github 라는 이름으로 폴더를 만듭니다. 그리고 그 안에 workflows라는 이름의 폴더명을 만들고 그 안에 main.yml라는 파일을 만듭니다.
.github
ㄴworkflows
ㄴmain.yml
main.yml을 편집 모드로 열고 차근차근 작성해나가겠습니다.
우선 name과 on을 적어줍니다.
* main.yml
name: CI
on: [push, pull_request]
name은 workflows의 이름으로 보기 편한 이름을 지어주면 됩니다.
on은 이 workflow를 발생시킬 trigger event를 정의합니다. push를 하거나 pull request를 남기면 trigger 되도록 합니다.
push와 pull request는 merge된 기준으로 code를 통합하기에 test를 실행시킬 때 merge된 상태의 코드를 test 하게 됩니다.
그다음 jobs를 적어줍니다. jobs 안에는 할 작업 목록들을 적을 수 있고 이들은 병렬로 실행됩니다. 직렬로 실행하게 만들려면 의존 작업을 need: 안에 명시해줄 수 있습니다.
jobs:
job1:
job2:
위와 같이 적으면 job1과 job2는 병렬로 실행됩니다.
jobs:
job1:
job2:
needs: job1
그러나 위와 같이 job2 안에 needs: job1를 명시해주면 job2는 job1을 마치고 난 뒤에 실행됩니다.
job 안에는 runs-on으로 어떤 OS에서 실행할지를 명시할 수 있습니다. 저는 간단하게 ubuntu-lateset를 사용했습니다.
jobs:
test:
runs-on: ubuntu-latest
그다음으로는 steps를 적어줍니다 해당 job이 수행할 일들을 단계별로 적는 것입니다. 저는 cypress로 test를 하는 프로젝트였고 "checkout -> 환경변수 파일 생성 -> cypress install -> 유닛 테스트 실행 -> 통합 테스트 실행" 순으로 step을 정의했습니다. 여기서부터는 어떤 test 프레임워크를 사용하는지, 그리고 테스트 전략에 따라 커스터마이징이 필요합니다. 저의 경우에는 cypress 공식문서의 CI파트를 참조하여 steps들을 작성했습니다.
checkout step은 다음과 같이 작성합니다.
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
환경변수 파일은 .github/workflows 폴더 안에 scripts폴더를 만들고 그 안에 env.sh파일을 만들어서 사용했습니다.
* env.sh
#!/bin/bash
echo REACT_APP_HOST_URL=http://localhost:3000 >> .env
echo REACT_APP_API_URL=http://localhost:4000 >> .env
main.yml에서는 환경변수 파일을 만드는 step을 추가합니다.
* main.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create env file
shell: bash
run: |
touch .env
bash ./.github/workflows/scripts/env.sh
이후 step들은 cypress를 설치하고 test를 실행하는 과정입니다.
- name: Cypress install
uses: cypress-io/github-action@v2
with:
# Disable running of tests within install job
runTests: false
build: yarn build
- name: Cypress run unit
run: yarn test:unit:run
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run integration
uses: cypress-io/github-action@v2
with:
# Specify Browser since container image is compile with Firefox
browser: firefox
start: yarn start
이제 작업한 workflows를 리모트에 푸시해줍니다.
이제부터는 리모트에 push되거나 pull request가 생성되면 test를 자동으로 실행하게 됩니다.
로컬에서는 git hooks로 트리거를 만들 수 있다.
리모트에서의 잦은 테스트 실패를 줄이기 위해서 로컬에서도 자동으로 테스트를 돌리도록 할 수 있습니다.
git hooks를 사용하면 commit이나 push 등의 이벤트를 hooking하여 스크립트를 실행할 수 있습니다. 이때 테스트를 실행하도록 스크립트를 작성합니다. 저는 매 커밋마다 테스트를 실행하여 테스트를 통과해야만 커밋이 완료되도록 pre-commit 이벤트에 테스트를 실행하는 스크립트를 작성했습니다.
husky를 사용하면 git hooks를 쉽게 편집할 수 있다.
한편 husky라는 라이브러리를 사용하면 git hooks를 쉽게 편집할 수 있습니다. husky를 통해 pre-commit 스크립트를 만들어보겠습니다. 저는 자바스크립트 프로젝트를 했으므로 자바스크립트를 기준으로 설명을 진행하겠습니다. 일단 husky를 개발 의존성 모듈로 설치합니다. (husky 공식문서 링크)
yarn add -D husky
그리고 package.json에 script를 추가합니다.
* package.json
{
"scripts": {
"prepare": "husky install"
}
}
저는 husky경로까지 입맛에 맞게 설정해주었습니다.
{
"scripts": {
"husky:install": "husky install ./src/config/husky"
}
}
터미널에서 만든 명령어를 실행합니다.
yarn prepare
다음으로 pre-commit script를 생성해줍니다.
npx husky add .husky/pre-commit "yarn test"
yarn test가 테스트 실행 명령어일 때 저렇게 써주고, 각자 프로젝트에서 테스트 실행 명령어를 ""안에 적어주면 됩니다.
저는 src/config 폴더에서 husky를 관리했기 때문에 다음과 같이 파일 경로를 지정해서 만들어줬습니다.
npx husky add ./src/config/husky/pre-commit "yarn test"
해당 파일을 열어보면 다음과 같은 스크립트가 작성되어있습니다.
* pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn test
여기서 스크립트를 수정할 수 있습니다.
pre-commit 스크립트 편집하기
코드 컨벤션 통일은 중요합니다. git code 변경 차이점에 진짜 변경된 코드만 남겨서 가독성에 방해를 받지 않으려면 pre-commit에서 코드 컨벤션 검사를 해주면 좋습니다. 따라서 저는 pre-commit에서 자바스크립트의 lint검사를 실행해주려고 합니다.
lint-staged 라이브러리 사용하기
lint-staged를 git hooks와 함께 사용하면 린트 검사 자동화를 할 수 있습니다. lint-staged를 설치하고 package.json에 스크립트를 추가해줍니다.
yarn add -D lint-staged
* package.json
"lint-staged": {
"*.{js,ts,tsx}": [
"eslint --fix"
]
}
그리고 다시 pre-commit 파일을 열어 스크립트를 한 줄 추가해줍니다. test를 실행하기 전에 lint검사를 먼저 진행하려고 합니다.
* pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged
yarn test
이제 코드 변경을 해보고 commit을 하여 터미널을 보며 pre-commit의 스크립트들이 실행되는 것을 지켜봅니다.
최근댓글