GitLab Package Registry

You can also publish your distribution packages in the package registry of your GitLab project. However, the following conditions must be met:

  • You must authenticate yourself when registering the package.

  • Your version information must be valid.

  • The package must be smaller than 5 GB and the description must not be longer than 4000 characters.

  • The package has not yet been published in the package registry. Attempting to publish the same version of a package will return 400 Bad Request.

You can then use the package with both pip and uv.

Authentication

To authenticate to the GitLab Package Registry, you can use one of the following methods:

.gitlab-ci.yml
variables:
  UV_VERSION: 0.5
  PYTHON_VERSION: 3.12
  BASE_LAYER: bookworm-slim
  UV_PUBLISH_USERNAME: <personal_access_token_name>
  UV_PUBLISH_PASSWORD: <personal_access_token>
.gitlab-ci.yml
variables:
  UV_VERSION: 0.5
  PYTHON_VERSION: 3.12
  BASE_LAYER: bookworm-slim
  UV_PUBLISH_USERNAME: <deploy_token_username>
  UV_PUBLISH_PASSWORD: <deploy_token>
.gitlab-ci.yml
variables:
  UV_VERSION: 0.5
  PYTHON_VERSION: 3.12
  BASE_LAYER: bookworm-slim
  UV_PUBLISH_USERNAME: <gitlab-ci-token>
  UV_PUBLISH_PASSWORD: $CI_JOB_TOKEN

… with a personal access token

To authenticate yourself with a personal access token, you can add the following to the ~/.pypirc file, for example:

[distutils]
index-servers=
    gitlab

[gitlab]
repository = https://ce.cusy.io/api/v4/projects/{PROJECT_ID}/packages/pypi
username = {NAME}
password = {YOUR_PERSONAL_ACCESS_TOKEN}

… with a deploy token

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://ce.cusy.io/api/v4/projects/{PROJECT_ID}/packages/pypi
username = {DEPLOY_TOKEN_USERNAME}
password = {DEPLOY_TOKEN}

… with a job token

image: python:latest

- name: Setup cached uv
  uses: hynek/setup-cached-uv@v2
- name: Create venv and install twine
  run: |
    uv venv
    echo "$PWD/.venv/bin" >> $PATH
    uv add --upgrade twine
- name: Build
  run: |
    uv build
- name: Retrieve and publish
  - 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/*

… for access to packages within a group

Use the GROUP_URL instead of the PROJECT_ID.

Publishing the distribution package

Now you can publish your package on GitLab with :

.gitlab-ci.yml

stages:
  - publish
uv:
  stage: publish
  image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER
  script:
    - uv build
    - uv publish --publish-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*

Tip

If necessary, you can use RUST_LOG=uv=trace to obtain further information on the authentication attempts, for example with RUST_LOG=uv=trace uv --verbose publish --publish-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*.

See also

In GitLab CI/CD you will find further instructions on how to configure the .gitlab-ci.yml file.

Installing the package

You can install the latest version of your package for example with

$ uv add -i https://{NAME}:{PERSONAL_ACCESS_TOKEN}@ce.cusy.io/api/v4/projects/{PROJECT_ID}/packages/pypi/simple --no-deps {PACKAGE_NAME}

… or from the group level with

$ uv add -i https://{NAME}:{PERSONAL_ACCESS_TOKEN}@ce.cusy.io/api/v4/groups/{GROUP_ID}/-/packages/pypi/simple --no-deps {PACKAGE_NAME}

… or in the pyproject.toml file with

pyproject.toml
[tool.uv]
extra-index-url = ["https://ce.cusy.io/api/v4/projects/{PROJECT_ID}/packages/pypi/simple {PACKAGE_NAME}"]