71호. 깃헙으로 라라벨 CI 하기 free

2019-10-14

2019년 8월에 깃헙 액션이 CI/CD를 지원한다고 공지했습니다. 제가 아직 다른 CI/CD 툴을 써보진 못했어요. 매번 CI/CD 해봐야지하고 벼르고만 있었는데, 이번에 마음을 다잡고 깃헙으로 한 번 해봤습니다. Continuous Integration with GitHub Actions and Laravel 6 라는 글을 참고해서 xly.kr에 적용했습니다. 참고한 글은 CI 환경에서 SQLite 데이터베이스를 사용하지만 저는 MySQL을 사용하도록 설정해봤습니다. 이전에 테스트 관련 글에서도 말씀드렸듯이 테스트 환경은 다소 느려질지라도 되도록 실제 환경과 같을 수록 좋다고 생각하고, 애플리케이션이 어느 정도 커지면 SQLite와 호환되지 않는 쿼리나 스키마가 생기게 마련이거든요. 아무튼 참고 글에 없는 내용까지 하려다 보니 꽤 삽질을 했습니다 ㅠ



모쪼록 제 삽질 경험이 여러분에게도 도움이 되길 바랍니다. :)


깃헙 액션 활성화


깃헙 액션은 아직 베타 서비스라서 사용하시려면 따로 신청을 하셔야 합니다.



신청을 하시고나면 저장소에 Actions 탭이 추가된게 보이실 겁니다.



Yaml 파일 작성


템플릿을 고르거나 우측에 있는 "Set up a workflow yourself"를 클릭하면 .github/workflows 디렉터리에 main.yml 파일이 생성됩니다. 파일 이름은 원하는대로 바꿔도 됩니다.


이름 정의


액션의 이름입니다. 여러가지 액션을 사용하는 경우 이를 이용해서 구분할 수 있습니다.


name: xLY CI

이벤트 정의


on 지시어에 언제 액션을 수행할 것인지 정의합니다.


on:
push:
branches:
- master
- develop
- features/*

위와 같이 하면 master, develop, features/* 브랜치에서 푸시가 발생하면 동작하도록 설정되어 있습니다. 따로 정해주지 않고 on: [push]로 두면 모든 push에 동작합니다. 깃헙 액션은 수행한 시간에 과금을 하기 때문에 모든 푸시에 액션이 동작하게 하면 비용이 많이 나올 수 있으니 일부 브랜치로 제한하는 것이 좋을 것 같습니다. 무료 플랜은 월 2000분까지 무료로 사용할 수 있습니다.


작업


jobs 지시어에 작업 내용을 작성하게 됩니다. 여러 작업이 있는 경우 병렬로 수행됩니다. needs 지시어를 이용해서 작업들 간 의존성을 정해줄 수 있습니다. build라는 이름의 작업을 최신 우분투에서 실행한다고 정의해봅시다.


jobs:
build:
runs-on: ubuntu-latest

MySQL 서비스 추가


ubuntu-latest에는 MySQL이 설치되어 있지 않습니다. MySQL을 사용하려면 컨테이너를 추가해야 합니다. 작업에 컨테이너를 추가할 때는 services 지시어를 이용해서 추가합니다.


jobs:
build:

runs-on: ubuntu-latest

services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: root
ports:
- 13306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5

MySQL 서비스에 포트를 지정해주는게 중요합니다. MySQL 서비스에 포트를 명확하게 정해주지 않으면 임의의 포트를 할당하기 때문에 라라벨 애플리케이션에 환경변수로 정확한 포트값을 넘겨줄 수 없게 됩니다.


DB 생성


이제 작업 절차를 하나씩 추가해보겠습니다. 작업 절차는 jobs.{작업 이름}.steps에 정의합니다. 우선 laravel이라는 이름으로 DB를 생성합시다.


steps:
- name: DB 생성
run: |
mysql --host 127.0.0.1 --port 13306 -uroot -proot -e "CREATE DATABASE laravel"

작업 절차는 크게 두 가지 방식으로 정의할 수 있습니다. 하나는 uses이고 다른 하나는 name & run 입니다. uses는 깃헙 액션이 제공하는 표준 명령어를 사용하는 것이고, name & run은 미리 정의되지 않은 명령어를 입력하는 것입니다. name에는 작업의 이름을, run에는 작업의 내용을 씁니다.


git 체크아웃


깃헙 액션이 제공하는 표준 명령어를 사용해서 체크아웃 합니다.


- uses: actions/checkout@v1

구동 환경 설정 파일 복사


우선 CI용 구동 환경 설정 파일을 하나 만듭니다. 저는 .env를 복사해서 .env.ci를 만들었습니다. 그런 후 다음 항목들을 수정했습니다.


APP_ENV=ci

DB_PORT=13306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=root

깃헙 액션 설정 파일에서 다음의 작업 절차를 추가합니다. .env.ci 파일을 복사해서 .env.env.testing을 만듭니다.


- name: .env 파일 복사
run: php -r "copy('.env.ci', '.env'); copy('.env.ci', '.env.testing');"

의존 패키지 설치


- name: 의존패키지 설치
run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist

키 생성


- name: 키 생성
run: php artisan key:generate

마이그레이션


- name: 마이그레이션
run: php artisan migrate

PHPUnit 실행


- name: PHPUnit 테스트 실행
run: vendor/bin/phpunit

완성


작성을 마치고 커밋을 하면(깃헙에서 직접 수정한 경우 Start commit 버튼을 누르면 됩니다) 깃헙 액션이 실행됩니다.



아래는 위의 단계들을 모두 종합한 파일입니다.


name: xLY CI

on:
push:
branches:
- master
- develop
- features/*

jobs:
build:

runs-on: ubuntu-latest

services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: root
ports:
- 13306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5

steps:
- name: DB 생성
run: |
mysql --host 127.0.0.1 --port 13306 -uroot -proot -e "CREATE DATABASE laravel"
- uses: actions/checkout@v1
- name: .env 파일 복사
run: php -r "copy('.env.ci', '.env'); copy('.env.ci', '.env.testing');"
- name: 의존패키지 설치
run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
- name: 키 생성
run: php artisan key:generate
- name: 마이그레이션
run: php artisan migrate
- name: PHPUnit 테스트 실행
run: vendor/bin/phpunit

마치며



이제 커밋 로그를 보면 테스트를 통과했는지 여부가 표시되고 체크 표시를 클릭하면 자세한 내용을 확인할 수 있습니다. 풀리퀘스트도 마찬가지로 테스트 통과 여부가 표현될 것이고 병합할지 여부를 판단할 때 유용할 것 같네요.


여러모로 살펴보면 더 다양하게 유용한 기능을 추가할 수 있을 것 같아요. 나중에 더 알게되면 다시 공유해보겠습니다.


1일 1식 라라벨 71호

2019년 10월 14일


이현석

메쉬 코리아 개발자. 바쁜 팀장님 대신 알려주는 신입 PHP 개발자 안내서를 쓰고, 클린 아키텍처 인 PHP를 번역했습니다. 2020년에 출간될 Laravel Up & Running 2nd Edition을 번역하고 있습니다.