GitHub Actions, PR에서는 캐시를 읽기 전용으로 쓰는 법
PR 테스트는 기존 캐시로 빠르게 돌리고 싶지만, PR이 새 캐시를 남기는 건 막고 싶다. 복원은 허용하고 저장만 막는 설정은 어디에 넣을까?

cache-mode: read는 GitHub Actions 캐시를 복원할 수 있게 하면서 저장을 제한한다.- 워크플로 전체에 적용하거나 특정 job에 넣을 수 있으며, job에 쓴 값이 우선한다.
- 일반
pull_request와pull_request_target은 기본 캐시 권한이 같지 않다.
PR job에 저장 권한을 주지 않아도 캐시는 쓸 수 있다
PR 테스트에서 기존 의존성 캐시만 가져오려면 cache-mode: read를 선언하면 된다. GitHub는 9월 10일부터 GitHub.com의 모든 요금제에 이 설정을 제공한다. 액션의 저장 단계를 조건문으로 건너뛰는 방식과 달리, 캐시 서비스가 해당 작업에 허용된 접근 범위를 제한한다.
다음은 npm 캐시를 복원하는 위치를 보여 주는 예시다. 실제 프로젝트의 설치·테스트 단계는 그 아래에 유지한다. 캐시를 만드는 작업과 복원하는 작업은 key와 path를 맞춰야 한다.
name: PR cache restore
on: pull_request
cache-mode: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/cache/restore@v5
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
# Keep your project's install and test steps below. actions/cache/restore는 캐시를 가져오는 전용 액션으로, 실행이 끝난 뒤 저장하는 단계가 없다. 이 액션을 선택하는 것은 작업 방식이고, cache-mode는 job의 권한이다. 다른 단계가 저장을 시도하더라도 막으려는 목적이라면 권한 설정까지 명시해야 한다.
위 예시는 GitHub 호스팅 러너를 사용한다. 자체 호스팅 러너에서 같은 v5 액션을 쓰려면 러너 2.327.1 이상이 필요하다. 캐시가 없을 때도 설치·테스트가 진행되도록 구성해야 하며, 캐시 복원 자체를 의존성 설치 완료로 취급해서는 안 된다.
read는 읽기만, write는 읽기와 쓰기 모두다
설정 위치는 YAML 최상위 또는 jobs.작업이름.cache-mode다. 최상위 값은 각 job에 적용되지만 job에서 다른 값을 선언하면 그 값이 우선한다.
| 값 | 기존 캐시 복원 | 새 캐시 저장 |
|---|---|---|
read | 허용한다. | 막는다. |
write | 허용한다. | 허용한다. |
write-only | 막는다. | 허용한다. |
none | 막는다. | 막는다. |
이름이 비슷해도 write와 write-only는 다르다. 기존 캐시를 사용하면서 새 항목도 만드는 작업은 write, 기존 항목을 읽지 않고 저장만 하는 작업은 write-only다. PR 테스트에 복원만 남기는 목적에는 read가 맞는다.
일반 PR까지 이미 읽기 전용이라고 생각하면 안 된다
트리거별 기본값에는 실행 문맥이 반영된다. pull_request_target이나 issue_comment처럼 외부 사용자의 입력으로 시작될 수 있고 기본 브랜치 문맥에서 실행되는 작업은 기본적으로 캐시 읽기만 허용된다.
일반 pull_request는 다르다. 여기서 만든 캐시는 PR 병합 참조인 refs/pull/.../merge 범위에 묶인다. 기본 브랜치 캐시 범위에 쓰는 것이 아니므로 앞의 읽기 전용 기본 제한 대상이 아니다. 일반 PR에서도 저장을 막고 싶다면 read를 명시한다.
저장 경고를 없애려고 저신뢰 작업에 write를 넣으면 기본 보호를 덮어쓴다. 공유 캐시는 신뢰하는 push 작업에서 만들고, 해당 캐시를 소비하는 PR 작업에는 필요한 복원만 허용하는 구성이 가능하다.
저장 생략과 워크플로 시작 실패는 구분한다
적용된 모드는 러너의 ACTIONS_CACHE_MODE와 캐시 단계 로그에서 확인할 수 있다. 권한 때문에 캐시 작업을 생략했다는 메시지 자체는 job 실패가 아니다. 다만 캐시가 없으면 뒤의 설치·빌드 단계는 자체 로직에 따라 실행된다.
재사용 워크플로를 호출하는 경우에는 호출하는 job에 cache-mode: read를 명시해 상한을 정할 수 있다. 호출받는 워크플로가 write처럼 더 큰 권한을 요구하면 자동으로 낮춰 실행하는 것이 아니라 검증 오류로 시작하지 않는다.
호출자가 트리거 기본값에만 의존하면 호출받는 쪽에서 쓰기를 명시할 수 있다. PR의 저장을 확실히 제한하려면 호출부의 명시적 모드와 호출 대상의 요구 권한을 함께 맞춰야 한다.