새 패키지 형식 지원 개발

이 문서는 GitLab에 새 패키지 관리 시스템을 지원하도록 안내합니다.

이미 지원되는 형식은 패키지 및 레지스트리 문서에서 확인할 수 있습니다.

새로운 형식을 추가하려면 백엔드 변경만으로 가능합니다. 본 안내서는 표면적이며 코드 작성 방법에 대해 다루지 않습니다. 그러나 다음 병합 요청을 살펴봄으로써 좋은 예제를 찾을 수 있습니다:

일반 정보

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

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

API 엔드포인트

패키지 시스템은 GitLab과 API를 통해 작동합니다. 예를 들어 lib/api/npm_project_packages.rb는 npm 클라이언트와 작업하기 위한 API 엔드포인트를 구현합니다. 따라서 처음 해야 할 일은 패키지 시스템 클라이언트가 작동하기에 필요한 API 엔드포인트가 포함된 새로운 lib/api/your_name_project_packages.rb 파일을 추가하는 것입니다. 보통 다음과 같은 엔드포인트를 갖는 것을 의미합니다:

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

프로젝트에 속한 패키지이므로 프로젝트 수준의 엔드포인트(원격)를 이용하여 업로드 및 다운로드할 수 있어야 한다. 예를 들어:

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로서, 프로젝트 수준의 엔드포인트로 시작하는 것이 좋습니다. 원격 계층 구조의 전형적인 반복 계획은 다음과 같습니다:

  • 프로젝트에 게시 및 설치
  • 그룹에서 설치
  • 인스턴스에 게시 및 설치 (자체 관리 고객을 위한 것)

인스턴스 수준의 엔트포인트 사용은 보다 엄격한 명명 규칙을 필요로 합니다.

명명 규칙

인스턴스 수준의 엔드포인트의 이름 충돌을 피하기 위해 패키지 명명 규약을 정의해야 합니다. 보통 이는 패키지가 속한 프로젝트 ID 또는 전체 프로젝트 경로를 패키지 이름에 사용하여 패키지가 어떤 프로젝트에 속하는지 식별할 수 있는 방법을 제공합니다. Conan의 명명 규약을 예로 살펴볼 수 있습니다.

그룹 및 프로젝트 수준의 엔드포인트의 명명은 덜 제약적일 수 있으며, 충돌이 없도록 하는 것은 그룹 및 프로젝트 구성원의 몫입니다. 그러나 시스템은 특정 범위 내에서 기존 이름을 재사용하는 것을 방지해야 합니다.

그렇지 않으면, 명명은 패키지 매니저의 명명 규칙을 따르고 해당 패키지 유형에 대한 package.md 모델의 유효성 검사를 포함해야 합니다.

서비스 및 파인더

패키지 생성 또는 패키지 파일 레코드 작성, 패키지 검색 등과 같은 작업을 수행하는 논리는 API 파일에 존재해서는 안 되지만, 서비스 및 파인더에 존재해야 합니다. 가능한 경우 기존 서비스 및 파인더를 사용하거나 확장하여 공통 패키지 논리를 최대한 그룹화하여야 합니다.

구성

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

패키지는 객체 저장소를 사용하도록 구성할 수 있으므로 코드가 이를 지원해야 합니다.

MVC 접근 방식

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

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

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

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

첫 번째 MVC 반복에는 원격 계층 구조의 프로젝트 수준에 머물기를 권장합니다. 다른 수준은 미래의 병합 요청에서 다룰 수 있습니다.

MVC에는 보통 두 단계가 있습니다:

작은 이터레이션 유지

새로운 패키지 매니저를 구현할 때 기본 사용을 지원하기 위한 모든 필요한 엔드포인트 및 서비스를 포함하는 큰 병합 요청을 만드는 것이 유혹스럽습니다.

대신:

  1. API 엔드포인트를 기능 플래그 뒤에 두세요.
  2. 각 엔드포인트 또는 동작(다운로드, 업로드 등)을 다른 병합 요청에 제출하여 리뷰 프로세스를 단축하세요.

분석

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

  • 인증: 이용 가능한 인증 메커니즘(OAuth, 기본 인증, 기타)은 무엇인가요. GitLab 사용자들은 종종 자사의 개인 액세스 토큰을 사용하려고 합니다. CI/CD 작업 토큰은 MVC 첫 번째 이터레이션에 필요하지는 않지만, 향후 어느 시점에서는 지원되어야 합니다.
  • 요청: 작동하는 MVC를 위해 필요한 요청은 어떤 것인가요. 이상적으로, MVC에 필요한 모든 요청(필요한 조치 포함)의 목록을 작성하세요. 추가 조사를 통해 각 요청에 대한 예제와 요청 및 응답 본문이 제공될 수 있습니다.
  • 업로드: 업로드 프로세스가 어떻게 작동하는지 주의 깊게 분석하세요. 이 요청은 아마도 구현하기 가장 복잡할 것입니다. 여기서는 업로드가 본문이나 멀티파트로 인코딩될 수 있으며 특정 필드의 Base64 값인 JSON 구조와 같이 완전히 다른 형식일 수 있음에 주목하세요. 이러한 다른 인코딩은 GitLab과 GitLab Workhorse에서 약간 다른 구현으로 이어집니다. 보다 자세한 정보는 파일 업로드를 확인하세요.
  • 엔드포인트: GitLab에 구현할 엔드포인트 URL 목록을 제안하세요.
  • 작업 분리: MVC를 점진적으로 구축하기 위해 수행할 변경 목록을 제안하세요. 수행해야 할 작업 양을 잘 나타내 주고 있습니다. 다음은 사례별로 적응해야 하는 예제 목록입니다.
    1. 빈 파일 구조(API 파일, 이 패키지를 위한 기본 서비스)
    2. 패키지 매니저에 “로그인”하기 위한 인증 시스템
    3. 메타데이터 식별 및 해당 테이블 생성
    4. 객체 스토리지 직접 업로드용 Workhorse 경로
    5. 업로드/배포에 필요한 엔드포인트
    6. 설치/다운로드에 필요한 엔드포인트
    7. 필요한 조치에 필요한 엔드포인트

이 분석은 보통 완전한 마일스톤이 소요되지만, 동일한 마일스톤에서 구현을 시작하는 것이 불가능한 것은 아닙니다.

특히, 업로드 요청은 GitLab Workhorse 프로젝트의 요구 사항이 있을 수 있습니다. 이 프로젝트는 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은 파일과 관련된 모든 정보(파일 이름, 측면, sha1 등)를 저장할 수 있어야 합니다.

특정 패키지 시스템 지원에만 저장해야 하는 특정 데이터가 있는 경우 별도의 메타데이터 모델을 만들어야 합니다. 패키지별 데이터의 예로 packages_maven_metadata 테이블과 Packages::Maven::Metadatum 모델을, 그리고 패키지 파일별 데이터의 예로 packages_conan_file_metadata 테이블과 Packages::Conan::FileMetadatum 모델을 확인해 보세요.

특정 패키지 매니저에 대한 패키지별 동작이 있는 경우 해당 메서드를 메타데이터 모델에 추가하고 패키지 모델에서 위임해야 합니다.

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

Tier: Free, Premium, Ultimate

파일 업로드

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

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

경로가 추가된 후에는 API 파일에 업로드 엔드포인트의 추가적인 /authorize 버전을 추가해야 합니다. 이 예제는 Maven을 위해 추가된 엔드포인트를 보여줍니다. /authorize 엔드포인트는 워크호스로부터의 요청을 확인하고 승인한 다음, 전형적인 업로드 엔드포인트가 아래에 구현되어 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
  • Push 이벤트 추적
  • Pull 이벤트 추적
  • 개인 액세스 토큰으로의 인증
  • Job 토큰으로의 인증
  • 배포 토큰으로의 인증 (그룹 및 프로젝트)
  • 파일 크기 제한
  • 파일 형식 가드 (패키지 유형에 대해 유효한 파일 형식만 허용)
  • 이름 정규식과 유효성 검사
  • 버전 정규식과 유효성 검사
  • 가속화된 업로드를 위한 Workhorse 경로
  • 패키지 메타데이터 추출을 위한 백그라운드 작업(해당하는 경우)
  • 문서 (기능 사용 방법)
  • API 문서 (curl 예제를 포함한 개별 엔드포인트)
  • db/fixtures/development/26_packages.rb에 시드 추가
  • Grafana 차트에 대한 런북 업데이트
  • (최소한) 패키지 게시 및 설치에 대한 엔드투엔드 기능 테스트

향후 작업

MVC 작업 중에 기여자는 MVC에는 필수가 아니지만 더 나은 사용자 경험을 제공할 수 있는 기능을 발견할 수 있습니다. 일반적으로 그러한 기능을 주시하고 이슈를 열어둘 것을 권장합니다.

다음은 일부 예시입니다

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

예외

이 설명서는 기존의 GitLab 구조와 논리에 부합하는 패키지 관리자를 구현하는 지침일 뿐입니다. 구조는 어떠한 패키지 관리자에도 대응할 수 있도록 확장 가능하고 유연하게 의도되었지만, 특정 패키지 관리자의 제약 사항 또는 요구 사항으로 인해 벗어나야 할 합당한 이유가 있다면, 구현 이슈나 병합 요청에서 해당 사항을 제기하고 효율적인 결과를 도출하도록 논의해야 합니다.