Plug-in multipiattaforma NuGet

In NuGet 4.8+ è stato aggiunto il supporto per plug-in multipiattaforma. Ciò è stato ottenuto creando un nuovo modello di estendibilità del plug-in, che deve essere conforme a un set rigoroso di regole di funzionamento. I plug-in sono eseguibili autonomi (eseguibili nel mondo .NET Core), che i client NuGet vengono avviate in un processo separato. Si tratta di una vera scrittura una sola volta, eseguire il plug-in ovunque. Funzionerà con tutti gli strumenti client NuGet. I plug-in possono essere .NET Framework (NuGet.exe, MSBuild.exe e Visual Studio) o .NET Core (dotnet.exe). Viene definito un protocollo di comunicazione con controllo delle versioni tra il client NuGet e il plug-in. Durante l'handshake di avvio, i 2 elaborano la versione del protocollo.

Per coprire tutti gli scenari degli strumenti client NuGet, è necessario un plug-in .NET Framework e un plug-in .NET Core. Di seguito vengono descritte le combinazioni client/framework dei plug-in.

Strumento client Framework
Visual Studio .NET Framework
dotnet.exe .NET Core
NuGet.exe .NET Framework
MSBuild.exe .NET Framework
NuGet.exe su Mono .NET Framework

Come funziona

Il flusso di lavoro di alto livello può essere descritto come segue:

  1. NuGet individua i plug-in disponibili.
  2. Se applicabile, NuGet eseguirà l'iterazione dei plug-in in ordine di priorità e li avvia uno alla sola.
  3. NuGet userà il primo plug-in in in grado di eseguire la richiesta.
  4. I plug-in verranno arrestati quando non sono più necessari.

Requisiti generali del plug-in

La versione corrente del protocollo è 2.0.0. In questa versione, i requisiti sono i seguenti:

  • Disporre di assembly di firma Authenticode validi e attendibili che verranno eseguiti in Windows e Mono. Non esiste ancora un requisito di attendibilità speciale per gli assembly eseguiti in Linux e Mac. Problema rilevante
  • Supportare l'avvio senza stato nel contesto di sicurezza corrente degli strumenti client NuGet. Ad esempio, gli strumenti client NuGet non eseguiranno l'elevazione dei privilegi o l'inizializzazione aggiuntiva all'esterno del protocollo del plug-in descritto più avanti.
  • Essere non interattivo, a meno che non sia specificato in modo esplicito.
  • Attenersi alla versione del protocollo del plug-in negoziata.
  • Rispondere a tutte le richieste entro un periodo di tempo ragionevole.
  • Rispettare le richieste di annullamento per qualsiasi operazione in corso.

La specifica tecnica è descritta in modo più dettagliato nelle specifiche seguenti:

Client - Interazione con plug-in

Gli strumenti client NuGet e i plug-in comunicano con JSON su flussi standard (stdin, stdout, stderr). Tutti i dati devono essere codificati con UTF-8. I plug-in vengono avviati con l'argomento "-Plugin". Nel caso in cui un utente avvii direttamente un eseguibile del plug-in senza questo argomento, il plug-in può fornire un messaggio informativo invece di attendere un handshake del protocollo. Il timeout dell'handshake del protocollo è di 5 secondi. Il plug-in dovrebbe completare la configurazione nel minor tempo possibile. Gli strumenti client NuGet eseguiranno query sulle operazioni supportate di un plug-in passando l'indice del servizio per un'origine NuGet. Un plug-in può usare l'indice del servizio per verificare la presenza di tipi di servizio supportati.

La comunicazione tra gli strumenti client NuGet e il plug-in è bidirezionale. Ogni richiesta ha un timeout di 5 secondi. Se le operazioni devono richiedere più tempo, il rispettivo processo deve inviare un messaggio di stato per impedire il timeout della richiesta. Dopo 1 minuto di inattività, un plug-in viene considerato inattivo e viene arrestato.

Installazione e individuazione dei plug-in

I plug-in verranno individuati tramite una struttura di directory basata su convenzioni. Gli scenari CI/CD e gli utenti esperti possono usare le variabili di ambiente per eseguire l'override del comportamento. Quando si usano variabili di ambiente, sono consentiti solo percorsi assoluti. Si noti che NUGET_NETFX_PLUGIN_PATHS e NUGET_NETCORE_PLUGIN_PATHS sono disponibili solo con la versione 5.3+ degli strumenti NuGet e versioni successive.

  • NUGET_NETFX_PLUGIN_PATHS : definisce i plug-in che verranno usati dagli strumenti basati su .NET Framework (NuGet.exe/MSBuild.exe/Visual Studio). Ha la precedenza su NUGET_PLUGIN_PATHS. (solo NuGet versione 5.3+)
  • NUGET_NETCORE_PLUGIN_PATHS : definisce i plug-in che verranno usati dagli strumenti basati su .NET Core (dotnet.exe). Ha la precedenza su NUGET_PLUGIN_PATHS. (solo NuGet versione 5.3+)
  • NUGET_PLUGIN_PATHS : definisce i plug-in che verranno usati per il processo NuGet, con priorità mantenuta. Se questa variabile di ambiente è impostata, esegue l'override dell'individuazione basata sulla convenzione. Ignorato se viene specificata una delle variabili specifiche del framework.
  • Posizione dell'utente, posizione della home page NuGet in %UserProfile%/.nuget/plugins. Impossibile eseguire l'override di questo percorso. Verrà usata una directory radice diversa per i plug-in .NET Core e .NET Framework.
Framework Percorso di individuazione radice
.NET Core %UserProfile%/.nuget/plugins/netcore
.NET Framework %UserProfile%/.nuget/plugins/netfx

Ogni plug-in deve essere installato nella propria cartella. Il punto di ingresso del plug-in sarà il nome della cartella installata, con le estensioni .dll per .NET Core e l'estensione .exe per .NET Framework.

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

Nota

Attualmente non esiste alcuna storia utente per l'installazione dei plug-in. È semplice come spostare i file necessari nella posizione predeterminata.

Operazioni supportate

Nel nuovo protocollo plug-in sono supportate due operazioni.

Nome operazione Versione minima del protocollo Versione minima del client NuGet
Scarica pacchetto 1.0.0 4.3.0
Autenticazione 2.0.0 4.8.0

Esecuzione di plug-in nel runtime corretto

Per gli scenari nuGet in dotnet.exe, i plug-in devono essere in grado di essere eseguiti in quel runtime specifico del dotnet.exe. Si trova nel provider di plug-in e il consumer per assicurarsi che venga usata una combinazione di dotnet.exe/plug-in compatibile. Un potenziale problema potrebbe verificarsi con i plug-in di posizione utente quando, ad esempio, un dotnet.exe nel runtime 2.0 tenta di usare un plug-in scritto per il runtime 2.1.

Memorizzazione nella cache delle funzionalità

La verifica di sicurezza e la creazione di istanze dei plug-in è costosa. L'operazione di download avviene più frequentemente rispetto all'operazione di autenticazione, ma è probabile che l'utente NuGet medio abbia solo un plug-in di autenticazione. Per migliorare l'esperienza, NuGet memorizza nella cache le attestazioni dell'operazione per la richiesta specificata. Questa cache è per plug-in con la chiave del plug-in che rappresenta il percorso del plug-in e la scadenza per questa cache delle funzionalità è di 30 giorni.

La cache si trova in %LocalAppData%/NuGet/plugins-cache ed essere sottoposto a override con la variabile NUGET_PLUGINS_CACHE_PATHdi ambiente . Per cancellare questa cache, è possibile eseguire il comando variabili locali con l'opzione plugins-cache . L'opzione all variabili locali ora eliminerà anche la cache dei plug-in.

Indice dei messaggi del protocollo

Messaggi protocollo versione 1.0.0 :

  1. Chiusura

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta non conterrà alcun payload
    • Non è prevista alcuna risposta. La risposta corretta è che il processo di plug-in venga immediatamente chiuso.
  2. Copiare i file nel pacchetto

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID e versione del pacchetto
      • percorso del repository di origine del pacchetto
      • percorso della directory di destinazione
      • enumerabile di file nel pacchetto da copiare nel percorso della directory di destinazione
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • enumerabile di percorsi completi per i file copiati nella directory di destinazione se l'operazione ha avuto esito positivo
  3. Copiare il file del pacchetto (con estensione nupkg)

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID e versione del pacchetto
      • percorso del repository di origine del pacchetto
      • percorso del file di destinazione
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
  4. Ottenere le credenziali

    • Direzione richiesta: plug-in -> NuGet
    • La richiesta conterrà:
      • percorso del repository di origine del pacchetto
      • il codice di stato HTTP ottenuto dal repository di origine del pacchetto usando le credenziali correnti
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • un nome utente, se disponibile
      • una password, se disponibile
  5. Ottenere file nel pacchetto

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID e versione del pacchetto
      • percorso del repository di origine del pacchetto
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • enumerabile di percorsi di file nel pacchetto se l'operazione ha avuto esito positivo
  6. Ottenere le attestazioni dell'operazione

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • il servizio index.json per un'origine del pacchetto
      • percorso del repository di origine del pacchetto
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • enumerabile di operazioni supportate (ad esempio: download di pacchetti) se l'operazione ha avuto esito positivo. Se un plug-in non supporta l'origine del pacchetto, il plug-in deve restituire un set vuoto di operazioni supportate.

Nota

Questo messaggio è stato aggiornato nella versione 2.0.0. Si trova nel client per mantenere la compatibilità con le versioni precedenti.

  1. Ottenere l'hash del pacchetto

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID e versione del pacchetto
      • percorso del repository di origine del pacchetto
      • algoritmo hash
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • hash del file di pacchetto che usa l'algoritmo hash richiesto se l'operazione ha avuto esito positivo
  2. Ottenere le versioni di un pacchetto

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID pacchetto
      • percorso del repository di origine del pacchetto
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • enumerabile delle versioni del pacchetto se l'operazione ha avuto esito positivo
  3. Ottenere l'indice del servizio

    • Direzione richiesta: plug-in -> NuGet
    • La richiesta conterrà:
      • percorso del repository di origine del pacchetto
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • indice del servizio se l'operazione ha avuto esito positivo
  4. Stretta di mano

    • Direzione richiesta: NuGet <- plug-in>
    • La richiesta conterrà:
      • versione corrente del protocollo del plug-in
      • versione minima del protocollo di plug-in supportato
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • versione del protocollo negoziata se l'operazione ha avuto esito positivo. Un errore comporterà la chiusura del plug-in.
  5. Inizializzare

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • Versione dello strumento client NuGet
      • il linguaggio efficace dello strumento client NuGet. Questa impostazione prende in considerazione l'impostazione ForceEnglishOutput, se usata.
      • timeout della richiesta predefinito, che sostituisce l'impostazione predefinita del protocollo.
    • Una risposta conterrà:
      • codice di risposta che indica il risultato dell'operazione. Un errore comporterà la chiusura del plug-in.
  6. Log

    • Direzione richiesta: plug-in -> NuGet
    • La richiesta conterrà:
      • livello di log per la richiesta
      • un messaggio da registrare
    • Una risposta conterrà:
      • codice di risposta che indica il risultato dell'operazione.
  7. Monitorare l'uscita del processo NuGet

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID processo NuGet
    • Una risposta conterrà:
      • codice di risposta che indica il risultato dell'operazione.
  8. Pacchetto di prelettura

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • ID e versione del pacchetto
      • percorso del repository di origine del pacchetto
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
  9. Impostare le credenziali

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • percorso del repository di origine del pacchetto
      • l'ultimo nome utente dell'origine del pacchetto noto, se disponibile
      • l'ultima password di origine del pacchetto nota, se disponibile
      • l'ultimo nome utente proxy noto, se disponibile
      • l'ultima password proxy nota, se disponibile
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
  10. Impostare il livello di log

    • Direzione richiesta: NuGet - plug-in>
    • La richiesta conterrà:
      • livello di log predefinito
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione

Messaggi di protocollo versione 2.0.0

  1. Ottenere attestazioni dell'operazione
  • Direzione richiesta: NuGet - plug-in>

    • La richiesta conterrà:
      • il servizio index.json per un'origine del pacchetto
      • percorso del repository di origine del pacchetto
    • Una risposta conterrà:
      • un codice di risposta che indica il risultato dell'operazione
      • enumerabile di operazioni supportate se l'operazione ha avuto esito positivo. Se un plug-in non supporta l'origine del pacchetto, il plug-in deve restituire un set vuoto di operazioni supportate.

    Se l'indice del servizio e l'origine del pacchetto sono Null, il plug-in può rispondere con l'autenticazione.

  1. Ottenere le credenziali di autenticazione
  • Direzione richiesta: NuGet - plug-in>
  • La richiesta conterrà:
    • URI
    • isRetry
    • NonInteractive
    • CanShowDialog
  • Una risposta conterrà
    • Username
    • Password
    • Messaggio
    • Elenco dei tipi di autenticazione
    • MessageResponseCode