콘텐츠로 이동

English · 한국어

점검과 게이트

pqcota의 다섯 리포지터리에 있는 점검이 무엇을 지키는지, 각각 누가 맡는지, 어디서 실행되는지, 통과(green)해도 보여 주지 않는 것이 무엇인지 설명합니다. 실행 방법은 빌드 안내의 작업 확인과 함께 읽고, 계약에 관한 점검은 계약 변경을 보세요. 개발자 문서가 목차입니다.

두 층

  • 리포지터리마다 자체 점검이 있습니다. 그 리포지터리에서 make로 실행하고, 그 리포지터리의 CI가 실행합니다.
  • 통합 리포지터리 pqcota는 다섯 리포지터리 전체를 가로질러 보는 게이트를 더합니다(문서, 임포트 방향, 배선, 수집기 목록). pqcota의 make all은 형제 리포지터리의 make를 먼저 모두 실행한 다음 이 게이트를 실행합니다.

내 기계에서 make all이 통과한 것과 CI가 통과한 것은 같은 말이 아닙니다. CI에는 로컬 실행에 없는 점검이 있고, 로컬 실행은 CI가 돌리는 테스트를 건너뛸 수 있으며, 그 반대도 있습니다. 아래 절에서 어느 쪽인지 밝힙니다.

리포지터리마다 실행하는 점검

맡는 곳: 그 make와 워크플로가 속한 리포지터리. 「로컬」은 그 리포지터리에서 make를 실행하는 것입니다.

점검 막는 것 로컬 CI 통과해도 보여 주지 않는 것
포맷(fmt-check) 포맷되지 않은 Go(생성된 gen/은 제외) 예 예 동작에 관한 모든 것
Vet go vet이 보고하는 것 예 예 go vet을 넘어서는 정확성
빌드 호스트, linux/amd64, windows/amd64용으로 컴파일되지 않는 코드(각 리포지터리의 make build가 둘 다 교차 컴파일합니다) 예 예 바이너리가 실행되는지. Linux 전용 코드를 교차 컴파일하므로 macOS나 Windows 호스트도 깨짐을 가리지 못하지만, 실행하지는 않습니다
Java 사이드카(build-jar, discovery) 빌드되지 않는 사이드카 JDK가 없으면 경고를 내고 건너뛰며 종료 코드 0 실행(CI가 JDK를 설치) JDK가 없으면 로컬에서 통과해도 아무것도 빌드하지 않은 것입니다. build/collector.jar가 있는지 확인하세요
테스트(go test ./...) 실패하는 테스트 예, 상세 출력 아님: 건너뛴 테스트를 나열하지 않음 예. inventory, discovery, provisioning의 CI는 상세 출력으로 실행하며 건너뛴 것의 목록을 출력하고, common과 통합 리포지터리는 -v 없이 실행하므로 건너뛴 것이 나열되지 않음 건너뛴 테스트가 확인했을 모든 것. 건너뛰는 테스트를 보세요
계약 린트(buf lint, common) proto 스타일 문제 예(buf 필요) 예 계약이 옳은지
계약 호환성(buf breaking, common) 지난 릴리스의 계약을 깨는 변경 예, 가져온 최신 릴리스 태그와 비교 예, 전체 클론이라 태그가 항상 있음 동작, 시그니처, 데이터베이스의 호환성. 계약 변경을 보세요
생성 코드 불일치(common) proto가 만드는 결과와 다른 gen/ 점검하지 않음. make generate는 다시 생성만 함 예: 다시 생성한 뒤 트리가 다르면 실패 아래를 보세요

생성 코드 불일치

로컬에서 make generate는 gen/을 다시 쓰고, 바뀌었어도 아무 표시를 하지 않습니다. 차이를 실패로 만드는 것은 CI뿐이며, CI는 버전을 고정한 buf를 쓰므로 로컬의 buf가 다르면 gen/도 달라질 수 있습니다. 그래서 로컬 make all이 깨끗해도 CI의 불일치 점검이 통과한다는 뜻은 아닙니다. proto를 바꾼 뒤에는 다시 생성한 코드를 함께 커밋하고, 깨끗한 트리에서 make generate && git diff --exit-code -- gen/을 실행하세요. CI의 점검과 가깝지만 똑같지는 않습니다. 커밋하지 않은 수정이 트리에 있기 때문입니다. 이유는 계약 변경에 있습니다.

통합 리포지터리의 게이트

pqcota/tools/에 있고 pqcota에서 실행합니다. 따로 적지 않으면 다섯 리포지터리 전체를 잽니다. make all에서는 형제의 자체 점검 뒤에 실행됩니다.

게이트 막는 것 로컬 CI 통과해도 보여 주지 않는 것
check-docs 각 리포지터리의 Markdown에서: 깨진 상대 링크와 앵커, 어느 문서를 가리키는지 적은 주석이 없는 절 참조(§N), 빈 절, 실제 의존성과 다른 라이선스 표, go.mod와 다른 문서의 Go 버전, 영문과 한국어의 뼈대 불일치, 홈 경로와 기계 이름 같은 개인 식별자, 일부 한국어 표현 규칙 예 예 글이 사실인지, 리포지터리 사이의 링크가 살아 있는 페이지를 가리키는지. git이 추적하는 파일만 읽으므로 새 문서는 실행 전에 stage하세요
check-deps 허용 목록이 허락하지 않는 방향의 임포트(예: discovery가 provisioning을 임포트, 수집기가 inventory를 임포트). 표가 분류하지 않은 패키지 경로도 실패 예 예 허용된 선이 모두 쓰이는지. pqcota 패키지 사이의 직접 임포트(테스트 포함)를 재며, 표준 라이브러리나 외부 모듈은 재지 않습니다
check-gates 함수로 적혀 있지만 어떤 제품 명령도 호출하지 않는 보장(// GATE로 표시했는데 아무도 잇지 않은 함수), 자리표시자 규칙 집합 버전 예 예 규칙 자체가 옳은지(별도의 테스트와 리뷰가 필요합니다), 배선이 보장이 주장하는 일을 하는지. 게이트 하나는 현재 보류로 표시되어 실패가 아니라 보고만 합니다
check-collectors 릴리스 워크플로와 참조 플레이북이 서로 다른 수집기를 나열하는 것 예 예 바이너리가 노드에서 동작하는지
check-boundary 다른 제품 계층(tier)을 가리키는 표현(.md와 .go) 예 예 그 표현 규칙 말고는 아무것도
check-prose 한때 지웠던 한국어 구절이 돌아오는 것. 파일별 기준선과 비교해 더 많으면 실패하고, 더 적어도 기준선을 낮출 때까지 실패 예 예 pqcota 리포지터리만 잽니다. 네 개의 단계 리포지터리는 재지 않습니다. 코드 블록과 인라인 코드 밖의 Markdown, 일부 Go 파일의 사용자에게 보이는 문자열, 목록에 올린 HTML 페이지의 텍스트를 읽고, 주석, 코드 블록, 한국어가 없는 줄은 건너뜁니다
통합 테스트(pqcota의 go test ./...) test/crossstage, 도구 자체의 테스트, 데모 토폴로지 생성기 테스트의 실패 예 예 단계 리포지터리 안의 모든 것. 그 테스트는 각자의 CI에서 실행됩니다.

실무상 두 가지입니다. check-docs는 검사기를 다시 빌드해 리포지터리마다 한 번씩 실행하므로, 문서 실패는 리포지터리 이름을 밝힙니다. 그리고 check-prose에는 기준선 파일이 있습니다. 표현을 고쳐서 개수가 줄었다면 그 기준선 명령을 실행해 같은 변경에 새 기준선을 커밋하세요. 그러지 않으면 게이트가 반대쪽으로 실패합니다.

건너뛰는 테스트

건너뛴 테스트는 통과가 아닙니다. 환경에 무언가 없으면 테스트가 스스로 건너뛰는데, make는 -v 없이 go test를 실행하므로 어느 것을 건너뛰었는지 알려 주지 않습니다. 워크플로 세 개(inventory, discovery, provisioning)는 -v로 실행해 건너뛴 사례의 목록을 출력하므로, 거기서 그 목록을 읽으세요. pqcota-common과 pqcota의 CI는 목록을 출력하지 않습니다. 그 둘이 중요하다면 직접 상세 출력으로 테스트를 실행하세요.

없는 것 건너뛰는 것 실행되는 곳
Postgres(PQCOTA_TEST_DSN 미설정) inventory 이력의 데이터베이스 테스트, provisioning 기록 저장소, pqcota-hosts와 pqcota-profile의 조직 테스트(현재 main) Postgres 서비스를 제공하는 inventory와 provisioning의 CI. 서비스가 없는 discovery의 CI는 아님: 거기서는 pqcota-hosts의 데이터베이스 테스트를 건너뛰고 규칙 테스트만 실행됨
CAP_NET_RAW 그 권한이 필요한 패킷 캡처 테스트. 권한이 없어야 하는 형제 테스트는 권한이 있으면 건너뛰므로 둘을 한꺼번에 실행할 수는 없음 CI는 앞의 것을 별도 단계에서 sudo로 다시 실행하고 PASS가 출력되었는지 확인함
JDK attach가 막힌 경로를 확인하는 테스트 CI가 JDK를 설치하므로 거기서 실행됨
포트 22의 로컬 sshd 실제 SSH 핸드셰이크를 관측하는 테스트 기계에 sshd가 없을 때마다 건너뜀. 러너에서 어떻게 되었는지는 CI의 건너뜀 목록에 나옴
읽을 수 있는 /proc, ELF 테스트 바이너리 OpenSSL 수집기의 호스트 스캔 경로 Linux 전용. 다른 시스템에서는 이 테스트를 컴파일조차 하지 않음
bash 데모 토폴로지 생성기 테스트 bash가 없는 곳 어디서나
git 체크아웃 임포트 방향 테스트(트리가 체크아웃이 아닐 때)

로컬에서 건너뜀을 보려면 테스트를 상세 출력으로 파일에 실행하고, 먼저 테스트 자체의 결과를 본 다음 건너뜀을 봅니다(go test ... | grep만 쓰면 실패한 실행이 가려집니다. 파이프라인이 grep의 상태를 보고하기 때문입니다).

go test ./... -count=1 -v > /tmp/test.log 2>&1; status=$?
echo "go test exit status: $status"
grep -- '--- SKIP' /tmp/test.log

환경 확인 뒤에 t.Skip을 호출하지 않고 일찍 반환하는 테스트는 -v로도 나열되지 않습니다.

로컬에서 Postgres 테스트를 실행하려면 버려도 되는 데이터베이스를 쓰세요. 이 테스트는 테이블을 만들고 행을 추가하며 삭제는 하지 않습니다. 아래의 컨테이너 이름과 호스트 포트는 예시입니다. 55432가 이미 쓰이고 있으면 빈 포트를 고르고, 끝나면 이 컨테이너만 제거하세요.

docker run -d --name pqcota-test-pg -e POSTGRES_USER=pqcota -e POSTGRES_PASSWORD=pqcota -e POSTGRES_DB=pqcota -p 127.0.0.1:55432:5432 postgres:16
docker exec pqcota-test-pg pg_isready -U pqcota        # repeat until it reports "accepting connections"
export PQCOTA_TEST_DSN='postgres://pqcota:pqcota@127.0.0.1:55432/pqcota?sslmode=disable'
# ... run the tests ...
docker rm -f pqcota-test-pg

PQCOTA_TEST_DSN은 환경 변수 레퍼런스에 있습니다.

통과한 make all이 보여 주지 않는 것

  • CI가 통과할지. 로컬에서는 불일치를 점검하지 않고, 건너뜀이 표시되지 않으며, CI 잡의 sudo 캡처 테스트, arm64 교차 빌드, Postgres 서비스는 재현되지 않습니다.
  • 아무것도 건너뛰지 않았는지. -v 출력이나 CI의 건너뜀 목록을 읽으세요.
  • Java 사이드카가 빌드되었는지. JDK가 없으면 그 단계는 경고하고 성공합니다.
  • 형제 리포지터리 자체의 CI가 통과하는지. pqcota에서 make all이 통과했다면 형제의 자체 make가 내 작업 트리에서 순서대로 통과했다는 뜻입니다. 하나라도 실패하면 멈추기 때문입니다. CI에서만 실행되는 것(불일치 점검, CI가 돌릴 수 있는 건너뛴 테스트, arm64 빌드)은 포함하지 않습니다. 위 표의 게이트는 형제 뒤에 통합 리포지터리에서 한 번 실행됩니다. 반대 방향으로, 통합 리포지터리 자체의 CI는 형제의 make를 실행하지 않고 게이트와 자체 테스트를 하나씩 호출하므로, 거기서 통과해도 형제의 CI에 관해서는 아무것도 알 수 없습니다.
  • 문서가 옳은지. 문서 게이트는 링크, 구조, 몇 가지 규칙을 확인하며 사실 여부는 확인하지 않습니다. 사용자 문서의 주장은 코드와 대조해 손으로 확인했고, 그것을 되풀이하는 게이트는 없습니다.
  • Windows 바이너리가 동작하는지. 교차 컴파일만 하며, 실행하는 점검은 없습니다.
  • 릴리스가 일관된지. 릴리스는 다섯 리포지터리에 같은 태그를 붙여 손으로 조율합니다(빌드 안내 참조). 이것은 현재의 관행이며 점검이 강제하는 것이 아닙니다.

CI 실행 읽기

네 개의 단계 리포지터리(pqcota-common, -inventory, -discovery, -provisioning)에는 각각 자체 점검을 위한 build 잡과, 그 단계의 커밋으로 통합 리포지터리의 워크플로를 호출하는 cross-stage 잡이 있습니다. 통합 리포지터리 pqcota에는 호출되는 워크플로가 있고(자체 푸시에서도 실행됩니다), discovery는 amd64와 arm64용 cross-build 잡을 더합니다.

cross-stage 잡이 실패했다면 내 커밋을 나머지 네 리포지터리의 main과 합친 상태에서 통합 점검이 실패했다는 뜻입니다. 이유는 알려 주지 않습니다. 임포트 방향, 게이트 배선, 문서 링크일 수 있고, 실패하는 단계 간 테스트, 빌드 문제, 검사기 환경, 다른 리포지터리의 main에 들어온 변경일 수도 있습니다. 실패한 단계의 로그를 여세요.

English