Compartilhar via


Plug-ins multiplataforma do NuGet

No NuGet 4.8+ foi adicionado suporte para plug-ins de plataforma cruzada. Isso foi feito com a criação de um novo modelo de extensibilidade de plug-in, que precisa estar em conformidade com um conjunto estrito de regras de operação. Os plug-ins são executáveis independentes (executáveis no ambiente do .NET Core), que os Clientes NuGet iniciam em um processo separado. Este é um verdadeiro plugin de "escreva uma vez, execute em qualquer lugar". Ele funcionará com todas as ferramentas de cliente do NuGet. Os plug-ins podem ser escritos em qualquer linguagem de programação, mas a experiência mais fácil de desenvolvimento e instalação do plug-in será com o .NET. Um protocolo de comunicação com versão entre o Cliente NuGet e o plug-in é definido. Durante o handshake de inicialização, os dois processos negociam a versão do protocolo.

Como funciona?

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

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

Requisitos gerais de plugin

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

  • Dê suporte à inicialização sem estado no contexto de segurança atual das ferramentas de cliente do NuGet. Por exemplo, as ferramentas de cliente do NuGet não executarão a elevação ou a inicialização adicional fora do protocolo de plug-in descrito posteriormente.
  • Não seja interativo, a menos que seja especificado explicitamente.
  • Siga a versão negociada do protocolo de plugin.
  • Responda a todas as solicitações dentro de um período de tempo razoável.
  • Respeite as solicitações de cancelamento para qualquer operação em andamento.

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

NuGet 6.12 (MSBuild 17.12 e .NET SDK 9.0.100) e anteriormente também exigiam que os plug-ins fossem assinados pelo Authenticode no Windows.

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

Cliente – Interação de plugin

As ferramentas de cliente do NuGet e os plug-ins se comunicam com JSON por meio de fluxos padrão (stdin, stdout, stderr). Todos os dados devem ser codificados em UTF-8. Os plug-ins são iniciados com o argumento "-Plug-in". Caso um usuário inicie diretamente um executável de plug-in sem esse argumento, o plug-in pode fornecer uma mensagem informativa em vez de aguardar um handshake de protocolo. O tempo limite do handshake do protocolo é de 5 segundos. O plug-in deve concluir a configuração no menor tempo possível. As ferramentas de cliente do NuGet consultarão as operações suportadas por um plug-in ao passar o índice de serviço para uma fonte NuGet. Um plug-in pode usar o índice de serviço para verificar a presença de tipos de serviço com suporte.

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

Instalação e descoberta do plug-in

O NuGet pesquisa plug-ins de uma estrutura de diretório 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 alterar o comportamento. Ao usar variáveis de ambiente, somente caminhos absolutos são permitidos. Observe que NUGET_NETFX_PLUGIN_PATHS e NUGET_NETCORE_PLUGIN_PATHS só estão disponíveis com a versão 5.3+ das ferramentas do NuGet e posteriores.

  • NUGET_NETFX_PLUGIN_PATHS – define os plug-ins que serão usados pelas ferramentas baseadas no .NET Framework (NuGet.exe/MSBuild.exe/Visual Studio). Tem precedência sobre NUGET_PLUGIN_PATHS. (Somente NuGet versão 5.3+ )
  • NUGET_NETCORE_PLUGIN_PATHS – define os plug-ins que serão usados pelas ferramentas baseadas no .NET Core (dotnet.exe). Tem precedência sobre NUGET_PLUGIN_PATHS. (Somente a versão 5.3+ do NuGet)
  • NUGET_PLUGIN_PATHS – definem os plug-ins que serão usados para esse processo do NuGet, com a prioridade preservada. Se essa variável de ambiente estiver 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 usuário, localização do NuGet Home em %UserProfile%/.nuget/plugins. Esse local não pode ser substituído. Um diretório raiz diferente será usado para plug-ins do .NET Core e do .NET Framework.
Estrutura Local de descoberta da raiz Usado por
.NET Core %UserProfile%/.nuget/plugins/netcore CLI do dotnet
.NET Framework %UserProfile%/.nuget/plugins/netfx MSBuild, NuGet.exe, Visual Studio

Cada plug-in 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 do .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 em busca de arquivos que correspondam ao padrão nuget-plugin-*. A correspondência de padrões diferencia maiúsculas de minúsculas e nuget-plugin- deve ser escrita inteiramente em letras minúsculas. No Windows, o arquivo deve ter uma .exe ou .bat extensão. No Linux e no Mac, o arquivo deve ter o conjunto de bits executável.

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

Recomendamos que os plug-ins sejam desenvolvidos no .NET, para que você possa usar o pacote NuGet.Protocol para evitar a necessidade de gravar o código JSON RPC e permitir que os clientes descubram seu plug-in por meio dotnet package search nuget-pluginde .

Operações com suporte

Há suporte para duas operações no novo protocolo plug-in.

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

Executando plug-ins no ambiente de execução correto

Para o NuGet em cenários de dotnet.exe, os plug-ins precisam ser capazes de executar nesse runtime específico do dotnet.exe. Cabe ao fornecedor do plugin e ao consumidor assegurar que se use uma combinação compatível de dotnet.execom plugin. Um problema potencial pode surgir com os plug-ins de localização do usuário quando, por exemplo, um dotnet.exe no runtime 2.0 tenta usar um plug-in gravado para o runtime 2.1.

Cache de capacidades

A verificação de segurança e a instanciação dos plug-ins são dispendiosas. A operação de download ocorre com muito mais frequência do que a operação de autenticação, no entanto, é provável que o usuário nuGet médio tenha apenas 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 de plug-in sendo o caminho do plug-in e a expiração para esse cache de recursos é de 30 dias.

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

Índice de mensagens de protocolo

Mensagens de protocolo versão 1.0.0 :

  1. Fechar

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação não conterá nenhum conteúdo
    • Nenhuma resposta é esperada. A resposta adequada é que o processo de plug-in seja finalizado prontamente.
  2. Copiar arquivos no pacote

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a ID e a versão do pacote
      • o local do repositório de origem do pacote
      • caminho do diretório de destino
      • uma lista de arquivos no pacote a serem copiados para o caminho do diretório de destino
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • um enumerável de caminhos completos para arquivos copiados no diretório de destino se a operação tiver sido bem-sucedida
  3. Copiar arquivo de pacote (.nupkg)

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a ID e a versão do pacote
      • o local do repositório de origem do pacote
      • o caminho do arquivo de destino
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
  4. Obter credenciais

    • Direção da solicitação: plug-in –> NuGet
    • A solicitação 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 as credenciais atuais
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • um nome de usuário, se disponível
      • uma senha, se disponível
  5. Obter arquivos do pacote

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a ID e a versão do pacote
      • o local do repositório de origem do pacote
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • um enumerável de caminhos de arquivo no pacote se a operação tiver sido bem-sucedida
  6. Obter declarações de operação

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • o serviço index.json para uma origem de pacotes
      • o local do repositório de origem do pacote
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • uma enumeração das operações com suporte (como o download de pacote) caso a operação tenha sido bem-sucedida. Se um plug-in não suportar a origem do pacote, ele deverá retornar um conjunto vazio de operações com suporte.

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 da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a ID e a versão do pacote
      • o local do repositório de origem do pacote
      • o algoritmo de hash
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • um hash de arquivo de pacote usando o algoritmo de hash solicitado se a operação tiver sido bem-sucedida
  2. Obter versões do pacote

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a ID do pacote
      • o local do repositório de origem do pacote
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • uma lista enumerável de versões de pacote se a operação tiver sido bem-sucedida
  3. Obter índice de serviço

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

    • Direção da solicitação: NuGet <–> plug-in
    • A solicitação conterá:
      • a versão atual do protocolo de plugin
      • a versão mínima com suporte do protocolo plugin
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • a versão do protocolo negociado se a operação tiver sido bem-sucedida. Uma falha resultará no encerramento do plug-in.
  5. Inicializar

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a versão da ferramenta de cliente do NuGet
      • o idioma efetivo da ferramenta de cliente do NuGet. Isso leva em consideração a configuração ForceEnglishOutput, se usada.
      • o tempo limite de solicitação padrão, que substitui o padrão de protocolo.
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação. Uma falha resultará no encerramento do plug-in.
  6. Registro

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

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

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • a ID e a versão do pacote
      • o local do repositório de origem do pacote
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
  9. Definir credenciais

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação 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 de proxy conhecido, se disponível
      • a última senha de proxy conhecida, se disponível
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
  10. Definir o nível de log

    • Direção da solicitação: NuGet –> plug-in
    • A solicitação conterá:
      • o nível de log padrão
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação

Mensagens de protocolo versão 2.0.0

  1. Obter declarações de operação
  • Direção da solicitação: NuGet –> plug-in

    • A solicitação conterá:
      • o serviço index.json para uma origem de pacotes
      • o local do repositório de origem do pacote
    • Uma resposta conterá:
      • um código de resposta que indica o resultado da operação
      • Se a operação for um sucesso, uma enumeração das operações suportadas. Se um plug-in não suportar a origem do pacote, ele deverá retornar um conjunto vazio de operações com suporte.

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

  1. Obter credenciais de autenticação
  • Direção da solicitação: NuGet –> plug-in
  • A solicitação conterá:
    • URI
    • éRepetição
    • NãoInterativo
    • PodeMostrarDialogo
  • Uma resposta conterá
    • Nome de usuário
    • Senha
    • Mensagem
    • Lista de tipos de autenticação
    • CódigoDeRespostaDeMensagem