-
Notifications
You must be signed in to change notification settings - Fork 2
Github Aciton
Github Action을 이용하면 github내 push, PR 등의 이벤트가 발생 했을 때 지정해놓은 Job을 수행하도록 만들 수 있다. Job을 통해서 자동 테스트 및 배포 등을 수행할 수 있다.
Pull Request가 수행될 때 마다 자동으로 테스트를 수행하는 Job을 만들 수 있다.
전문은 아래와 같다.
exec-mocha-test.yml
name: Execute Mocha Test
on:
pull_request:
branches: [ dev, main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
- run: npm install -g mocha
- run: npm install -g typescript
- run: npm install -g ts-node
- run: npm install
- run: npm audit fix
- run: npm ci
- run: npm run build --if-present
- name: run test code
run: npm test
env:
NODE_ENV: test
MYSQL_TST_USERNAME: '${{ secrets.MYSQL_TST_USERNAME }}'
MYSQL_TST_PASSWORD: '${{ secrets.MYSQL_TST_PASSWORD }}'
MYSQL_TST_DATABASE: '${{ secrets.MYSQL_TST_DATABASE }}'
MYSQL_TST_HOST: '${{ secrets.MYSQL_TST_HOST }}'
MYSQL_TST_PORT: '${{ secrets.MYSQL_TST_PORT }}'
MYSQL_TST_DIALECT: '${{ secrets.MYSQL_TST_DIALECT }}'
MONGO_URI: '${{ secrets.MONGO_URI }}'
CORS_ALLOW_LIST: '${{ secrets.CORS_ALLOW_LIST }}'
JWT_SECRET: '${{ secrets.JWT_SECRET }}'
AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}'
AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY}}'
ENCRYPTION_KEY: '${{ secrets.ENCRYPTION_KEY }}'
ENCRYPT_ALGORITHM: '${{ secrets.ENCRYPT_ALGORITHM }}'
AWS_S3_URL: '${{ secrets.AWS_S3_URL }}'
name은 workflow의 이름을 정의한다. 이 이름은 Github Action 탭에서 확인할 수 있다.
name: Execute Mocha Test
on은 구독할 이벤트를 정의한다. 자동 테스트의 경우는 PR이 생성되는 경우에만 수행하면 되기 때문에 pull_request만 구독한다. 또한 브랜치는 dev와 main으로 한정한다.
on:
pull_request:
branches: [ dev, main ]
jobs아래에는 각각의 독립된 job을 정의한다. 여기서는 build라는 job을 정의한다.
-
ㅇ
build보다는 test라는 job name이 더 적절해 보인다.
jobs:
build:
// ...
하나의 job에는 아래의 속성을 확인할 수 있다.
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x]
stpes:
// ...
runs-on: ubuntu-latest
먼저 runs-on은 실행할 환경을 정의한다. 자동 테스트의 경우에는 일회성으로만 동작하기 때문에 별도로 지정된 서버에서 돌릴필요가 없다. 따라서 Github에서 제공하는 Ubuntu Server(ubuntu-lateset)를 활용한다. 해당 서버는 테스트를 수행한 이후에 초기화 되기 때문에 Server의 설정값과 Dependency가 없는 상태로 테스트를 수행할 수 있다.
-
self-hosted
이와 다르게 지정된 서버에서 실행되도록 만드는 self-hosted가 존재한다. 이는 배포에서 다룬다.
strategy:
matrix:
node-version: [10.x]
strategy - matrix 인자를 사용하면 어떤버전에서 테스트할지 확인할 수 있다.
steps는 job을 정의하는 각각의 Comman를 선언한다.
stpes:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
- run: npm install -g mocha
- run: npm install -g typescript
- run: npm install -g ts-node
- run: npm install
- run: npm audit fix
- run: npm ci
- run: npm run build --if-present
- name: run test code
run: npm test
env:
NODE_ENV: test
MYSQL_TST_USERNAME: '${{ secrets.MYSQL_TST_USERNAME }}'
MYSQL_TST_PASSWORD: '${{ secrets.MYSQL_TST_PASSWORD }}'
MYSQL_TST_DATABASE: '${{ secrets.MYSQL_TST_DATABASE }}'
MYSQL_TST_HOST: '${{ secrets.MYSQL_TST_HOST }}'
MYSQL_TST_PORT: '${{ secrets.MYSQL_TST_PORT }}'
MYSQL_TST_DIALECT: '${{ secrets.MYSQL_TST_DIALECT }}'
MONGO_URI: '${{ secrets.MONGO_URI }}'
CORS_ALLOW_LIST: '${{ secrets.CORS_ALLOW_LIST }}'
JWT_SECRET: '${{ secrets.JWT_SECRET }}'
AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}'
AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY}}'
ENCRYPTION_KEY: '${{ secrets.ENCRYPTION_KEY }}'
ENCRYPT_ALGORITHM: '${{ secrets.ENCRYPT_ALGORITHM }}'
AWS_S3_URL: '${{ secrets.AWS_S3_URL }}'
테스트 자동화를 위해서 아래 작업을 정의한다.
-
checkout
github에서 최신 버전으로 Pull을 수행한다.
-
setup-node
node를 설치한다.
-
의존성 설치
github에서 제공되는 ubuntu 서버는 백지 상태이기 때문에, 의존성 모듈을 설치한다.
-
run test
test를 수행한다.
-
env
test를 수행할 때 환경 변수를 요구한다. 하지만 Github ubuntu서버에는 환경 변수가 저장되지 않기 때문에 job을 수행할 때 마다 매번 재지정 해줘야 한다. yml파일에 직접 환경변수 값을 지정할 수 있지만 보안 이슈가 있는 환경변수는 Github에서 제공하는 Secret를 활용한다.
-
Github Secret 선언
Girhub Repository > Settings > Secrets > Actions
Repository secrets
에서 확인할 수 있으며New repository secret
로 추가할 수 있다.환경변수는 생성, 삭제 및 업데이트만 가능하다. 즉 환경변수의 값을 읽을 수는 없다. (읽을 수 없다는 제약을 통해서 해당 값을 보호할 수 있다.)
Secret 생성은 name에 변수명 Value에 값을 넣으면 된다.
워크플로우 결과 화면
![스크린샷 2022-02-10 오전 12 48 32](https://user-images.githubusercontent.com/9072200/153237127-13cb1859-933f-4c99-9f7b-c5c59a00dea9.png)
-
각각 항목에 대해서 확대하여 확인 할 수 있다.
self-hosted 로 지정된 서버는 run.sh 스크립트를 실행해줘야지만 Github Action을 통해 이벤트를 수신하여 정해진 스크립트를 수행할 수 있다. 따라서 아래 명령어를 통해서 백그라운드로 설정해주는 것이 좋다.
./run.sh &
github Action을 통해서 배포를 수행하기 위해서는 실제 서버에서 동작을 수행해야 한다. 따라서 runs-on을 github에서 제공하는 ubuntu-latest로 지정하는 방법으로는 구현할 수 없다. 임시 리눅스가 아닌 실제 서버에서 작업을 수행하고 싶은 경우에는 서버를 Runner로 등록하는 과정을 수행해줘야 한다.
Github > Repo > Settings > Actions > Runner에서 New self-hosted runner를 통해 등록해줘야 한다.
등록하는 방법은 클릭 이후에 나타나는 가이드를 따라가면 된다.
-
ubuntu Computer architecture를 확인 하는 방법
uname -a
deploy의 경우 production과 development 버전 각각 하나로 만들었다. deploy-prodction.yml, deploy-developement.yml
Runner을 2개로 만들어서 수행할 수 있지만 이는 오버스펙으로 보여서 workflow 파일을 2개로 나누었다.
deploy-development.yml
name: Deploy development server to ec2
on:
push:
branches:
- dev
jobs:
build:
runs-on: self-hosted
strategy:
matrix:
node-version: [12.x]
defaults:
run:
working-directory: ${{ env.NODE_ENV }}
steps:
- uses: actions/checkout@v2
with:
path: ${{ env.NODE_ENV }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: ${{ env.NODE_ENV }}/package-lock.json
- run: cp ~/config-injection/ecosystem-${{ env.NODE_ENV }}.json ${{ env.PROJECT_PATH }}/ecosystem.json
- run: cp ~/config-injection/.env ${{ env.PROJECT_PATH }}/.env
- run: ${{ env.PROJECT_PATH }}/script/prebuild.sh
- run: ${{ env.PROJECT_PATH }}/script/reload.sh
env:
NODE_ENV: development
PROJECT_PATH: ~/actions-runner/_work/A.fume.Server/A.fume.Server/development
deploy-production.yml
name: Deploy production server to ec2
on:
push:
branches:
- main
jobs:
build:
runs-on: self-hosted
strategy:
matrix:
node-version: [12.x]
defaults:
run:
working-directory: ${{ env.NODE_ENV }}
steps:
- uses: actions/checkout@v2
with:
path: ${{ env.NODE_ENV }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: ${{ env.NODE_ENV }}/package-lock.json
- run: cp ~/config-injection/ecosystem-${{ env.NODE_ENV }}.json ${{ env.PROJECT_PATH }}/ecosystem.json
- run: cp ~/config-injection/.env ${{ env.PROJECT_PATH }}/.env
- run: ${{ env.PROJECT_PATH }}/script/prebuild.sh
- run: ${{ env.PROJECT_PATH }}/script/reload.sh
env:
NODE_ENV: production
PROJECT_PATH: ~/actions-runner/_work/A.fume.Server/A.fume.Server/production
여기서 Test와 다른 부분을 하나씩 살펴보자.
runs-on: self-hosted
runs-on은 우리가 생성한 Runner인 self-hosted로 설정한다. 이는 github에서 제공하는 Ubuntu 서버가 아닌 Runner로 등록한 실제 서버에서 Workflow를 수행하는 것을 의미한다.
같은 Runner를 사용하기 떄문에 production이든 development이든 동일한 경로를 사용하게 된다. 하지만 이는 충돌이 날 수 있기 떄문에 NODE_ENV를 가지는 폴더 이름으로 분리하였다.
defaults:
run:
working-directory: ${{ env.NODE_ENV }}
steps:
- uses: actions/checkout@v2
with:
path: ${{ env.NODE_ENV }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: ${{ env.NODE_ENV }}/package-lock.json
checkout과 setup-node 액션의 경우 default 경로가 workflow가 실행되는 경로에서 수행하기 때문에 Specific한 Path에서 작업하기 위해서는 path
와 cache-dependency-path
로 직접 지정해줘야 한다.
베포를 위한 코드는 3단계로 이루어진다.
- run: cp ~/config-injection/ecosystem-${{ env.NODE_ENV }}.json ${{ env.PROJECT_PATH }}/ecosystem.json
- run: cp ~/config-injection/.env ${{ env.PROJECT_PATH }}/.env
- run: ${{ env.PROJECT_PATH }}/script/prebuild.sh
- run: ${{ env.PROJECT_PATH }}/script/reload.sh
env:
NODE_ENV: production
PROJECT_PATH: ~/actions-runner/_work/A.fume.Server/A.fume.Server/production
- File Inject
- 서버에 사전에 정의된 .env 및 ecosystem.json을 cp 명령어를 통해서 주입한다.
- Prebuild
- 서버 실행을 위핸 Dependency를 설치하는 작업을 수행한다.
- reload
- 서버를 실핸하다.
- 참고 자료