Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Ou como conseguir fermosos distintivos para o teu proxecto nunha noite de codificación relaxada

Probablemente, todos os desenvolvedores que teñan polo menos un proxecto de mascota nalgún momento teñan picazón por fermosos distintivos con estados, cobertura de código, versións de paquetes en nuget... E esta comezón levoume a escribir este artigo. No proceso de prepararme para escribilo, adquirei esta beleza nun dos meus proxectos:

Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Este artigo abordará a configuración básica da integración e entrega continuas dun proxecto de biblioteca de clases .Net Core en GitLab, publicando documentación en GitLab Pages e enviando paquetes recollidos a unha fonte privada en Azure DevOps.

Utilizouse VS Code coa extensión como ambiente de desenvolvemento Fluxo de traballo de GitLab (para validar o ficheiro de configuración directamente desde o contorno de desenvolvemento).

Breve introdución

CD é cando só empurraches, pero o cliente xa perdeu todo?

Que é CI/CD e por que é necesario? Podes buscalo facilmente en Google. Atopa documentación completa sobre a configuración de canalizacións en GitLab tamén fácil. Aquí describirei brevemente e, se é posible, sen fallos, o proceso do sistema desde a vista de paxaro:

  • o desenvolvedor envía unha confirmación ao repositorio, crea unha solicitude de combinación a través do sitio web, ou dalgún outro xeito explícita ou implícitamente lanza o pipeline,
  • desde a configuración, selecciónanse todas as tarefas cuxas condicións permiten que se lancen nun contexto determinado,
  • as tarefas organízanse segundo as súas etapas,
  • as etapas execútanse á súa vez - é dicir. paralelo todas as tarefas desta etapa están completadas,
  • se unha etapa falla (é dicir, polo menos unha das tarefas da etapa falla) - o gasoduto detense (case sempre),
  • se todas as etapas se completan con éxito, o gasoduto considérase exitoso.

Así temos:

  • pipeline é un conxunto de tarefas organizadas en etapas nas que podes montar, probar, empaquetar código, implementar a montaxe rematada nun servizo na nube, etc.
  • etapa (etapa) — unidade de organización da canalización, contén 1+ tarefa,
  • tarefa (traballo) é unha unidade de traballo nunha canalización. Consiste nun script (obrigatorio), condicións de lanzamento, configuración para publicar/cachear artefactos e moito máis.

En consecuencia, a tarefa á hora de configurar CI/CD redúcese a crear un conxunto de tarefas que implementen todas as accións necesarias para montar, probar e publicar código e artefactos.

Antes de comezar: por que?

  • Por que GitLab?

Porque cando xurdiu a necesidade de crear repositorios privados para proxectos de mascotas, pagábanse en GitHub, e eu era cobizoso. Os repositorios fixéronse gratuítos, pero de momento esta non é unha razón suficiente para que me pase a GitHub.

  • Por que non Azure DevOps Pipelines?

Porque a configuración é sinxela: nin sequera necesitas coñecementos sobre a liña de comandos. A integración con provedores externos de git (nun par de clics, importación de claves SSH para enviar commits ao repositorio) tamén se configura facilmente a canalización incluso sen un modelo.

Posición inicial: o que tes e o que queres

Temos:

  • repositorio en GitLab.

Queremos:

  • montaxe e probas automáticas para cada solicitude de combinación,
  • construír paquetes para cada solicitude de combinación e enviar ao mestre, sempre que exista unha liña determinada na mensaxe de confirmación,
  • enviar paquetes recollidos a un feed privado en Azure DevOps,
  • montaxe de documentación e publicación en GitLab Pages,
  • distintivos!11

Os requisitos descritos encaixan naturalmente no seguinte modelo de canalización:

  • Fase 1 - montaxe
    • Recollemos o código, publicamos os ficheiros de saída como artefactos
  • Fase 2 - proba
    • Recibimos artefactos da fase de construción, realizamos probas, recompilamos datos de cobertura de código
  • Fase 3 - envío
    • Tarefa 1: recolle o paquete nuget e envíao a Azure DevOps
    • Tarefa 2: montamos o sitio desde xmldoc no código fonte e publicamos en GitLab Pages

Comecemos!

Montaxe da configuración

Elaboración de contas

  1. Crea unha conta en Microsoft Azure

  2. Ir a Azure DevOps

  3. Crea un novo proxecto

    1. Nome - calquera
    2. Visibilidade - calquera
      Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  4. Cando premes no botón Crear, crearase o proxecto e dirixirase á súa páxina. Nesta páxina podes desactivar funcións innecesarias accedendo á configuración do proxecto (ligazón inferior na lista da esquerda -> Visión xeral -> Bloque Azure DevOps Services)
    Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  5. Vaia a Atrifacts, fai clic en Crear feed

    1. Introduza o nome da fonte
    2. Seleccione visibilidade
    3. Desmarque a caixa Incluír paquetes de fontes públicas comúnspara que a fonte non se converta nun vertedoiro dun clon nuget
      Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  6. Fai clic en Conectar para alimentar, selecciona Visual Studio, copia a fonte desde o bloque Configuración da máquina
    Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  7. Vaia á configuración da conta, seleccione Token de acceso persoal
    Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  8. Crea un novo token de acceso

    1. Nome - arbitrario
    2. Organización - actual
    3. Prazo de vixencia: máximo 1 ano
    4. Ámbito: embalaxe/lectura e escritura
      Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  9. Copia o token creado - despois de pechar a xanela modal o valor non estará dispoñible

  10. Vaia á configuración do repositorio en GitLab, seleccione Configuración de CI/CD
    Unha guía de CI/CD en GitLab para o (case) principiante absoluto

  11. Expande o bloque Variables e engade un novo

    1. Nome: calquera sen espazos (estará dispoñible no shell de comandos)
    2. O valor é o token de acceso do paso 9
    3. Seleccione a variable Máscara
      Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Isto completa a configuración preliminar.

Preparación do marco de configuración

Por defecto, o ficheiro usado para configurar CI/CD en GitLab é .gitlab-ci.yml desde a raíz do repositorio. Podes configurar un camiño personalizado a este ficheiro na configuración do repositorio, pero neste caso non é necesario.

Como se pode ver na extensión, o ficheiro contén configuración no formato YAML. A documentación describe en detalle que chaves se poden conter no nivel superior da configuración e en cada un dos niveis aniñados.

En primeiro lugar, imos engadir ao ficheiro de configuración unha ligazón á imaxe do docker na que se executarán as tarefas. Para iso atopamos Páxina de imaxes .Net Core en Docker Hub. En GitHub Hai unha guía detallada sobre que imaxe escoller para diferentes tarefas. Unha imaxe con .Net Core 3.1 é adecuada para que poidamos construír, así que non dubide en engadila como primeira liña á configuración

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

Agora, cando inicie a canalización, a imaxe especificada descargarase do repositorio de imaxes de Microsoft, no que se executarán todas as tarefas da configuración.

O seguinte paso é engadir etapa's. Por defecto, GitLab define 5 etapas:

  • .pre - realizado en todas as fases,
  • .post - realizado despois de todas as etapas,
  • build - primeiro despois .pre etapa,
  • test - segunda fase,
  • deploy - terceira etapa.

Non obstante, nada lle impide declaralos explícitamente. A orde na que se enumeran os pasos afecta á orde en que se completan. Para completar a configuración, agreguemos:

stages:
  - build
  - test
  - deploy

Para a depuración, ten sentido obter información sobre o ambiente no que se executan as tarefas. Engademos un conxunto global de comandos que se executarán antes de usar cada tarefa before_script:

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

Queda por engadir polo menos unha tarefa para que cando se envíen as confirmacións, o pipeline se inicie. De momento, engadimos unha tarefa baleira para a demostración:

dummy job:
  script:
    - echo ok

Comezamos a validación, recibimos unha mensaxe de que todo está ben, commit, push, miramos os resultados no sitio... E recibimos un erro de script - bash: .PSVersion: command not found. WTF?

Todo é lóxico: por defecto, os corredores (responsables de executar scripts de tarefas e proporcionados por GitLab) usan bash para executar comandos. Podes corrixir isto indicando explícitamente na descrición da tarefa que etiquetas debe ter o executador de pipeline:

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

Genial! Agora o gasoduto está funcionando.

Un lector atento, repetindo estes pasos, notará que a tarefa está completada na etapa test, aínda que non especificamos o escenario. Como podes adiviñar, test é o paso predeterminado.

Continuemos creando o esqueleto de configuración engadindo todas as tarefas descritas anteriormente:

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

Temos unha canalización non especialmente funcional, pero non obstante correcta.

Configurando disparadores

Debido ao feito de que non se especifican filtros de activación para ningunha das tarefas, a canalización farase totalmente execútase cada vez que se envían commits ao repositorio. Dado que este non é o comportamento desexado en xeral, configuraremos filtros de activación para as tarefas.

Os filtros pódense configurar en dous formatos: só/excepto и regras. En resumo, only/except permite configurar filtros por disparadores (merge_request, por exemplo: configura a tarefa para que se execute cada vez que se crea unha solicitude de combinación e cada vez que se envían confirmacións á rama que é a orixe da solicitude de combinación) e os nomes das ramas (incluído o uso de expresións regulares); rules permite personalizar un conxunto de condicións e, opcionalmente, cambiar a condición de execución da tarefa dependendo do éxito das tarefas anteriores (when en GitLab CI/CD).

Lembremos o conxunto de requisitos: montaxe e probas só para solicitudes de fusión, empaquetado e envío a Azure DevOps, para solicitudes de fusión e envíos ao mestre, xeración de documentación, aos envíos ao mestre.

En primeiro lugar, imos configurar unha tarefa de ensamblaxe de código engadindo unha regra de activación que só desencadea unha solicitude de combinación:

build job:
  # snip
  only:
    - merge_request

Agora imos configurar a tarefa de empaquetado para activar unha solicitude de combinación e engadir commits ao mestre:

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

Como podes ver, todo é sinxelo e directo.

Tamén pode configurar a tarefa para que se active só se se crea unha solicitude de combinación cun destino ou rama de orixe específica:

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

En condicións pódese usar variables listadas aquí; regras rules non compatible coas normas only/except.

Configurando o aforro de artefactos

Mentres se executa a tarefa build job teremos artefactos de construción creados que poidan ser reutilizados en tarefas posteriores. Para iso, cómpre engadir camiños á configuración da tarefa, ficheiros ao longo dos cales terán que ser gardados e reutilizados en tarefas posteriores, á clave artifacts:

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

As rutas admiten comodíns, o que sen dúbida fai que sexan máis fáciles de establecer.

Se unha tarefa crea artefactos, cada tarefa posterior poderá acceder a eles; situaranse polos mesmos camiños en relación á raíz do repositorio ao longo da cal se recolleron da tarefa orixinal. Os artefactos tamén están dispoñibles para descargar no sitio web.

Agora que temos un marco de configuración listo (e verificado), podemos pasar a escribir scripts para tarefas.

Escribimos guións

Quizais, noutrora, nunha galaxia moi, moi lonxe, construír proxectos (incluídos os .net) desde a liña de comandos era unha dor. Agora podes montar, probar e publicar o proxecto en 3 equipos:

dotnet build
dotnet test
dotnet pack

Por suposto, hai algúns matices polos que complicaremos un pouco os comandos.

  1. Queremos unha versión, non unha depuración, compilación, polo que engadimos a cada comando -c Release
  2. Durante a proba, queremos recoller datos sobre a cobertura do código, polo que necesitamos conectar un analizador de cobertura ás bibliotecas de proba:
    1. O paquete debería engadirse a todas as bibliotecas de proba coverlet.msbuild: dotnet add package coverlet.msbuild dende o cartafol do proxecto
    2. Engadir ao comando de inicio de proba /p:CollectCoverage=true
    3. Engademos unha clave á configuración da tarefa de proba para obter resultados de cobertura (ver a continuación)
  3. Ao empaquetar o código en paquetes nuget, estableceremos o directorio de saída para os paquetes: -o .

Recopilación de datos de cobertura de código

Despois de executar as probas, Coverlet mostra as estatísticas de inicio na consola:

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% |
+---------+--------+--------+--------+

GitLab permítelle especificar unha expresión regular para obter estatísticas, que logo se poden obter en forma de distintivo. A expresión regular especifícase na configuración da tarefa coa tecla coverage; a expresión debe conter un grupo de captura, cuxo valor se transferirá ao distintivo:

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

Aquí obtemos estatísticas dunha liña cunha cobertura total por liñas.

Publicamos paquetes e documentación

Temos ambas accións asignadas á última etapa do gasoduto: xa que pasaron a montaxe e as probas, podemos compartir os nosos desenvolvementos co mundo.

En primeiro lugar, vexamos a publicación na fonte do paquete:

  1. Se o proxecto non ten un ficheiro de configuración nuget (nuget.config), crea un novo: dotnet new nugetconfig

    Para qué: É posible que a imaxe non teña acceso de escritura ás configuracións globais (usuario e máquina). Para non detectar erros, simplemente imos crear unha nova configuración local e traballar con ela.

  2. Engademos unha nova fonte de paquete á configuración local: nuget sources add -name <name> -source <url> -username <organization> -password <gitlab variable> -configfile nuget.config -StorePasswordInClearText
    1. name - nome da fonte local, non importante
    2. url — URL da fonte da fase "Preparación de contas", paso 6
    3. organization - nome da organización en Azure DevOps
    4. gitlab variable — o nome da variable co token de acceso engadido a GitLab (“Preparación de contas”, p. 11). Por suposto, no formato $variableName
    5. -StorePasswordInClearText — un hack para evitar o erro de acceso denegado (Non son o primeiro en pisar este rastrillo)
    6. En caso de erros pode ser útil engadir -verbosity detailed
  3. Enviamos o paquete á fonte: nuget push -source <name> -skipduplicate -apikey <key> *.nupkg
    1. Enviamos todos os paquetes desde o directorio actual, polo tanto *.nupkg.
    2. name - do paso anterior.
    3. key - Calquera liña. En Azure DevOps, na xanela Conectar ao feed, a liña de exemplo está sempre az.
    4. -skipduplicate — se tenta enviar un paquete xa existente sen esta chave, a fonte devolverá un erro 409 Conflict; coa chave, o envío será omitido.

Agora imos configurar a creación de documentación:

  1. Para comezar, no repositorio, na rama mestra, inicializamos o proxecto docfx. Para iso, cómpre executar o comando desde a raíz docfx init e establecer de forma interactiva os parámetros clave para a montaxe da documentación. Descrición detallada da configuración mínima do proxecto aquí.
    1. Ao configurar, é importante especificar o directorio de saída ..public - GitLab toma de forma predeterminada o contido do cartafol público na raíz do repositorio como fonte de Páxinas. Porque o proxecto estará situado nun cartafol anidado no repositorio - engade unha saída ao seguinte nivel ao camiño.
  2. Impulsemos os cambios en GitLab.
  3. Engade unha tarefa á configuración da canalización pages (palabra reservada para tarefas de publicación de sitios en páxinas de GitLab):
    1. Guión:
      1. nuget install docfx.console -version 2.51.0 - instalar docfx; A versión ofrécese para garantir que as rutas de instalación do paquete son correctas.
      2. .docfx.console.2.51.0toolsdocfx.exe .docfx_projectdocfx.json - Recollida de documentación
    2. Nodo de artefactos:

pages:
  # snip
  artifacts:
    paths:
      - public

Digresión lírica sobre docfx

Anteriormente, ao configurar un proxecto, especificaba a fonte do código para a documentación como ficheiro de solución. A principal desvantaxe é que tamén se crea documentación para proxectos de proba. Se isto non é necesario, pode definir este valor para o nodo metadata.src:

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

  1. metadata.src.src: "../" - subir un nivel en relación á localización docfx.json, porque A busca na árbore de directorios non funciona en patróns.
  2. metadata.src.files: ["**/*.csproj"] — un patrón global, recollemos todos os proxectos C# de todos os directorios.
  3. metadata.src.exclude: ["*.tests*/**"] - patrón global, excluír todo dos cartafoles con .tests No título

Subtotal

Esta configuración sinxela pódese crear en literalmente media hora e un par de cuncas de café, o que lle permitirá comprobar con cada solicitude de fusión e enviarlle ao mestre que o código se está a construír e as probas están a pasar, montando un novo paquete, actualizando a documentación e agradando a vista con fermosos distintivos no proxecto README.

.gitlab-ci.yml final

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 de distintivos

Foi polo seu ben que todo comezou!

As insignias con estados de canalización e cobertura de código están dispoñibles en GitLab na configuración de CI/CD no bloque de canalizacións Gtntral:

Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Creei un distintivo cunha ligazón á documentación da plataforma escudos.io — todo é moi sinxelo alí, podes crear o teu propio distintivo e recibilo mediante unha solicitude.

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

Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Azure DevOps Artifacts tamén che permite crear distintivos para paquetes que indican a versión máis recente. Para iso, na fonte do sitio web de Azure DevOps, cómpre facer clic en Crear distintivo para o paquete seleccionado e copiar a marca de rebaixa:

Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Unha guía de CI/CD en GitLab para o (case) principiante absoluto

Engadindo beleza

Destacamos fragmentos de configuración comúns

Mentres escribía a configuración e buscaba a documentación, atopeime cunha función YAML interesante: reutilizar fragmentos.

Como podes ver na configuración de tarefas, todos requiren unha etiqueta windows desde o corredor, e se activan cando se envía unha solicitude de combinación ao mestre/creado (excepto para a documentación). Engadimos isto ao fragmento que imos reutilizar:

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

E agora podemos inserir o fragmento anunciado anteriormente na descrición da tarefa:

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

Os nomes dos fragmentos deben comezar cun punto para evitar ser interpretados como unha tarefa.

Versionado de paquetes

Ao crear un paquete, o compilador verifica os interruptores da liña de comandos e, na súa ausencia, os ficheiros do proxecto; Despois de atopar o nodo Versión, toma o seu valor como a versión do paquete que se está a construír. Resulta que para construír un paquete cunha nova versión, cómpre actualizalo no ficheiro do proxecto ou pasalo como argumento de liña de comandos.

Engademos un desexo máis: deixe que os dous números máis baixos da versión sexan o ano e a data de compilación do paquete, e engade versións previas. Por suposto, podes engadir estes datos ao ficheiro do proxecto e comprobalos antes de cada envío, pero tamén podes facelo no proceso, recollendo a versión do paquete do contexto e pasándoa a través dun argumento da liña de comandos.

Aceptemos que se a mensaxe de confirmación contén unha liña como release (v./ver./version) <version number> (rev./revision <revision>)?, entón colleremos a versión do paquete desta liña, completaremos coa data actual e pasaremos como argumento ao comando dotnet pack. A falta dunha liña, simplemente non montaremos o paquete.

O seguinte script resolve este 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

Engadir un script a unha tarefa pack and deploy job e observe estrictamente a montaxe de paquetes se a liña especificada está presente na mensaxe de confirmación.

En total

Despois de pasar entre media hora e unha hora escribindo a configuración, depurando no Powershell local e, posiblemente, un par de lanzamentos sen éxito, recibimos unha configuración sinxela para automatizar tarefas rutineiras.

Por suposto, GitLab CI/CD é moito máis extenso e multifacético do que podería parecer despois de ler esta guía. iso non é certo en absoluto. Incluso hai Auto DevOps sipermitindo

detectar, construír, probar, implantar e supervisar as súas aplicacións automaticamente

Agora os plans son configurar unha canalización para a implantación de aplicacións en Azure, usando Pulumi e detectando automaticamente o ambiente de destino, que se tratará no seguinte artigo.

Fonte: www.habr.com

Engadir un comentario