Jenkins Pipeline
Введение | |
Пример создания | |
Multibranch Pipeline | |
Фильтрация веток | |
when | |
Credentials | |
Пример полного пайплайна | |
PowerShell команда в Pipeline | |
Статьи про Jenkins |
Введение
Существует два типа Pipeline: Declarative и Scripted
Отличить один от другого можно по первым строкам
Декларативный Pipeline начинается со слова pipeline
pipeline { agent { } }
Скриптовый Pipeline начинается со слова node и внутри содержит Groovy скрипт
node { // groovy script }
Pipeline
New Item → Pipeline
Создайте файл Jenkinsfile.template и скопируйте его содержание в Pipeline → Definition → Pipeline script
pipeline { agent { node { label 'jenkins-agent-goes-here' } } stages { stage('Build') { steps { echo "Building.." sh ''' echo "doing build stuff.." ''' } } stage('Test') { steps { echo "Testing.." sh ''' echo "doing test stuff.." ''' } } stage('Deliver') { steps { echo 'Deliver....' sh ''' echo "doing delivery stuff.." ''' } } } }
label нужно заменить на label вашего агента, который подходит для данного задания. В прошлом примере это был demo-docker-slave, сейчас я переименовал его в docker_slave_ssh
pipeline { agent { node { label 'docker_slave_ssh' } }
Запустим Pipeline и изучим статус
Добавим триггер по SCM
pipeline { agent { node { label 'docker_slave_ssh' } } triggers { pollSCM 'H/5 * * * *' }
Нужно изменить Pipeline Definition на Pipeline script from SCM
Затем указать Git в качестве SCM и добавить в Repository URL свой репозиторий. Если репозиторий публичный, то
Credentials указывать не нужно. Если репозиторий частный то можно задать логин и пароль с помощью плагина
Credentials.
Скопировать Jenkinsfile на удалённый репозиторий
Указать Jenkinsfile в Script Path
Пушим изменения в репозиторий и запускаем задание вручную.
Started by user andrei Obtained Jenkinsfile from git https://github.com/yourrepo/jenkins-docker-slave [Pipeline] Start of Pipeline [Pipeline] node Running on docker_slave_ssh-000i35hzxz96d on docker_ubuntu_esxi2 in /home/jenkins/workspace/my_first_build_pipeline [Pipeline] { [Pipeline] stage [Pipeline] { (Declarative: Checkout SCM) [Pipeline] checkout Selected Git installation does not exist. Using Default The recommended git tool is: NONE No credentials specified Cloning the remote Git repository Cloning repository https://github.com/yourrepo/jenkins-docker-slave > git init /home/jenkins/workspace/my_first_build_pipeline # timeout=10 Fetching upstream changes from https://github.com/yourrepo/jenkins-docker-slave > git --version # timeout=10 > git --version # 'git version 2.34.1' > git fetch --tags --force --progress -- https://github.com/yourrepo/jenkins-docker-slave +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url https://github.com/yourrepo/jenkins-docker-slave # timeout=10 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 Avoid second fetch Checking out Revision 0854f332c3f88754a31a57c873bdb4402cff59b2 (refs/remotes/origin/master) > git rev-parse refs/remotes/origin/master^{commit} # timeout=10 > git config core.sparsecheckout # timeout=10 > git checkout -f 0854f332c3f88754a31a57c873bdb4402cff59b2 # timeout=10 Commit message: "QA: changes poll interval to 2 minutes in Jenkinsfile" First time build. Skipping changelog. [Pipeline] } [Pipeline] // stage [Pipeline] withEnv [Pipeline] { [Pipeline] stage [Pipeline] { (Build) [Pipeline] echo Building.. [Pipeline] sh + echo doing build stuff.. doing build stuff.. [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Test) [Pipeline] echo Testing.. [Pipeline] sh + echo doing test stuff.. doing test stuff.. [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Deliver) [Pipeline] echo Deliver.... [Pipeline] sh + echo doing delivery stuff.. doing delivery stuff.. [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // withEnv [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
Schedule должен был подхватить наше правило
H/2 * * * *
Теперь нужно внести изменения в код на удалённом репозитории и подождать около пяти минут.
Multibranch Pipeline
В типичном проекте обычно более одной git ветки поэтому и в Jenkins обычно используется Multibranch Pipeline
Фильтрация веток
Указать какие именно ветки Multibranch Pipeline проекта вы хотите собирать можно через
Dashboard → Pipeline Name → Configuration → Branch Sources → Discover branches → Filter by name (with regular expression)
Значение
.*
Соответствует всем веткам репозитория.
А, например
^dev|master|feature.*$
Соответсвует тем веткам, которые начинаются на dev или master или feature .
when
В каждую стадию можно добавить условие выполнения. Если оно не сработает стадия (например "Test") будет пропущена с логом
Stage "Test" skipped due to when conditional
Пример проверки ветки
stage('Test') { when { branch 'master' } steps { echo "Testing.." sh ''' echo "doing test stuff.." ''' } }
Для проекта с несколькими ветками подойдёт использование как branch так и BRANCH_NAME
BRANCH_NAME For a multibranch project, this will be set to the name of the branch being built, for example in case you wish to deploy to production from master but not from feature branches; if corresponding to some kind of change request, the name is generally arbitrary (refer to CHANGE_ID and CHANGE_TARGET).
when { expression { env.BRANCH_NAME == 'dev' || env.BRANCH_NAME == 'master' } } steps { echo "Testing.." sh ''' echo $BRANCH_NAME ''' }
Добавить Groovy скрипт в декларативный Pipeline
Если вы создали декларативный Pipeline это не означает, что нельзя использовать
произвольные
Groovy
скрипты.
Достаточно обернуть скрипт тегом script {}
stage('Test') { steps { echo "Testing.." script { def test = 2 + 2 > 3 ? 'hopefully' : 'unlikely' echo test } } }
В логах должно появиться hopefully.
Проверять корректность скриптов проще всего через функцию Replay доступную
внутри рана.
Credentials
Рассмотрим как пользоваться учетными данными внутри Pipeline. О том как создавать учетные данные читайте в статье «Создание учетных данных в Jenkins»
pipeline { agent { node { label 'docker_slave_ssh' } } environment { SERVER_CREDENTIALS = credentials('esxi2-192') } stages { stage('Deploy') { steps { echo "Deploying with ${SERVER_CREDENTIALS} User: ${SERVER_CREDENTIALS_USR}" } } } }
… Deploying with **** User: andrei …
Можно использовать учетные данные не глобально, а внутри шага. Это делается с помощью withCredentials()
pipeline { agent { node { label 'docker_slave_ssh' } } stages { stage('Test') { steps { echo "Testing.." withCredentials([ usernamePassword(credentialsId: 'esxi2-192', usernameVariable: 'MY_USER', passwordVariable: 'MY_PWD')]) { echo "USER: ${MY_USER} PWD: ${MY_PWD}" } } } } }
Masking supported pattern matches of $MY_PWD [Pipeline] { (hide) [Pipeline] echo Warning: A secret was passed to "echo" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [MY_PWD] See https://jenkins.io/redirect/groovy-string-interpolation for details. USER: andrei PWD: ****
Пример полного пайплайна
pipeline { agent {label 'mkdocs_builder'} stages { stage("Pull Git Repository") { steps { script { sh 'pwd' sh 'ls -la' } git( url: "git@github.com:Aredel/git-experiments.git", branch: "main", changelog: true, poll: true ) } } stage("Backup") { steps { script { sh 'pwd' sh 'ls -la' } dir("mkdocs/documentation") { sh 'pwd' sh 'ls -la' script { if (fileExists('site_arj')) { dir("site_arj") { deleteDir() } } else { echo 'No site_arj dir found' } } script { if (fileExists('site')) { sh 'mv site site_arj' } else { echo 'No site dir found' } } } script { sh 'pwd' sh 'ls -la' } } } stage("Build") { steps { script { dir('mkdocs/documentation') { sh 'python -m mkdocs build' sh 'ls -la' } } } } stage("Deliver") { steps { dir('mkdocs/documentation/site') { sh 'pwd' sh 'ls -la' } script { sh 'cp -r mkdocs/documentation/site /home/jenkins/mkdocs/documentation/' } } } } post { // Clean after build always { cleanWs(cleanWhenNotBuilt: false, deleteDirs: true, disableDeferredWipeout: true, notFailBuild: true, patterns: [[pattern: '.gitignore', type: 'INCLUDE'], [pattern: '.propsfile', type: 'EXCLUDE']]) } } }
PowerShell команда в Pipeline
Пример выполенения обычной команды PowerShell
pipeline { agent { label "testcomplete" } stages { stage('Collect info about environment') { steps { powershell("ls") powershell("dir") powershell("ipconfig") } } } }
Каждая команда powershell запускает новую оболочку.
Поэтому если вам нужно
использовать то, что нуждается в сохранении какого-то состояния:
переменные окружения,
виртуальное окружение
в
Python
и тому подобное - делать это нужно в пределах
одной команды, с помощью """.
Пример пайплайна, где сперва явно указанной версией Python создаётся вирутальное окружение
а в следующей стадии в этом же окружении запускаются тесты на
Robot Framework
:
pipeline { agent { label "test" } stage('Install requirements') { steps { dir('desktop-tests') { powershell(""" whoami C:\Users\ao\AppData\Local\Programs\Python\Python312\python.exe -m venv venv .\venv\Scripts\Activate.ps1 python -m pip install -r ./requirements.txt """ ) } } } stage('Test') { steps { dir('desktop-tests/robot/') { powershell(""" whoami ..\venv\Scripts\Activate.ps1 ls Env: robot tests """) } } } } }
Jenkins | |
Установка Jenkins | |
Основы Jenkins | |
Jenkins Freestyle project | |
Jenkins Pipeline | |
Credentials | |
Задания по расписанию | |
Плагины | |
Разбор ошибок | |
DevOps | |
Docker | |
Make |