본문으로 건너뛰기

git-pkgs 생태계의 확장: 의존성 분석부터 라이선스·출처 검증까지

What’s new in git-pkgs

nesbitt.io

핵심 요약

  1. git-pkgs CLI가 v0.14에서 v0.20으로 올라가면서 changelog, freshness, deprecated, funding, maintainers, health, provenance, replace 등 하위 명령 8개가 새로 붙었다.
  2. 지원 생태계도 Guix, pre-commit, Lean, opam, Chef, Helm, Solaris IPS, Vagrant로 늘었고, lockfile·매니페스트·Maven 그래프 파서와 라이선스 변경, 실제 라이선스 파일 검사 기능까지 보강했다.
  3. git-pkgs 조직은 약 45개 저장소로 커졌으며, provenance·SBOM·SARIF·CWE·라이선스·콘텐츠 분석을 맡는 작은 Go 모듈을 조합해 패키지 도구를 만든다.

도입

git-pkgs는 의존성 이력을 뒤지는 Git subcommand에서 출발해, 패키지 메타데이터와 프로젝트 상태, 라이선스, 공급망 출처, 아티팩트 무결성까지 아우르는 Go 도구 모음으로 커졌다. 조직이 운영하는 저장소는 약 45개이고, 독립 도구 10개와 라이브러리 모듈 30여 개, GitHub Actions와 agent skills를 함께 제공한다. 각 모듈은 역할이 좁고 의존성도 작게 유지한다.

상세 요약

git-pkgs CLI의 변화

메인 CLI는 v0.14에서 v0.20으로 올라가면서 하위 명령 8개가 새로 붙었다.

  • changelog: 두 버전 사이의 upstream changelog 항목을 조회한다.
  • freshness: 각 의존성이 최신 릴리스보다 며칠 늦었는지 보여준다.
  • deprecated: 설치된 버전과 registry의 deprecation 플래그를 맞춰 본다.
  • funding: 의존성의 후원 링크를 표시하고, --missing으로 링크가 없는 항목을 찾는다.
  • maintainers: 유지보수자 수와 이름을 보고하며 --single로 1인 프로젝트를 찾는다.
  • health: ecosyste.ms 메타데이터를 바탕으로 프로젝트 상태를 점수로 매긴다.
  • provenance: npm, PyPI, RubyGems의 registry attestation과 trusted publishing 상태를 보고한다.
  • replace: downstream 테스트용으로 의존성을 로컬 checkout이나 git ref로 바꾼다.

새로 지원된 생태계는 Guix, pre-commit, Lean, opam, Chef, Helm, Solaris IPS, Vagrant다. GitHub Actions에는 .github/workflows/actions.lock 기반 lockfile 지원이 들어갔고, 기존 파서는 conda-lock.yml, Directory.Packages.props, setup.cfg, compose.yml, go.graph, Maven graph export 등을 계속 처리한다.

git pkgs licenses는 설치 버전과 최신 버전 사이의 라이선스 변경을 찾는 --drift와, 패키지 관리자의 선언과 무관하게 아카이브 안의 라이선스 파일을 직접 검사하는 --license-text를 제공한다. git pkgs diff에는 --stat, --summary, --by=ecosystem이 추가됐고, 릴리스 checksum은 cosign v4 bundle로 서명한다. Homebrew formula는 homebrew-core로 옮겨져 brew install git-pkgs로 바로 설치가 가능하다.

기존 도구의 확장

brief에는 패키지 전체 artifact 보고서를 만드는 inspect와, 소스 트리를 signature와 import 중심으로 줄이는 outline이 더해졌다. 지식 기반은 570개가 넘는 도구를 다루는데, Rust 기반 native-extension toolchain, 과학·연구 도구, agent instruction 파일, issue template을 감지한다. workspace와 선택적 submodule 재귀도 지원한다.

proxy가 지원하는 registry protocol은 16개에서 25개로 늘었다. Alpine APK, Helm, Homebrew JSON API와 bottle, Swift package registry, GitHub release asset용 generic HTTP proxy가 추가됐고, Web UI, GCS backend, ECR upstream 인증, Helm chart, 그리고 Trivy·ClamAV·사용자 지정 scanner를 호출하는 artifact scanning hook도 갖췄다. 다운로드 artifact에도 cooldown을 적용한다.

forge는 Bitbucket Cloud, Gerrit, Tangled adapter를 추가했다. forge pr checkout, 현재 branch의 forge pr view, forge branch show-base, forge pr create --push가 제공되며, Git remote에서 host를 파악하고 plain HTTP self-hosted instance, GitLab nested group path, agit-flow를 처리한다.

pin은 npm을 거치지 않고 browser asset을 저장소에 vendor한다. pin.yaml에 파일을 지정하면 registry tarball hash를 검증한 뒤 lockfile과 함께 저장하는데, 이 lockfile이 곧 CycloneDX SBOM이다. 기본 release age는 48시간이고 install script는 실행하지 않는다. --frozen은 오래된 lockfile로 CI가 진행되는 걸 막는다.

capcheck는 Go 코드나 의존성이 process 생성, socket 접근, cgo 호출 같은 새 privileged operation을 얻으면 CI를 실패시킨다. 기준은 capcheck.lock.json에 기록하며 init, 검사, update 명령으로 관리한다. licenses는 ScanCode rule corpus를 18MB Go binary에 넣었고, cargo 저장소 검사에서는 ScanCode보다 빠른 실행 결과를 보여준다. git-spdx는 저장소의 git history를 추적해 라이선스 표현식과 선언의 변화를 commit과 path 단위로 기록한다.

downstream은 의존 프로젝트를 복제해 공개 버전과 로컬 checkout을 각각 테스트한다. 현재 Go, Cargo, npm 계열이 연결돼 있고 GitHub Actions matrix 출력도 지원한다. distill은 README가 아니라 코드로 프로젝트 유형을 분류하는데, LLM은 학습 corpus 라벨링에만 쓰고 실제 분류는 offline classifier가 맡는다.

새 모듈과 재사용 구조

provenance 영역은 다섯 모듈로 나뉜다. attestation은 sigstore bundle의 DSSE envelope에서 SLSA Provenance v1 identity를 표준 라이브러리만으로 파싱하고, sigstore는 TUF trust root로 bundle을 검증한다. integrity는 여러 형식의 Subresource Integrity 문자열을 파싱해 다운로드를 streaming hash로 검사하며, artifacts는 PURL, OCI 형식 SHA-256 digest, byte count를 묶는다. cooldown은 패키지별 설정, ecosystem 기본값, 전역 기준 순서로 버전 설치 가능 시점을 계산한다.

sbom은 CycloneDX JSON·XML과 SPDX JSON을 읽고 쓴다. sarif는 SARIF 2.1.0 정적 분석 로그를 처리하고, cwe는 MITRE CWE catalogue를 빌드 시 포함해 offline 조회를 지원한다. reuse는 REUSE v3.3 선언을 읽고, magic은 제한된 prefix만으로도 파일 형식과 MIME type을 감지한다. outline은 35개 언어의 body를 제거하고 signature·type·doc comment·import만 남긴다.

저장소와 패키지 분석을 위해 clone은 shallow clone, retry, ref reset, submodule, checkout cache를 제공하고 os.Root로 저장소 범위를 제한한다. dependents는 ecosyste.ms API에서 의존 저장소를 찾아 native extension 사용 여부를 판별한다. Maven 영역에서는 pom이 parent POM, BOM, profile, property를 순수 Go로 해석하고, nexus는 Maven repository index를 읽는다. gcs는 전체 Cloud SDK 없이 GCS JSON API와 signed URL을 제공한다.

기존 라이브러리의 업데이트

2월에 소개된 14개 모듈 중 12개가 변했다. manifests는 47개 ecosystem과 저장소 전체 manifest·vendor directory 탐색을 지원하고, registries는 Helm, streaming fetch, retry, circuit breaking, 그리고 private-network upstream을 거부하는 safehttp를 추가했다. vers는 Bazel, Composer, Pub, PEP 440, apk-tools 버전 체계와 HighestSatisfying을 지원한다.

archives는 zstd와 .conda, extensionless archive, os.Root 기반 격리 추출, byte·entry 제한, 버전 간 archive 비교를 추가했다. enrichment은 endoflife.date와 다운로드·dependent·funding·maintainer 정보를 지원하고, managers는 30개 manager의 init과 replace를 제공한다. spdx, changelog, gitignore, resolve, purl도 각각 식별자 처리, 원격 changelog, ancestor 규칙, 의존성 해석, OSV·Swift registry 매핑으로 확장됐다.

설계 제약은 그대로다. 모듈은 작고 역할이 좁으며 cgo를 피한다. ecosyste.ms 서비스는 빠른 경로로 쓸 수 있지만, 각 모듈은 registry나 git remote를 직접 상대로도 독립 실행이 가능하다.

결론

이번 변화의 핵심은 기능을 하나의 큰 도구에 몰아넣지 않고 provenance·integrity·artifacts·cooldown·sbom·sarif·cwe 같은 재사용 모듈로 쪼갠 것이다. CLI가 여러 생태계와 파일 형식을 직접 다루고, proxy·brief·downstream·Scrutineer 같은 도구는 그 모듈을 조합해 쓴다. 대부분 MIT 라이선스로, cgo를 피하고 독립 실행을 지원한다.