Complementos multiplataforma de NuGet

En NuGet 4.8 y versiones posteriores, se ha agregado compatibilidad con complementos multiplataforma. Esto se logra mediante la creación de un nuevo modelo de extensibilidad de complementos, que tiene que ajustarse a un estricto conjunto de reglas de operación. Los complementos son archivos ejecutables autocontenidos (ejecutables en el mundo de .NET Core) que los clientes de NuGet inician en un proceso independiente. Se trata de un complemento de escritura única y ejecución en todas partes. Funcionará con todas las herramientas de cliente de NuGet. Los complementos pueden ser .NET Framework (NuGet.exe, MSBuild.exe y Visual Studio) o .NET Core (dotnet.exe). Se define un protocolo de comunicación con versión entre el cliente de NuGet y el complemento. Durante el protocolo de enlace de inicio, los dos procesos negocian la versión del protocolo.

Con el fin de cubrir todos los escenarios de herramientas de cliente de NuGet, se necesitaría tanto un complemento de .NET Framework como uno de .NET Core. A continuación se describen las combinaciones de cliente y marco de trabajo de los complementos.

Herramienta de cliente marco
Visual Studio .NET Framework
dotnet.exe .NET Core
NuGet.exe .NET Framework
MSBuild.exe .NET Framework
NuGet.exe en Mono .NET Framework

Cómo funciona

El flujo de trabajo de alto nivel puede describirse de la siguiente manera:

  1. NuGet detecta los complementos disponibles.
  2. En los casos oportunos, NuGet recorrerá en iteración los complementos en orden de prioridad y los iniciará uno por uno.
  3. NuGet usará el primer complemento que puede atender la solicitud.
  4. Los complementos se cerrarán cuando ya no se necesiten.

Requisitos generales de complementos

La versión actual del protocolo es 2.0.0. En esta versión, los requisitos son los siguientes:

  • Tener un ensamblado de firma Authenticode válido y de confianza que se ejecutará en Windows y Mono. Todavía no hay ningún requisito de confianza especial para ensamblados que se ejecutan en Linux y Mac. Problema relevante
  • Admitir el inicio de herramientas del cliente de NuGet sin estado en el contexto de seguridad actual. Por ejemplo, las herramientas del cliente de NuGet no realizarán elevaciones ni inicializaciones adicionales fuera del protocolo del complemento que se describe a continuación.
  • No ser interactivo, a menos que se especifique explícitamente.
  • Adaptarse a la versión del protocolo del complemento negociada.
  • Responder a todas las solicitudes dentro de un plazo de tiempo razonable.
  • Respetar las solicitudes de cancelación de cualquier operación en curso.

La especificación técnica se describe con más detalle en las siguientes especificaciones:

Interacción entre cliente y complemento

Las herramientas de cliente de NuGet y los complementos se comunican con JSON mediante flujos estándar (stdin, stdout y stderr). Todos los datos deben estar codificados en UTF-8. Los complementos se inician con el argumento "-Plugin". En caso de que un usuario inicie directamente un ejecutable de complemento sin este argumento, el complemento puede proporcionar un mensaje informativo en lugar de esperar a un protocolo de enlace. El tiempo de espera del protocolo de enlace es de cinco segundos. El complemento debe completar la configuración en el menor tiempo posible. Las herramientas de cliente de NuGet consultarán las operaciones admitidas de un complemento pasando el índice de servicio de un origen de NuGet. Un complemento puede usar el índice de servicio para comprobar la presencia de tipos de servicio compatibles.

La comunicación entre las herramientas del cliente de NuGet y el complemento es bidireccional. Cada solicitud tiene un tiempo de espera de cinco segundos. Si se supone que las operaciones deben tardan más tiempo, el proceso correspondiente debe enviar un mensaje de progreso para evitar que se agote el tiempo de espera de la solicitud. Después de un minuto de inactividad, un complemento se considera inactivo y se cierra.

Instalación y detección de complementos

Los complementos se detectarán mediante una estructura de directorios basada en convenciones. Los escenarios de CI/CD y los usuarios avanzados pueden utilizar variables de entorno para invalidar el comportamiento. Cuando se usan variables de entorno, solo se permiten rutas de acceso absolutas. Tenga en cuenta que NUGET_NETFX_PLUGIN_PATHS y NUGET_NETCORE_PLUGIN_PATHS solo están disponibles con las versiones 5.3 y posteriores de las herramientas de NuGet.

  • NUGET_NETFX_PLUGIN_PATHS: define los complementos que usarán las herramientas basadas en .NET Framework (NuGet.exe/MSBuild.exe/Visual Studio). Tiene prioridad sobre NUGET_PLUGIN_PATHS. (Solo en las versiones 5.3 y posteriores de NuGet)
  • NUGET_NETCORE_PLUGIN_PATHS: define los complementos que usarán las herramientas basadas en .NET Core (dotnet.exe). Tiene prioridad sobre NUGET_PLUGIN_PATHS. (Solo en las versiones 5.3 y posteriores de NuGet)
  • NUGET_PLUGIN_PATHS: define los complementos que se usarán para ese proceso de NuGet, con prioridad conservada. Si se establece esta variable de entorno, invalida la detección basada en convenciones. Se omite si se especifica cualquiera de las variables específicas del marco de trabajo.
  • User-location, ubicación de inicio de NuGet en %UserProfile%/.nuget/plugins. Esta ubicación no se puede invalidar. Se usará otro directorio raíz para los complementos de .NET Core y .NET Framework.
marco Ubicación de detección raíz
.NET Core %UserProfile%/.nuget/plugins/netcore
.NET Framework %UserProfile%/.nuget/plugins/netfx

Cada complemento debe instalarse en su propia carpeta. El punto de entrada del complemento será el nombre de la carpeta donde se ha realizado la instalación, con la extensión .dll para .NET Core y .exe para .NET Framework.

.nuget
    plugins
        netfx
            myPlugin
                myPlugin.exe
                nuget.protocol.dll
                ...
        netcore
            myPlugin
                myPlugin.dll
                nuget.protocol.dll
                ...

Nota:

Actualmente no hay ningún caso de usuario para la instalación de los complementos. Es tan sencillo como mover los archivos necesarios a la ubicación predeterminada.

Operaciones admitidas

Se admiten dos operaciones en el nuevo protocolo de complementos.

Nombre de operación Versión mínima del protocolo Versión mínima del cliente de NuGet
Descargar paquete 1.0.0 4.3.0
Autenticación 2.0.0 4.8.0

Ejecución de complementos en el entorno de ejecución correcto

Para NuGet en escenarios de dotnet.exe, los complementos deben poder ejecutarse en ese entorno de ejecución específico de dotnet.exe. El consumidor y el proveedor del complemento deben asegurarse de que se usa una combinación compatible de dotnet.exe y complemento. Podría surgir un posible problema con los complementos de user-location cuando, por ejemplo, un complemento dotnet.exe en el entorno de ejecución 2.0 intenta usar un complemento escrito para el entorno de ejecución 2.1.

Almacenamiento en caché de funcionalidades

La comprobación de seguridad y la creación de instancias de los complementos son costosas. La operación de descarga se realiza de forma más frecuente que la operación de autenticación; sin embargo, es probable que el usuario de NuGet medio solo tenga un complemento de autenticación. Para mejorar la experiencia, NuGet almacenará en caché las notificaciones de operaciones para la solicitud proporcionada. Esta caché se distribuye por complemento. La clave del complemento es la ruta de acceso del complemento y la expiración de esta caché de funcionalidades es de 30 días.

La memoria caché se encuentra en %LocalAppData%/NuGet/plugins-cache y se invalida con la variable de entorno NUGET_PLUGINS_CACHE_PATH. Para borrar esta caché, puede ejecutar el comando locals con la opción plugins-cache. La opción de locals all ahora también eliminará la memoria caché de los complementos.

Índice de mensajes de protocolo

Mensajes de la versión de protocolo 1.0.0:

  1. Cerrado

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud no contendrá ninguna carga.
    • No se espera ninguna respuesta. La respuesta correcta es que el proceso de complementos salga de forma rápida.
  2. Copiar archivos en el paquete

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. y la versión del paquete.
      • la ubicación del repositorio de origen del paquete.
      • la ruta de acceso del directorio de destino.
      • un enumerable de archivos del paquete que se va a copiar en la ruta de acceso del directorio de destino.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un enumerable de rutas de acceso completas para los archivos copiados en el directorio de destino si la operación se realizó correctamente.
  3. Copiar un archivo de paquete (.nupkg)

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. y la versión del paquete.
      • la ubicación del repositorio de origen del paquete.
      • la ruta de acceso del archivo de destino.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
  4. Obtener credenciales

    • Dirección de la solicitud: complemento -> NuGet
    • La solicitud contendrá lo siguiente:
      • la ubicación del repositorio de origen del paquete.
      • el código de estado HTTP obtenido del repositorio de origen del paquete con las credenciales actuales.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un nombre de usuario, si está disponible.
      • una contraseña, si está disponible.
  5. Obtener archivos en el paquete

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. y la versión del paquete.
      • la ubicación del repositorio de origen del paquete.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un enumerable de rutas de acceso de archivo en el paquete si la operación se realizó correctamente.
  6. Obtener notificaciones de operación

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el servicio index.json para un origen de paquete.
      • la ubicación del repositorio de origen del paquete.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un enumerable de las operaciones admitidas (por ejemplo, descarga de paquetes) si la operación se realizó correctamente. Si un complemento no admite el origen del paquete, el complemento debe devolver un conjunto vacío de operaciones admitidas.

Nota:

Este mensaje se ha actualizado en la versión 2.0.0. Está en el cliente para mantener la compatibilidad con versiones anteriores.

  1. Obtener hash del paquete

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. y la versión del paquete.
      • la ubicación del repositorio de origen del paquete.
      • el algoritmo hash.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un hash de archivo de paquete que usa el algoritmo hash solicitado si la operación se realizó correctamente.
  2. Obtener la versión de los paquetes

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. del paquete.
      • la ubicación del repositorio de origen del paquete.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un enumerable de versiones de paquete si la operación se realizó correctamente.
  3. Obtener el índice de servicio

    • Dirección de la solicitud: complemento -> NuGet
    • La solicitud contendrá lo siguiente:
      • la ubicación del repositorio de origen del paquete.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • el índice de servicio si la operación se realizó correctamente.
  4. Protocolo de enlace

    • Dirección de la solicitud: NuGet <-> complemento
    • La solicitud contendrá lo siguiente:
      • la versión actual del protocolo del complemento.
      • la versión mínima admitida del protocolo del complemento.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • la versión del protocolo negociada si la operación se realizó correctamente. Un error provocará la finalización del complemento.
  5. Inicialización

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • la versión de la herramienta cliente de NuGet.
      • el lenguaje efectivo de la herramienta de cliente de NuGet. Esto tiene en cuenta el valor de ForceEnglishOutput, si se usa.
      • el tiempo de espera de solicitud predeterminado, que sustituye al valor predeterminado del protocolo.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación. Un error provocará la finalización del complemento.
  6. Log

    • Dirección de la solicitud: complemento -> NuGet
    • La solicitud contendrá lo siguiente:
      • el nivel de registro de la solicitud.
      • un mensaje para el registro.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
  7. Supervisar el cierre del proceso de NuGet

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. de proceso de NuGet.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
  8. Capturar previamente un paquete

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el id. y la versión del paquete.
      • la ubicación del repositorio de origen del paquete.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
  9. Establecer Credenciales

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • la ubicación del repositorio de origen del paquete.
      • el último nombre de usuario conocido del origen del paquete, si está disponible.
      • la última contraseña conocida del origen del paquete, si está disponible.
      • el último nombre de usuario conocido del proxy del paquete, si está disponible.
      • la última contraseña conocida del proxy del paquete, si está disponible.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
  10. Establecer nivel de registro

    • Dirección de la solicitud: NuGet -> complemento
    • La solicitud contendrá lo siguiente:
      • el nivel de registro predeterminado.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.

Mensajes de la versión del protocolo 2.0.0

  1. Obtener notificaciones de operación
  • Dirección de la solicitud: NuGet -> complemento

    • La solicitud contendrá lo siguiente:
      • el servicio index.json para un origen de paquete.
      • la ubicación del repositorio de origen del paquete.
    • Una respuesta contendrá lo siguiente:
      • un código de respuesta que indica el resultado de la operación.
      • un enumerable de las operaciones admitidas si la operación se realizó correctamente. Si un complemento no admite el origen del paquete, el complemento debe devolver un conjunto vacío de operaciones admitidas.

    Si el índice de servicio y el origen del paquete son nulos, el complemento puede responder con la autenticación.

  1. Obtener credenciales de autenticación
  • Dirección de la solicitud: NuGet -> complemento
  • La solicitud contendrá lo siguiente:
    • Identificador URI
    • isRetry
    • NonInteractive
    • CanShowDialog
  • Una respuesta contendrá lo siguiente
    • Nombre de usuario
    • Contraseña
    • Mensaje
    • Lista de tipos de autenticación
    • MessageResponseCode