PyPI 패키지 레지스트리

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

프로젝트의 패키지 레지스트리에 PyPI 패키지를 게시합니다. 그런 다음 필요할 때마다 종속성으로 사용할 수 있도록 패키지를 설치하세요.

패키지 레지스트리는 다음과 함께 작동합니다:

piptwine 클라이언트가 사용하는 구체적인 API 엔드포인트의 문서에 대해서는 PyPI API 문서를 참조하세요.

PyPI 패키지 빌드하는 방법을 배우세요.

패키지 레지스트리 인증

패키지 레지스트리에 게시하려면 인증해야 합니다.

이를 위해 다음을 사용할 수 있습니다:

여기에 문서화되지 않은 인증 방법을 사용하지 마십시오. 문서화되지 않은 인증 방법은 향후에 제거될 수 있습니다.

개인 액세스 토큰으로 인증

개인 액세스 토큰을 사용하여 인증하려면 ~/.pypirc 파일을 편집하고 다음을 추가하세요:

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = <your_personal_access_token_name>
password = <your_personal_access_token>

<project_id>는 프로젝트의 URL 인코딩된 경로(예: group%2Fproject) 또는 프로젝트 ID(예: 42) 중 하나입니다.

배포 토큰으로 인증

배포 토큰을 사용하여 인증하려면 ~/.pypirc 파일을 편집하고 다음을 추가하세요:

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = <deploy token username>
password = <deploy token>

<project_id>는 프로젝트의 URL 인코딩된 경로(예: group%2Fproject) 또는 프로젝트 ID(예: 42) 중 하나입니다.

CI 작업 토큰으로 인증

GitLab CI/CD로 인증하려면 개인 액세스 토큰, 배포 토큰 또는 CI_JOB_TOKEN으로 인증해야 합니다. CI/CD 작업에서 PyPI 명령을 사용하려면 하나의 인증 방법만 필요합니다.

예시:

image: python:latest

run:
  script:
    - pip install build twine
    - python -m build
    - TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*

CI_JOB_TOKEN.pypirc 파일에 사용할 수도 있습니다. 이 파일은 GitLab에 체크인합니다:

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/pypi
username = gitlab-ci-token
password = ${env.CI_JOB_TOKEN}

그룹 내의 패키지에 액세스하기 위한 인증

토큰 유형에 대한 위의 지침을 따르되, 프로젝트 URL 대신 그룹 URL을 사용합니다:

https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi

PyPI 패키지 게시

전제 조건: - 패키지 레지스트리에 인증해야 합니다. - 버전 문자열이 유효해야 합니다. - 최대 허용 패키지 크기는 5GB입니다. - description 필드의 최대 길이는 4000자입니다. 더 긴 description 문자열은 잘립니다. - 동일한 버전의 패키지를 여러 번 업로드할 수 없습니다. 시도하면 400 Bad Request 오류가 발생합니다. - PyPI 패키지는 프로젝트ID를 사용하여 게시됩니다. - 프로젝트가 그룹에 속한 경우, 프로젝트 레지스트리에 게시한 PyPI 패키지는 그룹 수준 레지스트리(참조: 그룹 수준에서 설치)에서도 사용할 수 있습니다.

그런 다음 twine을 사용하여 패키지를 게시할 수 있습니다.

버전 문자열이 유효한지 확인

버전 문자열(예: 0.0.1)이 유효하지 않으면 거부됩니다. GitLab은 다음과 같은 정규식을 사용하여 버전 문자열을 유효성 검사합니다.

\A(?:
    v?
    (?:([0-9]+)!)?                                                 (?# epoch)
    ([0-9]+(?:\.[0-9]+)*)                                          (?# release segment)
    ([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)?  (?# pre-release)
    ((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))?       (?# post release)
    ([-_\.]?(dev)[-_\.]?([0-9]+)?)?                                (?# dev release)
    (?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))?                         (?# local version)
)\z}xi

이 정규식으로 여러 버전 문자열을 시도해볼 수 있는 정규 표현식 편집기를 사용하여 정규식을 실험할 수 있습니다.

이 정규식에 대한 더 자세한 내용은 이 문서를 확인하세요.

twine을 사용하여 PyPI 패키지 게시

PyPI 패키지를 게시하려면 다음과 같은 명령을 실행하세요:

python3 -m twine upload --repository gitlab dist/*

다음 메시지는 패키지가 성공적으로 게시되었음을 나타냅니다:

Uploading distributions to https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi
Uploading mypypipackage-0.0.1-py3-none-any.whl
100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.58k/4.58k [00:00<00:00, 10.9kB/s]
Uploading mypypipackage-0.0.1.tar.gz
100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.24k/4.24k [00:00<00:00, 11.0kB/s]

게시된 패키지를 보려면 프로젝트의 패키지 및 레지스트리 페이지로 이동하세요.

.pypirc 파일을 사용하여 리포지토리 소스를 정의하지 않은 경우 다음 명령을 사용하여 인증을 인라인으로 게시할 수 있습니다:

TWINE_PASSWORD=<personal_access_token 또는 deploy_token> TWINE_USERNAME=<username 또는 deploy_token_username> python3 -m twine upload --repository-url https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi dist/*

이 페이지의 단계를 따르지 않은 경우 패키지가 올바르게 빌드되었고, setuptools를 사용하여 PyPI 패키지를 생성했는지 확인하십시오.

그런 다음 다음 명령을 사용하여 패키지를 업로드할 수 있습니다:

python -m twine upload --repository <source_name> dist/<package_file>

동일한 이름이나 버전의 패키지를 게시하는 경우

동일한 이름과 버전의 패키지가 이미 존재하는 경우, 해당 패키지를 게시할 수 없습니다. 먼저 기존 패키지를 삭제해야 합니다. 동일한 패키지를 여러 번 게시하려고 하면 400 Bad Request 오류가 발생합니다.

PyPI 패키지 설치

패키지 레지스트리에서 PyPI 패키지를 찾을 수 없는 경우, 해당 요청은 pypi.org로 전달됩니다.

관리자는 Continuous Integration 설정에서 이 동작을 비활성화할 수 있습니다.

경고: --index-url 옵션을 사용할 때 기본 포트인 경우, 즉 http로 시작하는 URL의 경우 80, https로 시작하는 URL의 경우 443과 같은 기본 포트를 지정하지 마십시오.

프로젝트 레벨에서 설치

패키지의 최신 버전을 설치하려면 다음 명령을 사용하세요:

pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
  • <package_name>은 패키지 이름입니다.
  • <personal_access_token_name>read_api 스코프가 있는 개인 액세스 토큰 이름입니다.
  • <personal_access_token>read_api 스코프가 있는 개인 액세스 토큰입니다.
  • <project_id>는 프로젝트의 URL 인코딩된 경로(예: group%2Fproject)이거나 프로젝트 ID(예: 42)입니다.

이러한 명령에서 --extra-index-url 대신 --index-url을 사용할 수 있습니다. 그러나 --extra-index-url을 사용하면 커스텀 레지스트리를 확인하기 전에 PyPi 리포지토리를 확인하여 의존성 혼동 공격에 취약해질 수 있습니다. --extra-index-url은 제공된 URL을 추가 레지스트리로 추가하며, 이를 통해 클라이언트가 패키지의 존재 여부를 확인합니다. --index-url은 클라이언트에게 제공된 URL에서 패키지를 확인하도록 지시합니다.

가이드를 따라하기 위해 MyPyPiPackage 패키지를 설치하고 싶다면 다음을 실행할 수 있습니다:

pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/simple

이 메시지는 패키지가 성공적으로 설치되었음을 나타냅니다:

다음 인덱스에서 확인 중: https://<personal_access_token_name>:****@gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/simple
mypypipackage 수집 중
  https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB)에서 다운로드 중
설치 중인 수집된 패키지: mypypipackage
성공적으로 설치됨 mypypipackage-0.0.1

그룹 레벨에서 설치

그룹에서 패키지의 최신 버전을 설치하려면 다음 명령을 사용하세요:

pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi/simple --no-deps <package_name>

이 명령에서:

  • <package_name>은 패키지 이름입니다.
  • <personal_access_token_name>read_api 스코프가 있는 개인 액세스 토큰 이름입니다.
  • <personal_access_token>read_api 스코프가 있는 개인 액세스 토큰입니다.
  • <group_id>는 그룹 ID입니다.

이러한 명령에서 --extra-index-url 대신 --index-url을 사용할 수 있습니다. 그러나 --extra-index-url을 사용하면 커스텀 레지스트리를 확인하기 전에 PyPi 리포지토리를 확인하여 의존성 혼동 공격에 취약해질 수 있습니다. --extra-index-url은 제공된 URL을 추가 레지스트리로 추가하며, 이를 통해 클라이언트가 패키지의 존재 여부를 확인합니다. --index-url은 클라이언트에게 제공된 URL에서 패키지를 확인하도록 지시합니다.

가이드를 따라하기 위해 MyPyPiPackage 패키지를 설치하고 싶다면 다음을 실행할 수 있습니다:

pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/pypi/simple

패키지 이름

GitLab은 Python 표준화된 이름(PEP-503)을 사용하는 패키지를 찾습니다. -, _, . 문자는 모두 동일하게 처리되며 중복된 문자는 제거됩니다.

my.package에 대한 pip install 요청은 my-package, my_package, my....package와 같은 세 문자 중 하나와 일치하는 패키지를 찾습니다.

requirements.txt 사용

pip가 공개 레지스트리에 액세스하도록 하려면 requirements.txt 파일에 레지스트리 URL과 함께 --extra-index-url 매개변수를 추가합니다.

--extra-index-url https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
package-name==1.0.0

이것이 비공개 레지스트리인 경우, 몇 가지 방법으로 인증할 수 있습니다. 예를 들어:

  • requirements.txt 파일을 사용하는 경우:
--extra-index-url https://__token__:<your_personal_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
package-name==1.0.0
  • ~/.netrc 파일을 사용하는 경우:
machine gitlab.example.com
login __token__
password <your_personal_token>

문제 해결

성능을 향상시키려면 pip 명령이 패키지와 관련된 파일을 캐시합니다. Pip는 자체적으로 데이터를 제거하지 않습니다. 새로운 패키지가 설치될 때마다 캐시가 늘어납니다. 문제가 발생하면 다음 명령을 사용하여 캐시를 지울 수 있습니다:

pip cache purge

여러 index-url 또는 extra-index-url 매개변수

여러 index-urlextra-index-url 매개변수를 정의할 수 있습니다.

동일한 도메인 이름(예: gitlab.example.com)을 다른 인증 토큰과 함께 여러 번 사용하는 경우 pip가 패키지를 찾지 못할 수 있습니다. 이 문제는 pip이 명령 실행 중에 토큰을 등록하고 저장하는 방식 때문에 발생합니다.

이 문제를 해결하기 위해 모든 프로젝트 또는 그룹에 대상이 되는 모든 프로젝트 또는 그룹에 대한 공통 상위 그룹에서 read_package_registry 스코프를 가진 그룹 배포 토큰을 사용할 수 있습니다.

지원되는 CLI 명령어

GitLab PyPI 저장소는 다음과 같은 CLI 명령어를 지원합니다:

  • twine upload: 레지스트리에 패키지를 업로드합니다.
  • pip install: 레지스트리에서 PyPI 패키지를 설치합니다.