Alojando un repositorio privado de paquetes de Dart
Mejoras en Dart 2.15 para alojamiento seguro de paquetes empresariales
Nuestro reciente lanzamiento de Dart 2.15 añadió soporte para repositorios privados de paquetes. Un repositorio de paquetes es un servidor que aloja paquetes de Dart para que sean consumidos por el cliente de
dart pub. Este post discute cómo usar repositorios privados de paquetes junto con pub.dev, aprovechando el nuevo mecanismo de autenticación con tokens introducido en Dart 2.15.
Esta funcionalidad ya ha sido adoptada por Cloudsmith y JFrog Artifactory que ofrecen repositorios personalizados de paquetes como servicio:
¿Por qué usar un repositorio personalizado de paquetes?
#El repositorio de paquetes por defecto, pub.dev, es operado por el equipo de Dart. Facilita la publicación de paquetes de Dart para uso público, y permite a cualquier desarrollador de Dart consumir esos paquetes simplemente añadiendo el nombre del paquete a su archivo pubspec. Esto permite que un ecosistema activo cree una rica colección de paquetes de Dart. Sin embargo, un repositorio personalizado de paquetes puede ser útil en los siguientes escenarios:
-
Compartir paquetes privados dentro de una organización. Esto podría ser una organización buscando compartir paquetes propietarios internos entre los miembros de la organización, y no con el público general.
-
Control estricto de dependencias en entornos empresariales. Algunas corporaciones quieren crear explícitamente listas de permitidos para versiones específicas de paquetes aprobadas para uso. Esto puede hacerse para cumplir con políticas de revisión de código o de licencias.
-
Entornos seguros sin acceso a internet público. Algunas organizaciones operan en un entorno regulatorio donde las conexiones a internet público, y por extensión pub.dev, no están permitidas. Esto típicamente aplica a agencias/contratistas gubernamentales y algunos proveedores de servicios bancarios.
Organizaciones que solo necesitan compartir algunos paquetes propietarios (escenario 1) podrían usar git-dependencies. Este es un mecanismo potente porque el comando del cliente dart pub
invoca al cliente git para clonar las git-dependencies — de esta forma puedes autenticar la clonación de una dependencia usando tu clave SSH, y gestionar permisos usando equipos de GitHub/GitLab. Con
el soporte de GitHub para SSH usando Yubikeys
esta configuración funciona bien en algunos casos.
Sin embargo, las git-dependencies en dart pub tienen algunas limitaciones cuando se trata de resolución de versiones. Al usar una git-dependency,
dart pub simplemente clona el tag / branch / ref especificado en pubspec.yaml, porque no hay mecanismo para probar múltiples versiones de la dependencia. Por lo tanto, usar un repositorio privado personalizado puede ser atractivo porque un repositorio personalizado puede proveer al cliente de
dart pub una lista de versiones, permitiendo al
resolvedor de versiones
elegir una versión compatible y evitar conflictos. También facilita la actualización tanto de dependencias privadas como públicas usando
dart pub outdated y dart pub upgrade --major-versions.
Las git-dependencies no soportan a las organizaciones que buscan un control más estricto sobre las dependencias (escenario 2) o que usan un entorno seguro sin acceso a internet (escenario 3), ya que muchos paquetes tienen que ser replicados. En estos escenarios casi siempre es preferible simplemente tener un repositorio personalizado que replique un subconjunto permitido de pub.dev.
Usar un repositorio personalizado de paquetes
#A partir de Dart 2.15, puedes depender de un paquete desde un repositorio personalizado usando la sintaxis de dependencia hosted en formato corto:
dependencies:
foo:
hosted: https://dart-packages.example.com
version: ^1.4.0
environment:
sdk: >=2.15.0 <3.0.0
La sintaxis de formato corto requiere una restricción de SDK
>=2.15.0, porque las versiones anteriores del SDK de Dart no soportan esta sintaxis. Si no quieres preocuparte por la sintaxis, también puedes simplemente usar el comando
dart pub add para añadir una dependencia desde un repositorio personalizado:
$ dart pub add foo --hosted https://dart-packages.example.com
Resolving dependencies...
+ foo 1.4.0
Changed 1 dependency!
Usando la sintaxis de dependencia hosted, es posible mezclar dependencias de repositorios personalizados con dependencias del repositorio oficial de paquetes. El siguiente ejemplo depende del paquete
foo del repositorio
dart-packages.example.com, y del paquete
retry
de pub.dev:
dependencies:
retry: ^3.0.0
foo:
hosted: https://dart-packages.example.com
version: ^1.4.0
environment:
sdk: >=2.15.0 <3.0.0
Esto es útil cuando se comparten paquetes privados usando un repositorio personalizado (escenario 1). Pero para un control más estricto de las dependencias (escenario 2) o trabajar en un entorno seguro sin acceso a internet (escenario 3), puede ser preferible sobrescribir el repositorio de paquetes por defecto.
Sobrescribir el repositorio de paquetes por defecto
#Por defecto, dart pub get obtiene las dependencias de pub.dev a menos que se use la sintaxis de dependencia hosted para especificar un repositorio personalizado. Sin embargo, es posible sobrescribir el
repositorio de paquetes por defecto usando la variable de entorno PUB_HOSTED_URL. Este enfoque es particularmente útil cuando se replica un subconjunto de pub.dev (escenario 2 o 3), ya que no hay necesidad de actualizar el archivo
pubspec.yaml para referenciar la URL del repositorio personalizado. Por ejemplo, es suficiente con escribir lo siguiente:
dependencies:
retry: ^3.0.0
foo: ^1.0.0
Si las versiones permitidas de los paquetes
retry y
foo se copian al repositorio personalizado, y la variable de entorno
PUB_HOSTED_URL apunta a la URL del repositorio personalizado,
pub get puede funcionar de la siguiente manera:
$ export PUB_HOSTED_URL=https://dart-packages.example.com
$ dart pub get
Resolving dependencies...
+ retry 3.1.0
+ foo 1.4.0
Changed 2 dependencies!
Esto funciona mejor cuando el servidor de build está detrás de un firewall corporativo que no permite conexiones de red salientes para evitar ataques de inyección accidentales cuando alguien olvida configurar
PUB_HOSTED_URL. De forma similar, también es recomendable configurar
publish_to: <hosted-url>
en
pubspec.yaml para evitar publicaciones accidentales a pub.dev (cuando
PUB_HOSTED_URL
no está definido).
Autenticación con repositorios personalizados de paquetes
#La mayoría de los repositorios personalizados probablemente sean repositorios privados que requieren autenticación. Dart 2.15 introdujo el comando
dart pub token para gestionar tokens de autenticación. Las peticiones a un repositorio personalizado se autentican usando un token secreto. Obtienes el token secreto de tu repositorio personalizado y lo pasas a
dart pub token add <hosted-url>, que solicita el token como se muestra a continuación:
$ dart pub token add https://dart-packages.example.com
Enter secret token: [enter secret token]
Requests to "dart-packages.example.com" will now be authenticated using the secret token.
Autenticación desde entornos de CI
#Cuando se ejecuta en CI a menudo es posible almacenar secretos en variables de entorno, y si bien es posible pasar secretos usando
echo $TOKEN | dart pub token add <hosted-url>, también es posible decirle a
dart pub que lea un secreto de una variable de entorno cuando se comunica con un repositorio personalizado específico:
$ dart pub token add https://dart-packages.example.com --env-var MY_SECRET_TOKEN
Requests to "https://dart-packages.example.com" will now be authenticated using the secret token stored in the environment variable "MY_SECRET_TOKEN".
Esto asegura que dart pub no almacene realmente el secreto en su archivo de configuración, en su lugar simplemente almacena el hecho de que debería leer el secreto de la variable de entorno
$MY_SECRET_TOKEN. Esto permite que los secretos solo se almacenen en variables de entorno cuando se opera en un entorno de CI, y reduce el riesgo de que los secretos se filtren accidentalmente si el entorno de ejecución se comparte entre jobs de CI.
Publicar en repositorios personalizados de paquetes
#Para publicar un paquete en un repositorio personalizado, especifica
publish_to: <hosted-url>
en
pubspec.yaml, y ejecuta
dart pub publish. Esto usa el mismo token para autenticación que el usado por
dart pub get. Como mínimo, tu archivo
pubspec.yaml debería verse algo como lo siguiente:
name: mypkg
version: 1.0.0
publish_to: https://dart-packages.example.com
dependencies:
meta: ^1.7.0
environment:
sdk: >=2.15.0 <3.0.0
Al ejecutar
dart pub publish es importante revisar la información proporcionada. Antes de confirmar la acción de publicación siempre deberías hacer lo siguiente:
Verifica la URL donde se publicará el paquete.
Revisa la lista de archivos a incluir en el paquete.
Considera las recomendaciones de validación de paquetes. Por ejemplo:
$ dart pub publish
Publishing mypkg 1.0.0 to https://dart-packages.example.com
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- lib
| '-- mypkg.dart
'-- pubspec.yaml
Package validation found the following potential issue:
* It's strongly recommended to include a "homepage" or "repository" field in your pubspec.yaml
...
Para publicar en repositorios personalizados las recomendaciones pueden no ser importantes, pero proporcionar metadatos para un paquete a menudo es útil. En pub.dev, los paquetes con metadatos y documentación adecuados obtienen más pub points.
Es posible publicar en repositorios personalizados sobrescribiendo el
repositorio de paquetes por defecto
usando la variable de entorno
PUB_HOSTED_URL pero, si haces esto, se recomienda encarecidamente que especifiques
publish_to: <hosted-url> en tu archivo
pubspec.yaml; esto evita que publiques accidentalmente tus paquetes propietarios al repositorio público. Y si no quieres publicar tus paquetes propietarios en
ningún repositorio de paquetes, especifica
publish_to: none para evitar la publicación accidental.
Obtener un repositorio personalizado de paquetes
#Como se mencionó anteriormente, los repositorios personalizados de paquetes están disponibles como servicio por múltiples proveedores comerciales, aliviándote de la carga de alojar y mantener tu propio repositorio personalizado de paquetes.
Autenticación con token en Cloudsmith
#Cloudsmith ha estado ofreciendo repositorios privados y públicos de paquetes de Dart desde 2020. Cloudsmith anunció recientemente soporte para autenticación con tokens en su oferta de repositorios de paquetes de Dart. Para más información, consulta la documentación de Cloudsmith.
Soporte de Dart en JFrog Artifactory
#JFrog Artifactory recientemente anunció soporte para repositorios personalizados de paquetes de Dart, incluyendo soporte para repositorios en capas y replicación de paquetes del repositorio público de pub.dev. Para más información, consulta la documentación de JFrog Artifactory.
Comentarios finales
#Para aquellos que quieran escribir su propio repositorio personalizado de paquetes, hemos publicado una especificación para servir repositorios de paquetes de Dart. Es bastante simple, pero no dudes en abrir issues en el repositorio de pub.dev si algo no está claro, o si tienes sugerencias para mejoras.
Más de Dart
Dart en Google Summer of Code 2026
¡Estamos emocionados de anunciar que el proyecto Dart será mentor de contribuidores por séptima vez en Google Summer of Code 2026!
Resultados de Google Summer of Code 2025
El programa Google Summer of Code (GSoC) se enfoca en involucrar a nuevos desarrolladores de todo el mundo con el desarrollo de software de código abierto. Google…