참고한 글
토스 : Github Actions로 개선하는 코드문화
카카오 : JS Actions 만들기
이 두 글이 제 글보다 훨씬 퀄리티있고 도움이 많이 될것이기 때문에 무조건 먼저 보는걸 추천합니다...
이번에 새롭게 시작되는 프로젝트에 대한 컨벤션을 정하면서, 팀원 중 2명 이상이 Approve할 시 merge할 수 있게 하도록 PR 컨벤션을 정했다.
그 당시에는 그렇군.. 하고 넘어갔지만, 첫 PR을 올리면서 든 생각은
reviewer는 누구로 하지..? 였다
CODEOWNER 를 통해 모든 팀원 다 reviewer로 등록그래서 랜덤으로 리뷰어를 지정할 수 있는 기능이 있으면 좋겠다는 생각이 들었다
market에 검색하면 가장 먼저 나오는 action으로, 정말 간단하게 reviewers와 assignee까지 지정할 수 있다
하지만 쓰다보니 단점이 몇가지 생겼는데
그러다 최상단에 있는 토스 블로그의 포스트를 발견하고, 내가 직접 커스텀 해보기로 했다
actions는 보통 .yml 파일로 작성된다.
사실 name, on, jobs 같이 직관적인 네이밍으로 구분되기 때문에 사실 이 부분은 이해하기 어렵지 않지만,
특정 로직을 실행시켜야 하는 부분에서 기존에 익숙한 JS와는 다른 문법을 사용해야 하기 때문에 이 부분이 조금 어렵다
그래서, 해당 로직을 실행시키는 부분에서 JS코드를 쓸 수 있다면,
여기에서 더 나아가서 JS 파일을 실행시킬 수 있다면 유지보수 측면에서도 더 좋을 것 같아서 시도해 보았다.
actions의 경우에도 폴더를 나누어서 관리하는 게 가능하다.
나는 .github 폴더에 workflows 와 actions 라는 폴더로 나누어 관리하는데
워크플로는 하나 이상의 작업을 실행하는 구성 가능한 자동화된 프로세스입니다. 워크플로는 리포지토리에 체크 인된 YAML 파일에서 정의되며, 리포지토리의 이벤트로 트리거될 때 실행되거나 수동으로 또는 정의된 일정에 따라 트리거될 수 있습니다.
workflows 안에 있는 파일들은 특정 조건이 되었을 때(on), 해당 작업(jobs)을 수행해주는 역할을 한다
actions 안에 있는 파일들은 workflows가 실행하는 작업이 정의되어 있다고 보면 된다
//.github/workflows/deploy/yml
name: deploy
on:
pull_request:
types: [opened, ready_for_review]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 16
- name: Cache node modules
uses: actions/cache@v3
id: npm-cache
with:
path: "**/node_modules"
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: |
echo 'npm cache existed'
npm ci
//여기까지는 공통으로 필요한 작업 실행
- name: Assign reviewers randomly
uses: ./.github/actions/reviewers
with:
github_token: ${{secrets.token}}
reviewers: ${{vars.reviewers}}
//.github/actions/reviews/action.yml
name: "reviewers"
inputs:
reviewers:
required: true
github_token:
required: true
runs:
using: "node16"
main: "action.js"
//action.js는 현재 파일과 같은 폴더에 위치
해당 파일을 보면, runs 에서 action.js 를 실행해준다는 걸 알 수 있다
그럼 이제 action.js에서 리뷰어를 랜덤 지정해주는 로직만 만들면 된다.
하지만 action.js 파일에서는 현재 아무것도 알 수가 없다. 어떤 PR인지, 누가 작성했는지 등등 알 수가 없기 때문에, 이를 알기 위해 github에서 제공하는 toolkit을 사용해야 한다.
@actions/core - input,output,log,변수,secret 등등을 가져올 수 있음
@actions/github - github api를 이용하여 github과 관련된 정보를 가져올 수 있음
보통 이 두가지가 가장 많이 쓰이는 것 같다
import { getInput, setFailed } from "@actions/core"
import { context, getOctokit } from "@actions/github"
try {
const candidates = getInput("reviewers").split(", ")
const reviewers = selectRandomReviewer(candidates)
const token = getInput("github_token")
const octokit = getOctokit(token)
const { owner, repo } = context.repo
const pull_number = context.issue.number
await octokit.rest.pulls.requestReviewers({
owner,
repo,
pull_number,
reviewers: reviewers,
})
} catch (error) {
setFailed(error.message)
}
function selectRandomReviewer(reviewers) {
const requiredReviewer = 2
const creator = context.payload.pull_request.user.login
const candidates = reviewers.filter((reviewer) => reviewer !== creator)
const result = []
for (let i = 0; i < requiredReviewer; i++) {
const { length } = candidates
if (length === 0) {
break
}
const randomIndex = Math.floor(Math.random() * length)
result.push(...candidates.splice(randomIndex, 1))
}
return result
}
간단하게 설명하면
reviewers 라는 input 값을 읽어온다selectRandomReviewer 함수에서 랜덤으로 2명을 선택한다이 과정에 필요한 권한이나, PR 정보를 불러오는 걸 설치한 두 라이브러리에서 해 준다