Partilhar via


Plug-ins multiplataforma NuGet

No NuGet 4.8+ foi adicionado suporte para plugins multiplataforma. Isto foi conseguido com a construção de um novo modelo de extensibilidade de plugins, que deve seguir um conjunto rigoroso de regras de operação. Os plug-ins são executáveis autônomos (executáveis no mundo .NET Core), que os Clientes NuGet iniciam em um processo separado. Este é um plugin verdadeiramente "escrever uma vez, executar em qualquer lugar". Ele funcionará com todas as ferramentas de cliente NuGet. Os plugins podem ser escritos em qualquer linguagem de programação, mas a experiência mais fácil de desenvolvimento e instalação de plug-ins será com o .NET. Um protocolo de comunicação versionado entre o Cliente NuGet e o plug-in é definido. Durante o handshake de inicialização, os 2 processos negociam a versão do protocolo.

Como funciona

O fluxo de trabalho de alto nível pode ser descrito da seguinte forma:

  1. O NuGet descobre plug-ins disponíveis.
  2. Quando aplicável, o NuGet iterará sobre os plug-ins em ordem de prioridade e os iniciará um a um.
  3. O NuGet usará o primeiro plug-in que pode atender à solicitação.
  4. Os plugins serão desligados quando não forem mais necessários.

Requisitos gerais do plugin

A versão atual do protocolo é 2.0.0. Nesta versão, os requisitos são os seguintes:

  • Suporte à inicialização sem estado no contexto de segurança atual das ferramentas cliente do NuGet. Por exemplo, as ferramentas de cliente NuGet não executarão elevação ou inicialização adicional fora do protocolo de plug-in descrito posteriormente.
  • Não ser interativo, a menos que explicitamente especificado.
  • Aderir à versão negociada do protocolo do plugin.
  • Responder a todos os pedidos dentro de um período de tempo razoável.
  • Atender pedidos de cancelamento para qualquer operação em curso.

Os plug-ins descobertos a partir da variável de ambiente PATH (por exemplo, instalados via dotnet tool) também devem corresponder ao padrão nuget-plugin-*de nome de arquivo. A nuget-plugin- parte deve ser escrita inteiramente em letras minúsculas.

O NuGet 6.12 (MSBuild 17.12 e .NET SDK 9.0.100) e versões anteriores também exigiam que os plug-ins fossem assinados com Authenticode no Windows.

A especificação técnica é descrita com mais detalhes nas seguintes especificações:

Cliente - Interação com plug-ins

As ferramentas de cliente NuGet e os plug-ins se comunicam com JSON através de fluxos padrão (stdin, stdout, stderr). Todos os dados devem ser codificados em UTF-8. Os plugins são lançados com o argumento "-Plugin". No caso de um utilizador iniciar diretamente um executável do plugin sem este argumento, o plugin pode exibir uma mensagem informativa em vez de esperar por uma saudação de protocolo. O tempo limite do handshake do protocolo é de 5 segundos. O plugin deve completar a configuração no menor tempo possível. As ferramentas cliente do NuGet irão consultar as operações suportadas de um plug-in, utilizando o índice de serviço fornecido por uma fonte NuGet. Um plug-in pode usar o índice de serviço para verificar a presença de tipos de serviço suportados.

A comunicação entre as ferramentas do cliente NuGet e o plugin é bidirecional. Cada solicitação tem um tempo limite de 5 segundos. Se as operações devem demorar mais tempo, o respetivo processo deve enviar uma mensagem de progresso para evitar que a solicitação atinja o tempo limite. Após 1 minuto de inatividade, um plugin é considerado ocioso e é desligado.

Instalação e descoberta de plug-ins

O NuGet procura plug-ins a partir de uma estrutura de diretórios baseada em convenção e verifica a variável de ambiente PATH.

Descoberta baseada em convenção

Cenários de CI/CD e usuários avançados podem usar variáveis de ambiente para substituir o comportamento. Ao usar variáveis de ambiente, apenas caminhos absolutos são permitidos. Observe isso NUGET_NETFX_PLUGIN_PATHS e NUGET_NETCORE_PLUGIN_PATHS só estão disponíveis com a versão 5.3+ das ferramentas NuGet e posteriores.

  • NUGET_NETFX_PLUGIN_PATHS - define os plugins que serão usados pelas ferramentas baseadas no .NET Framework (NuGet.exe/MSBuild.exe/Visual Studio). Tem precedência sobre NUGET_PLUGIN_PATHS. (Apenas versão 5.3+ do NuGet)
  • NUGET_NETCORE_PLUGIN_PATHS - define os plugins que serão usados pelas ferramentas baseadas no .NET Core (dotnet.exe). Tem precedência sobre NUGET_PLUGIN_PATHS. (Apenas versão 5.3+ do NuGet)
  • NUGET_PLUGIN_PATHS - define os plugins que serão usados para esse processo NuGet, prioridade preservada. Se essa variável de ambiente for definida, ela substituirá a descoberta baseada em convenção. Ignorado se qualquer uma das variáveis específicas da estrutura for especificada.
  • Localização do utilizador, a localização do NuGet Home em %UserProfile%/.nuget/plugins. Este local não pode ser substituído. Um diretório raiz diferente será usado para plug-ins do .NET Core e do .NET Framework.
Framework Local de detecção de raiz Utilizado por
Núcleo do .NET %UserProfile%/.nuget/plugins/netcore CLI dotnet
.NET Framework %UserProfile%/.nuget/plugins/netfx MSBuild, NuGet.exe, Visual Studio

Cada plugin deve ser instalado em sua própria pasta. O ponto de entrada do plug-in será o nome da pasta instalada, com as extensões .dll para .NET Core e .exe extensão para .NET Framework.

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

Descoberta de PATH

A partir do NuGet 6.13, o NuGet pesquisará cada diretório fornecido na variável de ambiente PATH por arquivos correspondentes ao padrão nuget-plugin-*. A correspondência de padrões é sensível a maiúsculas e minúsculas, e nuget-plugin- deve ser escrita totalmente em letras minúsculas. No Windows, o ficheiro deve ter uma extensão .exe ou .bat. No Linux e Mac o arquivo deve ter o bit executável definido.

Isso permite que os plugins do NuGet sejam instalados por meio dotnet tool de comandos, WinGet, gerenciador de pacotes de uma distribuição Linux ou qualquer outro método que possa colocar executáveis no PATH do usuário. Isso também permite que os plugins do NuGet sejam escritos em qualquer linguagem de programação (anteriormente os plugins para Linux e Mac devem ser escritos em .NET).

Recomendamos que os plugins sejam desenvolvidos em .NET, para que você possa usar o pacote NuGet.Protocol para evitar a necessidade de escrever o código RPC json e para permitir que os clientes descubram seu plug-in via dotnet package search nuget-plugin.

Operações suportadas

Duas operações são suportadas sob o novo protocolo de plugin.

Nome da operação Versão mínima do protocolo Versão mínima do cliente NuGet
Transferir Pacote 1.0.0 4.3.0
Autenticação 2.0.0 4.8.0

Executando plugins sob o tempo de execução correto

Para o NuGet em cenários dotnet.exe, os plug-ins precisam ser capazes de ser executados nesse runtime específico do dotnet.exe. Cabe ao fornecedor de plug-ins e ao consumidor certificar-se de que uma combinação compatível dotnet.exe/plugin é usada. Um problema potencial pode surgir com os plug-ins de localização do usuário quando, por exemplo, um dotnet.exe sob o tempo de execução 2.0 tenta usar um plug-in escrito para o tempo de execução 2.1.

Cache de recursos

A verificação de segurança e instanciação dos plugins é cara. A operação de download acontece com muito mais frequência do que a operação de autenticação, no entanto, o usuário médio do NuGet provavelmente só terá um plug-in de autenticação. Para melhorar a experiência, o NuGet armazenará em cache as declarações de operação para a solicitação fornecida. Esse cache é por plug-in com a chave do plug-in sendo o caminho do plug-in, e a expiração desse cache de recursos é de 30 dias.

O cache está localizado em %LocalAppData%/NuGet/plugins-cache e pode ser substituído com a variável de ambiente NUGET_PLUGINS_CACHE_PATH. Para limpar esse cache, pode-se executar o comando locals com a plugins-cache opção. A all opção locais agora também excluirá o cache de plugins.

Índice de mensagens de protocolo

Mensagens do protocolo versão 1.0.0 :

  1. Fechar

    • Direção do pedido: NuGet -> plugin
    • O pedido não conterá carga útil
    • Não é esperada qualquer resposta. A resposta adequada é que o processo do plugin termine imediatamente.
  2. Copiar arquivos no pacote

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID e a versão do pacote
      • o local do repositório de origem do pacote
      • caminho do diretório de destino
      • Uma enumeração de ficheiros no pacote a serem copiados para o caminho do diretório de destino
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • Um enumerável de caminhos completos para arquivos copiados no diretório de destino se a operação foi bem-sucedida
  3. Copiar arquivo de pacote (.nupkg)

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID e a versão do pacote
      • o local do repositório de origem do pacote
      • O caminho do arquivo de destino
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
  4. Obter credenciais

    • Direção da solicitação: plugin -> NuGet
    • O pedido conterá:
      • o local do repositório de origem do pacote
      • o código de status HTTP obtido do repositório de origem do pacote usando credenciais atuais
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • um nome de utilizador, se disponível
      • uma palavra-passe, se disponível
  5. Obter arquivos no pacote

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID e a versão do pacote
      • o local do repositório de origem do pacote
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • Uma enumeração de caminhos de ficheiros no pacote caso a operação tenha sido bem-sucedida
  6. Obter declarações de operação

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o serviço index.json para uma fonte de pacote
      • o local do repositório de origem do pacote
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • Uma lista de operações suportadas, como o download de pacotes, se a operação foi bem-sucedida. Se um plug-in não suportar a origem do pacote, o plug-in deverá retornar um conjunto vazio de operações suportadas.

Observação

Esta mensagem foi atualizada na versão 2.0.0. Cabe ao cliente preservar a compatibilidade com versões anteriores.

  1. Obter hash do pacote

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID e a versão do pacote
      • o local do repositório de origem do pacote
      • o algoritmo de hash
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • um hash de arquivo de pacote usando o algoritmo de hash solicitado, caso a operação tenha sido bem-sucedida.
  2. Obter as versões dos pacotes

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID do pacote
      • o local do repositório de origem do pacote
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • Uma enumeração de versões de pacotes se a operação foi bem-sucedida
  3. Obter índice de serviço

    • Direção da solicitação: plugin -> NuGet
    • O pedido conterá:
      • o local do repositório de origem do pacote
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • O índice de serviço se a operação foi bem-sucedida
  4. Aperto de mão

    • Direção do pedido: NuGet <-> plugin
    • O pedido conterá:
      • a versão atual do protocolo do plugin
      • A versão mínima suportada do protocolo de plug-in
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • a versão do protocolo negociado se a operação tiver sido bem-sucedida. Uma falha resultará na rescisão do plugin.
  5. Inicializar

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • a versão da ferramenta cliente NuGet
      • a linguagem efetiva da ferramenta cliente NuGet. Isso leva em consideração a configuração ForceEnglishOutput, se usada.
      • O tempo limite padrão da solicitação, que prevalece sobre o padrão do protocolo.
    • A resposta conterá:
      • um código de resposta que indica o resultado da operação. Uma falha resultará na rescisão do plugin.
  6. Registo

    • Direção da solicitação: plugin -> NuGet
    • O pedido conterá:
      • o nível de log para a solicitação
      • uma mensagem para registar
    • A resposta conterá:
      • um código de resposta que indica o resultado da operação.
  7. Monitorar a saída do processo NuGet

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID do processo NuGet
    • A resposta conterá:
      • um código de resposta que indica o resultado da operação.
  8. Pacote de pré-carregamento

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o ID e a versão do pacote
      • o local do repositório de origem do pacote
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
  9. Definir credenciais

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • o local do repositório de origem do pacote
      • o último nome de usuário de origem do pacote conhecido, se disponível
      • a última senha de origem do pacote conhecida, se disponível
      • o último nome de usuário proxy conhecido, se disponível
      • A última senha de proxy conhecida, se disponível
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
  10. Definir nível de log

    • Direção do pedido: NuGet -> plugin
    • O pedido conterá:
      • O nível de log padrão
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação

Mensagens do protocolo versão 2.0.0

  1. Obter declarações de operação
  • Direção do pedido: NuGet -> plugin

    • O pedido conterá:
      • o serviço index.json para uma fonte de pacote
      • o local do repositório de origem do pacote
    • A resposta conterá:
      • um código de resposta que indique o resultado da operação
      • Um conjunto enumerável de operações suportadas caso a operação tenha sido bem-sucedida. Se um plug-in não suportar a origem do pacote, o plug-in deverá retornar um conjunto vazio de operações suportadas.

    Se o índice de serviço e a fonte do pacote forem nulos, o plug-in poderá responder com autenticação.

  1. Obter credenciais de autenticação
  • Direção do pedido: NuGet -> plugin
  • O pedido conterá:
    • Uri
    • isRetry
    • Não interativo
    • CanShowDialog
  • Uma resposta conterá:
    • Nome de utilizador
    • Palavra-passe
    • Mensagem
    • Lista de tipos de autenticação
    • CódigoDeRespostaMensagem