Já falamos várias vezes sobre a nossa ferramenta GitOps. , e desta vez gostaríamos de compartilhar a experiência de construir um site com a documentação do próprio projeto — (sua versão em russo é — ). Este é um site estático comum, mas sua construção é interessante porque foi feita com um número dinâmico de artefatos.

Não vamos entrar nos detalhes da estrutura do site: geração de um menu geral para todas as versões, páginas com informações sobre lançamentos, etc. — em vez disso, vamos focar nas questões e peculiaridades da construção dinâmica e um pouco nos processos associados de CI/CD.
Introdução: como o site é estruturado
Começando pelo fato de que a documentação do werf é armazenada juntamente com seu código. Isso impõe certos requisitos ao desenvolvimento, que geralmente vão além do escopo deste artigo, mas pelo menos podemos dizer que:
- Novas funcionalidades do werf não devem ser lançadas sem atualização da documentação e, inversamente, qualquer alteração na documentação implica o lançamento de uma nova versão do werf;
- O projeto tem um desenvolvimento bastante intenso: novas versões podem ser lançadas várias vezes ao dia;
- Qualquer operação manual para a implementação do site com uma nova versão da documentação é, no mínimo, cansativa;
- O projeto adota a abordagem de versão semântica , com 5 canais de estabilidade. O processo de lançamento envolve a passagem sequencial das versões pelos canais, em ordem crescente de estabilidade: de alpha a rock-solid;
- O site tem uma versão em russo, que "vive e se desenvolve" (ou seja, cujo conteúdo é atualizado) paralelamente à versão principal (ou seja, a versão em inglês).
Para ocultar toda essa "cozinha interna" do usuário e oferecer o que "simplesmente funciona", criamos uma ferramenta separada para instalação e atualização do werf seja . Basta indicar o número da versão e o canal de estabilidade que você está disposto a usar, e o multiwerf verificará se há uma nova versão no canal e a baixará, se necessário.
No menu de seleção de versões do site, as últimas versões do werf estão disponíveis em cada canal. Por padrão, no endereço abre-se a versão do canal mais estável para o último lançamento — que também é indexada pelos mecanismos de busca. A documentação para o canal está disponível em endereços separados (por exemplo, para o lançamento beta 1.0).
Portanto, as versões disponíveis para o site são:
- raiz (aberta por padrão),
- para cada canal ativo de atualizações de cada lançamento (por exemplo, ).
Para gerar uma versão específica do site, normalmente é suficiente compilar utilizando , executando no diretório /docs do repositório werf o comando apropriado (jekyll build), antes de alternar para a tag Git da versão necessária.
Resta apenas adicionar que:
- a própria utilidade (werf) é utilizada para a construção;
- os processos CI/CD são baseados no GitLab CI;
- e tudo isso, é claro, funciona no Kubernetes.
Tarefas
Agora vamos formular tarefas que considerem toda a especificidade descrita:
- Após a mudança de versão do werf em qualquer canal de atualizações, a documentação no site deve ser atualizada automaticamente..
- Para desenvolvimento, é necessário ter a capacidade de visualizar versões preliminares do site às vezes..
A recompilação do site deve ser realizada após a mudança de versão em qualquer canal a partir das respectivas tags Git, mas no processo de construção da imagem, teremos as seguintes características:
- Como a lista de versões nos canais muda, apenas a documentação para os canais onde a versão mudou precisa ser recompilada. Afinal, recompilar tudo novamente não é muito elegante.
- O próprio conjunto de canais para lançamentos pode mudar. Em algum momento, por exemplo, pode não haver versão nos canais mais estáveis do lançamento early-access 1.1, mas com o tempo elas aparecerão — não vamos mudar essa compilação manualmente, certo?
Assim, a construção depende de dados externos que mudam..
Implementação
Escolha da abordagem
Como uma opção, cada versão necessária pode ser executada como um pod separado no Kubernetes. Essa alternativa implica em um maior número de objetos no cluster, que aumentará com a quantidade de lançamentos estáveis do werf. E isso, por sua vez, exige uma manutenção mais complexa: para cada versão, há um servidor HTTP próprio, com uma carga pequena. Claro, isso também gera maiores custos de recursos.
Optamos pelo caminho de compilar todas as versões necessárias em uma única imagem.A estática compilada de todas as versões do site está contida em um contêiner com NGINX, e o tráfego para o Deployment correspondente chega através do NGINX Ingress. Uma estrutura simples — aplicação sem estado — permite fácil escalabilidade do Deployment (dependendo da carga) utilizando os próprios recursos do Kubernetes.
Para ser mais preciso, estamos criando duas imagens: uma para o ambiente de produção e outra adicional para o ambiente de desenvolvimento. A imagem adicional é usada (executada) apenas no ambiente de desenvolvimento junto com a principal e contém a versão do site do commit de revisão, com roteamento entre elas realizado por meio de recursos Ingress.
werf vs git clone e artefatos
Como já mencionado, para gerar a estática do site para uma versão específica da documentação, é necessário realizar a construção, mudando para a tag correspondente do repositório. Poderíamos fazer isso clonando o repositório toda vez que fizermos uma construção, escolhendo as tags correspondentes da lista. No entanto, isso é uma operação bastante exigente em recursos e, além disso, requer a escrita de instruções não triviais... Outro grande inconveniente é que, com essa abordagem, não há possibilidade de armazenar em cache durante a construção.
Aqui entra em cena a própria ferramenta werf, que implementa caching inteligente e permite usar . O uso do werf para adicionar código de repositórios acelerará significativamente a construção, pois o werf, na verdade, clona o repositório uma única vez e depois faz um apenas fetch quando necessário. Além disso, ao adicionar dados do repositório, podemos selecionar apenas os diretórios necessários (no nosso caso, é o diretório docs), o que reduz significativamente o volume de dados adicionados.
Uma vez que o Jekyll é uma ferramenta projetada para compilar estática e não é necessária na imagem final, seria lógico realizar a compilação no , e importar para a imagem final apenas o resultado da compilação. Escrevemos werf.yaml.
Assim, decidimos que vamos compilar cada versão em um artefato werf separado. No entanto, nós
não sabemos quantos desses artefatos haverá durante a construção , por isso não podemos escrever uma configuração de construção fixa (estritamente falando, podemos, mas isso não será muito eficiente).O werf permite usar
modelos Go ), o que dá a possibilidade dewerf.yamlgerar a configuração "em tempo real" dependendo de dados externos (o que é necessário!). Os dados externos, neste caso, são as informações sobre versões e lançamentos, com base nas quais montamos a quantidade necessária de artefatos e obtemos, como resultado, duas imagens: werf-doc werf-dev e werf-dev para ser executado em diferentes ambientes.
Os dados externos são passados através de variáveis de ambiente. Aqui está sua composição:
-
LANÇAMENTOS— uma linha com a lista de lançamentos e a versão atual correspondente do werf, no formato de lista separada por espaços%. Exemplo:1.0%v1.0.4-beta.20 -
CANAIS— uma linha com a lista de canais e a versão atual correspondente do werf, no formato de lista separada por espaços%. Exemplo:1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22 -
VERSÃO_RAIZ— versão do lançamento do werf para exibir por padrão no site (não é sempre necessário mostrar a documentação para o número de lançamento mais alto). Exemplo:v1.0.4-beta.20 -
REVIEW_SHA— hash do commit review, do qual a versão precisa ser construída para o ambiente de teste.
Essas variáveis serão preenchidas no pipeline GitLab CI, e como exatamente — está escrito abaixo.
Primeiro, para conveniência, vamos definir em werf.yaml variáveis de modelo Go, atribuindo valores das variáveis de ambiente:
{{ $_ := set . "WerfVersions" (cat (env "CANAIS") (env "LANÇAMENTOS") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "VERSÃO_RAIZ") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }} A descrição do artefato para a compilação da versão estática do site é basicamente a mesma para todos os casos necessários (incluindo a geração da versão raiz, assim como a versão para o ambiente dev). Portanto, vamos movê-la para um bloco separado utilizando a função definir — para reutilização posterior através de include. O template receberá os seguintes argumentos:
-
Versão— versão gerada (nome da tag); -
Canal— nome do canal de atualizações para o qual o artefato é gerado; -
Commit— hash do commit, se o artefato é gerado para o commit de revisão; - contexto.
Descrição do template do artefato
{{- define "doc_artifact" -}}
{{- $Root := index . "Root" -}}
artifact: doc-{{ .Channel }}
from: jekyll/builder:3
mount:
- from: build_dir
to: /usr/local/bundle
ansible:
install:
- shell: |
export PATH=/usr/jekyll/bin/:$PATH
- name: "Instalar Dependências"
shell: bundle install
args:
executable: /bin/bash
chdir: /app/docs
beforeSetup:
{{- if .Commit }}
- shell: echo "Revisar SHA - {{ .Commit }}."
{{- end }}
{{- if eq .Channel "root" }}
- name: "releases.yml HASH: {{ $Root.Files.Get "releases.yml" | sha256sum }}"
copy:
content: |
{{ $Root.Files.Get "releases.yml" | indent 8 }}
dest: /app/docs/_data/releases.yml
{{- else }}
- file:
path: /app/docs/_data/releases.yml
state: touch
{{- end }}
- file:
path: "{{`{{ item }}`}}"
state: directory
mode: 0777
with_items:
- /app/main_site/
- /app/ru_site/
- file:
dest: /app/docs/pages_ru/cli
state: link
src: /app/docs/pages/cli
- shell: |
echo -e "werfVersion: {{ .Version }}nwerfChannel: {{ .Channel }}" > /tmp/_config_additional.yml
export PATH=/usr/jekyll/bin/:$PATH
{{- if and (ne .Version "review") (ne .Channel "root") }}
{{- $_ := set . "BaseURL" ( printf "v%s" .Channel ) }}
{{- else if ne .Channel "root" }}
{{- $_ := set . "BaseURL" .Channel }}
{{- end }}
jekyll build -s /app/docs -d /app/_main_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/tmp/_config_additional.yml
jekyll build -s /app/docs -d /app/_ru_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/app/docs/_config_ru.yml,/tmp/_config_additional.yml
args:
executable: /bin/bash
chdir: /app/docs
git:
- url: https://github.com/flant/werf.git
to: /app/
owner: jekyll
group: jekyll
{{- if .Commit }}
commit: {{ .Commit }}
{{- else }}
tag: {{ .Version }}
{{- end }}
stageDependencies:
install: ['docs/Gemfile','docs/Gemfile.lock']
beforeSetup: '**/*'
includePaths: 'docs'
excludePaths: '**/*.sh'
{{- end }} O nome do artefato deve ser único. Podemos alcançar isso, por exemplo, adicionando o nome do canal (valor da variável .Channel) como um sufixo no nome do artefato: artifact: doc-{{ .Channel }}. No entanto, é necessário entender que ao importar dos artefatos será preciso referir a esses mesmos nomes.
Ao descrever o artefato, é utilizada a função do werf chamada . A montagem especificando o diretório de serviço build_dir permite manter o cache do Jekyll entre as execuções do pipeline, o que acelera significativamente a recompilação.
Você também pode notar o uso do arquivo releases.yml — este é um arquivo YAML com dados sobre lançamentos, solicitado com (artefato obtido durante a execução do pipeline). Ele é necessário na compilação do site, mas no contexto do artigo, nos interessa especialmente porque o seu estado afeta a recompilação de apenas um artefato — o artefato da versão raiz do site (nos outros artefatos, não é necessário).
Isso é implementado com o operador condicional if dos templates Go e a construção {{ $Root.Files.Get "releases.yml" | sha256sum }} na etapa . Funciona da seguinte maneira: ao compor o artefato para a versão raiz (variável .Channel igual a root) o hash do arquivo releases.yml afeta a assinatura de toda a etapa, pois é um componente do nome da tarefa Ansible (parâmetro nome). Portanto, ao alterar o conteúdo do arquivo releases.yml , o artefato correspondente será recomposto.
Observe também o trabalho com repositórios externos. No imagem do artefato de , é adicionado apenas o diretório /docs, e dependendo dos parâmetros passados, dados do respectivo tag ou commit de revisão são adicionados automaticamente.
Para usar o modelo do artefato para gerar uma descrição do artefato das versões de canais e lançamentos passados, organizamos um loop pela variável .WerfVersions em werf.yaml:
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}} Como o loop gerará vários artefatos (esperamos que sim), é necessário considerar um delimitador entre eles — a sequência --- (mais detalhes sobre a sintaxe do arquivo de configuração estão em ). Como definido anteriormente, ao chamar o modelo no loop, passamos os parâmetros de versão, URL e contexto raiz.
De maneira similar, mas sem loop, chamamos o modelo do artefato para 'casos especiais': para a versão raiz, bem como para a versão do commit de revisão:
{{ dict "Version" .WerfRootVersion "Channel" "root" "Root" $Root | include "doc_artifact" }}
---
{{- if .WerfReviewCommit }}
{{ dict "Version" "review" "Channel" "review" "Commit" .WerfReviewCommit "Root" $Root | include "doc_artifact" }}
{{- end }} Observe que o artefato para o commit de revisão será construído somente se a variável .WerfReviewCommit.
Os artefatos estão prontos — hora de lidar com a importação!
A imagem final, destinada a ser executada no Kubernetes, é um NGINX comum, ao qual foi adicionado um arquivo de configuração do servidor nginx.conf e estática dos artefatos. Além do artefato da versão raiz do site, precisamos repetir o loop pela variável .WerfVersions para importar os artefatos das versões de canais e lançamentos + obedecer a regra de nomeação dos artefatos que adotamos anteriormente. Como cada artefato armazena versões do site em dois idiomas, vamos importá-los para os locais designados pela configuração.
Descrição da imagem final werf-doc
imagem: werf-doc
origem: nginx:stable-alpine
ansible:
configurar:
- nome: "Configurar /etc/nginx/nginx.conf"
copiar:
conteúdo: |
{{ .Files.Get ".werf/nginx.conf" | indent 8 }}
destino: /etc/nginx/nginx.conf
- arquivo:
caminho: "{{`{{ item }}`}}"
estado: diretório
modo: 0777
com_itens:
- /app/main_site/assets
- /app/ru_site/assets
importar:
- artefato: doc-root
adicionar: /app/_main_site
para: /app/main_site
antes: configurar
- artefato: doc-root
adicionar: /app/_ru_site
para: /app/ru_site
antes: configurar
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artefato: doc-{{ $Channel }}
adicionar: /app/_main_site
para: /app/main_site/v{{ $Channel }}
antes: configurar
{{ end -}}
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artefato: doc-{{ $Channel }}
adicionar: /app/_ru_site
para: /app/ru_site/v{{ $Channel }}
antes: configurar
{{ end -}}A imagem adicional, que é executada junto com a principal no contêiner de desenvolvimento, contém apenas duas versões do site: a versão do commit de revisão e a versão raiz do site (onde estão os assets comuns e, se você se lembrar, os dados sobre os lançamentos). Assim, a imagem adicional diferirá apenas na seção de importação (e, claro, no nome):
imagem: werf-dev
...
importar:
- artefato: doc-root
adicionar: /app/_main_site
para: /app/main_site
antes: configurar
- artefato: doc-root
adicionar: /app/_ru_site
para: /app/ru_site
antes: configurar
{{- if .WerfReviewCommit }}
- artefato: doc-review
adicionar: /app/_main_site
para: /app/main_site/review
antes: configurar
- artefato: doc-review
adicionar: /app/_ru_site
para: /app/ru_site/review
antes: configurar
{{- end }} Como já mencionado anteriormente, o artefato para o commit de revisão será gerado apenas durante a ativação da variável de ambiente definida REVIEW_SHA. Poderíamos não gerar a imagem werf-dev, se não houver a variável de ambiente REVIEW_SHA, mas para que das imagens Docker no werf funcione para a imagem werf-dev, iremos mantê-la em processo apenas com o artefato da versão raiz (afinal, já está construído), para simplificar a estrutura do pipeline.
A construção está pronta! Vamos para o CI/CD e detalhes importantes.
Pipeline no GitLab CI e características da construção dinâmica
Ao iniciar a construção, precisamos definir as variáveis de ambiente utilizadas em werf.yaml. Isso não se aplica à variável REVIEW_SHA, que será definida ao chamar o pipeline por meio do webhook do GitHub.
A formação dos dados externos necessários será realizada em um script Bash generate_artifacts, que gerará dois artefatos no pipeline do GitLab:
- arquivo
releases.ymlcom dados sobre os lançamentos, - arquivo
common_envs.sh, contendo variáveis de ambiente para exportação.
Conteúdo do arquivo generate_artifacts você encontrará em nosso . A obtenção dos dados em si não é o objetivo do artigo, mas o arquivo common_envs.sh é importante para nós, pois a operação do werf depende dele. Um exemplo do seu conteúdo:
export RELEASES='1.0%v1.0.6-4'
export CHANNELS='1.0-alpha%v1.0.7-1 1.0-beta%v1.0.7-1 1.0-ea%v1.0.6-4 1.0-stable%v1.0.6-4 1.0-rock-solid%v1.0.6-4'
export ROOT_VERSION='v1.0.6-4' A saída de tal script pode ser usada, por exemplo, com uma função Bash source.
Agora vem a parte mais interessante. Para que tanto a construção quanto a implantação do aplicativo funcionem corretamente, é necessário garantir que werf.yaml era seja idêntico pelo menos dentro de um pipeline. Se essa condição não for atendida, as assinaturas das etapas que o werf calcula durante a construção e, por exemplo, a implantação, serão diferentes. Isso resultará em um erro de implantação, pois a imagem necessária para a implantação estará ausente.
Em outras palavras, se durante a construção da imagem do site as informações sobre lançamentos e versões forem uma, mas no momento da implantação sair uma nova versão e as variáveis de ambiente tiverem outros valores, a implantação terminará com erro: pois o artefato da nova versão ainda não foi construído.
Se a geração werf.yaml depende de dados externos (por exemplo, uma lista de versões atuais, como no nosso caso), então a composição e os valores desses dados devem ser fixados dentro do pipeline. Isso é especialmente importante se os parâmetros externos mudam com bastante frequência.
Nós iremos obter e fixar dados externos na primeira etapa do pipeline no GitLab (Prebuild) e passá-los adiante como artefatos do GitLab CI. Isso permitirá que tarefas do pipeline (construção, implantação, limpeza) sejam executadas e reiniciadas com a mesma configuração em werf.yaml.
Conteúdo da etapa Prebuild do arquivo .gitlab-ci.yml:
Prebuild:
stage: prebuild
script:
- bash .\/generate_artifacts 1> common_envs.sh
- cat .\/common_envs.sh
artifacts:
paths:
- releases.yml
- common_envs.sh
expire_in: 2 weeksTendo fixado os dados externos no artefato, podemos executar a construção e a implantação usando estágios padrão do pipeline do GitLab CI: Build e Deploy. O próprio pipeline é acionado por hooks do repositório do GitHub werf (isto é, quando há alterações no repositório do GitHub). Os dados para isso podem ser obtidos nas propriedades do projeto GitLab na seção CI / CD Settings -> Pipeline triggers, e então criaremos um Webhook correspondente no GitHub (Settings -> Webhooks).
A etapa de construção ficará assim:
Build:
stage: build
script:
- type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- source common_envs.sh
- werf build-and-publish --stages-storage :local
except:
refs:
- schedules
dependencies:
- Prebuild O GitLab adicionará dois artefatos da etapa de construção do estágio Prebuild, por isso exportamos variáveis com os dados de entrada preparados usando a construção source common_envs.sh. Iniciamos a fase de construção em todos os casos, exceto quando o pipeline é acionado pelo agendamento. No agendamento, teremos um pipeline para limpeza - neste caso, não é necessário realizar a construção.
Na fase de deploy, descreveremos duas tarefas - separadamente para o deploy nos ambientes de produção e desenvolvimento, utilizando um modelo YAML:
.base_deploy: &base_deploy
stage: deploy
script:
- type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- source common_envs.sh
- werf deploy --stages-storage :local
dependencies:
- Prebuild
except:
refs:
- schedules
Deploy para Produção:
<<: *base_deploy
variables:
WERF_KUBE_CONTEXT: prod
environment:
name: production
url: werf.io
only:
refs:
- master
except:
variables:
- $REVIEW_SHA
refs:
- schedules
Deploy para Teste:
<<: *base_deploy
variables:
WERF_KUBE_CONTEXT: dev
environment:
name: test
url: werf.test.flant.com
except:
refs:
- schedules
only:
variables:
- $REVIEW_SHA As tarefas diferem basicamente apenas na indicação do contexto do cluster, para o qual o werf deve executar o deploy (WERF_KUBE_CONTEXT), e na configuração das variáveis de ambiente do ambiente (environment.name e environment.url), que são então utilizadas nos modelos do Helm chart. Não iremos apresentar o conteúdo dos modelos, pois não há nada de interessante para o tema em questão, mas você pode encontrá-los no .
Toque Final
Como as versões do werf são lançadas com frequência, novas imagens estarão sempre sendo construídas e o Docker Registry ficará em constante crescimento. Portanto, é essencial configurar a limpeza automática das imagens de acordo com as políticas. Isso é muito fácil de fazer.
Para implementar isso, será necessário:
- Adicionar uma fase de limpeza em
.gitlab-ci.yml; - Adicionar a execução periódica da tarefa de limpeza;
- Configurar uma variável de ambiente com o token de acesso para gravação.
Adicionamos a fase de limpeza em .gitlab-ci.yml:
Cleanup:
stage: cleanup
script:
- type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- source common_envs.sh
- docker login -u nobody -p ${WERF_IMAGES_CLEANUP_PASSWORD} ${WERF_IMAGES_REPO}
- werf cleanup --stages-storage :local
only:
refs:
- schedules
Quase tudo que vimos anteriormente - apenas para a limpeza, é necessário se autenticar no Docker Registry com um token que tenha permissão para excluir imagens do Docker Registry (o token automaticamente gerado para as tarefas do GitLab CI não tem essas permissões). O token deve ser criado previamente no GitLab e seu valor deve ser especificado na variável de ambiente WERF_IMAGES_CLEANUP_PASSWORD Apache Traffic Control (Configurações de CI/CD -> Variáveis).
A adição da tarefa de limpeza com o cronograma necessário é feita em CI/CD ->
Cronogramas.
Tudo: o projeto no Docker Registry não crescerá mais constantemente devido a imagens não utilizadas.
Para concluir a parte prática, lembre-se de que os listagens completas do artigo estão disponíveis em :
- ;
- .
Resultado
- Obtivemos uma estrutura de build lógica: um artefato por versão.
- A construção é universal e não requer modificações manuais ao lançar novas versões do werf: a documentação no site é atualizada automaticamente.
- Dois imagens são construídas para diferentes cenários.
- Funciona rapidamente, pois utiliza cache ao máximo — ao lançar uma nova versão do werf ou ao chamar o webhook do GitHub para um commit de revisão — apenas o artefato correspondente à versão alterada é reconstruído.
- Não é necessário se preocupar em remover imagens não utilizadas: a limpeza por políticas do werf manterá a ordem no Docker Registry.
Como resultado, obtemos um serviço de "monitoramento como serviço", automatizado na linha de produção de integração contínua. O desenvolvedor ou testador precisa apenas definir a lista de métricas em um arquivo JSON, e tudo o mais acontece automaticamente. Obtemos um controle de qualidade transparente dos lançamentos: todas as notificações sobre desempenho, consumo de recursos ou regressões arquitetônicas.
- O uso do werf permite que a construção funcione rapidamente graças ao cache, tanto da própria build, quanto ao cache durante a interação com repositórios externos.
- Trabalhar com repositórios Git externos elimina a necessidade de clonar o repositório completamente toda vez, ou de reinventar a roda com uma lógica otimizada sofisticada. O werf utiliza cache e faz o clone apenas uma vez, e depois utiliza
fetche apenas conforme necessário. - A possibilidade de usar templates Go no arquivo de configuração da construção
werf.yamlpermite descrever uma construção cujo resultado depende de dados externos. - O uso de montagem no werf acelera significativamente a construção de artefatos — com o cache sendo compartilhado por todos os pipelines.
- O werf permite configurar facilmente a limpeza, o que é especialmente relevante em construções dinâmicas.
P.S.
Confira também em nosso blog:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
