이번엔 전에 배웠던 기초적인 actions의 문법으로 간단한 workflow를 만들어보겠습니다.
특정 브랜치에 pr을 보낼 경우 test를 돌리는 action을 작성해보도록 하겠습니다!
workflow를 만들때는 말 그대로 흐름을 미리 생각해두고 코드로 구현하면 더 쉬운것 같다.
순서대로 흐름을 나열해보면
- pr을 감지한다.
- pr을 보낸 브랜치를 판별한다.
- jest로 코드를 test한다.
- test가 성공할 경우 pr을 그대로 open.
- test가 실패할 경우 pr을 close하고 comment를 남긴다.
이런 흐름이 될 것이다.
이제 이걸 코드로만 바꿔주면 여러분도 Actions 마스터~~
걱정 마세요 이전 포스팅 처럼 workflow
, event
, job
, step
이 네가지만 생각하면 됩니다.!!
위의 순서도에서 어떤 부분을 어떤 개념에 넣어서 표현하면 될지를 생각해보면
- pr을 감지한다. => event
- pr을 보낸 브랜치를 판별한다. => event
- jest로 코드를 test한다. => step
- test가 성공할 경우 pr을 그대로 open. => step
- test가 실패할 경우 pr을 close하고 comment를 남긴다. => step
1 ~ 5 전체 흐름 => workflow
3 ~ 5 => job
이런 식으로 구성이 잡히게 된다. 이제 정말 다왔다. 이대로 workflow작성만 해주면 된다.
우선 workflow를 정의해보자.
풀리퀘스트를 테스트하는 workflow이니까 'PR Test'라는 이름으로 작성해보자.
// PR_Test.yml
name: PR Test
그리고 나서 event를 정의해준다.
우리의 조건은 test 브랜치에 pr이벤트가 일어났을 경우 해당 액션을 트리거 하는 것이다.
// PR_Test.yml
name: PR Test
on:
pull_request: #pr이벤트를 감지
branches:
- test #test라는 브랜치에 한해서
그다음은 job과 그안의 steps를 정의해준다.
job id를 'Run Jest'로 설정하고 가상환경 인스턴스를 ubuntu-latest
로 설정해 최신 우분투 환경에서 테스트를 돌리도록 하였다.
가상환경 인스턴스는 ubuntu 뿐만 아니라 windows, macos등도 사용이 가능하다.
그리고 npm
을 사용하기 위해서 노드 환경도 설정해주어야 한다.
jobs.<job_id>.strategy.matrix
키워드를 사용하여 다양한 노드 버전을 설정해줄 수 있다.
(Node.js workflow 템플릿을 사용하면 조금 더 편하게 사용할 수 있다. )
// PR_Test.yml
name: PR Test
on:
pull_request: #pr이벤트를 감지
branches:
- test #test라는 브랜치에 한해서
jobs:
Run Jest:
runs-on: [ubuntu-latest] # 우분투 가상환경 사용
strategy:
matrix:
node-version: [8.x, 10.x, 12.x] # ".x" 로 최신 버전도 사용하고 직접 버전 지정도 가능하다
이제 가상환경, 노드 환경까지 지정해주었으니 어떤 일을 하는 지만 정의해주면 된다.
steps
라는 키워드 아래에 step을 단계적으로 작성해나간다.
name
으로 각 step의 이름을 적어주고, run
혹은 uses
로 어떤 일을 할지를 지정해준다. run은 사용자가 직접 스크립트로 구현할 때 사용하고 uses는 마켓플레이스에 올라온 action을 가져다 쓸 때 사용한다.
여기서는 모두 간단한 코드여서 run을 사용해 직접 스크립트를 작성할 것이다. 이때 쉘스크립트를 사용한다.
3~5단계를 차례대로 적어보도록 하자.
- jest로 코드를 test한다. => step
- name: test code
run:
npm install
npm test
- test가 실패할 경우 pr을 close하고 comment를 남긴다. => step
여기에서는 github-script라는 액션을 사용한다. 이 액션은 간편하게 github API를 사용할수 있어서 자주 사용하게 된다.
이 액션에선 github
과 context
라는 변수를 사용할 수 있게 된다.
github
은 octokit객체이고, context
는 현재 실행중인 워크플로우에 대한 컨텍스트 객체로 sha, action, workflow등의 정보를 알아낼 수 있다.
(context객체 자세히 보기)
이제 코드를 보자.
- name: if fail
uses: actions/github-script@0.2.0 // github-script 액션을 사용한다.
with:
github-token: ${{github.token}} // github token을 선언해준다
script: | // script에 원하는 스크립트를 작성
const ref = "${{github.ref}}"
const pull_number = Number(ref.split("/")[2])
await github.pulls.createReview({
...context.repo,
pull_number,
body:"테스트코드를 다시 확인해주세요. ",
event: "REQUEST_CHANGES"
})
await github.pulls.update({
...context.repo,
pull_number,
state: "closed"
})
if: failure() // 이전 step이 실패했을 경우에만 이 step을 실행한다
마켓플레이스에 있는 액션을 가져다 쓰기 때문에 uses
를 사용해 github-script를 선언하였고, 기본적으로 깃허브 토큰이 필수적으로 있어야 하기 때문에 토큰을 선언해주었다.
script
부분에 내가 원하는 스크립트를 작성하면 된다.
풀리퀘스트 번호를 조회한 후 이를 이용해 원하는 코멘트를 달아주고 풀리퀘스트의 상태를 closed로 바꿔주는 스크립트이다.
그리고 마지막에 if: failure()
라는 구문이 중요하다.
우리가 아는 if문과 같은 역할을 한다. 이전의 step이 fail일 경우에만 이 "if fail" step이 실행되는 것이다! failure외에도 success, alwayse 등등의 옵션들이 있으니 링크 참고.
자 이제 나만의 워크플로우가 완성되었다!!👏👏👏
이제 원하는 브랜치(예제에서는 test브랜치)의 /.github/workflows/
디렉토리에 작성하면 끝이다.
// PR_Test.yml
// 완성된 코드
name: PR Test
on:
pull_request: #pr이벤트를 감지
branches:
- test #test라는 브랜치에 한해서
jobs:
Run Jest:
runs-on: [ubuntu-latest] # 우분투 가상환경 사용
strategy:
matrix:
node-version: [8.x, 10.x, 12.x] # ".x" 로 최신 버전도 사용하고 직접 버전 지정도 가능하다
steps:
- uses: actions/checkout@v2
- name: npm install
run: npm install
- name: run test code
run: npm test
- name: if fail
uses: actions/github-script@0.2.0 // github-script 액션을 사용한다.
with:
github-token: ${{github.token}} // github token을 선언해준다
script: | // script에 원하는 스크립트를 작성
const ref = "${{github.ref}}"
const pull_number = Number(ref.split("/")[2])
await github.pulls.createReview({
...context.repo,
pull_number,
body:"테스트코드를 다시 확인해주세요. ",
event: "REQUEST_CHANGES"
})
await github.pulls.update({
...context.repo,
pull_number,
state: "closed"
})
if: failure() // 이전 step이 실패했을 경우에만 이 step을 실행한다
test 브랜치에 pr을 날리고 Actions탭에 가면 아래와 같이 워크플로우가 실행되는 것을 볼 수 있다.
그리고 만약 테스트에 통과하지 못하면 아래와 같이 pr에 코맨트가 달리고 자동으로 Closed된다. (머지된건 무시해주세요)
다시 테스트코드를 수정하고 pr을 날려야 하는 것이다.
아래 링크는 이 코드에서 더 나아가 몇가지 설정을 추가해서 실제로 프로젝트에서 사용한 코드이다.
${{github.base_ref}}
를 이용해 pr을 보내는 브랜치?에 따라서 다른 폴더에있는 테스트코드를 테스트했다. 예를들어 search 브랜치에서 test브랜치로 pr을 보내는 경우라면, base_ref는 search가 되는 것이고 이 브랜치에서 만든 테스트코드가 들어있는 폴더만 테스트를 돌리게 되는 것이다. (github 객체 살펴보기)
그리고 env:
콘텍스트를 사용해 env 환경변수를 가상 인스턴스에 주입시켜줄 수 있다. 중요한 정보들은 github secret에 저장해서 사용할 수 있다.
Actions는 장점이 많다. 일단 깃허브 내에서 많은 관리들이 한번에 가능하다는 점이 생각보다 편리하다. 그리고 github api를 사용하는 것도 편리하게 잘 되어있어서 깃허브의 코멘트, 이슈생성과 같은 기능들을 엮어서 스크립트를 작성할 수 있다.
그리고 actions공식문서가 정리도 잘 되어있고 설명도 잘 되어있어서 나조차도 아무 도움 없이 이렇게 스크립트를 작성할 수 있었다. 개인적으로 travis는 다큐먼트가 좀 부실해서 그것만 보고는 잘 못따라했었다..
이렇게 직접 스크립트를 작성하는게 어렵다면 마켓플레이스의 다양한 액션들을 활용하는 것도 큰 장점이다. 자동머지 액션, 슬랙봇 알림 액션, 자동 배포 액션 등등 이미 많은 개발자들이 만들어 놓은 액션들이 많아서 정말 간편하게 사용이 가능하다. 물론 세세하게까지 설정을 할 수 없어 결국 내가 만들어버리는 경우도 있지만 왠만하면 마켓플레이스에 있는것만 써도 다 될 것 같다.
안녕하세요, Jest로 단위테스트를 하다 github Action으로 CI 구축을 할 수는 없을까 찾는 도중 읽게 되었습니다.
혹시 steps 에
이 과정이 빠진 것 같은데 이 step이 없어도 npm install이 잘 되나요,,?
저는 기존에 따로 쓰던 yml 파일보면서 추가해줘서 해결했네요 ㅠㅠ