Como vimos nos posts anteriores (.NET Core 2.1 Preview 1 e Global Tools) as Global Tools são parte das novas adições nesta versão do .NET Core. Esse texto é um tutorial simples mostrando como criar uma global tool.
Atenção! .NET Core 2.1 está em Preview 1, é possível que até a data de lançamento (ou a data que você esteja lendo este post) algo tenha mudado. Se for o caso, deixe um comentário que farei o possível para atualizar.
O que é uma Global Tool
Além da explicação dada no artigo anterior, uma Global Tool nada mais é do que uma aplicação console feita em .NET Core, simples assim. Não tem nada secreto, misterioso ou novo. A grande novidade é identificar o que é uma ferramenta que valha ser criada e distribuída desta forma.
Sendo uma aplicação console, a complexidade vai realmente depender do que você deseja fazer. Para este artigo, vamos criar uma tool que fornece a última cotação de Bitcoin em USD (dólares americanos) ou BRL (reais).
Nosso objetivo será ter uma ferramenta que faça (algo parecido com) isso:
$ cryptool BRL R$ 25.593,05
ou
$ cryptool USD 7.845,45 EUR 6.336,41 GBP 5.610,46
Notem que este comando está sendo executado diretamente no console/terminal, tanto no Windows quanto no Mac/Linux. É assim que as global tools se comportam e funcionam.
Criação do projeto
Todos os passos aqui serão executados em um Mac, rodando o .NET Core 2.1 Preview 1. Eu usarei a linha de comando para executar os comandos .NET e o Visual Studio Code para a edição do código. Todos os passos aqui descritos devem funcionar no Windows ou no Visual Studio. Vou colocar imagens logo após os comandos para que vocês possam conferir o output padrão.
$ dotnet new console --name cryptool
Feito isso, vamos abrir nossa solution e editar diretamente o arquivo Program.cs
. Vou colocar o código inteiro aqui, e explico logo abaixo. O que a aplicação faz, de forma bastante simples é:
-
- Decidir se foi passado algum argumento, e se foi verificamos se ele é válido;
-
- Retornar or argumento passado formatado para nossa URI ou uma string vazia;
-
- Realizar uma chamada para a API
-
- Exibir informação no console (vermelho em caso de erro).
using System; using System.Linq; using System.Net; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace cryptool { class Program { static HttpClient client = new HttpClient(); static string ArgsResolver(string[] args) { if(args.Any() && Regex.IsMatch(args[0], "^[a-zA-Z]{3}$")) return $"/{args[0]}"; return string.Empty; } static async Task Main(string[] args) { var uri = $"https://api.coindesk.com/v1/bpi/currentprice{ArgsResolver(args)}.json"; var result = await client.GetAsync(uri); var content = await result.Content.ReadAsStringAsync(); if (result.StatusCode != HttpStatusCode.OK) { Console.WriteLine("Ocorreu um problema 😬"); Console.ForegroundColor = ConsoleColor.Red; } Console.WriteLine(content); } } }
O código acima é bastante simples, encontrei uma api pública na Internet que fornece as informações de preço do Bitcoin, então tudo que faço é um request para essa API. Neste ponto já podemos executar nosso código, seja dando um play no Visual Studio Code/Visual Studio/Visual Studio for Mac, ou então pelo console, usando:
$ dotnet run
ou
$ dotnet run BRL
Sua tool poderia fazer qualquer outro tipo de coisa: se conectar ao Azure, enviar emails, gerar memes, postar algo no Twitter, conferir o status dos servidores de aplicação que você possui, baixar e executar uma outra global tool (dx, projeto do Giovanni), listar processos dotnet core (dotnetps, uma outra tool que eu criei), e muito mais. As possibilidades são diversas.
Empacotando com nuget
Para podermos distribuir nossa app como uma global tool, via nuget, permitindo que seja instalada com o comando dotnet install
precisamos utilizar o nuget para gerar o pacote. Antes de gerar o pacote, vamos atualizar algumas informações no .csproj
. Adicione algo parecido com o código abaixo antes do fechamento de </PropertyGroup>
:
<PackAsTool>true</PackAsTool> <Version>1.0.0</Version> <Description>A tool for obtaining the latest Bitcoin value in USD, EUR, GBP or BRL. Install with the .NET CLI 2.1 or newer: dotnet install tool -g cryptool Run cryptool from the command line, for example: `cryptool` or `cryptool BRL` </Description>
Agora já podemos gerar nosso pacote. Na pasta raiz do nosso projeto vamos executar o seguinte comando:
$ dotnet pack . -c Release -o nupkg
O que este comando faz é:
- Faz o build da aplicação para release (-c ou –configuration);
- Define o diretório onde será colocado o pacote gerado (-o ou –output)
Com isso devemos ter um arquivo .nupkg
na pasta nupkg
.
Testando a instalação do pacote localmente
É possível realizar o teste da geração do pacote localmente. Para isso vamos configurar, dentro da pasta nupkg
um arquivo de nuget.config
com o seguinte conteúdo:
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <clear/> <add key="local-packages" value="." /> </packageSources> </configuration>
O que este arquivo quer dizer é: sempre que o comando nuget for executado de dentro desta pasta, ignore todas as outras fontes do nuget e procure os pacotes somente dentro desta pasta. Com isso poderemos instalar nosso pacote sem publicá-lo no nuget.org, o que é extremamente válido durante o desenvolvimento.
Feito isso, basta executar o seguinte comando, dentro da pasta nupkg
:
$ dotnet install tool -g cryptool
Finalizando
Como vimos ao longo desse breve artigo, a criação de uma Global Tool, no .NET Core 2.1 é bastante simples. Uma console application empacotada e distribuída via nuget. Como puderam reparar, o código desta global tool que eu criei ainda responde um json na saída do console. Quem quiser enviar um pull request para o parser do json, adicionar tratamento de exception, etc., o código está aqui no Github.
Você também pode instalar esse pacote via nuget, está publicado aqui. A realização do public para o repositório oficial do nuget é bastante simples, e pode ser feita com um único comando:
$ dotnet nuget push --api-key <sua key> -s nuget.org <nome do pacote>.nupkg
Em um outro post podemos abordar melhor a questão da publicação, falando apenas sobre nuget.
Espero comentários de vocês aqui no blog, ou então podem me achar no Twitter como @vquaiato.
Vinicius Quaiato