Инструменты пользователя

Инструменты сайта


jenkins:pipelines

Pipelines

Общее

if (params.getOrDefault('BOOLEAN_PARAM_NAME', true))
 
if (params.CREDENTIAL_ID.toString().isEmpty()) { 
  currentBuild.result = 'ABORTED'
  error("CREDENTIAL_ID is empty")
}

Переменные

:!: Примеры
pipeline {
    agent any
 
    stages {
        stage("Variables") {
            steps {
               my_var = sh label: 'my echo', returnStdout: true, script: 'echo edede'    
            }
        } 
        stage("Variables") {
            steps {
                script{
                  // хотя хз, чет не сработало 
                  script: '''
                    echo "$my_var"
                  '''
                }
            }
        }
    }
}

Переменные среды

Дока Глобальная переменная, доступная через env. Объявляется в любом месте, либо в блоке environment либо в script
Хранится только в формате строки, в т.ч. и булевы значения
Обратится можно и без «env» но если нет обычной переменной с таким же именем иначе будет путаница

:!: Лист всех переменных
pipeline {
    agent any
 
    stages {
        stage("Env Variables") {
            steps {
                sh "printenv"
                // можно
                sh "printenv | sort"
            }
        }
    }
}
:!: Установка переменных

Переменные среды могут быть установлены декларативно с помощью environment { }блока, императивно с помощью env.VARIABLE_NAMEили с помощью withEnv([«VARIABLE_NAME=value»]) {}блока.

pipeline {
    agent any
 
    environment {
        FOO = "bar"
    }
 
    stages {
        stage("Env Variables") {
            environment {
                NAME = "Alan"
            }
 
            steps {
                echo "FOO = ${env.FOO}"
                echo "NAME = ${env.NAME}"
 
                script {
                    env.TEST_VARIABLE = "some test value"
                }
 
                echo "TEST_VARIABLE = ${env.TEST_VARIABLE}"
 
                withEnv(["ANOTHER_ENV_VAR=here is some value"]) {
                    echo "ANOTHER_ENV_VAR = ${env.ANOTHER_ENV_VAR}"
                }
            }
        }
    }
}
:!: Переопределение переменных
  • Блок withEnv([«env=value]) { }может переопределить любую переменную среды.
  • Переменные, заданные с помощью environment {}блока, не могут быть переопределены с помощью императивного env.VAR = «value»присваивания.
  • Императивное env.VAR = «value»присваивание может переопределить только переменные среды, созданные с помощью императивного присваивания.
pipeline {
    agent any
 
    environment {
        FOO = "bar"
        NAME = "Joe"
    }
 
    stages {
        stage("Env Variables") {
            environment {
                NAME = "Alan" // overrides pipeline level NAME env variable
                BUILD_NUMBER = "2" // overrides the default BUILD_NUMBER
            }
 
            steps {
                echo "FOO = ${env.FOO}" // prints "FOO = bar"
                echo "NAME = ${env.NAME}" // prints "NAME = Alan"
                echo "BUILD_NUMBER =  ${env.BUILD_NUMBER}" // prints "BUILD_NUMBER = 2"
 
                script {
                    env.SOMETHING = "1" // creates env.SOMETHING variable
                }
            }
        }
 
        stage("Override Variables") {
            steps {
                script {
                    env.FOO = "IT DOES NOT WORK!" // it can't override env.FOO declared at the pipeline (or stage) level
                    env.SOMETHING = "2" // it can override env variable created imperatively
                }
 
                echo "FOO = ${env.FOO}" // prints "FOO = bar"
                echo "SOMETHING = ${env.SOMETHING}" // prints "SOMETHING = 2"
 
                withEnv(["FOO=foobar"]) { // it can override any env variable
                    echo "FOO = ${env.FOO}" // prints "FOO = foobar"
                }
 
                withEnv(["BUILD_NUMBER=1"]) {
                    echo "BUILD_NUMBER = ${env.BUILD_NUMBER}" // prints "BUILD_NUMBER = 1"
                }
            }
        }
    }
}

Переменные

Обращаться к переменным следует всегда с префиксами если они есть, например для переменных окружения это «env», для входных параметров это «params». т.к. переменная легко может подменится локальной с таким же именем, не имеющей отношения к переменной окружения или параметру

:!: Работа с переменными, модуль sh

Модуль sh по всей видимости выполняется напрямую в оболочке, поэтому ему доступны только переменные окружения среды
Задать переменные окружения из скрипта можно в блоке Environment

  // Входящий параметр (видимо по умолчанию доступны в переменных окружения)
stage('Clone source') {
	steps {
		echo params.MY_BRANCH
		sh label: 'repo sync', script: '''
            repo init -u ssh://myrepository.ru
            repo sync
            if [ $MY_BRANCH != "master" ] ; then
                repo forall -c git checkout $MY_BRANCH
            fi
        '''
	}
}
 
// Объявление в скрипте
stage('Increment & push MGA_TAG') {
    environment{
		myLocalVar = getValueFromFunction()
	}
    steps {
        script{
            if (env.myLocalVar == null || env.myLocalVar.equals("")) {
                currentBuild.result = 'ABORTED'
            }
        }
		sh label: 'Push tag if it is set', 
		script: '''
			cd $WORKSPACE/igas
            repo forall -c git tag -a $myLocalVar -m $myLocalVar
            repo forall -c git push origin "$myLocalVar"
        '''
    }
}
 
//
// Или вот пример 
stage('Build') {
    environment {
        VERSION_STRING = new SimpleDateFormat("yyyy_MM_dd_HH_mm").format(new Date())
    }
    steps {
        sh label: 'my scritp', script: '''
            echo variable in other block1 - $VERSION_STRING
            echo variable in other block2 - "$VERSION_STRING"
            echo variable in other block3 - '$VERSION_STRING' <-- эта не раскрывается
        '''
    }
}
 
 
 
 
// Объявление входных параметров
def setParameters() {
    properties([
        parameters([
            gitParameter(
                name: 'MY_BRANCH',
                description: 'Тег или ветка, откуда делать сборку',
                branch: '',
                branchFilter: '.*',
                defaultValue: 'origin/master',
                listSize: '10',
                quickFilterEnabled: false,
                requiredParameter: true,
                selectedValue: 'DEFAULT',
                sortMode: 'ASCENDING_SMART',
                tagFilter: '[0-9]*',
                type: 'PT_BRANCH_TAG'
            ),
            string(
                name: 'APP_VERSION',
                description: '',
                defaultValue: '',
                trim: true
            ),
            booleanParam(
                name: 'RUNACTION',
                description: '',
                defaultValue: false
            )
        ])
    ])
}
:!: multiline
// Так не работает, переменные не раскрываются
script{
    echo ''' second $MY_PARAM '''
    echo ''' three ${MY_PARAM} '''
    echo ''' four ${params.MY_PARAM} '''
}
 
// Работает в тройных двойных кавычках, раскрылись все переменные
script{
    echo """ second $MY_PARAM """
    echo """ three ${MY_PARAM} """
    echo """ four ${params.MY_PARAM} """
}

Дата/Время

  • java.time.LocalDateTime - Дата и время без часового пояса в календарной системе ISO-8601, например 2007-12-03T10:15:30
    неизменяемый объект даты и времени, с точностью до наносекунды, не хранит и не представляет часовой пояс
  • java.time.Instant - тут что то более жесткое
  • ZoneId - (java.time.ZoneId) больше связано с правилами преобразования между часовыми поясами
  • ZoneOffset - (java.time.ZoneOffset) тут уже больше про смещение относительно UTC
:!: more
import java.time.LocalDateTime
 
// Локальная ДТ, в формате "2024-02-01T19:34:11.905900287"
def start = LocalDateTime.now()
 
// Прибавить минуты
def start = LocalDateTime.now().plusMinutes(360)
 
// Тоже текущая дата, формат такой же, но дженкинс попросил аппрув (хотя не помню с первым возможно тоже был)
import java.time.Instant
def current_instant = Instant.now()
:!: Часовые пояса

Неплохая статья

import java.time.LocalDateTime
import java.time.ZoneId
 
// ZoneId, тут есть явное определение временных зон, пример из джавы
ZoneId zone = ZoneId.of("Asia/Almaty")
ZonedDateTime time = ZonedDateTime.now(zone)
 
// В груви так работает (тут есть перечень зон https://csharpcoderr.com/5267/ )
def zoned_dt = LocalDateTime.now(ZoneId.of("Asia/Almaty"))
 
 
// Offset, собсна "смещение", тут в основном фиксированный какой то сдвиг времени от полученного из системы
// Так работает 
def current_dt = LocalDateTime.now()
def offset_dt = LocalDateTime.now(ZoneOffset.ofHours(+6))
 
// Вот тоже пример, по сути тоже самое
ZoneOffset zoneOffSet = ZoneOffset.of("+02:00");
OffsetTime time = OffsetTime.now(zoneOffSet);

Примеры

:!: Работа с grafana API
import java.time.LocalDateTime
import java.time.ZoneId
 
pipeline {
    agent {
        label 'master'
    }
 
    environment {
        GRAFANA_API_TOKEN = credentials('sdcsdcdscdsc')
    }
 
    stages {
        stage('make silence') {
            steps {
				SetParameters()
                script{
 
                    //def start_time_silence = LocalDateTime.now(ZoneId.of("Asia/Almaty"))
                    //def end_time_silence = start_time_silence.plusMinutes(params.DURATION_MIN.toInteger())
 
                    def start_time_silence = LocalDateTime.now()
                    def end_time_silence = start_time_silence.plusMinutes(params.DURATION_MIN.toInteger())
 
                    def response = httpRequest acceptType: 'APPLICATION_JSON', 
                            contentType: 'APPLICATION_JSON',
                            responseHandle: 'NONE',
                            httpMode: 'POST',
                            ignoreSslErrors: true, 
                            url: 'https://url-grafana/api/alertmanager/grafana/api/v2/silences', 
                            wrapAsMultipart: false,
                            authentication: 'dcdcdcdcdc',
                            requestBody: """{
                              "comment": "comment_string",
                              "createdBy": "user_my",
                              "startsAt": "${start_time_silence}",
                              "endsAt": "${end_time_silence}",
                              "matchers": [
                                {
                                  "isEqual": true,
                                  "isRegex": false,
                                  "name": "alertname",
                                  "value": "${ALERT_NAME}"
                                }
                              ]
                            }"""
                }
            }
        }
 
    }
}
 
def SetParameters() {
    properties([
        parameters([
            string(
                name: 'ALERT_NAME',
                description: 'Название alert-правила в grafana',
                trim: true
            ),
            string(
                name: 'DURATION_MIN',
                defaultValue: '60',
                description: 'Продолжительность режима тишины в минутах',
                trim: true
            )
        ])
    ])
}
:!: Минимальный пример, скачивание репозитория
pipeline {
 
    agent {
        label 'main-node'
    }
 
    options {
        quietPeriod 5
        ansiColor('xterm')
        timestamps()
        buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', numToKeepStr: '10')
    }
 
    stages {
        stage('Prepare') {
            steps {
                script {
                    cleanWs()
                    sh(
                    label: 'repo sync',
                    script: '''
                        PATH="${HOME}/.bin:${PATH}"
                        repo init -u ssh://username:port/myproject --depth=1
                        repo sync
                        repo forall -c git checkout "master"
                    '''
                    )
                }
            }
        }
    }
}
 
 
#
# Выбор ветки
#
        stage('Prepare') {
            steps {
                script {
                    SetParameters()
                    cleanWs()
                    sh(
                    label: 'repo sync',
                    script: '''
                        PATH="${HOME}/.bin:${PATH}"
                        repo init -u ssh://username:port/project --depth=1
                        repo sync
                        if [ ${BRANCH} != "master" ] ; then
                            repo forall -c git checkout ${BRANCH}
                        fi
                        if [ ${GERRIT_REFSPEC} != "master" ] ; then
                            cd igs/smodls/i_adm && git fetch ssh://url-repo:port/myproject ${GERRIT_REFSPEC} && git checkout FETCH_HEAD
                        fi
                    '''
                    )
                }
            }
        }
:!: Проверка и откат
    - name: "Проверка и откат"
      block:
        - name: "Перезапускаем сервис"
          import_tasks: 60-restart_service.yml
 
        - name: "Делаем паузу и проверяем состояние сервиса"
          ansible.builtin.shell:
            cmd: "sleep 25 && systemctl is-active myservice@{{ instance_name }}.service"
      rescue:
        - name: "Откатываемся на бекап"
          ansible.builtin.shell:
            cmd: 'tar -xzvf ./backups/previous_version.tar.gz -C .'
            chdir: '{{ instance.root_path }}/{{ instance_name }}'
 
        - name: "Перезапускаем сервис, уже после отката"
          import_tasks: 60-restart_service.yml
 
        - name: "Прерываем выполнение в случае отката"
          ansible.builtin.fail:
            msg: "!!! Откат изменений после сбоя. Прерываем дальнейшее выполнение !!!"
:!: Выбор инстансов
pipeline {
 
    agent {
        label 'ConfigServerExt'
    }
 
    options {
        quietPeriod 5
        ansiColor('xterm')
        timestamps()
        buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', numToKeepStr: '10')
    }
 
    environment {
        EXTRAS = getExtras()
    }
 
    stages {
        stage('Prepare') {
            steps {
                script {
                    SetParameters()
                    cleanWs()
                    script {
                        currentBuild.displayName = "${params.VERSION}"
                        buildDescription "${params.APP_INSTANCE}"
                    }
                    sh(
                    label: 'repo sync',
                    script: '''
                        PATH="${HOME}/.bin:${PATH}"
                        repo init -u ssh://jenkins@gerrit.ru/igs-meta --depth=1
                        repo sync
                        if [ ${BRANCH} != "master" ] ; then
                            repo forall -c git checkout ${BRANCH}
                        fi
                        if [ ${GERRIT_REFSPEC} != "master" ] ; then
                            cd igs/modules/repo && git fetch ssh://gerrit.ru/proj ${GERRIT_REFSPEC} && git checkout FETCH_HEAD
                        fi
                    '''
                    )
                }
            }
        }
        stage('Build') {
            when {
                expression {
                    !params.SKIP_BUILD
                }
            }
            environment {
                NEXUS_CREDS = credentials('11111-1111-1111')
            }
            steps {
                sh label: 'gradle publish', script: '''
                    cd $WORKSPACE/igas
                    ./gradlew \
                        "-PnexusUrl=https://nexus.ru/repository" \
                        "-PnexusUser=${NEXUS_CREDS_USR}" \
                        "-PnexusPassword=${NEXUS_CREDS_PSW}" \
                        :my_app:publish
                '''
            }
        }
        stage('Deploy') {
            steps {
                dir("${WORKSPACE}/proj/pathToPlaybook") {
                    ansiblePlaybook(
                        playbook: "playbooks-deploy/my_role.yml",
                        extras: "${env.EXTRAS}",
                        colorized: true,
                    )
                }
            }
        }
    }
}
 
def getExtras() {
    if ("all".equals(params.APP_INSTANCE)) {
        return "-e version=${params.VERSION}"
    } else {
        return "-e version=${params.VERSION} -e instances=${params.APP_INSTANCE}"
    }
}
 
def SetParameters() {
    properties([
        parameters([
            booleanParam(
                name: 'SKIP_BUILD',
                description: 'Поставьте галочку и выберите версию если нужен только деплой существующей версии',
                defaultValue: false
            ),
            [
                $class: 'ChoiceParameter',
                choiceType: 'PT_SINGLE_SELECT',
                description: 'Ветка для сборки приложения',
                name: 'BRANCH',
                randomName: 'choice-parameter-73664823423423',
                filterable: false,
                script: [
                    $class: 'GroovyScript',
                    fallbackScript: [
                        classpath: [],
                        sandbox: false,
                        script:
                        '''
                            return['Could not get branches list from gerrit']
                        '''.trim()
                    ],
                    script: [
                        classpath: [],
                        sandbox: false,
                        script:
                        '''
                            def cmd = ['/bin/bash',  '-c',  'git ls-remote --quiet --heads ssh://login@gerrit.ru/proj | grep -oP refs.* | sed "s|refs/heads|origin|g; s|master|master:selected|"']
                            def result = cmd.execute().text.tokenize()
                            return result
                        '''.trim()
                    ]
                ]
            ],
            [
                $class: 'ChoiceParameter',
                choiceType: 'PT_SINGLE_SELECT',
                name: 'VERSION',
                description: 'Укажите, если нужен деплой уже существующей версии',
                randomName: 'choice-parameter-5631314456178618',
                script: [
                    $class: 'GroovyScript',
                    script: [
                        classpath: [],
                        sandbox: false,
                        script: '''\
                            import com.cloudbees.plugins.credentials.CredentialsMatchers
                            import com.cloudbees.plugins.credentials.CredentialsProvider
                            import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials
                            import com.cloudbees.plugins.credentials.domains.DomainRequirement
                            import jenkins.model.Jenkins
                            import hudson.security.ACL
                            jenkins = Jenkins.get()
                            def lookupSystemCredentials = {
                                credentialsId -> return CredentialsMatchers.firstOrNull(
                                    CredentialsProvider.lookupCredentials(
                                        StandardUsernameCredentials.class,
                                        jenkins,
                                        ACL.SYSTEM,
                                        Collections.<DomainRequirement>emptyList()
                                    ),
                                    CredentialsMatchers.withId(credentialsId)
                                )
                            }
                            credential = lookupSystemCredentials("111111-1111-111")
                            nexusLogin = credential.getUsername()
                            nexusPasswd = credential.getPassword().getPlainText()
                            def targetUrl="https://$nexusLogin:$nexusPasswd@nexus.url.ru/repository/myapp-snapshots/com/gmware/applications/myapp/maven-metadata.xml"
                            def sout = new StringBuilder(), serr = new StringBuilder()
                            def proc = "curl -X GET $targetUrl".execute()
                            proc.consumeProcessOutput(sout, serr)
                            proc.waitForOrKill(1000)
                            def response=sout.toString()
                            def metadata = new XmlParser().parseText(response)
                            def versions = ['latest:selected']
                            versions.addAll(metadata.versioning.versions.version.collect({it.text()}).reverse())
                            return versions
                        '''.stripIndent()
                    ]
                ]
            ],
            [
                $class      : 'ChoiceParameter',
                choiceType  : 'PT_MULTI_SELECT',
                filterLength: 1,
                filterable  : false,
                name        : 'FM_INSTANCE',
                randomName  : 'choice-parameter-5631314339613980',
                script      : [
                    $class: 'GroovyScript',
                    script: [
                        classpath: [],
                        sandbox  : false,
                        script   : '''\
                            def fm_instances = []
                            def file1 = new File("/pathToFile/file.txt")
                            file1.eachLine {
                                fm_instances.add(it)
                            }
                            def result = ["all:selected"]
                            result.addAll(fm_instances)
                            return result'''.stripIndent()
                    ]
                ]
            ],
            string(
                defaultValue: 'master',
                description: 'Укажите патчсет, например, refs/changes/12/34567/1, откуда забирать плейбуки ansible',
                name: 'GERRIT_REFSPEC',
                trim: true
            )
        ])
    ])
}
:!:
 

Use Gradle

:!: Общее

:!: Скрипты справа все таки совпадают с тасками что есть в файле «build.gradle.kts» внутри проекта
вот только как он обновляется ? таску вроде прописал, а справа не появляется этого

  // Проверка переданной переменной, через аргументы вызова, "-Pversion"
if(!project.hasProperty("version")) throw Exception("no value stop it")
 
  // Обращаться к свойству
project.properties["buildVersion"]
 
  // Вообще таска для ShadowJar
tasks {             
    "shadowJar"(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) {
        mergeServiceFiles()
        isZip64 = true
        val serverAppName = "server_app-$serverAppVersion.jar"
        archiveFileName.set(serverAppName)
        doFirst {
            //assert(buildVersion != "non-value") { "Can not get version by git." }
            if(!project.hasProperty("version")) throw Exception("no value stop it")
        }
    }
}
:!: Работа из пайплайна
  # Если скритп "gradlew" в папке с проектом
stage('Build jar') {
	steps {
		sh "bash ./gradlew shadowJar"
    }
}
 
  # Если нет, тогда 
stage('Build jar') {
	steps {
		sh "bash ./gradlew myProject:modules:shadowJar" (хотя не точно уже)
    }
}
jenkins/pipelines.txt · Последнее изменение: 2024/07/26 03:00 — admin