As expectativas das ferramentas de integração contínua (CI) e entrega contínua (CD) diferem entre equipes e organizações. Projetos pequenos requerem soluções de CI / CD relativamente simples, onde a simplicidade de configuração (com alguns padrões) é a chave para o sucesso. No entanto, equipes corporativas maduras têm processos mais complexos, com centenas de milhares de testes e pipelines de liberação avançada. A configuração como código (Configuration-as-code) é uma melhoria natural para essas equipes. Mas você precisa de uma ferramenta sofisticada para suportá-la.

Mesmo quando se pensa em equipes de pequeno a médio porte, se o número de membros da equipe cresce rápido, estamos lidando com um novo problema de coordenação e organização adequada, que também afeta o mundo do CI.

O Bamboo 6, introduz o suporte para configuração como código, com Java como a linguagem preferida para definir planos de build. Nas versões atuais, os já clientes podem usar uma nova abordagem de configuração como código para implantações, usar configurações YAML (se você não estiver familiarizado com Java, que é o foco deste Post), armazenando suas configurações codificadas nos repositórios e controlando as permissões nesses repositórios.

Então, agora a questão é: como as equipes e os administradores podem aproveitar melhor todo esse poder?

Eu tenho algumas dicas e sugestões para você. A maioria é destinada a usuários do dia a dia que criam planos e implantações. Mas não feche esta guia ainda, administradores do Bamboo - você também encontrará algumas informações úteis.

1. Aprenda exportando planos e implementações existentes do Bamboo para Especificações(Specs)

Se você já tiver uma instância do Bamboo com planos e implantações, a exportação acelerará seu processo de aprendizado e tornará sua experiência de migração perfeita. É um ponto de partida perfeito se você não sabe muito sobre as especificações (Specs) do Bamboo ou a configuração como código em geral.

Verifique a documentação sobre como exportar suas configurações existentes do Bamboo para Specs. No código gerado durante a exportação, você verá como a estrutura do Bamboo é representada por várias classes Java dedicadas e chamadas de método.

Se você ainda não tem planos do Bamboo e está apenas começando sua jornada com o Bamboo, o recurso de exportação ainda pode ser útil. Primeiro de tudo, você pode tentar criar um plano por meio da interface do usuário e exportá-lo para ter uma base de código funcional. Além disso, ele pode ser usado para ajudá-lo a descobrir como configurar áreas específicas do Bamboo via código. Se você souber onde ir na interface do usuário para aplicar as alterações, mas não tiver ideia de como refletir essas alterações no mundo das especificações, tente aplicá-las no navegador e exporte sua configuração.

Observe, no entanto, que qualquer conteúdo exportado não se parecerá com o que você deseja na forma final de suas especificações. É apenas algo para começar. A especificação gerada funcionará para que possa ser imediatamente confirmada em um repositório VCS para uso com as especificações armazenadas no Repositório. A partir daí, é uma questão de melhorias de código e refatoração.

2. Teste suas especificações(Specs)!

Um dos pontos fortes das especificações Java do Bamboo é que a validação offline está disponível gratuitamente. A validação local permite que você escreva testes unitários mais significativos para seu conteúdo. Simplesmente construir seu plano ou projeto de implantação executa a maioria das verificações. Além disso, testar sua configuração traz possibilidades como consistência em toda a empresa. Testes também podem ajudá-lo a validar a compatibilidade com políticas e estruturas organizacionais.

Há, no entanto, algo que você precisa estar ciente. Como a validação local está acontecendo off-line, algumas restrições do Bamboo não serão verificadas. Não é 100% garantido que os planos que passarem nos testes serão aceitos posteriormente pelo Bamboo. No entanto, muitos erros típicos e erros de programação podem ser detectados precocemente.

Aqui está um exemplo de código para demonstrar a verificação básica da sua especificação de plano:

import com.atlassian.bamboo.specs.api.builders.plan.Plan;
import com.atlassian.bamboo.specs.api.util.EntityPropertiesBuilders;
import org.junit.Test;

public class MyPlanTest {
    @Test
    public void testMyPlan() {
        final Plan myPlan = ...;

        // if validation fails, an exception will be thrown
        EntityPropertiesBuilders.build(myPlan);
    }
}

3. Se possível, mantenha as especificações do Bamboo e seu código de construção juntos

Esta é uma grande decisão a tomar: onde armazenar as especificações da Bamboo. Meu conselho é manter o código e a definição do IC juntos, pois eles estão intimamente acoplados. Considere as especificações da Bamboo como Makefile de nível mais alto para o seu código. Suas fontes, bem como as informações “como construí-lo”, “como testá-lo adequadamente” e até “como implantá-lo” devem ser co-localizados.

Dito isso, há casos em que você deseja separar suas especificações do bamboo da sua base de origem. Para dar alguns exemplos, um repositório contendo Bamboo Specs pode operar em vários repositórios de código-fonte, e nenhum deles pode tecnicamente “possuir” a definição do pipeline de construção. Ou, é mais eficiente manter permissões para um único repositório VCS.

Em última análise, você deve procurar usar fontes e especificações juntos, mas não forçar esta premissa. Geralmente, os pipelines de construção complexa são únicos e, portanto, é difícil dizer qual opção é objetivamente melhor.

4. Extrair progressivamente a configuração de compilação comum para componentes compartilhados

Ao migrar sua infraestrutura de criação para as especificações do Bamboo, você encontrará mais e mais semelhanças de configuração em seus planos de construção e publicação. O comportamento compartilhado não precisa ser repetido e as redundâncias podem ser removidas. Esse é um dos muitos benefícios de definir seus planos usando código! Essa abordagem permite que você extraia a lógica compartilhada em classes auxiliares / utilitárias e use padrões de programação como fábricas(factories) ou métodos de fábrica(factory).

O compartilhamento de partes da configuração nos planos reduz o custo de manutenção do código. Também torna mais fácil adicionar novos conteúdos às suas especificações de build no futuro. Ambos os fatores são críticos para a infraestrutura de build escalonável.

Para dar um exemplo: a equipe de desenvolvimento da Bamboo descobriu um padrão muito comum de testar plugins no núcleo do Bamboo. As tarefas que foram executadas para cada plugin pareciam quase idênticas. Foi quando decidimos criar helpers e utilitários para eles. Atualmente, definir um plugin para ser construído e testado contra o Bamboo requer a adição de apenas algumas linhas de código, com algumas opções de configuração disponíveis. Um bug descoberto para um plugin será automaticamente corrigido para todos eles. Alterações gerais na configuração do IC? Sem problemas! Aplicado em todos planos.

Nos planos de criação (build) e teste do Bamboo, compartilhamos a lógica de tarefas, projetos, planos, capacidades, variáveis, artefatos, notificações e muito mais!

Abaixo está um exemplo de uma classe e método auxiliares. Ele se baseia em um enum para garantir que apenas versões conhecidas e disponíveis do Node.js sejam usadas por nossas construções:

/**
 * Node.js task shortcuts.
 */
public class NodeTasks {
    /**
     * Node.js executables configured on our agents.
     */
    public enum NodeExecutable {
        NODE_8("Node.js 8"),
        NODE_6("Node.js 6"),
        NODE_4("Node.js 4");

        private final String executableLabel;

        NodeExecutable(String executableLabel) {
            this.executableLabel = executableLabel;
        }
    }

    public static NpmTask npmTask(String description,
                                  String command,
                                  NodeExecutable nodeExecutable) {
        return new NpmTask()
                .description(description)
                .nodeExecutable(nodeExecutable.executableLabel)
                .command(command);
    }

    ...
}

5. Maximize o poder do Java

Isso não pode ter sido enfatizado o suficiente, mas depois que você começar a "programar" / controlar seu IC, ficará difícil imaginar como alguém poderia viver sem ele. Escrevendo uma tarefa de script? Defina-a como um recurso e verifique se ele está disponível no caminho de classe quando o código é executado. Isto lhe dará o realce e a validação da sintaxe do seu IDE. Quer garantir que todos os planos criados por alguém sejam sempre testados? Use Java reflections para testes genéricos.

Abaixo está um exemplo de nossa classe de utilitários para definir tarefas de script, com o corpo de script retirado de recursos Java:

/**
 * Script task shortcuts.
 */
public class ScriptTasks {
    /**
     * Create a script task with inline body from a classpath available resource.
     */
    public static ScriptTask scriptTaskFromResource(Class<?> acquiringClass,
                                                    String resourceName,
                                                    String description) throws IOException {
        // search for the resource on the classpath under various paths
        final URL resource = ObjectUtils.firstNonNull(
                acquiringClass.getResource(resourceName),
                acquiringClass.getResource("/" + resourceName),
                acquiringClass.getResource(acquiringClass.getSimpleName() + "/" + resourceName));

        if (resource == null) {
            throw new NullPointerException("Script body not found for " + resourceName);
        }

        try (Scanner scanner = new Scanner(resource.openStream(), StandardCharsets.UTF_8.name())) {
            final String scriptBody = scanner.useDelimiter("\\A").next();
            return new ScriptTask()
                    .description(description)
                    .inlineBody(scriptBody);
        }
    }

    ...
}

6. Compartilhe partes de sua configuração entre as equipes

Se você estiver familiarizado com a cultura de DevOps, talvez já tenha encontrado equipes dedicadas responsáveis por manter a infraestrutura de criação e liberação para um grupo de equipes de desenvolvimento. Por exemplo, um pipeline de release compartilhado pode existir e deve ser usado em toda a empresa. Independentemente do motivo (manutenção, aspectos legais, o nome dele), o Bamboo Java Specs pode ajudá-lo.

Se você pode usar ferramentas como Maven ou Gradle. Tudo o que é necessário é ter dependências de artefatos mantidos por outras equipes. Esses artefatos podem produzir ou alterar suas especificações do Java no Bamboo de qualquer forma. Muitas possibilidades incluem o compartilhamento de classes auxiliares para adicionar requisitos, tarefas, estágios, variáveis ... até mesmo o código para configurar planos e implementações inteiras pode ser comum.

Além disso, não vamos esquecer as permissões. O conteúdo compartilhado pode ajudar você a configurar corretamente o esquema de permissão para o seu CI. Os utilitários comuns podem conceder permissões corretas a usuários, grupos e funções específicos para que cada equipe não precise se preocupar com a segurança no Bamboo.

7. Construa progressivamente uma estrutura para suas especificações à medida que você escala

Para muitas equipes, essa etapa pode parecer desnecessária e pode parecer um sintoma de engenharia excessiva, e isso é totalmente compreensível. Com a abordagem de pequenos módulos criados e mantidos independentemente, sua configuração de CI nunca vair exceder o tamanho para exigir uma camada adicional sobre o conjunto de ferramentas fornecido.

Mas imagine que você esteja construindo e testando um produto grande. O que você faria se precisasse testar centenas de dependências e opções de configuração? Vários sistemas operacionais, sistemas de gerenciamento de banco de dados, versões de bibliotecas… Manter uma matriz de construção multidimensional pode lhe dar dores de cabeça.

Quanto mais planos você tem, e quanto mais tempo leva para organizar suas especificações em um todo logicamente consistente, mais surge a necessidade de uma nova camada de abstração. Isso é o que eu chamo de "framework". Um pouco de inversão de controle, alguma lógica de processamento adicional, o que melhor lhe convier. Essa abordagem, na minha opinião, leva o aspecto de configuração como código do seu CI para um novo patamar. Paradoxalmente, você pode achar mais fácil controlar seu CI com “inversão de controle” no lugar.

Para dar um exemplo: a equipe de desenvolvimento do Bamboo, ao definir os planos que constroem e testam o Bamboo, surgiu com um conceito de “grupo de trabalho”. Grupos de trabalho ... bem, logicamente, agrupe os trabalhos relacionados uns com os outros (por exemplo, um grupo de tarefas que criam e testam plug-ins empacotados com o Bamboo). Os grupos de trabalho são definidos em um nível abstrato e não estão vinculados diretamente a nenhum "plano" de build.

Em um certo ponto, o framework entra em ação, o que combina grupos de trabalho em planos. Acionadores, repositórios e configurações de notificação são validados e mesclados para formar uma definição completa do plano. Grupos de trabalho definidos desta maneira podem ser passados entre planos de acordo com nossas necessidades mais livremente. Em um certo ponto, isso nos permitiu mesclar muitos planos (demais ...) juntos e simplificar uma configuração de CI excessivamente complexa.

"Configuration-as-code" tornou muito mais fácil mover blocos de construção, e é por isso que eu encorajo você a experimentar nesta área se quiser.

8. Use especificações armazenadas no repositório para log de auditoria refinado e controle de acesso delegado

Se você configurar as especificações do Bamboo armazenadas no repositório, descobrirá muitas melhorias de disponibilidade disponíveis para sua configuração de CI*.

Para melhorar a rastreabilidade, configure as especificações armazenadas no repositório como a interação principal da sua equipe com a Bamboo. Você pode restringir possíveis maneiras de os usuários alterarem os planos do Bamboo, não permitindo o acesso à UI para eles, deixando as especificações(Specs) do Bamboo como a única opção. Independentemente de como isso soa ruim, simplifica imediatamente muitas coisas, incluindo o gerenciamento de permissões do Bamboo. A acessibilidade pode ser controlada no nível do repositório (ou seja, somente usuários autorizados a submeter alterações ao repositório de Specs podem efetivamente fazer alterações no Bamboo), enquanto no próprio Bamboo apenas alguns esquemas de permissão precisam ser configurados (por exemplo, quais repositórios terão acesso a quais componentes do Bamboo).

Somente a mudança acima lhe dará o benefício de um log de auditoria alternativo e claro - via o histórico de commits do seu repositório. Além disso, com as especificações armazenadas no repositório em vigor, você pode configurar seu host VCS para permitir somente mudanças através de pull requests aprovados, para ter ainda mais controle sobre o conteúdo do Bamboo. Nunca mais se preocupe com modificações indesejadas e não detectadas em seu pipeline de CI / CD!

* Seguir esta rota significa que você perderá o acesso ao mecanismo de aprendizado sugerido na "Dica 1", acima. Por isso, recomendo ser razoável com limitações.

Configuração-como-código para a vitória

Se você nunca tentou configurar seu CI/CD via código-fonte, pode parecer um pouco estranho no começo. É uma questão de exploração e familiaridade suficientes para começar a otimizar sua configuração de CI para manutenção e escalabilidade. Espero que as dicas que eu forneci ajudem você a trabalhar mais rápido. Se você tiver experiência com configuração como código, espero que as dicas aqui trarão ao menos algumas novas ideias para melhorar seu pipeline de CI e a base de código de especificações.

A equipe de desenvolvimento do Bamboo aprendeu muito em todo o processo de desenvolvimento das especificações de Java do Bamboo. Temos migrado constantemente nosso próprio canal de desenvolvimento para o Specs, o que nos deu uma ótima oportunidade de aprender e melhorar (com um loop de feedback bastante rápido!). É por isso que acredito que as lições que aprendemos ajudarão você em sua jornada com o Bamboo.

Se o gerenciamento do seu pipeline de entrega contínua com configuração como código parece bom, espere até ver tudo o que o Bamboo tem a oferecer.


Conheça mais sobre o Bamboo


Fonte: How to win at CI with configuration-as-code and Bamboo Specs


Gostou do post? Compartilhe e siga nossas Redes Sociais 


Posts