Atualização do processo de CI / CD: teamcity

imagem
Este é o segundo artigo de uma série sobre a atualização de processos de CI / CD. Até esse momento, estavam sendo feitos preparativos para a criação de novas ferramentas, a saber: planejamento, comícios diários, resolução de divergências, em geral, tudo sem o qual não seria possível construir um processo de trabalho com competência. E agora, todas as questões foram resolvidas, estamos confiantes de que podemos continuar o desenvolvimento e nosso código não afundará no buraco negro no início do verão. 

Deixe-me lembrá-lo do índice da lista de artigos, bem como dos breves resultados da parte anterior.

Parte 1: o que é, por que não é, como planejar, um pouco de festa. Eu chamaria essa parte de quase técnica.
Parte 2: cidade da equipe.
Parte 3: implantação do polvo.
Parte 4: nos bastidores. Momentos desagradáveis, planos para o futuro, possivelmente FAQ. Provavelmente, também pode ser chamado de quase técnico.

Fornecemos ao cliente uma prova de conceito de um novo sistema de entrega de atualizações, identificamos as deficiências do sistema existente, selecionamos a base para o novo, fizemos um plano de transição e convertemos nosso repositório mercurial em git. Além disso, na parte anterior, descrevemos os recursos do projeto que afetarão todo o processo subsequente. 

Como mencionado anteriormente, a solução existente não atendia aos requisitos modernos. Inicialmente, muito provavelmente, uma compilação foi configurada no ccnet. A primeira compilação com a qual tudo começou (como um big bang, sim). Aparentemente, a pessoa que configurou tudo, pressionou ctrl + c, ctrl + v, corrigiu algumas linhas e recebeu uma nova configuração. E durante todo o tempo subsequente, isso foi feito um número suficiente de vezes, para que o código-fonte no servidor de construção ocupasse mais de 60G. E estas são apenas a fonte! E há logs, compilação de artefatos, arquivos temporários e assim por diante. Só isso me fez pensar. Observando o sistema antigo, era possível ver o seguinte: uma etapa de construção foi executada para cada módulo. De fato, o mesmo núcleo foi montado. E esse assembly foi armazenado para cada módulo (junto com a origem) no servidor.Os resultados da compilação (90% idênticos) foram inseridos nos repositórios locais (implantação do git) e, é claro, também foram substituídos. Era possível e necessário deixar isso. 

Configurações Gerais 


Nesse estágio, supõe-se que já haja uma cidade e um polvo configurados. No estágio de instalação e configuração, não paramos em detalhes. Por conveniência, anotamos o URL e o token de API do polvo na env teamcity, que, a propósito, para o projeto raiz tem a seguinte aparência:

imagem

env.apiUserName e env.apiUserPassword são acessos api ao usuário da teamcity (serão necessários mais tarde), env.buildPath e env .sourcePath - o caminho padrão para os arquivos de compilação e de origem, respectivamente, env.octoApiKey e env.octoUrl - o token e o URL do polvo. Eles ainda env.teamcityUrl acrescentou. Bem, env.tt.exe- caminho para o utilitário de transformação de texto. Este utilitário gera todas as configurações.

Dos plugins de terceiros, apenas a integração do Octopus Deploy está instalada. 

Para não sobrecarregar a enorme quantidade de texto, apenas as etapas em que há algo que vale a pena atenção serão examinadas em detalhes. Supõe-se que tudo o mais seja compreensível com base nos dados apresentados e no conhecimento do leitor. De qualquer forma, se você tiver alguma dúvida, ficarei feliz em respondê-las.

Detalhamento do projeto, controle de versão, nomes


O resultado foi um esquema de projeto (como uma imagem, porque há um problema com a exibição de uma lista multinível):
imagem

Versão dos pacotes da seguinte forma: major.minor.patch, em que major ainda é 1, menor - contador de compilação na configuração de compilação, contador de compilação de patch para a configuração Implantar (não necessário para a configuração Build, portanto, sempre 0).

Nota: a versão antiga é descrita aqui. Estamos redesenhando-o para que seja baseado na tag git.

imagem

Por exemplo, aqui 1 é maior, 95 é menor e 1 é patch.

No novo processo para módulos, haverá uma construção que será implantada em cada módulo. Ou seja, o código-fonte é armazenado em uma única cópia para cada ambiente, o resultado da compilação também é, pois é comum a todos os módulos. Configurações e bibliotecas exclusivas são empacotadas em um pacote individual no estágio de implantação. Isso usará efetivamente o espaço em disco e reduzirá o tempo de entrega de cada pacote.

No estágio de preparação, houve uma breve reunião separada sobre a convenção de nomeação de arquivos de configuração. Costumava ser (era apenas), mas nem sempre o mesmo. Além disso, o nome da configuração nem sempre contém informações suficientes. Como resultado, todos os nomes de configuração foram os seguintes:
ConfigurationType.Environment.ModName.configonde ConfigurationType pode ser AppSettings, Web etc. Ambiente - desenvolvimento, teste, preparação, produção. ModName é o nome exclusivo do módulo.

Módulos


Todos os projetos de módulos funcionam com o mesmo princípio. 

Todo ambiente possui uma configuração de compilação que:

  1. Executa restauração de nuget (instalador do NuGet, restauração de nuget)
  2. Gera configurações (linha de comando, transformação de texto)
  3. Solução Buildit (Visual studio sln)
  4. Pega os arquivos do env.buildPath no zip e os envia para o polvo (Octopus deploy: push packages)
  5. Criação de versão (sem implantação) (Octopus deploy create release)
  6. Redefine a versão do patch (PowerShell)

Também existem configurações de implantação que funcionam com base no modelo e fazem o seguinte:

  1. Pega as configurações geradas no estágio de compilação (etapa 2) (Octopus implementa pacotes push)
  2. Implantar a versão principal (criada na etapa 6 da compilação) (Octopus deploy: deploy release)
  3. Versão individual de implantação (criada na etapa 1 da configuração atual) (Octopus deploy: deploy release)
  4. Exibe uma lista de todos os domínios deste módulo no log (etapa para a conveniência do testador e desenvolvedor). (Powershell).

Para cada configuração de implantação, a configuração de compilação é adicionada à dependência. Isso possibilita iniciar automaticamente a compilação quando for implantada, se não for relevante, além da capacidade de redefinir a versão do patch.

Deploy_all configuration. De fato, essa é uma cadeia de construção que descreve que você primeiro precisa executar a construção, se não for relevante, e depois instalar simultaneamente todos os modos.

É algo parecido com isto:

imagem

Vejamos algumas das etapas com mais detalhes.

Configurações gerais


imagem

De incomum formato de número apenas compilação Será explicado mais tarde.

Build.env


imagem


De interesse aqui são: env.coreProjectName - definido para todo o projeto. Necessário para identificar o projeto no polvo.
env.Environment - definido para o subprojeto Módulos. É necessário selecionar as configurações corretas, dependendo do ambiente.
env.octoChannel - o canal no polvo no qual o pacote cai. O mesmo que ambiente .
env.serviceName é o nome da solução. Basicamente, a variável é adicionada para facilitar a visualização.
env.tenantRoleTag - tag de inquilino no polvo. Mais detalhes na seção de polvo.

Build.4


imagem

Adicione ao arquivo morto com o nome % env.serviceName%.% Build.number% .zip arquivos do diretório com o resultado da construção, excluindo todas as configurações e DLL da pasta bin / native. Os últimos foram adicionados manualmente ao servidor da Web uma vez e ninguém os tocará novamente. Se necessário, eles também serão atualizados manualmente (para isso, está planejado escrever um script separado, mas seremos honestos). Isso se deve ao fato de essas bibliotecas serem "mantidas" pelo pool do IIS e, para uma implantação bem-sucedida, ela deve ser interrompida e iniciada, o que leva algum tempo. Ao excluir essas bibliotecas da implantação, podemos pular a etapa de parar o pool, o que reduzirá o tempo da implantação e, consequentemente, o tempo de inatividade.

Build.5


imagem

Acho que tudo está claro aqui, exceto por que o campo Ambiente está vazio. Em que ambiente o pacote fica, o polvo toma uma decisão com base na tag de pré-lançamento (configurada nos canais). Essa tag está contida em % build.number% (o mesmo estágio na tela em Build.General). Portanto, neste caso, acabou sendo mais conveniente. Também vale a pena prestar atenção na caixa de seleção "Mostrar processo de implantação" . Se não estiver instalado, o timsity considerará a compilação bem-sucedida assim que o polvo começar (mas não terminar!) O trabalho. Ou seja, se a caixa de seleção não estiver instalada e algo der errado durante a fase de implantação - sem olhar para a interface do polvo, não saberemos.

Build.6


Nada incomum, apenas um script do PowerShell e informações da documentação da equipe da cidade.

$pair = "%env.apiUserName%:%env.apiUserPassword%"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$depUri="%env.teamcityUrl%/app/rest/buildTypes?locator=snapshotDependency:(from:(build:(id:%teamcity.build.id%)),includeInitial:false)"
# Get all dependencies of main build
$result = (Invoke-RestMethod -Headers @{'Origin'='http://localhost:8090'; "Authorization"="$basicAuthValue"} -Uri $depUri)
foreach ($i in $result.buildTypes.buildType.Count) { $buildId += $result.buildTypes.buildType.id }
$buildId = $buildId | Where-Object { $_ -ne 'Module_DeployAll' }
# Reset all child build counters to 1. This build counters are patch versions in every build. (1.build.patch)
for ($i=0; $i -lt $buildId.Count; $i++) {
  $buildCounterUri = "%env.teamcityUrl%/httpAuth/app/rest/buildTypes/"+$buildId[$i]+"/settings/buildNumberCounter"
  Invoke-RestMethod -Method Put -Headers @{'accept'='text/plain'; 'Origin'='http://localhost:8090'; "Authorization"="$basicAuthValue"} -Uri $buildCounterUri -ContentType "text/plain" -Body 1
}

Aqui precisamos de um usuário da API no teamcity (o ambiente é criado para ele). Efetuamos login, pegamos todas as configurações que dependem da configuração Build e redefinimos seu contador de build para 1. Isso é, de fato, para cada versão de patch, este é um indicador de quantas vezes a mesma build foi implantada para um módulo específico. Se não houver 1, significa que algo deu errado no processo de implantação ou funcionamento do módulo na versão atual e requer atenção.

Deploy.General


imagem

Formato da versão: 1.% dep.Module_Build.build.counter%.% Build.counter% -staging , em que
% dep.Module_Build.build.counter% é a variável de sistema teamcity cujo valor corresponde ao contador de compilação da configuração de compilação correspondente (deve ser adicionado a dependências). De fato, aqui 1 é a versão principal, % dep.Module_Build.build.counter% é menor e % build.counter% é patch. a preparação é uma tag de pré-lançamento.

Deploy.Env


imagem

Ao adicionar um novo módulo, apenas a configuração para sua implementação é adicionada e o valor da variável env.modName é indicado . Todas as outras variáveis ​​são herdadas dos projetos pais. A variável env.tenantModTag para um polvo é formada a partir de env.modName .

Deploy.2


imagem

Implante o pacote principal. 

Número da versão mais recente - use a versão mais recente disponível para este ambiente.
Etiqueta do inquilino - etiqueta do cliente / organização. Mais detalhes na seção de polvo.
Parâmetros cli adicionais. Aqui, indicamos o canal em que nosso pacote cairá, bem como parâmetros adicionais. Isso também será discutido separadamente na seção de polvos.

Implantar.3


Como Deploy.2, apenas um pacote de módulo individual é implantado.

Implantar.4


Esta etapa também será descrita em detalhes abaixo, porque recebe dados do polvo.

As configurações para o site da empresa e o módulo Especial são construídas com o mesmo princípio, e os principais pontos nelas são os mesmos, portanto, não vejo o objetivo de descrevê-las nos mesmos detalhes. Eles são um, eles não precisam ser implantados muitas vezes e, de fato, há restauração de pepitas, transformação de texto, msbuild, envio de polvo, lançamento de polvo, lançamento de polvo + implantação.

Saiba mais sobre configurações exclusivas. Para alguns mods, pode não haver ambientes (por exemplo, teste), eles devem ser implantados em outros servidores ou você deve definir manualmente o identificador do cliente (faça a configuração básica e altere alguns campos usando o PowerShell). Ou seja, eles funcionam com o mesmo princípio que os módulos principais. Sua singularidade reside no fato de que as etapas são adicionadas / alteradas para eles ou o servidor de implantação é alterado e elas não se encaixam no modelo, portanto, leva um pouco mais de tempo para criá-las. Felizmente, existem alguns deles.

Teamcity: Resumo


A implementação do teamcity permitiu uma abordagem mais otimizada para o processo de montagem do aplicativo. Agora, leva muito menos tempo: em vez de criar o mesmo código a cada vez, criamos uma vez. Também fazemos melhor uso do espaço em disco, tráfego de rede e tempo de computação. Anteriormente, o número de pacotes para implementação (repositórios com artefatos) era igual ao número de módulos. Cada embalagem pesava aproximadamente 100M na forma compactada. Agora temos o número de pacotes um a mais que o número de módulos, com um pacote pesando aproximadamente os mesmos 100M e o restante cerca de 500K. Além de uma interface mais amigável, logs convenientes e, o mais importante - reduzindo o tempo para manter o sistema de compilação e adicionar configurações. Agora, a adição de um novo módulo leva de 15 minutos a meia hora.

Separadamente, deve-se dizer sobre os modelos, pois é a padronização que nos permite economizar tempo na criação de novas configurações e em sua manutenção posterior. Todas as configurações para interagir com o polvo (implantar) são construídas com base em um único modelo. Em primeiro lugar, permite unificar e, portanto, simplificar o processo. Em segundo lugar, como já mencionado, economiza tempo adicionando novas configurações: conectamos um modelo, alteramos uma variável e é isso. E o mais importante, os modelos simplificam a manutenção. Todas as alterações feitas no modelo são herdadas por configurações baseadas nele. Portanto, se precisarmos adicionar uma etapa a todas as configurações de uma só vez, não precisamos clicar em todas, basta adicionar essa etapa ao modelo.

Naturalmente, o processo de configuração da cidade da equipe andava de mãos dadas com a configuração do polvo. É simplesmente impossível descrever em paralelo no texto, pois há uma grande chance de confusão. Portanto, a descrição foi compartilhada e, nesta parte, apenas as etapas para o fornecimento de IC são descritas. O processo de instalação do polvo será descrito a seguir.

All Articles