Github Actions를 이용해서 CI 구축 해본 과정을 작성하였습니다.
원본 소스가 있는 레포를 보기 원하시면 여기를 클릭해주세요.
현재 프로젝트에선 Git Flow
전략을 이용해서 main
브랜치는 배포브랜치로, develop
브랜치는 개발 브랜치를 통합하는 브랜치로 feauture/..
브랜치는 기능 개발하는 브랜치 생성하여 개발을 하였다.
Github Actions로 동작하는 CI/CD 워크플로우 시점이 각각 다른데, CI
의 경우에는 각 feature
브랜치가 develop
브랜치로 PR
날려 질때 동작하도록 하여 해당 브랜치에서 개발한 코드가 정상동작하는지 확인하고 통합할 수 있도록 CI
를 구축하고
main
브랜치로 push될 때 미리 생성한 AWS EC2에 배포되는 CD 구축을 하였다.
현재 프로젝트는 nginx, gunicorn + django, mysql을 docker-compose
를 이용하여 각각의 컨테이너로 실행시키도록 했다.
그래서 github actions
에서 제공하는 runner(Workflow가 실행될 인스턴스)에 해당소스를 카피한 후 컨테이너를 실행시킨 뒤, 테스트를 실행시키도록 했다.
하지만 그전에 .env
에서 설정한 환경변수를 Github Secret
변수로 등록하여, 이것을 이용하여 .env
파일을 Github Actions 가상환경 안에 생성해줘야된다.
New repository secret
버튼을 눌러 .env
내용을 그대로 카피하여 붙여넣는다.ENV_VARS
로 저장해놨다.name: PR Test [Service]
on: # 해당 이벤트에서만 동작
pull_request:
branches:
- develop # develop 브랜치에 pull request 날라왔을 떄 동작
push:
branches:
- develop # develop 브랜치에 push 되었을 떄 동작
jobs: # 워크플로우 작업, 복수의 작업을 비동기로 동작가능하다.
Test:
name: test
runs-on: ubuntu-latest # ubuntu 가상환경 사용
steps:
- uses: actions/checkout@v3 # 소스를 ruuner에 카피
- name: Build
run: |
touch .env
echo "${{ secrets.ENV_VARS }}" >> .env
docker-compose up -d --build
docker exec backend python manage.py wait_for_db
- name: Migrations
run: |
docker exec backend python manage.py makemigrations user product order payment
docker exec backend python manage.py migrate
- name: Test
run: |
docker exec backend python manage.py test tests/
touch .env
echo "${{ secrets.ENV_VARS }}" >> .env
docker exec backend python manage.py wait_for_db
docker exec backend python manage.py makemigrations user product order payment
docker exec backend python manage.py migrate
docker exec backend python manage.py test tests/
다중 컨테이너가 실행될 때, mysql 컨테이너가 먼저실행 된 뒤 django가 실행되야하기에 커스텀명령어를 작성하고 컨테이너들이 실행되어질 때 사용하여 전체 컨테이너가 정상적으로 실행될 수 있도록 한다.
from django.core.management.base import BaseCommand
from django.db.utils import OperationalError
import time
class Command(BaseCommand):
"""Django command to pause execution until database is available"""
def handle(self, *args, **kwargs):
self.stdout.write("waiting for db ...")
# time.sleep(10)
db_up = False
while db_up is False:
try:
# get the database with keyword 'default' from settings.py
self.check(databases=["default"])
db_up = True
except OperationalError:
self.stdout.write("Database unavailable, waiting 3 second ...")
time.sleep(3)
self.stdout.write(self.style.SUCCESS("db available"))
github repo에서 따로 브랜치설정을 하지 않으면 위에서 애써만든 CI 워크플로우를 통과하든 통과하지 않든 머지가 될 수 있다.
그래서 github repo에서 설정하는 것을 해보겠다.
Add rule
버튼을 누른다.Require status checks to pass before merging
옵션을 체크한다.job name
을 검색하여 등록한다.자 이제 feature
브랜치에서 develop
브랜치로 PR을 날려보고 작성한 CI 워크플로우가 동작하고, 패스되고 머지가 가능한지 확인해보자
develop
브랜치로 PR이 날려지고 CI 워크플로우가 동작하는 모습