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

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


jenkins:pipelines

Это старая версия документа!


Pipelines

Общее

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

Переменные

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

Дока Глобальная переменная, доступная через 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». т.к. переменная легко может подменится локальной с таким же именем, не имеющей отношения к переменной окружения или параметру

:!: Работа с переменными в pipeline
  // Входящий параметр
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"
        '''
    }
}
 
// Объявление входных параметров
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
            )
        ])
    ])
}
:!:
 

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" (хотя не точно уже)
    }
}
:!: Типичный скрипт для сборки

Тут модификация shadowJar для того чтобы в имя файла не добавлялся постфикс »-all«
Так же можно явно задавать имя артефакту
Так же таска для публикации в nexus

plugins {
    application
    java
    id("com.github.johnrengelman.shadow")
    id("com.coditory.manifest")
    id("maven-publish")
}
 
dependencies {
	(зависимости могут варьироваться)
    implementation(Deps.toml)
    implementation(Deps.opencsv)
}
 
application {
    mainClass.set("com.gmware.applications.(тут какой то класс)")
}
 
group = "com.gmware.applications"
version = "0.0.0.1-SNAPSHOT" 
 
// При желании, так можно получить хэш последнего коммита, для записи в манифест
fun getGitCommit(): String {
    val result = StringBuilder()
    val process = ProcessBuilder("git", "rev-parse", "HEAD").start()
    process.inputStream.reader(Charsets.UTF_8).use {
        result.append(it.readText())
    }
    process.waitFor()
    return result.toString().trim()
}
 
tasks {
    "shadowJar"(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) {
        archiveClassifier.set("")
        manifest {
            attributes(mapOf(
                "Main-Class" to application.mainClass,
                "Version" to version,
	        "Module-version" to getGitCommit()
            ))
        }
    }
}
 
publishing {
    repositories {
        maven {
            url = uri("${properties["nexusUrl"]}/myApp-snapshot")
            credentials {
                username = "${properties["nexusUser"]}"
                password = "${properties["nexusPassword"]}"
            }
        }
    }
    publications {
        register("mavenJava", MavenPublication::class) {
            artifact(tasks["shadowJar"])
        }
    }
}

Избавится от постфикса »-all« в имени джарки
параметр «jar.archiveClassifier.set(»»)«

# Вариант с таской shadowJar
tasks {
    "shadowJar"(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) {
        archiveClassifier.set("")
        manifest {
            attributes(mapOf(
                "Main-Class" to application.mainClass,
                "Version" to version,
                "Module-version" to getGitCommit()
            ))
        }
    }
}
 
 
# Таска с Jar
fun configureJar(jar: Jar) {
    jar.setManifestClassPathToRuntimeDependencies()
    jar.doFirst {
        jar.manifest {
            attributes["Main-Class"] = application.mainClass
            attributes["Module-Name"] = jar.archiveBaseName.get()
            attributes["Module-Commit-Date"] = getCommitDate()
            attributes["Created-By"] = System.getProperty("java.version")
        }
    }
    jar.archiveFileName.set("my-name.jar")
    jar.archiveClassifier.set("")
}

Запуск из консоли

Сборка и загрузка в репозиторий

./gradlew -PnexusUrl=https://url/repository -PnexusUser=<user> -PnexusPassword=<passwd> :module-name:publish

ShadowJar

Есть несколько вариантов, один из это подключить плагин, в файле «build.gradle.kts» добавляем
plugins { id(«com.github.johnrengelman.shadow») }

Тут есть описание

jenkins/pipelines.1706801491.txt.gz · Последнее изменение: 2024/02/01 15:31 — admin