GitHub Actions: 모범 사례


이 작업 중인 문서는 GitHub Actions를 활용하기 위한 모범 사례를 모아 둔 곳이에요. 제안하거나 추가하고 싶은 내용이 있다면 GitHub에서 풀 리퀘스트를 열어 주세요!

모범 사례 모음

워크플로에 타임아웃 설정하기

기본적으로 GitHub Actions는 워크플로가 6시간 안에 끝나지 않으면 중단해요. 대부분의 워크플로는 그렇게 오랜 시간이 필요하지 않지만, 예기치 않은 오류가 발생하거나 작업이 멈춰서 시작한 지 6시간 뒤에 워크플로 실행이 강제로 중단되는 경우가 있어요. 그래서 더 짧은 타임아웃을 지정하는 걸 권장해요.

이상적인 타임아웃은 워크플로마다 다르지만, Exercism 저장소에서 사용하는 워크플로에는 보통 30분이면 충분히 넉넉해요.

이렇게 하면 다음과 같은 장점이 있어요:

  • PR이 반나절 내내 CI 대기 상태에 머무르지 않고, 문제를 일찍 발견하거나 워크플로 실행을 다시 시작할 수 있어요.
  • 전체 병렬 빌드 수가 제한적이라, 멈춘 작업을 일찍 취소하면 다른 PR에 문제를 일으키지 않아요.

예시

jobs:
  configlet:
    timeout-minutes: 30
    runs-on: ubuntu-latest
    steps:
      - [...]

(서드 파티) 액션이 정말 필요한지 고려하기

액션은 즐겨 쓰는 프로그래밍 언어의 의존성처럼 다뤄야 해요1. 액션은 Exercism의 통제 밖에 있는 서드 파티 작성자가 작성한 코드예요. 액션 작성자를 신뢰하더라도 저장소가 적대적으로 인수되어, 그 사람들이 간접적으로 Exercism 저장소에 접근하게 될 수 있어요. 쓰기 권한까지 얻게 될 수도 있고요.

그래서 새 액션을 도입하는 게 정말 가치 있는 일인지, 아니면 그 코드를 Exercism이 관리하는 (새) 액션으로 옮기는 게 나은지 신중하게 고려해야 해요.

또한 그 액션이 활발히 유지 관리되는지도 고려해 봐요. 예를 들어 최근 저장소 활동을 확인하거나, 액션이 개인 계정이 아니라 조직에 속해 있는지 살펴보는 거예요.

GitHub이나 Exercism 조직이 게시한 액션은 일반적으로 별다른 고려 없이 포함해도 (어느 정도는) 안전하다고 볼 수 있어요.

워크플로 토큰의 범위 제한하기

기본적으로 워크플로에 주어지는 액세스 토큰은 읽기와 쓰기 모두에 걸쳐 폭넓은 권한을 가져요.

최소 권한 원칙은 워크플로에도 적용해야 해요.

워크플로에 필요한 권한은 워크플로 단위로 지정할 수 있어요.

예시

워크플로가 저장소의 내용을 읽기만 하면 되고 쓰기는 필요 없을 때, 예를 들어 평범한 CI 검사라면, 다음과 같이 토큰을 제한할 수 있어요:

permissions:
  contents: read

권한의 전체 목록은 GitHub 문서를 확인해 보세요.

액션을 SHA에 고정하기

다른 액션을 사용할 때는 브랜치나 태그가 아니라 커밋(SHA)에 고정해요. 이렇게 하면 매번 같은 코드가 실행되는데, 브랜치나 태그에 고정하면 이건 보장되지 않아요.

이렇게 하면 두 가지 이점이 있어요:

  1. 빌드가 _안정적_이 돼요.
  2. 공격자가 브랜치/태그를 악성 코드를 가리키도록 바꾸는 것을 막아요.

이 규칙의 유일한 예외는 우리(Exercism)가 직접 만든 액션이에요.

커밋 SHA 찾기

보통은 특정 릴리스의 커밋 SHA에 고정하고 싶을 거예요. 릴리스의 커밋 SHA를 찾으려면 액션 저장소의 릴리스 페이지(예: https://github.com/actions/checkout/releases)로 가요. 사용하려는 릴리스를 찾아, 릴리스 왼쪽의 요약 섹션에 나열된 축약 SHA(예: a12a394)를 클릭해요. 그러면 사용할 수 있는 전체 커밋 SHA가 나열된 릴리스 세부 정보 페이지로 이동해요.

예시

- name: Checkout code
  uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846

테스트 러너를 버전에 고정하기

대부분의 워크플로는 GitHub이 지원하는 러너에서 실행돼요. 이러한 러너 중 하나를 사용할 때는 최신 버전 대신 특정 버전을 사용해요.

이렇게 하면 워크플로가 항상 같은 러너에서 실행되어 빌드가 _안정적_이 돼요.

예시

다음과 같이 쓰는 대신:

runs-on: ubuntu-22.04

이렇게 써요:

runs-on: ubuntu-latest

동시성 전략 설정 고려하기

그사이 더 새로운 커밋이 푸시되었다면, 중간 커밋에 대해 CI를 실행하는 게 불필요하거나 유용하지 않은 경우가 많아요.

같은 컨텍스트에서 실행 중인 워크플로를 자동으로 취소하려면 동시성 전략을 설정할 수 있어요.

예시

PR에서 중간 빌드를 취소하려면 다음 동시성 설정을 사용하면 돼요:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
서드 파티 고지

위 예시는 MIT 라이선스로 배포된 PkgTemplates.jl의 CI 워크플로를 바탕으로 했어요:

MIT License

Copyright (c) 2017-2020 Chris de Graaf, Invenia Technical Computing Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

어떤 트리거가 정말 필요한지 고려하기

"GitHub Actions 보안 강화" 가이드 읽기

위에서 언급한 사례가 전부는 아니에요. GitHub Actions를 안전하게 사용하기 위한 좋은 보안 사례를 종합적으로 다룬 GitHub의 보안 가이드를 확인해 보세요.

워크플로 체크리스트

다음 체크리스트로 워크플로가 모범 사례를 따르는지 확인할 수 있어요. 이 체크리스트는 완전한 목록이 아니라, 가장 중요한 항목에 초점을 맞춘 것이에요.

복사해서 붙여넣을 수 있는 버전, 예를 들어 PR에 쓸 수 있어요

  1. 그 언어가 npm 생태계를 사용하는 경우는 예외예요. ↩