Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

Ou como obter belos crachás para o seu projeto em uma noite de codificação fácil

Provavelmente, todo desenvolvedor que tem pelo menos um projeto de estimação em algum momento tem uma coceira por emblemas bonitos com status, cobertura de código, versões de pacotes em nuget ... E essa coceira me levou a escrever este artigo. Em preparação para escrevê-lo, consegui esta belezura em um de meus projetos:

Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

Este artigo o guiará pela configuração básica de integração e entrega contínuas para um projeto de biblioteca de classe .Net Core no GitLab, publicação de documentação nas páginas do GitLab e envio de pacotes criados para um feed privado no Azure DevOps.

O VS Code foi usado como ambiente de desenvolvimento com a extensão Fluxo de trabalho do GitLab (para validar o arquivo de configurações diretamente do ambiente de desenvolvimento).

Breve introdução

CD - é quando você acabou de empurrar e tudo já caiu no cliente?

O que é CI / CD e por que você precisa - você pode facilmente pesquisar no Google. Encontre a documentação completa sobre como configurar pipelines no GitLab também fácil. Aqui vou descrever brevemente e, se possível, sem falhas, o processo do sistema do ponto de vista de um pássaro:

  • o desenvolvedor envia um commit para o repositório, cria uma solicitação de merge através do site, ou de alguma outra forma, explicitamente ou implicitamente inicia o pipeline,
  • todas as tarefas são selecionadas na configuração, cujas condições permitem que sejam iniciadas no contexto determinado,
  • as tarefas são organizadas de acordo com suas etapas,
  • estágios são executados por sua vez - ou seja, paralelo a todas as tarefas desta etapa são concluídas,
  • se o estágio falhar (ou seja, pelo menos uma das tarefas do estágio falhar), o pipeline será interrompido (quase sempre),
  • se todas as etapas forem concluídas com êxito, o pipeline será considerado bem-sucedido.

Assim, temos:

  • pipeline - um conjunto de tarefas organizadas em estágios nos quais você pode criar, testar, empacotar código, implantar uma compilação finalizada em um serviço de nuvem, etc.,
  • estágio (etapa) — unidade de organização do pipeline, contém 1+ tarefa,
  • tarefa (trabalho) é uma unidade de trabalho no pipeline. Ele consiste em um script (obrigatório), condições de inicialização, configurações para artefatos de publicação/cache e muito mais.

Assim, a tarefa de configuração do CI/CD se resume à criação de um conjunto de tarefas que implementam todas as ações necessárias para construir, testar e publicar códigos e artefatos.

Antes de começar: por quê?

  • Por que o Gitlab?

Porque quando se tornou necessário criar repositórios privados para projetos de estimação, eles foram pagos no GitHub e eu era ganancioso. Os repositórios se tornaram gratuitos, mas até agora isso não é motivo suficiente para eu mudar para o GitHub.

  • Por que não o Azure DevOps Pipelines?

Porque lá a configuração é elementar - o conhecimento da linha de comando nem é necessário. Integração com provedores git externos - em alguns cliques, importação de chaves SSH para enviar confirmações para o repositório - também, o pipeline é facilmente configurado, mesmo não a partir de um modelo.

Posição inicial: o que você tem e o que você quer

Nós temos:

  • repositório no GitLab.

Nós queremos:

  • montagem e teste automáticos para cada solicitação de mesclagem,
  • construindo pacotes para cada solicitação de mesclagem e enviando para o mestre, desde que haja uma certa linha na mensagem de confirmação,
  • envio de pacotes construídos para um feed privado no Azure DevOps,
  • montagem de documentação e publicação em GitLab Pages,
  • insígnias!11

Os requisitos descritos se enquadram organicamente no seguinte modelo de pipeline:

  • Etapa 1 - montagem
    • Coletamos o código, publicamos os arquivos de saída como artefatos
  • Fase 2 - teste
    • Obtemos artefatos do estágio de construção, executamos testes, coletamos dados de cobertura de código
  • Etapa 3 - Enviar
    • Tarefa 1 - crie o pacote nuget e envie-o para o Azure DevOps
    • Tarefa 2 - coletamos o site do xmldoc no código-fonte e publicamos no GitLab Pages

Vamos começar!

Coletando a configuração

Preparando contas

  1. Crie uma conta em e Microsoft Azure

  2. Ir para DevOps do Azure

  3. Criamos um novo projeto

    1. Nome - qualquer
    2. Visibilidade - qualquer
      Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  4. Ao clicar no botão Criar, o projeto será criado e você será redirecionado para a página dele. Nesta página, você pode desabilitar recursos desnecessários acessando as configurações do projeto (link inferior na lista à esquerda -> Visão geral -> Bloco Azure DevOps Services)
    Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  5. Vá para Atrifacts, clique em Criar feed

    1. Digite o nome da fonte
    2. Escolha a visibilidade
    3. Desmarcar Incluir pacotes de fontes públicas comuns, para que a fonte não se transforme em um clone nuget de dump
      Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  6. Clique em Conectar ao feed, selecione Visual Studio, copie Source do bloco Machine Setup
    Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  7. Vá para as configurações da conta, selecione Token de acesso pessoal
    Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  8. Criar um novo token de acesso

    1. Nome - arbitrário
    2. Organização - Atual
    3. Válido por no máximo 1 ano
    4. Escopo - Embalagem/Leitura e Gravação
      Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  9. Copie o token criado - após o fechamento da janela modal, o valor ficará indisponível

  10. Vá para as configurações do repositório no GitLab, selecione as configurações de CI/CD
    Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

  11. Expanda o bloco Variáveis, adicione um novo

    1. Nome - qualquer sem espaços (estará disponível no shell de comando)
    2. Valor - token de acesso do parágrafo 9
    3. Selecione a variável de máscara
      Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

Isso conclui a pré-configuração.

Preparando a estrutura de configuração

Por padrão, a configuração de CI/CD no GitLab usa o arquivo .gitlab-ci.yml da raiz do repositório. Você pode definir um caminho arbitrário para este arquivo nas configurações do repositório, mas neste caso não é necessário.

Como você pode ver na extensão, o arquivo contém uma configuração no formato YAML. A documentação detalha quais chaves podem estar contidas no nível superior da configuração e em cada um dos níveis aninhados.

Primeiro, vamos adicionar um link para a imagem docker no arquivo de configuração, no qual as tarefas serão executadas. Para isso encontramos Página de imagens .Net Core no Docker Hub. Em GitHub há um guia detalhado sobre qual imagem escolher para diferentes tarefas. Uma imagem com .Net Core 3.1 é adequada para construirmos, portanto, sinta-se à vontade para adicionar a primeira linha à configuração

image: mcr.microsoft.com/dotnet/core/sdk:3.1

Agora, quando o pipeline for iniciado a partir do repositório de imagens da Microsoft, será feito o download da imagem especificada, na qual todas as tarefas da configuração serão executadas.

O próximo passo é adicionar etapa's. Por padrão, o GitLab define 5 estágios:

  • .pre - realizada em todas as etapas,
  • .post - realizada após todas as etapas,
  • build - primeiro depois .pre estágio,
  • test - segunda fase,
  • deploy - a terceira fase.

No entanto, nada o impede de declará-los explicitamente. A ordem em que as etapas são listadas afeta a ordem em que são executadas. Para completar, vamos adicionar à configuração:

stages:
  - build
  - test
  - deploy

Para depuração, faz sentido obter informações sobre o ambiente em que as tarefas são executadas. Vamos adicionar um conjunto global de comandos que serão executados antes de cada tarefa com before_script:

before_script:
  - $PSVersionTable.PSVersion
  - dotnet --version
  - nuget help | select-string Version

Resta adicionar pelo menos uma tarefa para que, quando os commits forem enviados, o pipeline seja iniciado. Por enquanto, vamos adicionar uma tarefa vazia para demonstrar:

dummy job:
  script:
    - echo ok

Iniciamos a validação, recebemos uma mensagem de que está tudo bem, confirmamos, pressionamos, verificamos os resultados no site ... E recebemos um erro de script - bash: .PSVersion: command not found. wtf?

Tudo é lógico - por padrão, os executores (responsáveis ​​por executar scripts de tarefas e fornecidos pelo GitLab) usam bash para executar comandos. Você pode corrigir isso especificando explicitamente na descrição da tarefa quais tags o executor do pipeline em execução deve ter:

dummy job on windows:
  script:
    - echo ok
  tags:
    - windows

Ótimo! O pipeline agora está em execução.

Um leitor atento, tendo repetido as etapas indicadas, notará que a tarefa foi concluída na etapa test, embora não tenhamos especificado o palco. Como você pode imaginar test é a etapa padrão.

Vamos continuar criando o esqueleto de configuração adicionando todas as tarefas descritas acima:

build job:
  script:
    - echo "building..."
  tags:
    - windows
  stage: build

test and cover job:
  script:
    - echo "running tests and coverage analysis..."
  tags:
    - windows
  stage: test

pack and deploy job:
  script:
    - echo "packing and pushing to nuget..."
  tags:
    - windows
  stage: deploy

pages:
  script:
    - echo "creating docs..."
  tags:
    - windows
  stage: deploy

Obtivemos um pipeline não particularmente funcional, mas ainda assim correto.

Configurando gatilhos

Devido ao fato de que nenhum filtro de gatilho é especificado para nenhuma das tarefas, o pipeline será totalmente ser executado toda vez que um commit for enviado para o repositório. Como esse não é o comportamento desejado em geral, configuraremos filtros de gatilho para tarefas.

Os filtros podem ser configurados em dois formatos: apenas/exceto и regras. Brevemente, only/except permite configurar filtros por gatilhos (merge_request, por exemplo - define a tarefa a ser executada sempre que uma solicitação pull é criada e cada vez que os commits são enviados para a ramificação que é a origem da solicitação de mesclagem) e os nomes das ramificações (incluindo o uso de expressões regulares); rules permite personalizar um conjunto de condições e, opcionalmente, alterar a condição de execução da tarefa dependendo do sucesso das tarefas anteriores (when no GitLab CI/CD).

Vamos relembrar um conjunto de requisitos - montagem e teste apenas para solicitação de mesclagem, empacotamento e envio para Azure DevOps - para solicitação de mesclagem e pushes para o mestre, geração de documentação - para pushes para o mestre.

Primeiro, vamos configurar a tarefa de compilação de código adicionando uma regra que é acionada somente na solicitação de mesclagem:

build job:
  # snip
  only:
    - merge_request

Agora vamos configurar a tarefa de empacotamento para disparar na solicitação de mesclagem e adicionar confirmações ao mestre:

pack and deploy job:
  # snip
  only:
    - merge_request
    - master

Como você pode ver, tudo é simples e direto.

Você também pode definir a tarefa para disparar apenas se uma solicitação de mesclagem for criada com um destino específico ou ramificação de origem:

  rules:
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"

Sob condições, você pode usar variáveis ​​listadas aqui; regras rules incompatível com as regras only/except.

Configurando o Salvamento de Artefato

Durante uma tarefa build job teremos artefatos de construção que podem ser reutilizados em tarefas subsequentes. Para fazer isso, você precisa adicionar os caminhos para a configuração da tarefa, os arquivos ao longo dos quais você precisará salvar e reutilizar nas tarefas seguintes, para a chave artifacts:

build job:
  # snip
  artifacts:
    paths:
      - path/to/build/artifacts
      - another/path
      - MyCoolLib.*/bin/Release/*

Os caminhos suportam curingas, o que definitivamente os torna mais fáceis de configurar.

Se uma tarefa criar artefatos, cada tarefa subseqüente poderá acessá-los - eles estarão localizados nos mesmos caminhos relativos à raiz do repositório que foram coletados da tarefa original. Artefatos também estão disponíveis para download no site.

Agora que temos a estrutura de configuração pronta (e testada), podemos continuar a escrever scripts para tarefas.

Nós escrevemos roteiros

Talvez, uma vez, em uma galáxia muito, muito distante, construir projetos (incluindo aqueles em .net) a partir da linha de comando fosse uma dor de cabeça. Agora você pode construir, testar e publicar o projeto em 3 times:

dotnet build
dotnet test
dotnet pack

Naturalmente, existem algumas nuances pelas quais complicaremos um pouco os comandos.

  1. Queremos uma compilação de lançamento, não uma compilação de depuração, então adicionamos a cada comando -c Release
  2. Ao testar, queremos coletar dados de cobertura de código, então precisamos incluir um analisador de cobertura nas bibliotecas de teste:
    1. Adicione o pacote a todas as bibliotecas de teste coverlet.msbuild: dotnet add package coverlet.msbuild da pasta do projeto
    2. Adicionar ao comando de execução de teste /p:CollectCoverage=true
    3. Adicione uma chave à configuração da tarefa de teste para obter resultados de cobertura (veja abaixo)
  3. Ao compactar o código em pacotes nuget, defina o diretório de saída para os pacotes: -o .

Coletando dados de cobertura de código

Depois de executar os testes, o Coverlet imprime as estatísticas de execução no console:

Calculating coverage result...
  Generating report 'C:Usersxxxsourcereposmy-projectmyProject.testscoverage.json'

+-------------+--------+--------+--------+
| Module      | Line   | Branch | Method |
+-------------+--------+--------+--------+
| project 1   | 83,24% | 66,66% | 92,1%  |
+-------------+--------+--------+--------+
| project 2   | 87,5%  | 50%    | 100%   |
+-------------+--------+--------+--------+
| project 3   | 100%   | 83,33% | 100%   |
+-------------+--------+--------+--------+

+---------+--------+--------+--------+
|         | Line   | Branch | Method |
+---------+--------+--------+--------+
| Total   | 84,27% | 65,76% | 92,94% |
+---------+--------+--------+--------+
| Average | 90,24% | 66,66% | 97,36% |
+---------+--------+--------+--------+

O GitLab permite que você especifique uma expressão regular para obter estatísticas, que podem ser obtidas na forma de um emblema. A expressão regular é especificada nas configurações da tarefa com a chave coverage; a expressão deve conter um grupo de captura, cujo valor será passado para o badge:

test and cover job:
  # snip
  coverage: /|s*Totals*|s*(d+[,.]d+%)/

Aqui obtemos estatísticas de uma linha com cobertura total da linha.

Publicar pacotes e documentação

Ambas as ações estão programadas para a última etapa do pipeline - já que a montagem e os testes passaram, podemos compartilhar nossos desenvolvimentos com o mundo.

Primeiro, considere publicar na fonte do pacote:

  1. Se o projeto não tiver um arquivo de configuração nuget (nuget.config), crie um novo: dotnet new nugetconfig

    Para que: a imagem pode não ter acesso de gravação às configurações globais (usuário e máquina). Para não pegar erros, simplesmente criamos uma nova configuração local e trabalhamos com ela.

  2. Vamos adicionar uma nova fonte de pacote à configuração local: nuget sources add -name <name> -source <url> -username <organization> -password <gitlab variable> -configfile nuget.config -StorePasswordInClearText
    1. name - nome da fonte local, não crítico
    2. url - URL da fonte da etapa "Preparação de contas", p. 6
    3. organization - nome da organização no Azure DevOps
    4. gitlab variable - o nome da variável com o token de acesso adicionado ao GitLab ("Preparando contas", p. 11). Naturalmente, no formato $variableName
    5. -StorePasswordInClearText - um hack para contornar o erro de acesso negado (Eu não sou o primeiro a pisar neste ancinho)
    6. Em caso de erros, pode ser útil adicionar -verbosity detailed
  3. Enviando o pacote para a fonte: nuget push -source <name> -skipduplicate -apikey <key> *.nupkg
    1. Enviamos todos os pacotes do diretório atual, então *.nupkg.
    2. name - do passo acima.
    3. key - qualquer linha. No Azure DevOps, na janela Conectar ao feed, o exemplo é sempre a linha az.
    4. -skipduplicate - ao tentar enviar um pacote já existente sem esta chave, a fonte retornará um erro 409 Conflict; com a tecla, o envio será ignorado.

Agora vamos configurar a criação da documentação:

  1. Primeiro, no repositório, na ramificação master, inicializamos o projeto docfx. Para fazer isso, execute o comando da raiz docfx init e defina interativamente os principais parâmetros para a documentação de construção. Descrição detalhada da configuração mínima do projeto aqui.
    1. Ao configurar, é importante especificar o diretório de saída ..public - O GitLab, por padrão, leva o conteúdo da pasta pública na raiz do repositório como uma fonte para as páginas. Porque o projeto estará localizado em uma pasta aninhada no repositório - adicione uma saída ao nível acima no caminho.
  2. Vamos enviar as alterações para o GitLab.
  3. Adicionar uma tarefa à configuração do pipeline pages (palavra reservada para tarefas de publicação de sites no GitLab Pages):
    1. Roteiro:
      1. nuget install docfx.console -version 2.51.0 - instalar docfx; a versão é especificada para garantir que os caminhos de instalação do pacote estejam corretos.
      2. .docfx.console.2.51.0toolsdocfx.exe .docfx_projectdocfx.json - coleta de documentação
    2. Artefatos do nó:

pages:
  # snip
  artifacts:
    paths:
      - public

Digressão lírica sobre docfx

Anteriormente, ao configurar um projeto, eu especificava a fonte do código para a documentação como um arquivo de solução. A principal desvantagem é que a documentação também é criada para projetos de teste. Caso isso não seja necessário, você pode definir esse valor para o nó metadata.src:

{
  "metadata": [
    {
      "src": [
        {
          "src": "../",
          "files": [
            "**/*.csproj"
          ],
          "exclude":[
            "*.tests*/**"
          ]
        }
      ],
      // --- snip ---
    },
    // --- snip ---
  ],
  // --- snip ---
}

  1. metadata.src.src: "../" - subimos um nível em relação ao local docfx.json, porque em padrões, pesquisar na árvore de diretórios não funciona.
  2. metadata.src.files: ["**/*.csproj"] - um padrão global, coletamos todos os projetos C # de todos os diretórios.
  3. metadata.src.exclude: ["*.tests*/**"] - padrão global, exclua tudo das pastas com .tests no nome

Subtotal

Uma configuração tão simples pode ser criada em apenas meia hora e algumas xícaras de café, o que permitirá verificar se o código foi construído e os testes foram aprovados, criar um novo pacote, atualizar a documentação e agradar aos olhos com belos badges no README do projeto a cada requisição de merge e envio ao master.

Final .gitlab-ci.yml

image: mcr.microsoft.com/dotnet/core/sdk:3.1

before_script:
  - $PSVersionTable.PSVersion
  - dotnet --version
  - nuget help | select-string Version

stages:
  - build
  - test
  - deploy

build job:
  stage: build
  script:
    - dotnet build -c Release
  tags:
    - windows
  only:
    - merge_requests
    - master
  artifacts:
    paths:
      - your/path/to/binaries

test and cover job:
  stage: test
  tags:
    - windows
  script:
    - dotnet test -c Release /p:CollectCoverage=true
  coverage: /|s*Totals*|s*(d+[,.]d+%)/
  only:
    - merge_requests
    - master

pack and deploy job:
  stage: deploy
  tags:
    - windows
  script:
    - dotnet pack -c Release -o .
    - dotnet new nugetconfig
    - nuget sources add -name feedName -source https://pkgs.dev.azure.com/your-organization/_packaging/your-feed/nuget/v3/index.json -username your-organization -password $nugetFeedToken -configfile nuget.config -StorePasswordInClearText
    - nuget push -source feedName -skipduplicate -apikey az *.nupkg
  only:
    - master

pages:
  tags:
    - windows
  stage: deploy
  script:
    - nuget install docfx.console -version 2.51.0
    - $env:path = "$env:path;$($(get-location).Path)"
    - .docfx.console.2.51.0toolsdocfx.exe .docfxdocfx.json
  artifacts:
    paths:
      - public
  only:
    - master

Falando em insígnias

Por causa deles, afinal, tudo começou!

Badges com status de pipeline e cobertura de código estão disponíveis no GitLab nas configurações de CI/CD no bloco de pipelines Gtntral:

Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

Criei um crachá com um link para a documentação da plataforma escudos.io - tudo é bastante simples lá, você pode criar seu próprio crachá e recebê-lo por meio de um pedido.

![Пример с Shields.io](https://img.shields.io/badge/custom-badge-blue)

Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

O Azure DevOps Artifacts também permite criar crachás para pacotes com a versão mais recente. Para fazer isso, na fonte do site Azure DevOps, você precisa clicar em Criar crachá para o pacote selecionado e copiar a marcação de remarcação:

Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

Um guia para CI/CD no GitLab para o iniciante (quase) absoluto

Adicionando beleza

Destacando fragmentos de configuração comuns

Enquanto escrevia a configuração e pesquisava a documentação, encontrei um recurso interessante do YAML - a reutilização de fragmentos.

Como você pode ver nas configurações da tarefa, todas elas exigem a tag windows no executor e são acionados quando uma solicitação de mesclagem é enviada ao mestre/criado (exceto documentação). Vamos adicionar isso ao fragmento que vamos reutilizar:

.common_tags: &common_tags
  tags:
    - windows
.common_only: &common_only
  only:
    - merge_requests
    - master

E agora podemos inserir o fragmento declarado anteriormente na descrição da tarefa:

build job:
  <<: *common_tags
  <<: *common_only

Os nomes dos fragmentos devem começar com um ponto, para não serem interpretados como uma tarefa.

Controle de versão do pacote

Ao criar um pacote, o compilador verifica as opções da linha de comando e, na ausência delas, os arquivos do projeto; quando encontra um nó Versão, assume seu valor como a versão do pacote que está sendo construído. Acontece que, para construir um pacote com uma nova versão, você precisa atualizá-lo no arquivo do projeto ou passá-lo como um argumento de linha de comando.

Vamos adicionar mais uma lista de desejos - deixe os dois números menores na versão serem o ano e a data de criação do pacote e adicione versões de pré-lançamento. Claro, você pode adicionar esses dados ao arquivo do projeto e verificar antes de cada envio - mas também pode fazer isso no pipeline, coletando a versão do pacote do contexto e passando-a pelo argumento da linha de comando.

Vamos concordar que se a mensagem de commit contiver uma linha como release (v./ver./version) <version number> (rev./revision <revision>)?, então vamos pegar a versão do pacote desta linha, complementá-la com a data atual e passá-la como argumento para o comando dotnet pack. Na ausência de fila, simplesmente não coletaremos o pacote.

O script a seguir resolve esse problema:

# регулярное выражение для поиска строки с версией
$rx = "releases+(v.?|ver.?|version)s*(?<maj>d+)(?<min>.d+)?(?<rel>.d+)?s*((rev.?|revision)?s+(?<rev>[a-zA-Z0-9-_]+))?"
# ищем строку в сообщении коммита, передаваемом в одной из предопределяемых GitLab'ом переменных
$found = $env:CI_COMMIT_MESSAGE -match $rx
# совпадений нет - выходим
if (!$found) { Write-Output "no release info found, aborting"; exit }
# извлекаем мажорную и минорную версии
$maj = $matches['maj']
$min = $matches['min']
# если строка содержит номер релиза - используем его, иначе - текущий год
if ($matches.ContainsKey('rel')) { $rel = $matches['rel'] } else { $rel = ".$(get-date -format "yyyy")" }
# в качестве номера сборки - текущие месяц и день
$bld = $(get-date -format "MMdd")
# если есть данные по пререлизной версии - включаем их в версию
if ($matches.ContainsKey('rev')) { $rev = "-$($matches['rev'])" } else { $rev = '' }
# собираем единую строку версии
$version = "$maj$min$rel.$bld$rev"
# собираем пакеты
dotnet pack -c Release -o . /p:Version=$version

Adicionando um script a uma tarefa pack and deploy job e observe a montagem de pacotes estritamente na presença de uma determinada string na mensagem de confirmação.

No total

Depois de passar cerca de meia hora ou uma hora escrevendo a configuração, depurando no powershell local e, possivelmente, algumas inicializações malsucedidas, obtivemos uma configuração simples para automatizar tarefas de rotina.

Obviamente, o GitLab CI / CD é muito mais extenso e multifacetado do que pode parecer depois de ler este guia - isso está completamente errado. lá mesmo Auto DevOps épermitindo

detectar, construir, testar, implantar e monitorar automaticamente seus aplicativos

Agora os planos são configurar um pipeline para implantação de aplicativos no Azure, usando o Pulumi e determinando automaticamente o ambiente de destino, que será abordado no próximo artigo.

Fonte: habr.com

Adicionar um comentário