9.3 KiB
kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source
| kind | slug | title | topic | project | status | sourceRevision | rootTreeNode | evidenceCapturedOn | assets | evidence | source | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CASE | a-release-gate-with-no-evidence-producer | 릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다 | what-a-gate-does-not-prove | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | case:a-release-gate-with-no-evidence-producer | 2026-09-02 |
|
|
|
릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다
gRPC 안정 릴리스 게이트는 증거 객체를 읽어 판정한다. 그 객체를 만드는 곳은 게이트 자신의 단위 테스트뿐이다. 그 테스트는 매 PR 의 check 를 타고 돌지만, 거기서 게이트가 읽는 것은 테스트가 손으로 채운 값이다.
관계
- 아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다 이 사건에서 레인이 실행되지 않으면 게이트가 실제 결과 대신 이전 상태나 손으로 만든 입력만 보게 된다는 규칙을 정리했다.
- 빠뜨림이 통과가 되는 게이트는 게이트가 아니다 증거 생산자가 연결되지 않은 상태를 성공으로 처리하지 않도록 하는 규칙이다.
- 시작 검증기 13개 규칙이 유일한 조립 지점에서 호출되지 않는다 같은 gRPC 블록에서 검증 로직은 존재하지만 확인한 조립·실행 경로가 이를 호출하지 않았다.
문제
게이트는 증거 객체를 입력으로 받아 안정 등급 승격을 판정한다. 판정 로직은 존재하고 테스트되어 있다.
증거 객체의 다섯 성분은 전부 호출자가 넘기는 값이다. 등급과 능력이 둘이고, 문서 셋의 존재 여부가 나머지다. 어느 것도 파일 시스템이나 테스트 리포트를 보지 않는다.
결론
searched direct construction 기준으로 증거 객체를 만드는 코드는 게이트 자신의 테스트 네 군데에서만 확인했다.
등급 넷에 대응하는 증거 레인 넷은 존재한다. 리프의 build.gradle 이 아니라 컨벤션 플러그인이 등록하고, 지원 매트릭스가 등급마다 그 이름을 적는다.
없는 것은 둘이다. 레인이 낸 결과를 증거 객체로 바꾸는 코드가 없고, 그 레인 넷을 check 나 워크플로에 붙이는 배선이 없다.
messaging 쪽은 그 둘을 세 층으로 닫았다. 레인이 증거 파일을 쓰고, Gradle 태스크가 실행 산출물과 커밋본을 대조하고, 워크플로가 실제 브로커를 띄워 그 태스크를 돌린다.
gRPC 블록이 어떤 런타임 컴포지션에도 속하지 않는다는 것은 지원 매트릭스가 스스로 적고 있으며 결함이 아니다. 남는 것은 게이트의 입력이다.
검증 환경
OpenJDK : 21.0.12 Gradle : 9.0.0 확인 방식 : 정적 도달성 확인과 태스크 그래프 확인 소스 수정 : x
재현 조건
- 증거 레코드의 성분을 읽고, 그중 파일 시스템이나 리포트를 보는 것이 있는지 확인한다.
- 그 객체를 생성하는 코드를 저장소 전체에서 찾고 main 과 test 를 구분한다.
- 게이트의 테스트에 태그가 붙어 있는지 확인하고, check 그래프에 그 테스트가 들어 있는지 확인한다.
- grpc-testkit 에 등록된 증거 레인을 나열하고, 그중 몇 개가 check 그래프에 있는지 센다.
- CI 워크플로 중 grpc 를 담은 것의 수를 세고, root check 를 도는 워크플로를 확인한다.
- 대비를 위해 messaging 쪽의 증거 파일과 대조 태스크와 워크플로를 확인한다.
본문
docs/compatibility/grpc-support-matrix.md 는 안정 릴리스 게이트를 현재 시제로 적는다. 인증된 레인에 결과가 없거나 실패하면 릴리스를 막는다는 것이다.
게이트는 그 판정을 증거 객체 하나에서 읽는다.
다섯 성분은 전부 호출자가 넘긴다
:::evidence key="a-release-gate-with-no-evidence-producer" alt="코드베이스에서 게이트가 읽는 증거 레코드의 다섯 성분과 그 객체를 만드는 네 지점, 그 테스트에 태그가 없어 check 그래프 안에 있다는 것과 그 check 를 도는 워크플로 줄, 등급 넷에 대응해 컨벤션이 등록한 증거 레인 넷과 그중 check 그래프에 들어 있는 수와 grpc 를 담은 워크플로 수, 그리고 messaging 쪽에서 레인이 쓰는 증거 파일과 그것을 대조하는 태스크와 그 태스크를 돌리는 워크플로 단계를 뽑은 출력 39줄. 게이트의 테스트는 check 안에 있고 증거 레인 넷은 밖에 있다는 것이 그 출력에 보인다." caption="증거의 다섯 성분 · 생성 지점 넷 전부 테스트 · 그 테스트는 check 안 · 레인 넷은 check 밖 · messaging 의 세 층 — 39줄" zoom="true" :::
증거 레코드는 실행한 등급 집합과 인증된 능력 집합, 그리고 런북과 결정 기록과 지원 매트릭스의 존재 여부 셋을 담는다.
문서 존재 여부 셋은 파일 시스템을 직접 확인하지 않고 호출자가 넘긴 boolean을 그대로 저장한다. 실행 등급 집합과 인증 능력 집합도 호출자가 구성한다.
확인한 직접 생성 지점은 게이트 테스트 네 곳이다
생성 지점이 넷이고 전부 같은 파일, 게이트 자신의 단위 테스트다.
그 테스트에는 태그가 붙어 있지 않다. 그래서 기본 test 태스크에 들어가고, check 그래프 안에 있고, 매 PR 마다 도는 워크플로가 그 check 를 돌린다.
판정 로직 자체는 기본 테스트에서 실행된다. 다만 그 실행에서 게이트가 읽는 다섯 성분은 실제 lane 산출물이 아니라 테스트가 직접 구성한 값이다.
레인은 등록돼 있는데 아무 게이트에도 붙어 있지 않다
증거 등급이 넷이고, 그 넷에 대응하는 레인이 넷 등록되어 있다. 인프로세스 계약, 실제 Netty, 결함 주입, 성능이다.
등록은 리프의 build.gradle 이 아니라 컨벤션 플러그인이 한다. 지원 매트릭스가 등급마다 이 이름들을 적어 둔다.
그 레인 넷 중 check 그래프에 들어 있는 것은 0 이다. 28개 워크플로 중 grpc 를 이름이나 내용에 담은 것도 0 이다.
레인 태스크는 직접 실행할 수 있지만 check 그래프와 확인한 CI workflow에서는 호출되지 않는다.
없는 것은 레인과 증거 사이의 코드다
레인이 낸 결과를 증거 객체의 다섯 성분으로 바꾸는 코드가 없다.
그래서 게이트가 읽는 값은 레인이 실제로 무엇을 했는지와 연결되어 있지 않다. 블록이 출하되기 시작해도 이 연결은 저절로 생기지 않는다.
같은 저장소에 그 사슬을 이어 놓은 예가 있다
messaging 쪽은 세 층이다.
레인이 실행 결과를 증거 파일로 쓴다. Gradle 태스크가 그 산출물과 커밋된 매니페스트를 대조하고, 커밋본이 레인이 내지 않은 시나리오를 주장하면 실패한다. 워크플로가 실제 브로커를 띄워 그 태스크를 돌리고 결과를 산출물로 올린다.
해당 태스크는 결과 캐시를 끄고, 인증 판단에는 이번 실행에서 생성한 증거가 필요하다는 이유를 주석으로 남긴다.
워크플로는 레인이 현재 커밋 해시를 읽어 증거에 기록하도록 한다. 인증 결과를 특정 소스 트리와 연결하기 위해서다.
게이트의 설계가 차단 사유를 만드는 방식
게이트는 빠진 결과와 빠진 등급과 스키마 판정과 문서 존재를 합쳐 차단 사유 목록을 만든다.
문서 누락도 차단 사유로 둔다. 런북 없이 동작만 출하하면 운영자가 장애 시점에 절차를 즉석에서 추론해야 하기 때문이다.
출하되지 않는다는 사실은 결함이 아니다
지원 매트릭스는 모든 gRPC leaf의 runtime membership을 비워 두고 build-only로 표시한다. 이 상태에서는 코드는 컴파일되고 증거 lane도 실행할 수 있지만 현재 배포 산출물에는 포함되지 않는다.
같은 문서는 안정 릴리스 전에 추가로 필요한 입력으로 성능 측정 결과와 스키마 코드 생성 검증을 적는다.
확인하지 못한 것
gRPC 블록이 어떤 배포에도 들어가지 않아서 런타임에서 볼 방법이 없다. 레인 넷을 실제로 돌려 결과를 보지는 않았다.