깃허브는 10월 14일 Actions 워크플로 의존성 잠금 파일을 공개 프리뷰로 제공한다고 발표했다. 대상 플랜은 Free, Team, Enterprise Cloud와 데이터 상주형 Enterprise Cloud다. 태그나 브랜치는 검토 후 다른 커밋을 가리킬 수 있는데, 잠금 파일은 이름을 워크플로에 유지하면서 실제 실행을 검토한 커밋에 연결한다.
읽기 쉬운 참조와 실제 실행 코드를 나눈다
이 기능은 이동 가능한 참조로 인해 저장소 변경 없이 실행 코드가 달라지는 위험을 줄이려는 수단이다. 그러나 잠근 커밋 자체가 안전한지는 별도 검토 대상이다. 잠금 성공을 악성 코드나 취약점이 없다는 보안 검사 결과로 받아들여서는 안 된다.
잠금 파일의 두 부분과 저장소 정체성
공식 개념 문서에서 파일 위치는 .github/workflows/actions.lock이다. GitHub CLI 확장인 gh actions-lock가 생성하며 손으로 편집하지 않도록 안내한다. workflows 영역은 적용한 워크플로별 의존성을, dependencies 영역은 참조가 해석된 커밋과 관련 정보를 담는다.
각 의존성에는 원래 ref와 실행할 commit, 원본 저장소의 숫자 owner_id·repo_id가 기록된다. 런타임은 이름 뒤에 있는 저장소가 잠갔던 대상인지도 확인한다. 사람이 읽는 이름과 실제 자원의 식별자를 함께 보존한다는 점이 단순히 파일에 해시 문자열을 적는 것과 다른 관리상의 의미다.
점진 적용하되 범위 안에서는 빠짐없이 기록
워크플로는 하나씩 또는 한꺼번에 잠금 대상으로 편입할 수 있다. 편입된 워크플로는 쓰는 액션 의존성이 모두 잠금 파일에 있어야 하고 기록된 커밋을 실행한다. 그 커밋은 원본 저장소에서 잠금 파일에 기록한 해당 브랜치나 태그로 도달 가능해야 한다. 원본 저장소의 아무 브랜치에 존재하기만 하면 된다는 뜻은 아니다. 관리자는 Require lockfile 정책으로 적용을 요구할 수 있다.
잠금 범위에는 전이 액션도 들어가지만 jobs.<job_id>.uses 형식의 재사용 워크플로 호출 자체는 들어가지 않는다. 호출은 전체 커밋 SHA로 따로 고정하고, 그 워크플로 내부의 액션은 정의 저장소의 잠금 파일로 관리한다. 호출하는 저장소의 파일 하나로 외부 워크플로의 호출 코드와 내부 액션을 모두 잠갔다고 가정하면 안 된다.
태그·직접 SHA·잠금 파일이 바꾸는 범위
동일한 deploy 액션을 가리킨다고 가정해 세 방식을 비교했다. @v3 같은 태그는 사람이 버전을 읽기 쉽지만 태그가 다른 커밋으로 옮겨가면 다음 실행 코드도 바뀔 수 있다. 전체 커밋 SHA를 직접 쓰면 그 액션의 참조는 고정되지만 액션 내부가 부르는 다른 액션까지 자동으로 고정되는 것은 아니다. 잠금 파일은 온보딩한 워크플로의 액션 의존성을 전이 관계까지 기록하고, 저장소 숫자 식별자도 대조한다. 표는 공식 문서의 적용 범위를 비교한 것이며 새 CI 실행을 측정한 결과는 아니다.
가령 주 액션은 고정했지만 재사용 배포 워크플로는 @main으로 부르는 저장소라면, 잠금 파일이 생겼다는 이유만으로 배포 절차 전체가 고정되지는 않는다. 호출 줄의 전체 SHA와 외부 저장소 안의 잠금 관리 여부를 따로 확인해야 한다. 또한 같은 액션 커밋도 runner 이미지나 입력값, secrets가 바뀌면 다른 결과를 낼 수 있다. 여기서 재현성은 우선 액션 코드의 해석에 관한 것이며 빌드의 모든 입력이 같다는 보증은 아니다.
| 방식 | 고정하는 대상 | 별도로 남는 일 |
|---|---|---|
| 태그·브랜치 | 실행 시점에 참조가 가리키는 커밋 | 참조 이동을 감시하고 실행 코드 검토 |
| 전체 SHA 직접 참조 | 그 참조의 액션 또는 재사용 워크플로 코드 | 내부 의존성의 참조도 별도 확인 |
| actions.lock | 온보딩한 워크플로의 액션 및 전이 액션 | 재사용 워크플로 호출 고정, runner·입력·secrets 관리 |
Actions 잠금 파일은 읽기 쉬운 태그와 검토한 커밋의 실행을 연결한다. 공개 프리뷰의 지원 범위와 재사용 워크플로 내부의 별도 의존성, 업데이트·검토 절차를 함께 관리해야 한다.
ARCH.B 의견
공식 확장의 일반 실행은 이미 잠긴 참조를 무조건 최신 커밋으로 올리지 않는다. 새로 추가된 참조를 해석하고 잠긴 커밋의 유효성을 확인하는 방식이다. 이동하는 브랜치나 일부 버전 태그를 최신 상태로 다시 해석하려면 재잠금 절차를 사용한다. 고정된 상태를 유지하는 작업과 의도적으로 갱신하는 작업을 구분한 설계다.
파일을 바꾸지 않는 verify는 CI에서 최신성·유효성을 점검하는 데 쓸 수 있다. 반면 verify-local은 네트워크 없이 참조마다 항목이 있는지만 확인하며 항목의 신뢰성을 검사하지 않는다. 두 검사의 이름이 비슷해도 공급망 검증 범위가 같지는 않다. Dependabot은 이미 잠금 대상인 워크플로의 액션 버전을 올릴 때 같은 PR에서 관련 잠금 항목도 다시 생성한다고 공지는 설명한다. 버전 이름만 바꾸고 실행 커밋을 옛 상태로 남기는 불일치를 줄이는 흐름이다. 검토자는 워크플로 변경과 잠금 파일 변경을 함께 살필 수 있다.
잠금은 업데이트를 불필요하게 만드는 기능이 아니다. 고정된 커밋에 문제가 발견되면 검토한 대안으로 바꾸어야 하고, 새 액션을 추가하면 그 의존성도 포함해야 한다. 반대로 자동으로 최신 버전을 따라가는 일이 안전하다고 가정할 수도 없다. 재현 가능한 실행과 의도적인 갱신을 각각 운영 절차로 두는 것이 중요하다.
공식 확장 저장소는 아직 1.0 이전의 공개 프리뷰이며 파일 형식·플래그·동작이 바뀔 수 있다고 밝힌다. GitHub Enterprise Server는 지원하지 않는다. 클라우드 플랜에 제공된다는 발표를 자체 서버 전체에 확대 적용할 수 없는 이유다. 도입팀은 대표 워크플로부터 생성 결과를 검토하고 적용 저장소와 재사용 워크플로의 소유 범위를 확인할 수 있다. 그 뒤 CI 검증과 정책 강제를 넓히면 변경 영향을 파악하기 쉽다. 잠금 파일이 제공하는 것은 실행 대상의 고정과 감사 가능한 변경 기록이며, 의존 코드의 안전성 판단을 대체하는 것은 아니다.
