Github action self-hosted runner 사용시 주의사항 (feat. go module)
ruinnel
gitgithubgithub-actionself-hosted runner
2067 Words CHANGE ME READ TIME 9 Minutes, 23 Seconds
2024-12-27 02:35 +0000
한줄 정리
- github-action에서 self-hosted runner 사용 할때는 host의 설정을 영구적으로 변경해서는 안된다.
문제 발생
github access token의 유효기간이 만료되어서 갱신했을 뿐인데 기존에 잘 동작하던 golang으로 된 어플리케이션을 빌드하는 github action이 아래의 로그를 출력하며 실패한다.
github.com/<user>/<repo>@v0.0.0: reading github.com/<user>/<repo>/go.mod at revision v0.0.0: git ls-remote -q origin in /home/actions-runner/go/pkg/mod/cache/vcs/7deabca04a332d18793c6dcc94c73a8b84e83f3b7ee3b3d5de5fd84c06839c2b: exit status 128:
fatal: could not read Password for 'https://***@github.com': terminal prompts disabled
원인 찾기
로그에 찍힌 go module은 github private repository에 있는 module이고, 로그 문구들과 access token이 변경된 상황을 봤을때 인증문제 인 것은 거의 100% 확신 가능하다. go module이 private repository에 접근하는 방식을 확인하고 거기서 어떤 인증 정보를 참조하는지 확인 후 해당 인증 설정이 제대로 설정 되어 있는지 확인하면 정확한 원인 파악이 가능 할 것으로 생각된다.
- go module이 private repository에 접근하는 방식은
GOPRIVATE
으로 private repository에서 가져 올 모듈을 정의하면, git(또는 다른 버전관리툴)의 인증방식을 이용해 모듈을 가져오게 됩니다. - 단, 이떄 local git config (
${WORKSPACE}/.git/config
)은 의도적으로 무시됩니다.
그렇다면, ${HOME}/.gitconfig
를 확인 하면 private repository에 접근하기 위한 설정 정보를 확인 할 수 있습니다.
[url "https://<gh_access_token1>@github.com/"]
insteadOf = https://github.com/
[url "https://:x-oauth-basic@github.com/"]
insteadOf = https://github.com/
[url "https://<gh_access_token1>@github.com/<org-name>"]
insteadOf = https://github.com/<org-name>
[url "https://<gh_access_token1>@github.com/<org-name>"]
insteadOf = https://github.com/<org-name>
[url "https://<gh_access_token2>@github.com/"]
insteadOf = https://github.com/
[url "https://<gh_access_token2>@github.com/"]
insteadOf = https://github.com/
[url "https://<gh_access_token2>:x-oauth-basic@github.com/"]
insteadOf = https://github.com/
😱… ${HOME}/.gitconfig
파일이 🐶 판입니다.
github access token이 일정기간에 한번씩 갱신되는데 그떄 마다 쌓이고, 이것이 원인으로 적절한 github access token이 사용되지 못해서 문제가 발생한 것이죠.
일단 빠르게 해결하기
빌드는 일단 해야 하니까 ${HOME}/.gitconfig
파일을 꺠끗하게 지워버리니 다시 빌드에 성공하였습니다.
어짜피 정의된 action yaml 파일에 private repository에 접근하기 위해서 아래 script가 포함되어 있어서 ${HOME}/.gitconfig
파일을 삭제해버려도 다시 생성되고 빌드도 성공했습니다.
git config --global url.https://$GH_ACCESS_TOKEN@github.com/.insteadOf https://github.com/
# ... or ...
git config --global url.https://$GH_ACCESS_TOKEN@x-oauth-basic@github.com/.insteadOf https://github.com/
재발방지하기
github access token은 생성할때 만료없이 만들면 경고를 합니다. 보안상 일정주기에 한번씩 교체하는 것이 좋습니다. 그러므로 다음에 access token이 변경 되어도 문제가 없도록 조치하는 방법을 찾아봤습니다.
${WORKSPACE}/.git/config
를 사용 가능하다면 git config --local ..
형태로 local 설정을 활용하면 좋습니다. 하지만, go module은 git local config를 의도적으로 무시하도록 디자인 되어 있습니다.. 이유는 go module은 node의 npm_modules처럼 WORKSPACE 하위에 위치하도록 설계되어 있지 않은 것이 그 이유 일것 같습니다. 애초에 go module 자체가 개별 프로젝트 단위로 관리 되는 것이 아니라 HOST 전체에서 공유해서 사용하도록 설계 된 것입니다.
- 결론: go module을 사용하는 경우
${HOME}/.gitconfig
파일을 사용하면서 문제를 해결 해야 합니다.
해결방법 찾기
- github action 정의시 마지막에
${HOME}/.gitconfig
파일을 삭제해버리거나,git config --global ..
로 설정한 내용을 unset 하도록 합니다. ${HOME}/.ssh/...
에 ssh key를 추가 & github에 등록하고 빌드시${HOME}/.gitconfig
을 건드리는 작업을 뺀다.
2번은 self-hosted runner를 추가하거나 할떄 빼먹으면 그 runner에서는 빌드가 실패하거나 하게 되므로 채택불가.
1번은 정석적인 접근방법이지만 action-runner
실행을 위해 별도의 user가 생성되어 있다면 괜찮지만, 기존에 사용하던 user로 실행된 경우라면 의도치않은 설정변경이 발생하므로 채택불가.
고민하다 문득 github checkout도 private reopsitory에서 코드 받아오는데 이쪽은 어떻게 인증 정보를 처리하고 있을까? 는 생각이 들어 코드를 찾아보니..
임시 디렉토리를 만들고 거기로 ${HOME}
을 옮기는 방법으로 회피하고 있는 것을 확인 할 수 있었습니다.
해결방법 적용
${RUNNER_TEMP}
는 github action 실행시 제공되는 환경변수로 action이 완료되면 자동으로 삭제 되는 디렉토리입니다.
${RUNNER_TEMP}
하위에 디렉토리를 생성하고 ${HOME}
을 옮긴 후 go module을 가져옵니다.
단, 이렇게 할 경우 GOMODCACHE
디렉토리도 임시 디렉토리 하위로 지정되므로 다른 step을 수행할떄 GOMODCACHE
를 임시디렉토리 하위를 바라보도록 환경 변수 설정이 필요합니다.
github action yaml 로 작성하면 아래 처럼 됩니다.
jobs:
build:
steps:
- name: install dependency
run: |
TEMP_HOME=${RUNNER_TEMP}/$(uuidgen)
export HOME="${TEMP_HOME}"
git config --global url.https://$GH_ACCESS_TOKEN@github.com/.insteadOf https://github.com/
go mod tidy
echo "GOMODCACHE=$(go env GOMODCACHE)" >> ${GITHUB_ENV}
- name: build
env:
GOMODCACHE: ${{ env.GOMODCACHE }}
run: |
go build ...
결론
- github action은 HOST의 설정을 변경하면 안되며, HOST의 환경에 의존성을 최소화하는 방향으로 작성되어야 합니다.
- HOST 설정을 변경하게 되면 다른 action이 동작할떄 영향을 미칠 수 있으며, 이 경우 실패하는 원인을 찾기가 상당히 어려워 집니다.
- HOST의 환경에 의존하게 되면, 예를들어 git 인증정보를 HOST에 저정된 ssh key를 사용하도록 구성 할 경우, self-hosted runner를 추가로 증설 할 경우 설정이 누락되면 특정 runner에서 만 빌드가 실패하는 상황이 발생 할 수 있습니다.
- linux 계열에서는
${HOME}
디렉토리 하위에 숨김파일(.
으로 시작하는 이름) 형태로 사용자에 반영되는 전역설정이 저정되는 경우가 많은데 이 경우 github action이 동작할때 제공해주는${RUNNER_TEMP}
같은 임시디렉토리 하위로${HOME}
을 옮기는 전략을 사용 할 수 있다. - 막힐떄는, open source library 코드를 참조하면 좋은 해결 방법을 발견하기도 한다.