- GitHub Actions는 생산성과 기능 면에서 유용하지만, 실제 워크플로 작성에서는 디버깅 지연, 보안 실수, 타입 부재, 공식 액션 부족이 반복적인 시간 손실로 이어짐
- 작은 수정에도
git add; git commit; git push와 브라우저 로그 확인을 반복해야 하며, 간단한 릴리스 워크플로에서도 4번의 커밋과 실패한 릴리스가 필요했던 사례가 있음 ${{... }}확장,pull_request_target, 넓은GITHUB_TOKEN기본 권한, fork의 SHA 참조는 모두 실수하기 쉬운 보안 지점이며, 특히 fork SHA는 의도한 저장소의 커밋처럼 보일 수 있음- 액션 입력에는
type:검증이 없고workflow_call·workflow_dispatch와 지원 범위도 달라, 배열·객체 입력 대신 CSV식 문자열이나 평면화된 입력을 직접 처리해야 함 - push 시점 검증, 런타임 보안 체크, 개인 저장소의 기본 토큰 권한 축소, 더 엄격한 타입 체크, 더 많은 공식·준공식 액션이 워크플로 신뢰성을 높일 수 있음
유용하지만 반복적으로 발목 잡는 GitHub Actions
- GitHub Actions는 2019년부터 전문 프로젝트와 취미 프로젝트에서 매일 쓰일 만큼 생산성과 안정감에 큰 도움을 주는 도구임
- 기능 확장도 꾸준히 이어져 왔음
- 그럼에도 실제 개발 과정에서는 큰 좌절과 시간 손실의 원인이 되기도 함
디버깅은 작은 오류에도 너무 무거움
- 릴리스 워크플로를 설정하는 과정에서 작은 오류를 잡기 위해 4개의 커밋과 4번의 실패한 릴리스가 필요했던 사례가 있음
- 필요한 곳에
${{ ... }}를 쓰지 않음 needs:관계를 빠뜨림
- 필요한 곳에
- 현재 디버깅 주기는 단순한 실수 하나를 확인하는 데도 단계가 많음
- 개발 환경에서 브라우저로 전환해야 함
- 올바른 탭을 찾아야 함
- Actions 요약과 상태 화면을 클릭해 들어가야 함
- 버퍼링된 콘솔 로그를 새로고침하며 다음 오류를 찾아야 함
- 작은 변경에도 전체 과정이 30초 이상 걸릴 수 있음
-
개선 방향
- 대화형 디버깅 셸을 제공하거나, 최소한
git add; git commit; git push없이 작은 변경으로 워크플로를 다시 실행할 수 있어야 함 - 저장소 설정으로 명백히 잘못된 워크플로를 push 시점에 거부할 수 있어야 함
- 동작할 수 없는 문법
- 존재하지 않는 job이나 step 참조
- 잘못된 YAML 때문에 워크플로가 조용히 실행되지 않는 상황
- 대화형 디버깅 셸을 제공하거나, 최소한
보안 실수는 너무 쉽게 발생함
- GitHub Actions에서는 사용자가 작성한 워크플로가 의도치 않게 취약해지기 쉬움
${{ ... }}확장을 셸이나 다른 실행 맥락에서 사용할 때, 확장 값이 사용자가 제어하는 입력이면 악성 코드 주입으로 이어질 수 있음- 예시에서는
inputs.frob를 통해 코드가 주입되고$MY_IMPORTANT_SECRET가 유출될 수 있음
- 예시에서는
pull_request_target은 사소하지 않은 워크플로에서 안전하게 쓰기 매우 어려움- 의도된 사용 사례는 fork에서 온 PR에 라벨을 붙이거나 댓글을 다는 좁은 범위로 보임
- 하지만 실제로는 큰 foot-gun처럼 노출돼 있음
- 워크플로와 job 수준 권한도 과도하게 설정되기 쉬움
- 일반
GITHUB_TOKEN의 기본 접근 권한은 매우 넓음 - 개인 계정 저장소에서는 기본 토큰 권한 축소를 자주 잊게 됨
- 필요한 권한 범위를 정확히 몰라 토큰 권한을 과도하게 부여하게 됨
- 일반
- GitHub 권한 모델이
read/write/none단일 축에 끼워 맞춰져 혼란을 더함id-token: write가 워크플로의 OpenID Connect 토큰을 읽을 수 있게 함- 일부 security advisory
GET작업은write권한을 요구하고, 다른 작업은read만 요구함
SHA 고정 액션은 fork 커밋과 헷갈릴 수 있음
actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e처럼 보이는 참조가 실제로는actions/checkout저장소의 커밋이 아닐 수 있음- 해당 SHA는
actions/checkout네트워크 안의 fork에 있는 커밋이며, GitHub의 alternates 사용 때문에 부모 저장소에 속한 것처럼 보일 수 있음 - Chainguard의 관련 글은 문제를 세 가지로 나눔
- fork의 SHA 참조와 대상 저장소의 SHA 참조가 시각적으로 구분되지 않음
- GitHub REST API의
/repos/{user}/{repo}/commits/{ref}는{ref}가 fork에만 있어도{user}/{repo}만 참조하는 JSON 응답을 반환함 - fork와 비-fork SHA를 구분하지 못하면 GitHub Actions의 신뢰 소스 제한을 우회할 수 있음
- GitHub의 대응은 지금까지 문서에 추가 문구를 넣는 수준이었음
-
개선 방향
- 명백히 안전하지 않은 워크플로를 push 시점에 거부하는 paranoid workflow security 모드가 필요함
- AddressSanitizer 같은 런타임 계측처럼, 워크플로 실행 중 보안상 위험한 패턴을 실패 처리할 수 있어야 함
- 예:
pull_request_target에서 대상 저장소가 아닌 ref로actions/checkout을 사용하는 경우 실패
- 예:
pull_request_target은 폐기하거나 제거하는 방안도 검토할 수 있음- 개인 저장소에서도 조직·엔터프라이즈처럼 기본
GITHUB_TOKEN범위를 더 제한적으로 설정할 수 있어야 함 - SHA가 참조된 저장소에는 없고 fork에만 있는 SHA-pinned action은 기본적으로 거부해야 함
타입 시스템은 일관성과 표현력이 부족함
- 커스텀 GitHub Action은
inputs:아래에 입력을 정의할 수 있지만, 액션 입력에는 타입 강제가 없음 type: number같은 선언은 액션 입력에서 동작하지 않음- GitHub Actions 내부에서도 타입 지원 위치가 일관되지 않음
workflow_call:boolean,number,string지원workflow_dispatch:boolean,choice,number,string지원- action inputs: 타입 지원 없음
- 타입을 지원하는 입력도 배열이나 객체 같은 복합 데이터 구조를 지원하지 않음
paths: [foo, bar, baz]같은 배열 입력 불가headers:아래에 계층 구조를 두는 객체 입력 불가
- 액션 작성자는 대신 임시 형식의 입력을 요구하게 됨
paths: foo,bar,baz처럼 CSV식 파싱을 직접 구현header-foo,header-baz처럼 자연스러운 계층 구조를 평면화
- 이런 방식은 유지보수성과 보안에 모두 좋지 않음
- 단일 평면 입력 네임스페이스를 직접 관리해야 함
- 복잡한 입력을 위해 임의의 미명세 언어를 만들게 됨
-
개선 방향
- action과 workflow 작성자가
type:을 모든 곳에서 사용할 수 있어야 함 choice도workflow_dispatch에만 제한하지 않고 모든 곳에서 사용할 수 있어야 함- 정적으로 타입을 추론할 수 있는 경우, 잘못된 타입의 워크플로 변경을 push 시점에 거부해야 함
type: object와type: array가 필요함- 내부 타입이 이질적일 수 있어 완벽하지는 않더라도 현재보다 나아질 수 있음
- 필요하면 JSON 직렬화 문자열로 전달할 수 있음
- GitHub Actions에는 이미
fromJSON(...)함수가 있음
- action과 workflow 작성자가
공식 액션은 플랫폼 신뢰와 직접 연결됨
- GitHub Actions의 서드파티 생태계에는 고품질 액션이 많음
- 그 아래에는 GitHub가 유지보수하는 공식 액션들이 있음
- 핵심
git작업:actions/checkout - GitHub 작업과 저장소 관리:
actions/{upload,download}-artifact,actions/cache,actions/stale - 필수 설정:
actions/setup-python,actions/setup-node
- 핵심
- 이런 액션은 범용성과 중요성이 높아 공식 유지보수 구현의 가치가 큼
- 하지만 공식 액션 수는 적고, GitHub 기능을 직접 연결하는 작업도 공식 액션으로 제공되지 않는 경우가 있음
- 예: pull request를 merge queue에 프로그래밍 방식으로 추가하는 액션
- GitHub CLI에는
gh pr merge가 있지만 액션으로 노출되지는 않음
-
중단된 공식 액션 사례
actions/create-release: 2021년 3월부터 유지보수 중단- 사용자는 커뮤니티 유지보수 워크플로로 이동하도록 권장됨
- 대표적으로
softprops/action-gh-release가 언급됨 actions/upload-release-asset:actions/create-release와 같은 시기에 유지보수 중단 표시actions/setup-ruby: 2021년 2월부터 유지보수 중단- 사용자는
ruby/setup-ruby로 이동하도록 권장됨 - 전환 자체는 비교적 고통이 적었지만, 핵심 구성 요소가 버려질 수 있다는 인상은 플랫폼 신뢰에 악영향을 줌
- 공식 고품질 액션이 부족하면 사용자는 GitHub API 표면을 직접 다루며 보안 실수를 계속 만들 수 있음
-
생태계 개선 방향
- GitHub 인프라의 서로 다른 부분을 직접 연결하고, 현재 REST API 호출이나
gh실행으로 수동 처리해야 하는 작업은 공식 액션으로 제공될 가치가 있음 - 대형 서드파티 액션과 협력해
community-actions같은 준공식 조직을 만들 수 있음- GitHub의 검토를 받은 액션
- 저장소 보안 모범 사례 준수
- 시맨틱 버전 업데이트
- 주요 생태계 액션에 대한 명확한 신뢰 경로
- GitHub 인프라의 서로 다른 부분을 직접 연결하고, 현재 REST API 호출이나
기존 도구와 GitHub 로드맵
- 여러 사람이 로컬 GitHub Actions 에뮬레이션 도구인
nektos/act를 추천함- 단순 워크플로를 빠르게 반복하고 디버깅하는 데 유용함
- 하지만 이미지와 이벤트가 GitHub의 실제 환경과 완전히 같지 않은 경우가 있어 손실 있는 도구로 평가됨
rhysd/actionlint는 로컬 린팅과 보안 린팅에 사용됨- workflows만 lint할 수 있고 actions는 lint하지 못하는 점이 한계임
- GitHub Actions extension for VS Code는 편집기 내 lint와 저장소 워크플로 통합을 제공함
- 공개 JSON schema를 기반으로 함
- 실행 중인 workflow 표시, 변수 완성 등을 제공함
- 하지만 secrets 오타나 동적으로 생성된 output 이름 오타처럼 감지하지 못하는 문제가 있어 add-commit-push 디버깅은 여전히 필요함
- GitHub Actions 프로젝트 관리 책임자 Julian Dunn은 몇 가지 진행 중인 기능과 우선순위를 공유함