[Avançado] Criando templates customizados em C#
Vinícius Beloni
Posted on May 10, 2022
Portanto, se alguém está em Cristo, é nova criação. As coisas antigas já passaram; eis que surgiram coisas novas!
2 Coríntios 5.17
Sumário:
- Estrutura final
- Preparando a solução
- Criando repositório remoto
- Github Secrets
- Configurando o pacote
- Publicando o template
- Fontes
- Agradecimentos
No tutorial anterior vimos juntos como criar um template de um jeito bem simples, agora porém, vamos escalar a simplicidade e criar uma solução completa de forma replicável, onde teremos publicação automática utilizando Github Actions, Nuget registry e muito mais!
Estrutura final
PS C:/repos/my-templates> tree /f
│ .gitignore
│ TemplatePack.csproj
│
├───.github
│ └───workflows
│ publish.yml
│
└───templates
└───customapi
│ .dockerignore
│ .editorconfig
│ .gitattributes
│ .gitignore
│ Dockerfile
│ MyProject.sln
│
├───.template.config
│ template.json
│
├───src
│ │ appsettings.Development.json
│ │ appsettings.json
│ │ MyProject.csproj
│ │ Program.cs
│ │ WeatherForecast.cs
│ │
│ ├───Controllers
│ │ WeatherForecastController.cs
│ │
│ └───Properties
│ launchSettings.json
│
└───tests
MyProject.Tests.csproj
UnitTest1.cs
Vamos começar criando um diretório para hospedar os templates, pois com esse tutorial será possível ter vários em um único pacote. Então para a API vamos criar dois projetos, um para o código de produção(src) e outro para testes de unidade(tests) mas fique a vontade para seguir o que funciona pra você, também vamos criar uma solution e outros arquivos.
Preparando a solução
> mkdir templates/customapi
> cd templates/customapi
> dotnet new webapi --no-https -n MyProject -o src
> dotnet new xunit -n MyProject.Tests -o tests
> dotnet new sln -n MyProject
> dotnet add ./tests/ reference ./src
> dotnet sln add ./src/ ./tests/
Agora vamos criar o restante dos arquivos (Encoding: UTF-8):
> '' > Dockerfile
> '' > .editorconfig
> '' > .gitignore
> '' > .dockerignore
> '' > .gitattributes
> mkdir .template.config
> '' > .template.config/template.json
.gitignore
:
https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
Dockerfile
:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
# remover se não usar .editorconfig
ENV PATH="$PATH:/root/.dotnet/tools"
RUN dotnet tool install -g dotnet-format
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet build -c Release --no-restore
RUN dotnet test -c Release --no-build
# remover se não usar .editorconfig
RUN dotnet format --verify-no-changes
RUN dotnet publish "src/MyProject.csproj" -c Release --no-build -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyProject.dll"]
.dockerignore
:
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
.gitattributes
:
* text=auto
*.cs text eol=crlf
.editorconfig
(Opcional):
Padrão do .NET
O padrão que eu utilizo
Para formatar seu código instale o dotnet format e execute o seguinte comando:
> dotnet tool install -g dotnet-format
> dotnet format
template.json
:
Podemos seguir o mesmo do tutorial anterior:
{
"$schema": "http://json.schemastore.org/template",
"author": "@confianodev",
"identity": "MyCustomWebApi",
"name": "My Custom Web Api",
"shortName": "customapi",
"preferNameDirectory": false,
"sourceName": "MyProject",
"classifications": ["Web API", "API"],
"tags": {
"language": "C#",
"type": "project"
}
}
Criando repositório remoto
Agora começa as diferenças, no caso como estamos trabalhando com multiplos projetos e até templates, vamos criar um arquivo .csproj
na raiz da nossa solução. Este arquivo terá várias informações para empacotar todos os templates e publicá-los posteriormente, mas antes vamos criar um repositório remoto.
Vá até o Github, crie um novo repositório vazio e siga este passo-a-passo:
> cd ../..
> git init
> git add .
> git commit -m "initial template files"
> git branch -M main
> git remote add origin https://github.com/SEU-USER/seurepo.git
> git push -u origin main
Github Secrets
Para publicar o pacote devemos criar um Token, basta criar um Personal Access Token com permissões de write:packages
e copiar o conteúdo, depois vá para a aba
Setting > Secrets > Actions
do repositório que criamos e clique em "New repository secret", ao pedir um Name coloque como "PACKAGES_TOKEN" (válido para este tutorial, mas pode colocar o nome que quiser) e no Value cole o Token que você acabou de criar.
Configurando o pacote
Com tudo isso pronto, vamos criar nosso arquivo de template que será utilizado pelo comando dotnet pack
. Lembrando que o campo <RepositoryUrl>
precisa ser preenchido corretamente com o nome do repositório que acabamos de criar, caso contrário teremos problemas ao publicar o nosso pacote:
> '' > TemplatePack.csproj
TemplatePack.csproj
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageType>Template</PackageType>
<PackageVersion>1.0.0</PackageVersion>
<PackageId>my.templates</PackageId>
<Title>My Templates</Title>
<Authors>@confianodev</Authors>
<RepositoryUrl>ALÔ, GALERA DE COWBOY</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Description>Templates utilizados para criar meus projetos HAHA</Description>
<PackageTags>dotnet-new;templates;</PackageTags>
<TargetFramework>net6.0</TargetFramework>
<IncludeContentInPack>true</IncludeContentInPack>
<IncludeBuildOutput>false</IncludeBuildOutput>
<ContentTargetFolders>content</ContentTargetFolders>
<NoDefaultExcludes>true</NoDefaultExcludes>
<NoWarn>$(NoWarn);NU5128</NoWarn>
</PropertyGroup>
<ItemGroup>
<Content Include="templates\**\*" Exclude="templates\**\bin\**;templates\**\obj\**" />
<Compile Remove="**\*" />
</ItemGroup>
</Project>
Para mais informações, acesse este link.
Customize do jeito que for melhor, nesse momento poderiamos aplicar nossos padrões, criar classes de apoio(repositórios, métodos de extensão, configurações de log, startup, etc). Após tudo feito, podemos testar:
> dotnet test templates/customapi/tests
> dotnet run --project templates/customapi/src
Agora vamos empacotar tudo e testar nosso novo template, pois o próximo passo será jogar isso para o Nuget:
> dotnet pack
> dotnet new -i ./bin/Debug/my.templates.1.0.0.nupkg
> dotnet new customapi -n Pimba -o sample
> rm /sample
> dotnet new --uninstall my.templates
Excelente! Template testado e funcional, agora vamos automatizar a publicação de novas versões e publicar o nosso pacote Nuget.
Publicando o template
Vamos configurar o Github Actions:
> mkdir .github/workflows
> '' > .github/workflows/publish.yml
publish.yml
:
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET 6 # atualize se for necessário
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.202 # atualize se for necessário
- name: Generate package
run: dotnet pack -c Debug -o out --include-symbols --include-source --verbosity Detailed
- name: Publish NuGet
run: |
cd out
dotnet nuget push *.nupkg --api-key ${{ secrets.PACKAGES_TOKEN }} --source https://nuget.pkg.github.com/SEU-USER/index.json --skip-duplicate
Faça o commit das alterações e vamos ver o resultado do Github Actions:
> copy ./templates/customapi/.gitignore .gitignore
> git add .
> git commit -m "add publish action"
> git push
Se tudo deu certo, na aba Actions do seu reposítorio o pacote estará sendo preparado e pronto para ser utilizado. Mas agora que seu pacote está disponível, precisamos adicioná-lo localmente:
Observação: Vou utilizar o Token que criei acima, mas o ideal para utilizar pacotes privados é criar um outro Token somente com o acesso read:packages
.
> dotnet nuget add source "https://nuget.pkg.github.com/SEU-USER/index.json" -n Github -u "SEU-USER" -p "TOKEN-QUE-CRIAMOS" --store-password-in-clear-text
> dotnet new -i my-templates
> dotnet new customapi -n Opa -o sample
Saída do meu terminal:
PS C:\repos\criando-template> dotnet new -i power.templates
The following template packages will be installed:
power.templates
Failed to download package 'power.templates.1.0.0' from 'https://nuget.pkg.github.com/confianodev/download/power.templates/1.0.0/power.templates.1.0.0.nupkg'.
The HTTP request to 'GET https://nuget.pkg.github.com/confianodev/download/power.templates/1.0.0/power.templates.1.0.0.nupkg' has timed out after 100000ms.
Warning: Failed to scan C:\repos\criando-template\src.
Details: Template package location C:\repos\criando-template\src is not supported, or doesn't exist.
Success: power.templates::1.0.0 installed the following templates:
Template Name Short Name Language Tags
------------- ---------- -------- -----------
My Web Api customapi [C#] Web API/API
Para adicionar novos templates, basta criar novas pastas e projetos dentro da pasta templates
assim como fizemos para a templates/customapi
:
Exemplo:
> mkdir templates/customrobot
> cd templates/customrobot
> dotnet new console -n MyProject -o src
E é isso! Fico muito feliz de ter compartilhado com você esta experiência. Espero que consiga aumentar a sua produtividade e das pessoas que trabalham com você. Qualquer dúvida por favor deixem nos comentários!
Até a próxima, se assim o Senhor Pai nos permitir, Abraços!
Fontes
Como criar um pacote modelo
Working with the Nuget registry
https://docs.microsoft.com/pt-br/nuget/nuget-org/publish-a-package
Agradecimentos
Agradecimentos especiais ao SammyROCK, pois trabalhando com ele aprendi muita coisa, principalmente sobre Docker, Github Actions, Secrets, Nuget Registry, etc. Obrigado!
Posted on May 10, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.