새로운 패키지 형식 지원 개발

이 문서는 GitLab에 새로운 패키지 관리 시스템에 대한 지원을 추가하는 방법을 안내합니다.

패키지 및 레지스트리 문서에서 이미 지원되는 형식을 확인하세요.

백엔드 변경만으로 새로운 형식을 추가할 수 있습니다.

이 가이드는 표면적이며 코드 작성 방법은 다루지 않습니다.

그러나 다음의 병합 요청을 살펴보면 좋은 예를 찾을 수 있습니다:

일반 정보

기존 데이터베이스 모델은 다음을 요구합니다:

  • 모든 패키지는 프로젝트에 속합니다.
  • 모든 패키지 파일은 패키지에 속합니다.
  • 패키지는 하나 이상의 패키지 파일을 가질 수 있습니다.
  • 패키지 모델은 패키지와 그 버전에 대한 정보를 저장하는 데 기반하고 있습니다.

API 엔드포인트

패키지 시스템은 API를 통해 GitLab과 작업합니다. 예를 들어 lib/api/npm_project_packages.rb는 npm 클라이언트와 작업하기 위한 API 엔드포인트를 구현합니다. 따라서 첫 번째로 해야 할 일은

새로운 lib/api/your_name_project_packages.rb 파일을 추가하고 패키지 시스템 클라이언트가 작동하는 데 필요한 API 엔드포인트를 정의하는 것입니다. 일반적으로 이는 다음과 같은 엔드포인트를 포함해야 함을 의미합니다:

  • 패키지 정보 가져오기.
  • 패키지 파일 내용 가져오기.
  • 패키지 업로드하기.

패키지는 프로젝트에 속하기 때문에, 업로드 및 다운로드를 위한 프로젝트 수준의 엔드포인트(원격)가 필요합니다. 예를 들어:

GET https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/
PUT https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/

그룹 수준 및 인스턴스 수준 엔드포인트는 프로젝트 수준 엔드포인트가 프로덕션에서 사용 가능한 후에만 고려해야 합니다.

원격 계층 구조

패키지는 다양한 액세스 수준 내에서 범위가 설정되며, 이는 일반적으로 원격 설정을 통해 구성됩니다.

원격 엔드포인트는 프로젝트 수준에서 설정될 수 있으며, 이는 패키지를 설치할 때 해당 프로젝트에 속하는 패키지만 보이게 됩니다. 또는 그룹 수준 엔드포인트를 사용하여 특정 그룹 내의 모든 패키지에 대한 가시성을 허용할 수 있습니다. 마지막으로, 인스턴스 수준 엔드포인트를 사용하여 전체 GitLab 인스턴스의 모든 패키지에 대한 가시성을 허용할 수 있습니다.

MVC로서, 프로젝트 수준의 엔드포인트에서 시작하는 것을 권장합니다.

원격 계층 구조의 일반적인 반복 계획은 다음과 같습니다:

  • 프로젝트에서 게시 및 설치
  • 그룹에서 설치
  • 인스턴스에서 게시 및 설치 (이는 셀프 관리 고객을 위한 것입니다)

인스턴스 수준 엔드포인트를 사용하려면 더 엄격한 명명 규칙이 필요합니다.

참고: Composer 패키지 명명 범위는 인스턴스 수준입니다.

명명 규칙

인스턴스 수준 엔드포인트의 이름 충돌을 피하기 위해서는 패키지가 속하는 프로젝트를 식별할 수 있는 패키지 명명 규칙을 정의해야 합니다.

이는 일반적으로 패키지 이름에 프로젝트 ID 또는 전체 프로젝트 경로를 사용하는 것을 포함합니다.

예시로 Conan의 명명 규칙을 참고하세요.

그룹 및 프로젝트 수준의 엔드포인트의 경우, 명명은 덜 제한적이며 그룹 및 프로젝트 구성원이 두 패키지 이름 간의 충돌이 없도록 하는 것이 중요합니다.

그러나 시스템은 주어진 범위 내에서 기존 이름의 재사용을 방지해야 합니다.

그렇지 않으면 명명은 패키지 관리자의 명명 규칙을 따르고 해당 패키지 유형에 대한 package.md 모델에서 검증을 포함해야 합니다.

서비스 및 파인더

패키지나 패키지 파일 레코드를 생성하거나 패키지를 찾는 작업을 수행하는 논리는 API 파일에 존재해서는 안 되며, 서비스 및 파인더에 있어야 합니다. 가능한 경우 기존 서비스와 파인더를 사용하거나 확장하여 일반적인 패키지 논리가 최대한 그룹화되도록 해야 합니다.

구성

GitLab의 구성 파일(gitlab.rb 또는 gitlab.yml)에는 packages 섹션이 있습니다. 이는 GitLab이 지원하는 모든 패키지 시스템에 적용됩니다. 보통 그곳에 아무것도 추가할 필요는 없습니다.

패키지는 오브젝트 스토리지를 사용하도록 구성할 수 있으므로 코드는 이를 지원해야 합니다.

MVC 접근 방식

새로운 패키지 시스템이 GitLab에 통합되는 방식은 MVC를 사용합니다. 따라서 첫 번째 반복은 최소한의 사용자 동작을 지원해야 합니다:

  • GitLab 작업, 개인 액세스, 프로젝트 액세스 또는 배포 토큰으로 인증
  • 패키지 업로드 및 사용자 인터페이스에서 기본 메타데이터 표시
  • 패키지 가져오기
  • 필요한 작업

필요한 작업은 GitLab이 처리해야 하는 추가 요청으로, 해당 패키지 관리자 CLI가 제대로 작동할 수 있도록 합니다. 검색 기능이나 패키지에 대한 메타 정보를 제공하는 엔드포인트가 될 수 있습니다. 예를 들면:

  • NuGet의 경우, Visual Studio를 지원하기 위해 첫 번째 MVC 반복 중에 검색 요청이 구현되었습니다.
  • npm의 경우, npm이 tarball URL을 얻기 위해 사용하는 메타데이터 엔드포인트가 있습니다.

첫 번째 MVC 반복의 경우, 원격 계층의 프로젝트 수준에 머무르는 것이 좋습니다. 다른 수준은 향후 병합 요청으로 다룰 수 있습니다.

MVC는 일반적으로 두 가지 단계로 나뉩니다:

반복을 작게 유지하기

새로운 패키지 관리자를 구현할 때, 필요한 모든 엔드포인트와 서비스를 포함한 하나의 대형 병합 요청을 만드는 것이 유혹이 될 수 있습니다. 대신:

  1. API 엔드포인트를 기능 플래그 뒤에 두세요.
  2. 각 엔드포인트나 동작(다운로드, 업로드 등)을 별도의 병합 요청으로 제출하여 검토 프로세스를 단축하세요.

분석

이 단계에서는 패키지 시스템에서 사용하는 API에 대한 정보를 최대한 많이 수집하는 것이 목표입니다. 포함할 수 있는 몇 가지 유용한 측면은 다음과 같습니다:

  • 인증: 어떤 인증 메커니즘이 가능한지 (OAuth, Basic Authorization, 기타). GitLab 사용자는 종종 개인 액세스 토큰을 사용하고 싶어합니다. 첫 번째 MVC 반복에서는 필요하지 않지만, CI/CD 작업 토큰도 언젠가 지원해야 합니다.

  • 요청: 작동하는 MVC를 가지려면 어떤 요청이 필요한지. 이상적으로는 MVC에 필요한 모든 요청의 목록을 작성하십시오 (필요한 작업 포함). 추가 조사가 요청 및 응답 본문에 대한 예를 제공할 수 있습니다.

  • 업로드: 업로드 프로세스가 어떻게 작동하는지 신중히 분석합니다. 이 요청은 구현하기 가장 복잡할 가능성이 높습니다. 여기에서 세부 분석이 필요하며, 업로드는 다양한 방법(본문 또는 멀티파트)으로 인코딩될 수 있으며, 완전히 다른 형식(예를 들어 패키지 파일이 특정 필드의 Base64 값인 JSON 구조)일 수 있습니다. 이러한 다양한 인코딩으로 인해 GitLab 및 GitLab Workhorse에서 약간 다른 구현이 필요합니다. 더 자세한 정보는 파일 업로드를 검토하십시오.

  • 엔드포인트: GitLab에 구현할 엔드포인트 URL 목록을 제안합니다.

  • 작업 분할: MVC를 점진적으로 구축하기 위해 수행할 변경 사항 목록을 제안합니다. 이는 수행해야 할 작업량에 대한 좋은 아이디어를 제공합니다. 여기에 사례별로 조정해야 할 예시 목록이 있습니다:

    1. 빈 파일 구조 (API 파일, 이 패키지의 기본 서비스)

    2. 패키지 관리자로 “로그인”하기 위한 인증 시스템

    3. 메타데이터 식별 및 적용 가능한 테이블 생성

    4. 오브젝트 스토리지 직접 업로드를 위한 Workhorse 경로

    5. 업로드/게시를 위한 엔드포인트

    6. 설치/다운로드를 위한 엔드포인트

    7. 필요한 작업을 위한 엔드포인트

분석은 일반적으로 전체 마일스톤을 소요하지만, 같은 마일스톤에서 구현을 시작하는 것은 불가능하지 않습니다.

특히, 업로드 요청은 GitLab Workhorse 프로젝트에 요구 사항이 있을 수 있습니다. 이 프로젝트는 Rails 백엔드와 다른 릴리즈 주기를 가지고 있습니다. 업로드 요청 분석이 완료되는 즉시 그곳에 문제를 열기를 강력히 권장합니다. 이렇게 하면 Rails 백엔드에서 업로드 요청이 구현될 때 GitLab Workhorse가 이미 준비되어 있습니다.

구현

다양한 병합 요청의 구현은 서로 다른 패키지 시스템 통합에 따라 다릅니다. 기여자는 구현 단계에서 몇 가지 중요한 측면을 고려해야 합니다.

인증

MVC는 처음부터 개인 액세스 토큰을 지원해야 합니다. 이 토큰에 대해 두 가지 옵션을 지원합니다: OAuth 및 기본 액세스.

OAuth 인증은 이미 지원됩니다. npm API에서 예제를 확인할 수 있습니다.

기본 액세스 인증 지원은 API 헬퍼에서 특정 기능을 오버라이드하여 수행됩니다, 예를 들어 Conan API의 이 예제와 같이요. 이 인증 메커니즘을 위해, 일부 클라이언트는 인증되지 않은 요청을 먼저 보내고, WWW-Authenticate 필드가 포함된 401 Unauthorized 응답을 기다린 후, 업데이트된(인증된) 요청을 보내는 점을 유의해야 합니다. 이 경우는 GitLab이 401 Unauthorized 응답을 처리해야 하므로 더욱 복잡합니다. NuGet API는 이 경우를 지원합니다.

권한

프로젝트 권한 및 그룹 권한은 read_package, create_package, destroy_package에 대해 존재합니다. 각 엔드포인트는 요청 사용자에 대한 권한을 부여해야 합니다 프로젝트 또는 그룹에 대해 계속 진행하기 전에.

데이터베이스 및 메타데이터 처리

현재 데이터베이스 모델은 각 패키지에 대한 이름과 버전을 저장할 수 있습니다.

새로운 패키지를 업로드할 때마다 Package의 새 레코드를 생성하거나 기존 레코드에 파일을 추가할 수 있습니다. PackageFile은 파일 name, side, sha1 등과 같은 모든 파일 관련 정보를 저장할 수 있어야 합니다.

특정 패키지 시스템 지원을 위해 저장해야 하는 특정 데이터가 있는 경우, 별도의 메타데이터 모델을 만드는 것을 고려하세요. 패키지 특정 데이터를 위한 예로 packages_maven_metadata 테이블과 Packages::Maven::Metadatum 모델을 참고하세요, 그리고 패키지 파일 특정 데이터를 위한 예로 packages_conan_file_metadata 테이블과 Packages::Conan::FileMetadatum 모델을 참고하세요.

특정 패키지 관리자에 대한 패키지 특정 동작이 있는 경우, 이러한 메서드를 메타데이터 모델에 추가하고 패키지 모델에서 위임하세요.

기존 패키지 UI는 packages_packagespackages_package_files 테이블의 정보만 표시합니다. 메타데이터 테이블에 저장된 데이터를 표시해야 하는 경우, ~frontend 변경이 필요합니다.

파일 업로드

파일 업로드는 GitLab Workhorse를 통해 객체 가속 업로드를 사용하여 처리해야 합니다. 이것은 GitLab에 들어오는 모든 요청을 체크하는 워크호스 프록시가 업로드 요청을 가로채고 파일을 업로드하며 메타데이터와 파일 위치만 포함된 요청을 주 GitLab 코드베이스로 전달한다는 것을 의미합니다. 이 프로세스에 대한 개요는 개발 문서에서 확인할 수 있습니다.

코드 측면에서, 추가된 각 업로드 엔드포인트(인스턴스, 그룹, 프로젝트)에 대해 GitLab Workhorse 프로젝트에 라우트를 추가해야 합니다. 이 병합 요청은 Conan을 위해 workhorse에 인스턴스 수준의 엔드포인트를 추가하는 것을 보여줍니다. 동일한 파일에서 Maven 프로젝트 수준의 엔드포인트 구현도 확인할 수 있습니다.

라우트가 추가된 후, API 파일에 업로드 엔드포인트의 추가 /authorize 버전을 추가해야 합니다. 이 예제는 Maven을 위한 추가 엔드포인트가 추가된 것을 보여줍니다. /authorize 엔드포인트는 workhorse에서 요청을 검증하고 승인한 후, 전형적인 업로드 엔드포인트가 아래에 구현되어 Workhorse가 제공하는 메타데이터를 사용하여 패키지 레코드를 생성합니다. Workhorse는 유형, 크기 및 다양한 체크섬 형식과 같은 다양한 파일 메타데이터를 제공합니다.

테스트 목적으로, 로컬 개발 환경에서 객체 스토리지를 활성화하고 싶을 수 있습니다.

파일 크기 제한

GitLab 패키지 레지스트리에 업로드된 파일은 형식에 따라 제한됩니다.

GitLab.com에서는 일반적으로 5GB로 설정되어 시간 초과 문제와 남용을 방지합니다.

Packages::Package 모델에 새 패키지 유형이 추가되면, 이 예제와 유사한 크기 제한이 추가되어야 하며,

파일 크기 제한이 적용되지 않는 경우 관련 테스트를 업데이트해야 합니다. 크기 제한이 적용되지 않는 유일한 이유는 패키지 형식이 패키지 파일을 업로드하고 저장하지 않기 때문입니다.

GitLab.com의 속도 제한

패키지 관리자 클라이언트는 GitLab.com 표준 API 속도 제한을 초과하는 빠른 요청을 할 수 있습니다.

이로 인해 429 Too Many Requests 오류가 발생합니다.

우리는 더 높은 속도 제한을 허용하기 위해 여러 경로를 열었습니다. 불가능하지 않은 한,

새 패키지 관리자는 확장된 패키지 속도 제한을 활용할 수 있도록 이러한 관습을 따라야 합니다.

이 경로 접두사는 더 높은 속도 제한을 보장합니다:

/api/v4/packages/
/api/v4/projects/:project_id/packages/
/api/v4/groups/:group_id/-/packages/

MVC 체크리스트

GitLab에 새로운 패키지 관리자를 지원하는 기능을 추가할 때, 첫 번째 반복은 다음 기능을 포함해야 합니다.

필요에 따라 여러 병합 요청을 통해 기능을 추가할 수 있지만,

기능 플래그가 제거될 때까지 모든 기능이 구현되어야 합니다.

  • 프로젝트 수준 API
  • 푸시 이벤트 추적
  • 풀 이벤트 추적
  • 개인 액세스 토큰을 통한 인증
  • Job Tokens를 통한 인증
  • 배포 토큰(그룹 및 프로젝트)을 통한 인증
  • 파일 크기 제한
  • 파일 형식 보호(패키지 유형에 대해 유효한 파일 형식만 허용)
  • 유효성 검증이 포함된 이름 정규 표현식
  • 유효성 검증이 포함된 버전 정규 표현식
  • 가속화된 업로드를 위한 Workhorse 경로
  • 패키지 메타데이터 추출을 위한 백그라운드 작업자(해당되는 경우)
  • 문서(기능 사용 방법)
  • API 문서(각 개별 엔드포인트와 curl 예제)
  • db/fixtures/development/26_packages.rb에서 시딩
  • Grafana 차트를 위한 운영 매뉴얼 업데이트
  • 패키지를 게시하고 설치하는 것에 대한 최소한의 엔드 투 엔드 기능 테스트

향후 작업

MVC 작업 중 기여자는 MVC에 필수적이지 않지만 더 나은 사용자 경험을 제공할 수 있는 기능을 발견할 수 있습니다.

이러한 기능에 주목하고 문제를 열어두는 것이 일반적으로 좋은 아이디어입니다.

여기 몇 가지 예시가 있습니다.

  1. 검색을 위한 엔드포인트
  2. 추가 패키지 정보 및 메타데이터를 표시하기 위한 프론트엔드 업데이트
  3. 파일 크기에 대한 제한
  4. 메트릭 추적
  5. 프론트엔드에 제공할 수 있도록 패키지에서 더 많은 메타데이터 필드를 읽기. 예를 들어, 패키지에 태그를 달 수 있는 것이 일반적입니다. 이러한 태그는 백엔드에서 읽고 저장한 후 패키지 UI에 표시될 수 있습니다.
  6. 원격 계층의 상위 수준에 대한 엔드포인트. 이 단계에서는 이름 규칙을 만들어야 할 수 있습니다.

예외 사항

이 문서는 GitLab에 이미 존재하는 구조와 논리에 맞춰 패키지 관리자를 구현하는 방법에 대한 가이드라인일 뿐입니다.

구조는 모든 패키지 관리자를 허용할 수 있도록 확장 가능하고 유연하도록 설계되었지만, 패키지 관리자의 제약이나 요구로 인해 벗어날 이유가 있다면,

그런 사항은 효율적인 결과를 위해 구현 이슈나 병합 요청에서 제기하고 논의해야 합니다.