Github Actions 환경

GwangSoo·2025년 7월 7일
0

개인공부

목록 보기
28/35
post-thumbnail

이번 글은 인턴하는 곳에서 마주했던 신기한(?) 내용에 대해 이야기 해보려고 한다.

발견한 과정

현재 프론트엔드 배포는 Vercel을 이용해서 하고 있다. 초기에 혼자 진행할 당시에 코드를 꼼꼼히 확인하지 않고 production에 머지를 했을 때 빌드 오류로 인해서 배포를 실패한 경우가 자자했다. 이러한 오류를 방지하고자 PR을 올리면 Github Action을 통해 pnpm build를 실행하여 배포 실패를 사전에 방지할 수 있게 workflow를 작성했다.

그런데 최근에 여기서 이상하게 빌드가 실패하는 현상이 발생했다.

어떻게 빌드가 실패했는가?

action 로그를 보니 중복된 변수가 있다고 나오는 것이다. 그런데 54, 55번째 줄을 보았을 때 눈을 씻고 찾아봐도 중복된 변수가 존재하지 않았다. 아래는 문제의 파일이다.

55번째는 심지어 컴포넌트를 닫는 태그가 있었다. 그래서 단순 action 오류인가 해서 다시 돌렸다.

그런데 똑같이 실패해서 action의 로그를 더 확인해보니 위처럼 나오고 있었다. 하지만 파일의 상태는 이전 이미지와 동일한 상태였다.

문제가 30여분 가까이 지속되었고, 깃허브 오류인가 싶어 우선 머지를 해보았다.

그런데 머지를 하고 나니까 정말 중복된 변수가 보였다.

왜 이런 일이 발생했을까?

아래의 가설을 세우고 문제를 접근해보았다.

혹시 내가 합치려는 브랜치(feature 브랜치)와 합쳐지는 브랜치(dev)가 합쳐졌다는 가상의 커밋에서 액션이 돌아가는건가?

사실 이렇게 되면 말이 되는 것이, 동시에 작업하던 다른 프론트엔드 개발자분께서 같은 파일 내용을 수정하고 먼저 머지하셨기 때문이다.

위 가설에 대해 GPT와 이야기하며 구글링까지 진행한 결과 다음과 같은 사실을 알아냈다.

우선 actions/checkout 레포지토리의 예제 코드는 다음과 같다.

- uses: actions/checkout@v4
  with:
	  # The branch, tag or SHA to checkout. When checking out the repository that
    # triggered a workflow, this defaults to the reference or SHA for that event.
    # Otherwise, uses the default branch.
    ref: ''

ref를 지정하지 않으면 해당 이벤트(push, pull request 등)의 참조 혹은 SHA가 기본값이 된다.

내부 로직은 다음과 같았다.

// Workflow repository?
const isWorkflowRepository =
  qualifiedRepository.toUpperCase() ===
  `${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase()

// Source branch, source version
result.ref = core.getInput('ref')
if (!result.ref) {
  if (isWorkflowRepository) {
    result.ref = github.context.ref
    result.commit = github.context.sha

    // Some events have an unqualifed ref. For example when a PR is merged (pull_request closed event),
    // the ref is unqualifed like "main" instead of "refs/heads/main".
    if (result.commit && result.ref && !result.ref.startsWith('refs/')) {
      result.ref = `refs/heads/${result.ref}`
    }
  }
}

먼저 isWorkflowRepository 변수는 checkout 액션이 현재 가져오려는 저장소(qualifiedRepository)와 이 워크플로를 실제로 트리거한 저장소(github.context.repo)가 같은지 여부를 판별하는 변수이다.

이제 result.ref가 지정되지 않고 isWorkflowRepository가 true라면 result.ref를 github.context.ref로 지정한다.

그렇다면 github.context.ref는 무엇을 나타낼까?

actions/github에 정의된 context.ts 파일에 들어가보면 Context에 대한 class를 아래와 같이 정의한 것을 확인할 수 있다.

export class Context {
	...
  ref: string
	...

  /**
   * Hydrate the context from the environment
   */
  constructor() {
	  ...
    this.ref = process.env.GITHUB_REF as string
		...
  }
  ...
}

GITHUB_REF 환경변수는 workflow의 기본 환경변수로 이벤트 트리거 종류에 따라 참조 값이 다르다. push와 pull request의 경우만 보자면 다음과 같다.

이벤트기본 github.ref 실질적으로 체크아웃되는 대상¹
pushrefs/heads/<브랜치> (혹은 refs/tags/<태그>)푸시된 브랜치/태그의 HEAD 커밋
pull_requestrefs/pull/<PR 번호>/merge베이스(dev) + PR 브랜치를 가상으로 병합한 머지 커밋

여기서 베이스는 앞서 언급했던 “합쳐지는 브랜치(dev)”를 의미한다.

따라서 중복 변수 에러는 가상 머지 커밋에서 빌드를 실행했기 때문에 발생한 것이 맞았다.

마무리하며

Github Action 환경에 대해 새롭게 알게 된 부분이 많았고, 앞으로도 공부해야 할 부분이 많다는 것을 다시 한번 깨닫게 되었다.

참고

0개의 댓글