DEV Community

Vinícius Beloni
Vinícius Beloni

Posted on

[Avançado] Criando templates customizados em C#

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:

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

voltar ao topo

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
Enter fullscreen mode Exit fullscreen mode

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

voltar ao topo

> 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/
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar o restante dos arquivos (Encoding: UTF-8):

> '' > Dockerfile
> '' > .editorconfig
> '' > .gitignore
> '' > .dockerignore
> '' > .gitattributes
> mkdir .template.config
> '' > .template.config/template.json
Enter fullscreen mode Exit fullscreen mode

.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"]
Enter fullscreen mode Exit fullscreen mode

.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
Enter fullscreen mode Exit fullscreen mode

.gitattributes:

* text=auto
*.cs text eol=crlf
Enter fullscreen mode Exit fullscreen mode

.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
Enter fullscreen mode Exit fullscreen mode

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"
    }
}
Enter fullscreen mode Exit fullscreen mode

Criando repositório remoto

voltar ao topo

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
Enter fullscreen mode Exit fullscreen mode

Github Secrets

voltar ao topo

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

voltar ao topo

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Excelente! Template testado e funcional, agora vamos automatizar a publicação de novas versões e publicar o nosso pacote Nuget.

Publicando o template

voltar ao topo

Vamos configurar o Github Actions:

> mkdir .github/workflows
> '' > .github/workflows/publish.yml
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

voltar ao topo

Como criar um pacote modelo
Working with the Nuget registry
https://docs.microsoft.com/pt-br/nuget/nuget-org/publish-a-package

Agradecimentos

voltar ao topo

Agradecimentos especiais ao SammyROCK, pois trabalhando com ele aprendi muita coisa, principalmente sobre Docker, Github Actions, Secrets, Nuget Registry, etc. Obrigado!

Top comments (0)