Навигация
Реестр пакетов
Как публиковать и устанавливать пакеты npm, PyPI, Cargo, Maven, NuGet, Composer и Generic в GitRiver и как отдавать внешние пакеты через посредника
GitRiver имеет встроенный реестр пакетов для 7 форматов. Отдельный сервис не нужен - пакеты хранятся рядом с кодом. Тот же реестр умеет отдавать и внешние пакеты, забирая их у источника и складывая в кеш.
Это бесплатная функция - доступна в Community без ограничений.
Зачем
- Приватные пакеты для вашей команды (не публикуются в npm/PyPI)
- Автоматическая публикация из CI/CD при каждом релизе
- Единый доступ через те же токены, что и к репозиториям
- Не зависите от внешних реестров
Как передаётся токен
Все вызовы реестра принимают токен пятью способами - выбирайте тот, который умеет ваш клиент:
| Способ | Вид |
|---|---|
| Своя схема | Authorization: Bearer <токен> |
| Схема GitHub | Authorization: token <токен> |
| Клиенты GitLab | заголовок PRIVATE-TOKEN: <токен> |
| HTTP Basic | Authorization: Basic <base64(имя:токен)> |
| Браузер | сеансовая кука |
В паре Basic токен стоит на месте пароля, а имя пользователя не проверяется вовсе - личность берётся из токена. Именно так его кладут pip (https://имя:токен@узел), Maven (<password>) и NuGet (ClearTextPassword), поэтому примеры ниже работают как есть.
Пароль учётной записи не подойдёт - принимается только токен: личный токен доступа или токен развёртывания. Пароль с логином разбирают лишь git по HTTP и Git LFS, у них свои правила и свой счёт неудачных попыток. Для публикации нужен токен с правом записи.
npm
Для Node.js проектов.
Публикация
Создайте файл .npmrc в проекте:
@owner:registry=https://git.example.com/api/v1/packages/owner/repo/npm
//git.example.com/api/v1/packages/owner/repo/npm:_authToken=ВАШ_ТОКЕН
Затем:
npm publish
Установка
npm install @owner/package \
--registry https://git.example.com/api/v1/packages/owner/repo/npm
Или добавьте в .npmrc проекта, чтобы не указывать каждый раз:
@owner:registry=https://git.example.com/api/v1/packages/owner/repo/npm
PyPI
Для Python-проектов.
Публикация
pip install twine
twine upload dist/* \
--repository-url https://git.example.com/api/v1/packages/owner/repo/pypi/legacy/ \
-u __token__ -p ВАШ_ТОКЕН
Логин всегда
__token__, пароль - ваш персональный токен или токен развёртывания.
Установка
pip install my-package \
--index-url https://git.example.com/api/v1/packages/owner/repo/pypi/simple
Cargo
Для Rust-проектов.
Настройка
Добавьте в ~/.cargo/config.toml (или .cargo/config.toml в проекте):
[registries.gitriver]
index = "sparse+https://git.example.com/api/v1/packages/owner/repo/cargo/index/"
Публикация
cargo publish --registry gitriver --token ВАШ_ТОКЕН
Установка
В Cargo.toml зависимого проекта:
[dependencies]
my-lib = { version = "1.0", registry = "gitriver" }
Maven
Для Java/Kotlin-проектов.
Публикация
Добавьте в pom.xml:
<distributionManagement>
<repository>
<id>gitriver</id>
<url>https://git.example.com/api/v1/packages/owner/repo/maven/</url>
</repository>
</distributionManagement>
И в ~/.m2/settings.xml:
<servers>
<server>
<id>gitriver</id>
<username>ваш_логин</username>
<password>ВАШ_ТОКЕН</password>
</server>
</servers>
Затем:
mvn deploy
Установка
Добавьте репозиторий в pom.xml:
<repositories>
<repository>
<id>gitriver</id>
<url>https://git.example.com/api/v1/packages/owner/repo/maven/</url>
</repository>
</repositories>
NuGet
Для .NET-проектов.
Публикация
dotnet nuget push MyPackage.1.0.0.nupkg \
--source https://git.example.com/api/v1/packages/owner/repo/nuget \
--api-key ВАШ_ТОКЕН
Установка
Добавьте источник:
dotnet nuget add source \
https://git.example.com/api/v1/packages/owner/repo/nuget/ \
--name gitriver \
--username ваш_логин \
--password ВАШ_ТОКЕН
Затем:
dotnet add package MyPackage
Generic
Для произвольных файлов (бинарники, архивы, документация).
Загрузка
curl -T myapp-v1.0.tar.gz \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
https://git.example.com/api/v1/packages/owner/repo/generic/myapp/1.0.0/myapp-v1.0.tar.gz
Скачивание
curl -L -O \
https://git.example.com/api/v1/packages/owner/repo/generic/myapp/1.0.0/myapp-v1.0.tar.gz
Composer
Появилось в 1.1.0.
Для PHP-проектов.
Публикация
Публикует не клиент composer, а вызов GitRiver: сервер сам достаёт composer.json из указанного тега и берёт оттуда имя и версию.
curl -X POST \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
"https://git.example.com/api/v1/packages/owner/repo/composer/publish?tag=v1.0.0"
Тег обязан существовать. Права - запись в репозиторий. Ответ 201; побайтный повтор - 200, повтор с другим содержимым - 409: опубликованная версия неизменяема.
Установка
В composer.json проекта:
{
"repositories": [
{ "type": "composer", "url": "https://git.example.com/api/v1/packages/owner/repo/composer" }
],
"require": { "vendor/package": "^1.0" }
}
Адрес - без /packages.json: composer дописывает его сам.
Токен для приватного репозитория - в auth.json, раздел bearer:
{ "bearer": { "git.example.com": "ВАШ_ТОКЕН" } }
Выдача пакетов через посредника
Появилось в 1.1.0.
Репозиторий отдаёт не только свои пакеты, но и внешние: если пакета нет в локальном хранилище, сервер идёт к источнику сам, кладёт ответ в кеш и отдаёт клиенту. Адрес для клиента тот же, что для приватных пакетов, - настройки сборки менять не нужно, достаточно заменить адрес внешнего реестра на адрес GitRiver.
Локальный пакет всегда сильнее внешнего: подменить вашу зависимость одноимённой внешней нельзя.
Источник заводится в Настройки репозитория → Пакеты → Выдача пакетов через посредника:
| Тип | Адрес источника |
|---|---|
| npm | https://registry.npmjs.org |
| PyPI | https://pypi.org/simple |
| Cargo | https://index.crates.io |
| Maven | https://repo1.maven.org/maven2 |
| NuGet | https://api.nuget.org/v3/index.json |
| Generic | корень внешнего хранилища |
| Docker | https://registry-1.docker.io (без /v2) |
У источника настраиваются маски разрешённых и запрещённых имён, предельный размер файла, срок жизни метаданных, свой предел объёма кеша и признак закрытого контура. Токен источника наружу не отдаётся никогда - в выдаче виден только признак, что он задан. Отдельно заказывается прогрев: пакеты забираются заранее, не дожидаясь первого обращения.
Cargo: при настроенном посреднике токен обязателен даже в публичном репозитории - наружу от имени сервера аноним не ходит, и config.json объявляет auth-required.
Зеркало внешнего реестра образов
Репозиторий-зеркало тянется обычным docker pull:
docker pull git.example.com/owner/mirror/library/nginx:1.25
Слои лежат в общем хранилище наравне с локальными образами: дедупликация, сборка мусора и квота - общие. Анонимный запрос наружу не выпускается. Образы, пришедшие от посредника, в автоматическое сканирование не попадают - лавина проверок на зеркале никому не нужна; проверяйте их по требованию кнопкой «Сканировать».
Пределы и обслуживание на всю установку
Администрирование → Хранилище → Кеш выдачи пакетов через посредника: включение обслуживания, промежуток между проходами (по умолчанию 6 часов), срок хранения метаданных (30 дней; 0 - не удалять по сроку), предельный объём кеша (0 - без предела) и признак закрытого контура на всю установку - ни один источник не опрашивается, отдаётся только прогретое.
Проход обслуживания убирает метаданные, к которым дольше срока не обращались, вытесняет файлы сверх пределов объёма, начиная с самых давних по обращению (пределов два, и они вложены: свой у каждого источника и общий у установки), и чистит журнал завершённых заявок прогрева. Кнопка запускает тот же проход немедленно.
Автопубликация из CI/CD
Типичный сценарий: при push тега v* автоматически собирать и публиковать пакет.
name: Release
on:
push:
tags: ['v*']
jobs:
publish:
image: node:22
steps:
- run: |
echo "//git.example.com/api/v1/packages/$CI_REPOSITORY_OWNER/$CI_REPOSITORY_NAME/npm:_authToken=$CI_JOB_TOKEN" > .npmrc
npm publish
CI_JOB_TOKEN автоматически доступен в каждой CI-задаче и имеет права на реестр текущего репозитория.
Управление пакетами
Просмотр, версии и удаление пакетов: вкладка «Пакеты» в репозитории.