Como posso testar uma alteração feita no Jenkinsfile localmente?

210

Ao escrever pipelines da jenkins, parece ser muito inconveniente confirmar cada nova alteração para verificar se funciona.

Existe uma maneira de executá-los localmente sem confirmar o código?

sorin
fonte

Respostas:

139

Você não pode executar o script Pipeline localmente, pois seu objetivo é criar scripts para o Jenkins. (Essa é uma das razões pelas quais é melhor manter seu Jenkinsfilecódigo curto e limitado que realmente lida com os recursos do Jenkins; sua lógica de compilação real deve ser tratada com processos externos ou ferramentas de compilação que você chama por uma linha shou batetapa).

Se você quiser testar uma mudança para Jenkinsfileviver, mas sem enviá- la, use o recurso Replay adicionado em 1.14

O JENKINS-33925 rastreia o desejado para uma estrutura de teste automatizada.

Jesse Glick
fonte
A postagem do blog diz que há um botão 'replay'. Alguma idéia de onde? Não consigo localizá-lo.
BoltzmannBrain
8
@BoltzmannBrain, vá para a página Jenkins do seu trabalho de construção. No lado esquerdo, você deve ver a lista de execuções anteriores da compilação. Quando você passa o mouse sobre um ID de execução de construção (por exemplo, "# 123") ou uma data de uma execução de construção, uma pequena seta para baixo aparece. Clicar nele revela um menu de contexto com a opção "Replay". A opção também está disponível na página de uma execução de construção.
Good Nerd Pride
2
O Concourse permite que você execute seus scripts locais em um servidor de construção de destino, para que você possa validar que ele também funcionará no servidor remoto antes de confirmar suas alterações. concourse.ci/fly-cli.html . O recurso de reprodução do Jenkins é algo análogo a isso, exceto que ele tem limitações e você deve criar uma compilação primeiro para reproduzi-la.
Md123 19/07
2
Você pode dar uma olhada neste projeto que visa fornecer o que você está procurando.
Romain
1
Dê uma olhada no JenkinsPipelineUnit ( github.com/jenkinsci/JenkinsPipelineUnit )
user864279
78

Eu tenho uma solução que funciona bem para mim. Ele consiste em um jenkins local em execução no docker e um gancho da web git para acionar o pipeline no jenkins local em cada consolidação. Você não precisa mais enviar para o seu repositório github ou bitbucket para testar o pipeline.

Isso foi testado apenas em um ambiente Linux.

É bastante simples fazer isso funcionar, embora essa instrução seja um pouco longa. A maioria das etapas está lá.

Isto é o que você precisa

  • Docker instalado e funcionando. Isso não faz parte desta instrução.
  • Um Jenkins rodando na janela de encaixe localmente. Explicou como abaixo.
    • Os direitos adequados (chave de acesso ssh) para o usuário do docker Jenkins local obter do seu repositório git local. Explicou como abaixo.
    • Um projeto de pipeline do Jenkins que é extraído do repositório git local. Explicado abaixo.
    • Um usuário git em seu Jenkins local com direitos mínimos. Explicado abaixo.
  • Um projeto git com um gancho da web pós-confirmação que aciona o projeto de pipeline. Explicado abaixo.

é assim que se faz

Jenkins Docker

Crie um arquivo chamado Dockerfile no lugar de sua escolha. Estou colocando em /opt/docker/jenkins/Dockerfilepreenchê-lo com isso:

FROM jenkins/jenkins:lts
USER root
RUN apt-get -y update && apt-get -y upgrade
# Your needed installations goes here
USER jenkins

Construa a imagem local_jenkins

Você precisará fazer isso apenas uma vez ou depois de adicionar algo ao Dockerfile.

$ docker build -t local_jenkins /opt/docker/jenkins/

Iniciar e reiniciar local_jenkins

De tempos em tempos, você deseja iniciar e reiniciar o jenkins facilmente. Por exemplo, após uma reinicialização da sua máquina. Para isso, criei um pseudônimo que coloquei .bash_aliasesna minha pasta pessoal.

$ echo "alias localjenkinsrestart='docker stop jenkins;docker rm jenkins;docker run --name jenkins -i -d -p 8787:8080 -p 50000:50000 -v /opt/docker/jenkins/jenkins_home:/var/jenkins_home:rw local_jenkins'" >> ~/.bash_aliases
$ source .bash_aliases  # To make it work

Verifique se a /opt/docker/jenkins/jenkins_homepasta existe e se você possui direitos de leitura e gravação.

Para iniciar ou reiniciar o seu jenkins, digite:

$ localjenkinsrestart

Tudo o que você faz no jenkins local será armazenado na pasta / opt / docker / jenkins / jenkins_home e preservado entre as reinicializações.

Crie uma chave de acesso ssh no docker jenkins

Esta é uma parte muito importante para que isso funcione. Primeiro, iniciamos o contêiner do docker e criamos um shell bash para ele:

$ localjenkinsrestart
$ docker exec -it jenkins /bin/bash

Agora você entrou no contêiner do docker, isso pode ser visto por algo como jenkins@e7b23bad10aa:/$no seu terminal. O hash após o @ certamente será diferente.

Crie a chave

jenkins@e7b23bad10aa:/$ ssh-keygen

Pressione enter em todas as perguntas até receber o prompt de volta

Copie a chave para o seu computador. No contêiner do docker, seu computador é 172.17.0.1, você deve se perguntar.

jenkins@e7b23bad10aa:/$ ssh-copy-id [email protected]

user = seu nome de usuário e 172.17.0.1 é o endereço IP do seu computador a partir do contêiner do docker.

Você precisará digitar sua senha neste momento.

Agora vamos tentar concluir o loop enviando ssh para o seu computador a partir do contêiner do docker.

jenkins@e7b23bad10aa:/$ ssh [email protected]

Desta vez, você não precisa digitar sua senha. Se o fizer, algo deu errado e você deve tentar novamente.

Agora você estará na pasta inicial do seu computador. Experimente lse dê uma olhada.

Não pare por aqui, pois temos uma cadeia de conchas ssh da qual precisamos sair.

$ exit
jenkins@e7b23bad10aa:/$ exit

Certo! Agora estamos de volta e prontos para continuar.

Instale seu Jenkins

Você encontrará o Jenkins local no navegador em http: // localhost: 8787 .

Na primeira vez em que você apontar o navegador para o Jenkins local, você será agraciado com um Assistente de Instalação. Os padrões são bons, mas certifique-se de instalar o plugin do pipeline durante a instalação.

Configure seu jenkins

É muito importante que você ative a segurança baseada em matriz em http: // localhost: 8787 / configureSecurity e conceda todos os direitos adicionando-se à matriz e marque todas as caixas. (Existe um ícone de marcar todas as caixas na extrema direita)

  • Selecione Jenkins’ own user databasecomo o domínio de segurança
  • Selecione Matrix-based securityna seção Autorização
  • Escreva seu nome de usuário no campo User/group to add:e clique no [ Add ]botão
  • Na tabela acima, seu nome de usuário deve aparecer com um ícone de pessoas ao lado. Se estiver cruzado, você digitou seu nome de usuário incorretamente.
  • Vá para a extrema direita da tabela e clique no botão de seleção de todos ou marque manualmente todas as caixas da sua linha.
  • Verifique se a caixa de seleção Prevent Cross Site Request Forgery exploitsestá desmarcada. (Como esse Jenkins só pode ser acessado no seu computador, isso não é um problema)
  • Clique [ Save ]e saia do Jenkins e faça o login novamente apenas para garantir que funcione. Caso contrário, é necessário recomeçar do zero e esvaziar a /opt/docker/jenkins/jenkins_homepasta antes de reiniciar

Adicione o usuário git

Precisamos permitir que nosso gancho git faça login no Jenkins local com direitos mínimos. Apenas ver e criar empregos é suficiente. Portanto, criamos um usuário chamado gitcom senha login.

Direcione seu navegador para http: // localhost: 8787 / securityRealm / addUser e adicione gitcomo nome de usuário e loginsenha. Clique em [ Create User ].

Adicione os direitos ao usuário git

Vá para a página http: // localhost: 8787 / configureSecurity no seu navegador. Inclua o usuário git na matriz:

  • Escreva gitno campo User/group to add:e clique em[ Add ]

Agora é hora de marcar as caixas para obter direitos mínimos para o usuário git. Apenas estes são necessários:

  • geral: ler
  • trabalho: construir
  • trabalho: descobrir
  • trabalho: ler

Verifique se a Prevent Cross Site Request Forgery exploitscaixa de seleção está desmarcada e clique em[ Save ]

Crie o projeto de pipeline

Assumimos que temos o nome de usuário usere nosso projeto habilitado para git com o qual Jenkinsfileele é chamado projecte está localizado em/home/user/projects/project

No seu http: // localhost: 8787 Jenkins, adicione um novo projeto de pipeline. Eu o nomeei hookpipeline para referência.

  • Clique no New Itemmenu Jenkins
  • Nomeie o projeto hookpipeline
  • Clique em Pipeline
  • Clique [ OK ]
  • Marque a caixa de seleção Poll SCMna seção Build Triggers. Deixe o agendamento em branco.
  • Na seção Pipeline:
    • selecionar Pipeline script from SCM
    • no Repository URLcampo insira[email protected]:projects/project/.git
    • no Script Pathcampo insiraJenkinsfile
  • Salve o projeto hookpipeline
  • Crie o hookpipeline manualmente uma vez, isso é necessário para que o Poll SCM comece a funcionar.

Crie o gancho git

Vá para a /home/user/projects/project/.git/hookspasta e crie um arquivo chamado post-commitque contém este:

#!/bin/sh
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD)
MASTERBRANCH='master'

curl -XPOST -u git:login http://localhost:8787/job/hookpipeline/build
echo "Build triggered successfully on branch: $BRANCHNAME"

Torne este arquivo executável:

$ chmod +x /home/user/projects/project/.git/hooks/post-commit

Teste o gancho pós-confirmação:

$ /home/user/projects/project/.git/hooks/post-commit

Faça check-in no Jenkins se o projeto do seu hookpipeline foi acionado.

Finalmente, faça algumas alterações arbitrárias no seu projeto, adicione as alterações e faça uma confirmação. Agora, isso acionará o pipeline em seu Jenkins local.

Dias felizes!

javabeangrinder
fonte
Eu tive que substituir docker build -t local_jenkins /opt/docker/jenkins/Dockerfilecom docker build -t local_jenkins /opt/docker/jenkinsporque Docker reclamou "incapaz de preparar contexto: contexto deve ser um diretório".
precisa
1
Estou recebendo esse erro no Mac. Alguém pode me ajudar com isso? >> ERRO: ssh: conectar ao host 172.17.0.1 porta 22: Conexão recusada -
Manoj Shrestha
@ManojShrestha: O ip 172.17.0.1 é o ip padrão da máquina que está executando os contêineres do docker. Você pode usar o ip de suas máquinas (MAC: s).
Javabeangrinder
@ManojShrestha: Você também pode tentar descobrir o ip do gateway de sua instalação como este: $ docker inspect jenkins | grep Gateway
javabeangrinder
2
Se o host do docker estiver instalado no macOS e você desejar fazer o login ssh nele a partir do contêiner do docker, você deve, em ssh [email protected] vez de usar o endereço IP. Também verifique se você ativou o recurso de login remoto a partir das Preferências MacOS Sistema -> menu de pasta compartilhada
Paolo Angioletti
61

TL; DR

Versão longa
O teste do Jenkins Pipeline se torna cada vez mais doloroso. Diferentemente da abordagem clássica de configuração da tarefa declarativa, em que o usuário estava limitado ao que a interface do usuário expôs o novo Jenkins Pipeline, é uma linguagem de programação completa para o processo de construção, onde você mistura a parte declarativa com seu próprio código. Como bons desenvolvedores, também queremos fazer alguns testes de unidade para esse tipo de código.

Há três etapas que você deve seguir ao desenvolver os pipelines Jenkins. A etapa 1. deve cobrir 80% dos casos de uso.

  1. Faça o máximo possível nos scripts de construção (por exemplo, Maven, Gradle, Gulp etc.). Em seguida, nos scripts de seu pipeline, basta chamar as tarefas de compilação na ordem certa. O pipeline de construção apenas orquestra e executa as tarefas de construção, mas não possui nenhuma lógica principal que precise de um teste especial.
  2. Se a regra anterior não puder ser totalmente aplicada, vá para as bibliotecas compartilhadas do pipeline, onde é possível desenvolver e testar a lógica personalizada por conta própria e integrá-las ao pipeline.
  3. Se todas as opções acima falharem, tente uma dessas bibliotecas que surgiram recentemente (março de 2017). Estrutura de teste da unidade de pipeline Jenkins ou unidade pipeline (exemplos). Desde 2018, também existe o Jenkinsfile Runner , um pacote para executar pipelines Jenkins a partir de uma ferramenta de linha de comando.

Exemplos

O repositório pipelineUnit GitHub contém alguns exemplos de Spock sobre como usar a estrutura de teste da Jenkins Pipeline Unit

Vadimo
fonte
1
Você também pode incluir uma breve comparação dessas duas bibliotecas?
sorin
24

Jenkins possui um recurso 'Replay', que permite reproduzir rapidamente um trabalho sem atualizar as fontes:

Recurso de repetição

AhmedDrira
fonte
1
Observe que ele aparece na página de construção, não no projeto ou na página de ramificação.
ArtOfWarfare 27/09/19
17

No momento da escrita (final de julho de 2017) com o plug-in Blue Ocean, é possível verificar a sintaxe de um pipeline declarativo diretamente no editor de pipeline visual . O editor funciona a partir da interface do usuário do Blue Ocean quando você clica em "configurar" apenas para projetos do github (este é um problema conhecido e eles estão trabalhando para que também funcionem no git etc.).

Mas, como explicado nesta pergunta, você pode abrir o editor navegando para:

[Jenkins URL]/blue/organizations/jenkins/pipeline-editor/

Em seguida, clique no meio da página e pressione Ctrl+S, isso abrirá uma área de texto onde você poderá colar um script declarativo de pipeline. Quando você clica em Atualizar , se houver um erro de sintaxe, o editor informará onde está o erro de sintaxe. Como nesta captura de tela:

Como teste rápido, digitei erroneamente "stepps" em vez de "steps"

Se não houver erro de sintaxe, a área de texto será fechada e a página visualizará seu pipeline. Não se preocupe, isso não salvará nada (se for um projeto do github, ele confirmará a alteração do Jenkinsfile).

Eu sou novo no Jenkins e isso é bastante útil, sem isso eu tive que cometer um arquivo Jenkins muitas vezes, até que funcione (muito irritante!). Espero que isto ajude. Felicidades.

firepol
fonte
2
Isso ocorre porque, a partir de 2017, Jenkins ainda tem como objetivo solucionar problemas de engenheiros de software apontar e clicar;) .... ... Pelo menos, o Atom possui um decente Groovy decente. É apenas Groovy, mas ajuda.
sorin
O editor com destaque de sintaxe também faz parte da interface clássica do jenkins.
Vadimo
6

Um pouco atrasado para a festa, mas foi por isso que escrevi jenny, uma pequena reimplementação de algumas etapas principais do arquivo Jenkins. ( https://github.com/bmustiata/jenny )

bogdan.mustiata
fonte
Sem ofensas, mas, a menos que você esteja constantemente atualizando suas coisas, será bastante inútil, pois a sintaxe do pipeline está em um estado constante de fluxo que parece no momento.
krad
Não pego. Pelo que vi até agora, a sintaxe do pipeline, é praticamente padronizada para as etapas básicas do pipeline ( jenkins.io/doc/pipeline/steps/workflow-basic-steps ). Estou usando-o há ~ 2 anos, sem encontrar nenhuma alteração incompatível com versões anteriores. Os plugins Jenkins não devem ser usados ​​imho, e a API em mudança pode ser abstraída usando comandos personalizados em bibliotecas compartilhadas, nas quais você terá garantias de API. Se você está falando sobre a sintaxe declarativa, isso pode ser verdade. Eu uso apenas a API programática em meus pipelines, e é isso que Jenny suporta. Rock solid :)
bogdan.mustiata
5

Tanto quanto eu sei este plugin Pipeline - é o "mecanismo" da nova mecânica do Jenkinsfile, por isso estou certo de que você poderia usá-lo para testar localmente seus scripts.

Não tenho certeza se são necessárias etapas adicionais quando você o copia em um arquivo Jenkins, no entanto, a sintaxe etc. deve ser exatamente a mesma.

Editar: encontrou a referência no "mecanismo", verifique esta descrição do recurso, último parágrafo, primeira entrada.

Dominik Gebhart
fonte
5

Na minha configuração de desenvolvimento - faltando um editor Groovy adequado - muitos problemas do Jenkinsfile se originam de simples erros de sintaxe . Para resolver esse problema, você pode validar o arquivo Jenkins contra sua instância do Jenkins (executando em $JENKINS_HTTP_URL):

curl -X POST -H $(curl '$JENKINS_HTTP_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)') -F "jenkinsfile=<Jenkinsfile" $JENKINS_HTTP_URL/pipeline-model-converter/validate

O comando acima é uma versão ligeiramente modificada de https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Validating-(or-linting)-a-Declarative-Jenkinsfile-from-the-command-line

Juuso Ohtonen
fonte
4
Este é exatamente o tipo de coisa que eu estava procurando - infelizmente, só funciona para declarativas oleodutos e não scripted pipelines :(
thom_nic
2

Além do recurso de reprodução que outros já mencionaram (o mesmo se aplica à sua utilidade!), Achei o seguinte útil também:

  1. Crie um trabalho de Pipeline de teste no qual você possa digitar o código do Pipeline ou apontar para o repositório / filial de um arquivo Jenkins para testar rapidamente algo. Para testes mais precisos, use um pipeline multibranch que aponte para sua própria bifurcação, onde você poderá fazer alterações rapidamente e confirmar sem afetar o produto. Coisas como BRANCH_NAME env estão disponíveis apenas na Multibranch.
  2. Como Jenkinsfile é um código Groovy, basta invocá-lo com "groovy Jenkinsfile" para validar a sintaxe básica.
Max Zheng
fonte
Usar tarefas separadas que você pode ocultar e não confundir seus usuários é uma das coisas mais importantes. Eu edito os arquivos Jenkins com o IntelliJ. É muito bom em mostrar falhas de sintaxe. No entanto, o botão de resposta é a chave. Eu crio um ramo com a execução básica de alteração que - geralmente dá um pouco de errado. Em seguida, edito o arquivo Jenkins, copio e colo na janela Replay e executo novamente - repito isso até que funcione OK e confirmo a versão de trabalho.
johnfo
2

Coloque sua chave SSH no seu perfil Jenkins e use o linter declarativo da seguinte maneira:

ssh jenkins.hostname.here declarative-linter < Jenkinsfile

Isso fará uma análise estática no seu arquivo Jenkins. No editor de sua escolha, defina um atalho de teclado que execute esse comando automaticamente. No Código do Visual Studio, que é o que eu uso, vá para Tarefas> Configurar Tarefas e use o seguinte JSON para criar um comando Validar Jenkinsfile :

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Validate Jenkinsfile",
      "type": "shell",
      "command": "ssh jenkins.hostname declarative-linter < ${file}"
    }
  ]
}
Hendrik M Halkow
fonte
0

Estou usando o replay futuro, para fazer algumas atualizações e executar rapidamente.

AhmedDrira
fonte
1
Você pode fornecer mais algumas informações sobre como você faz isso funcionar?
Kosnik
1
Estou usando o Bit-bucket como um gerenciador de código-fonte e, em seguida, criei um projeto no Jenkins para descobrir meu repositório automaticamente, recomendo este post. Após cada pressão no meu repo, o Jenkins reproduzirá automaticamente o meu arquivo Jenkins e, se falhar, no menu esquerdo, haverá um botão chamado Replay, ==> esse botão abre um editor que contém o seu arquivo Jenkins, você pode editá-lo e repetir o trabalho ,
AhmedDrira 4/07
0

Com algumas limitações e para pipelines com script, eu uso esta solução:

  1. Trabalho de pipeline com um script groovy embutido:

node('master') {
    stage('Run!') {
                def script = load('...you job file...')
    }
}

  1. O arquivo Jenkinsfile para teste tem a mesma estrutura que para lesfurets:

def execute() {
 ... main job code here ...
}
execute()
user3148458
fonte