Slide 1

Slide 1 text

Строим свой тестовый фреймворк– c Jenkins Pipeline и библиотеками Олег Ненашев (@oleg_nenashev) CloudBees, Inc. Москва, 2017

Slide 2

Slide 2 text

2 @oleg_nenashev, #heisenbug • Jenkins, Scripted Pipeline и библиотеки • Интеграции: Java, Maven, FindBugs, Cobertura • Обработка ошибок, параллелизация, инкапсуляция • Проблемы при разработке Pipeline О чём доклад? https://github.com/oleg-nenashev/heisenbug2017-demo

Slide 3

Slide 3 text

3 @oleg_nenashev, #heisenbug Jenkins и Pipeline “для чайников” •https://jenkins.io/doc/book/pipeline Чего НЕТ в докладе? Disclaimer: • Презентация отражает личное мнение докладчика • Оно может не совпадать с позицией сообщества Jenkins и/или CloudBees

Slide 4

Slide 4 text

4 @oleg_nenashev, #heisenbug Jenkins и Pipeline “для чайников” Blue Ocean, Declarative Pipeline, … •https://jenkins.io/doc/book/pipeline •Дискуссионная зона Чего НЕТ в докладе? Disclaimer: • Презентация отражает личное мнение докладчика • Оно может не совпадать с позицией сообщества Jenkins и/или CloudBees

Slide 5

Slide 5 text

5 @oleg_nenashev, #heisenbug Jenkins и Pipeline “для чайников” Blue Ocean, Declarative Pipeline, … Внутренностей Jenkins Pipeline •Митап JUG.ru 4 декабря: https://goo.gl/x9x7Zm Чего НЕТ в докладе? Disclaimer: • Презентация отражает личное мнение докладчика • Оно может не совпадать с позицией сообщества Jenkins и/или CloudBees

Slide 6

Slide 6 text

6 @oleg_nenashev, #heisenbug Jenkins и Pipeline “для чайников” Blue Ocean, Declarative Pipeline, … Внутренностей Jenkins Pipeline CloudBees Jenkins Enterprise •https://go.cloudbees.com Чего НЕТ в докладе? Disclaimer: • Презентация отражает личное мнение докладчика • Оно может не совпадать с позицией сообщества Jenkins и/или CloudBees

Slide 7

Slide 7 text

7 @oleg_nenashev, #heisenbug Обо мне @oleg_nenashev oleg-nenashev librecores.org Jenkins СПб / Jenkins RU Политех

Slide 8

Slide 8 text

8 @oleg_nenashev, #heisenbug Мой Hall of fameshame • Ядро Jenkins • Remoting • Windows Service Wrapper • >25 плагинов Примеры плагинов

Slide 9

Slide 9 text

9 @oleg_nenashev, #heisenbug Русскоязычное сообщество Jenkins • Митапы в Москве, СПб и Минске • Gitter: #jenkinsci-ru/public • YouTube: http://bit.ly/jenkins-ru-youtube • Facebook: http://bit.ly/jenkins-ru-facebook • Twitter: @jenkins_ru Москва: Здесь может быть Ваше лого

Slide 10

Slide 10 text

10 @oleg_nenashev, #heisenbug О Вас Используете ли Вы Jenkins Pipeline? https://jenkins.io/doc/book/pipeline/

Slide 11

Slide 11 text

11 @oleg_nenashev, #heisenbug TODO: Oil Pipelines Image Jenkins Pipeline pipeline { agent label:"linux" tools { maven ”M3" } stages { stage("build") { steps { sh 'mvn clean verify' } } } post { always { junit ”target/…/*.xml" } } } * Declarative

Slide 12

Slide 12 text

12 @oleg_nenashev, #heisenbug TODO: Oil Pipelines Image Jenkins Pipeline

Slide 13

Slide 13 text

13 @oleg_nenashev, #heisenbug О Вас Насколько большой у Вас Jenkins? https://jenkins.io/doc/book/pipeline/

Slide 14

Slide 14 text

14 @oleg_nenashev, #heisenbug Команда А(втоматизации) • Внутренний консалтинг • Поддержка • Автоматизация as a Service

Slide 15

Slide 15 text

15 @oleg_nenashev, #heisenbug Команда А(втоматизации) + Jenkins Конфиги Инфра- структура Общая логика Пла- гины Документация Инфра- структура Инфра- структура

Slide 16

Slide 16 text

16 @oleg_nenashev, #heisenbug Марио Инженер команды А Марио знает Jenkins. Он не хочет автоматизировать один за всех и всех за одного

Slide 17

Slide 17 text

17 @oleg_nenashev, #heisenbug Луиджи Автоматизатор QA Луиджи – инженер. Он не хочет учить Jenkins, он хочет Pipeline

Slide 18

Slide 18 text

18 @oleg_nenashev, #heisenbug Луиджи нужен Pipeline Тесты #1 Тесты #2 Тесты #3 Сборка Coverage Уведом- ления “maven clean verify”

Slide 19

Slide 19 text

19 @oleg_nenashev, #heisenbug Но сегодня мы играем за Марио…

Slide 20

Slide 20 text

20 @oleg_nenashev, #heisenbug Пользователей много…. Марио нужен фреймворк….

Slide 21

Slide 21 text

21 @oleg_nenashev, #heisenbug А зачем мне фреймворк?

Slide 22

Slide 22 text

22 @oleg_nenashev, #heisenbug Документация, ага Фреймворк МАРИО ЛУИДЖИ Это решит все твои проблемы!

Slide 23

Slide 23 text

23 @oleg_nenashev, #heisenbug Что делать Луиджи? 1. Взять компоненты из фреймворка

Slide 24

Slide 24 text

24 @oleg_nenashev, #heisenbug Что делать Луиджи? 1. Взять компоненты из фреймворка 2. Собрать свой велосипед Pipeline Просто добавь клея!

Slide 25

Slide 25 text

25 @oleg_nenashev, #heisenbug Фреймворк на Jenkins 5 лет назад

Slide 26

Slide 26 text

26 @oleg_nenashev, #heisenbug 5 лет назад... • Freestyle • Parameterized Trigger • Copy Artifact • TemplateProject / Inheritance • Плагины… Чудовище Дженкинсштейна

Slide 27

Slide 27 text

Почему Jenkins Pipeline? ”Легко” использовать • Blue Ocean • Declarative • Multi-branch • Интеграции

Slide 28

Slide 28 text

Почему Jenkins Pipeline? “Легко” использовать “Легко” разрабатывать • … as Code • Snippet Generator • Документация pipeline { agent label:"linux" tools { maven ”M3" } stages { stage("build") { steps { sh 'mvn clean verify' } } } post { always { junit ”target/…/*.xml" } } }

Slide 29

Slide 29 text

Почему Jenkins Pipeline? “Легко” использовать “Легко” разрабатывать “Легко” шарить логику • Библиотеки # Jenkinsfile buildPlugin()

Slide 30

Slide 30 text

30 @oleg_nenashev, #heisenbug Давайте строить фреймворк. мне начать?

Slide 31

Slide 31 text

31 @oleg_nenashev, #heisenbug Прототип! 1. Jenkinsfile 2. Scripted Pipeline 3. Вызов Maven через Shell https://jenkins.io/doc/book/pipeline

Slide 32

Slide 32 text

32 @oleg_nenashev, #heisenbug Первые шаги node(‘linux’) { checkout scm sh “mvn clean verify” } https://jenkins.io/doc/book/pipeline

Slide 33

Slide 33 text

33 @oleg_nenashev, #heisenbug Публикация результатов node(‘linux’) { checkout scm sh “mvn clean verify -Dmaven.test.failure.ignore” junit ”target/…/*.xml” findbugs pattern: “**/target/findbugsXml.xml” } https://jenkins.io/doc/book/pipeline

Slide 34

Slide 34 text

34 @oleg_nenashev, #heisenbug А можно ли добавить Coverage? • Cobertura • sh “mvn clean verify -Pcoverage”

Slide 35

Slide 35 text

35 @oleg_nenashev, #heisenbug •Cobertura Plugin •Pipeline Syntax Cobertura? Легко!

Slide 36

Slide 36 text

36 @oleg_nenashev, #heisenbug •Cobertura Plugin •Pipeline Syntax •НО: В Cobertura Plugin нет шага для Pipeline •https://github.com/jenkinsci/cobertura-plugin/issues/50 Cobertura? Легко! Возможно

Slide 37

Slide 37 text

37 @oleg_nenashev, #heisenbug Pipeline Snippet Generator

Slide 38

Slide 38 text

38 @oleg_nenashev, #heisenbug Шаг 3. Cobertura step([$class: 'CoberturaPublisher', autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: ‘target/coverage.xml', failNoReports: false, failUnhealthy: false, failUnstable: false, maxNumberOfBuilds: 0, onlyStable: false, sourceEncoding: 'ASCII', zoomCoverageChart: false]) И ТАК СОЙДЁТ?

Slide 39

Slide 39 text

39 @oleg_nenashev, #heisenbug Шаг 3. Cobertura В каждой задаче??? step([$class: 'CoberturaPublisher', autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: ‘target/coverage.xml', failNoReports: false, failUnhealthy: false, failUnstable: false, maxNumberOfBuilds: 0, onlyStable: false, sourceEncoding: 'ASCII', zoomCoverageChart: false])

Slide 40

Slide 40 text

40 @oleg_nenashev, #heisenbug @jenkins_ru, что мне делать? https://gitter.im/jenkinsci-ru/public

Slide 41

Slide 41 text

41 @oleg_nenashev, #heisenbug Pipeline Shared Libraries •Независимое версионирование •Инкапсуляция •Области видимости

Slide 42

Slide 42 text

42 @oleg_nenashev, #heisenbug Пример Jenkinsfile с библиотекой my_imaginary_lib // Run build using My Imaginary Test Framework buildProject(runCobertura: true)

Slide 43

Slide 43 text

43 @oleg_nenashev, #heisenbug Объявление библиотеки [1/2] • Глобальные настройки Jenkins • Настройки папки

Slide 44

Slide 44 text

44 @oleg_nenashev, #heisenbug Объявление библиотеки [2/2] https://github.com/oleg-nenashev/my-imaginary-lib

Slide 45

Slide 45 text

45 @oleg_nenashev, #heisenbug Строение библиотеки

Slide 46

Slide 46 text

46 @oleg_nenashev, #heisenbug Классы •SomethingHelper, SomethingBuilder •@Override •Поддержка ресурсов •… Строение библиотеки

Slide 47

Slide 47 text

47 @oleg_nenashev, #heisenbug Строение библиотеки

Slide 48

Slide 48 text

48 @oleg_nenashev, #heisenbug Строение библиотеки

Slide 49

Slide 49 text

49 @oleg_nenashev, #heisenbug Классы Глобальные “переменные” • Живут внутри контекста Pipeline • Не обязательно являются переменными… Строение библиотеки

Slide 50

Slide 50 text

50 @oleg_nenashev, #heisenbug Cobertura – глобальная “переменная” (root) +- vars +- cobertura.groovy def call(String file, boolean failUnhealthy=false, boolean failUnstable=false) { step([$class: 'CoberturaPublisher', autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: file, failNoReports: true, failUnhealthy: failUnhealthy, failUnstable: failUnstable, maxNumberOfBuilds: 0, onlyStable: false, sourceEncoding: 'ASCII', zoomCoverageChart: false]) }

Slide 51

Slide 51 text

51 @oleg_nenashev, #heisenbug Cobertura – глобальная “переменная” node(‘linux’) { checkout scm sh “mvn clean verify -Dmaven.test.failure.ignore -Pcoverage” junit ”target/…/*.xml” findbugs pattern: ”**/target/findbugsXml.xml” cobertura(“target/coverage.xml”) }

Slide 52

Slide 52 text

52 @oleg_nenashev, #heisenbug ОК, как мне теперь показать Pipeline? • stage() • Blue Ocean

Slide 53

Slide 53 text

53 @oleg_nenashev, #heisenbug stage() – для визуализации node(‘linux’) { stage(“Checkout”) { checkout scm } stage(“Build”) { sh “mvn clean verify -Pcoverage” } stage(“Archive”) { junit ”target/…/*.xml” findbugs pattern: “**/target/findbugsXml.xml” cobertura(file: “target/coverage.xml”) } }

Slide 54

Slide 54 text

54 @oleg_nenashev, #heisenbug Что получили? Blue Ocean

Slide 55

Slide 55 text

55 @oleg_nenashev, #heisenbug stage() – для визуализации node(‘linux’) { stage(“Checkout”) { checkout scm } stage(“Build”) { sh “mvn clean verify -Pcoverage” } stage(“Archive”) { junit ”target/…/*.xml” findbugs pattern: “**/target/findbugsXml.xml” cobertura(file: “target/coverage.xml”) } } Что не так?

Slide 56

Slide 56 text

56 @oleg_nenashev, #heisenbug Обработка ошибок???

Slide 57

Slide 57 text

57 @oleg_nenashev, #heisenbug Declarative – post {…} Обработка ошибок

Slide 58

Slide 58 text

58 @oleg_nenashev, #heisenbug Declarative – post {…} Scripted - исключения Обработка ошибок

Slide 59

Slide 59 text

59 @oleg_nenashev, #heisenbug Обработка ошибок node(‘linux’) { stage(“Checkout”) { checkout scm } try { stage(“Build”) { sh “mvn clean verify -Pcoverage” } } finally { stage(“Archive”) { junit ”target/…/*.xml” findbugs pattern: “**/target/findbugsXml.xml” cobertura(file: “target/coverage.xml”) } } }

Slide 60

Slide 60 text

60 @oleg_nenashev, #heisenbug Пример. Failover теста при инфраструктурной ошибке Системная ошибка (код 253) Агент №1 Агент №2 . . . . . . for (def board : boards) { echo "trying board " + board; try { node(board) { checkout scm sh ‘./bin/run.sh’ // Call passed => DONE break; } } catch (Exception ex) { if (ex.message.contains ("exit code 253")) { // Fatal error fail("Test run failed") } } } Попробовать все стенды:

Slide 61

Slide 61 text

61 @oleg_nenashev, #heisenbug Достаточно ли исключений? try {…} / catch {…}

Slide 62

Slide 62 text

62 @oleg_nenashev, #heisenbug Достаточно ли исключений? try {…} / catch {…} timeout(60) {…} timestamps {…} …

Slide 63

Slide 63 text

63 @oleg_nenashev, #heisenbug Достаточно ли исключений? try {…} / catch {…} timeout(60) {…} timestamps {…} limitLogSize(“10Gb”) {…} databaseHealthCheck {…} * Не существуют, но можно сделать

Slide 64

Slide 64 text

64 @oleg_nenashev, #heisenbug Closure – лучший друг фреймворкостроителя (root) +- vars +- cobertura.groovy +- commons.groovy Object withErrorHandlers( int timeout, Closure body) { timeout(timeout) { timestamps { try { body() } catch (Exception ex) { echo "Caught exception: ${ex}" throw ex // Propagate it } } } }

Slide 65

Slide 65 text

65 @oleg_nenashev, #heisenbug Пример использования Closure node('linux') { stage("Checkout") { checkout scm } } try { stage("Build") { commons.withErrorHandlers(10) { sh "mvn clean verify -Dmaven.test.failure.ignore -Pcoverage" } } } finally { stage("Archive") { junit "target/**/TEST-*.xml" findbugs pattern: "**/target/findbugsXml.xml" cobertura("target/coverage.xml") } } }

Slide 66

Slide 66 text

66 @oleg_nenashev, #heisenbug Параллелизация тестов?

Slide 67

Slide 67 text

67 @oleg_nenashev, #heisenbug Параллелизация тестов (root) +- vars +- cobertura.groovy +- commons.groovy +- runTests.groovy Parallel Test Executor Plugin Глобальная “переменная” +

Slide 68

Slide 68 text

68 @oleg_nenashev, #heisenbug tmp tmp Параллелизация тестов Parallel Test Executor Plugin * Для простоты: Нет обработки ошибок

Slide 69

Slide 69 text

69 @oleg_nenashev, #heisenbug Параллелизация тестов stage(“Build”) { node(‘linux’) { checkout scm try { sh “mvn clean verify -PspotChecksOnly” } finally { junit ”target/…/*.xml” findbugs(”**/target/findBugs.xml”) } } } stage(“Test”) { runTests() }

Slide 70

Slide 70 text

70 @oleg_nenashev, #heisenbug Итого

Slide 71

Slide 71 text

71 @oleg_nenashev, #heisenbug Итого

Slide 72

Slide 72 text

72 @oleg_nenashev, #heisenbug Готово? tmp tmp

Slide 73

Slide 73 text

73 @oleg_nenashev, #heisenbug Он забыл Cobertura!

Slide 74

Slide 74 text

74 @oleg_nenashev, #heisenbug tmp tmp Параллелизация тестов cobertura(file: “target/coverage.xml”) -Pcoverage

Slide 75

Slide 75 text

75 @oleg_nenashev, #heisenbug tmp tmp Параллелизация тестов -Pcoverage stash includes: 'target/coverage.xml', name: “coverage-${i}.xml” cobertura(file: “target/coverage.xml”) Disclaimer: Концепт

Slide 76

Slide 76 text

76 @oleg_nenashev, #heisenbug Cobertura и parallel() (root) +- vars +- cobertura.groovy +- commons.groovy +- runTests.groovy Disclaimer: Концепт def mergeStashes(int testParallelism) { node('linux') { for (int I = 0; I < testParallelism; i++) { unstash"coverage-${i}.xml" } cobertura.merge("coverage-*.xml", "coverage-merged.xml") cobertura(file: "coverage-merged.xml") } } def merge(String pattern, String out) { //TODO: Write your own impl sh "cp coverage-1.xml ${out}" }

Slide 77

Slide 77 text

77 @oleg_nenashev, #heisenbug Там еще про классы было. Зачем они мне вообще? • Для простых случаев – не нужны

Slide 78

Slide 78 text

78 @oleg_nenashev, #heisenbug Там еще про классы было. Зачем они мне вообще? • Для простых случаев – не нужны • НО: • Все плюсы [и минусы] ООП • Builder-классы • Меньше проблем с типизацией

Slide 79

Slide 79 text

79 @oleg_nenashev, #heisenbug MailExtSender. Что хотим? import my.pipeline.lib.MailExtSender … stage(“Test”) { runTests() } stage(“Notify”) { def builder = new MailExtSender(this) .withSubject(”Test results for project Foo”) .withRecipient(”[email protected]”) .withTestReports(true) .send() } * Для простоты: Нет обработки ошибок

Slide 80

Slide 80 text

80 @oleg_nenashev, #heisenbug MailExt через классы (root) +- src +- my +- pipeline +- lib +- MailExtSender.groovy +- vars +- cobertura.groovy +- cobertura.txt +- runTests.groovy +- runTests.txt class MailExtSender { final def script String subject = "Undefined" List recipients = [] String attachmentsPattern = null MailExtSender(def script) { this.script = script } def withSubject(String subject) { this.subject = subject return this } def withRecipient(String email) { this.recipients << email return this } …

Slide 81

Slide 81 text

81 @oleg_nenashev, #heisenbug MailExt через классы (root) +- src +- my +- pipeline +- lib +- MailExtSender.groovy +- vars +- cobertura.groovy +- cobertura.txt +- runTests.groovy +- runTests.txt class MailExtSender { final def script String subject = "Undefined" List recipients = [] String attachmentsPattern = null MailExtSender(def script) { this.script = script } def withSubject(String subject) { this.subject = subject return this } def withRecipient(String email) { this.recipients << email return this } …

Slide 82

Slide 82 text

82 @oleg_nenashev, #heisenbug MailExt через классы (root) +- src +- my +- pipeline +- lib +- MailExtSender.groovy +- vars +- cobertura.groovy +- cobertura.txt +- runTests.groovy +- runTests.txt … def withTestReports(boolean add) { this.attachmentsPattern = add ? ”target/**/TEST-*.xml" : null return this } void send() { script.emailext subject: subject, body: body, attachmentsPattern: attachmentsPattern, to: recipients.join(',') } }

Slide 83

Slide 83 text

83 @oleg_nenashev, #heisenbug То есть я могу писать, как в Groovy?

Slide 84

Slide 84 text

Pipeline DSL – это НЕ Groovy

Slide 85

Slide 85 text

85 @oleg_nenashev, #heisenbug •Вызовы java.io.File не имеют смысла •Запросы должны выполняться через Remoting •Плагин: Pipeline Basic Steps Pipeline ВСЕГДА исполняется на мастере

Slide 86

Slide 86 text

86 @oleg_nenashev, #heisenbug Чем опасен вызов System.exit(0)?

Slide 87

Slide 87 text

87 @oleg_nenashev, #heisenbug Groovy Sandbox • Библиотеки по-умолчанию работают в режиме Sandbox • Ограниченный доступ к публичному API Jenkins • Аппрув вызовов через Script Security

Slide 88

Slide 88 text

88 @oleg_nenashev, #heisenbug ЧТО НЕ ТАК? Разрешения в Script Security: • static method jenkins.model.Jenkins jenkins.model.Jenkins#getInstance() • method hudson.model.Job jenkins.model.Jenkins#copy(…)

Slide 89

Slide 89 text

89 @oleg_nenashev, #heisenbug Хранение контекста – CPS/NonCPS hudson.model.FreeStyleProject

Slide 90

Slide 90 text

90 @oleg_nenashev, #heisenbug @NonCPS @NonCPS def dumpEnvVars() { def str = "Dumping build environment variables...\n" for (Map.Entry entry : currentBuild.build().environment) { str += " ${entry.key} = ${entry.value}\n" } echo str }

Slide 91

Slide 91 text

91 @oleg_nenashev, #heisenbug 1. Переключаться в NonCPS ТОЛЬКО один раз В библиотеках…

Slide 92

Slide 92 text

92 @oleg_nenashev, #heisenbug 1. Переключаться в NonCPS ТОЛЬКО один раз 2. Не смешивать CPS/NonCPS логику В библиотеках…

Slide 93

Slide 93 text

93 @oleg_nenashev, #heisenbug 1. Переключаться в NonCPS ТОЛЬКО один раз 2. Не смешивать CPS/NonCPS логику 3. toString() и Co – всегда @NonCPS В библиотеках…

Slide 94

Slide 94 text

94 @oleg_nenashev, #heisenbug А как мне вообще писать библиотеки?

Slide 95

Slide 95 text

95 @oleg_nenashev, #heisenbug

Slide 96

Slide 96 text

96 @oleg_nenashev, #heisenbug Pipeline. Средства разработки Интеграция с IDE Unit Test Framework Статический анализ Библиотеки Pipeline Средства отладки Докумен- тация Деплоймент скриптов Средства миграции на DSL Хорошо Слабовато Не хватает

Slide 97

Slide 97 text

97 @oleg_nenashev, #heisenbug Патч => Коммит => Запуск

Slide 98

Slide 98 text

98 @oleg_nenashev, #heisenbug Патч => Коммит => Запуск => Патч => Коммит => Запуск => Патч => Коммит => Запуск => ….?

Slide 99

Slide 99 text

99 @oleg_nenashev, #heisenbug Патч => Коммит => Запуск => Патч => Коммит => Запуск => Патч => Коммит => Запуск => ….?

Slide 100

Slide 100 text

100 @oleg_nenashev, #heisenbug

Slide 101

Slide 101 text

101 @oleg_nenashev, #heisenbug Как я работаю? Intellij IDEA Filesystem SCM Plugin • Подсветка синтаксиса • Документация Jenkins Исходники (папка Git) • Configuration-as-Code • Статическая конфигурация • Библиотеки • Библиотеки • Проекты с Jenkinsfile volume volume https://github.com/oleg-nenashev/heisenbug2017-demo

Slide 102

Slide 102 text

102 @oleg_nenashev, #heisenbug Документирование библиотек (root) +- README.md +- LICENSE.txt +- … +- src +- org +- oleg +- MailExtSender.groovy +- vars +- cobertura.groovy +- cobertura.txt +- runTests.groovy +- runTests.txt Documentation as Code? Текстовые файлы • Сторонние средства

Slide 103

Slide 103 text

103 @oleg_nenashev, #heisenbug Документирование библиотек (root) +- README.md +- LICENSE.txt +- … +- src +- org +- oleg +- MailExtSender.groovy +- vars +- cobertura.groovy +- cobertura.txt +- runTests.groovy +- runTests.txt Текстовые файлы Javadoc • GMaven: compile stubs • Maven Javadoc Plugin • Работает: Классы библиотек • В процессе: “vars”

Slide 104

Slide 104 text

104 @oleg_nenashev, #heisenbug Документирование библиотек (root) +- README.md +- LICENSE.txt +- … +- src +- pipeline.gdsl +- org +- oleg +- MailExtSender.groovy +- vars +- cobertura.groovy +- cobertura.txt +- … Текстовые файлы Javadoc GDSL • Генерация по плагинам • Для библиотек автогенерации нет L https://st-g.de/2016/08/jenkins-pipeline- autocompletion-in-intellij

Slide 105

Slide 105 text

105 @oleg_nenashev, #heisenbug PipelineUnit • https://github.com/jenkinsci/JenkinsPipelineUnit • Вызывается из Pipeline “mvn verify” был вызван… И вызов успешен… Для Jenkinsfile…

Slide 106

Slide 106 text

106 @oleg_nenashev, #heisenbug PipelineUnit. Тестируем библиотеки String clonePath = 'path/to/clone' def library = library() .name('commons') .retriever(gitSource('git@orgithub/devteam/jenkins-shared.git')) .targetPath(clonePath) .defaultVersion("master") .allowOverride(true) .build() helper.registerSharedLibrary(library) // Как в предыдущем примере… loadScript("job/library/exampleJob.jenkins") printCallStack() …

Slide 107

Slide 107 text

107 @oleg_nenashev, #heisenbug Автотесты есть, что дальше?

Slide 108

Slide 108 text

108 @oleg_nenashev, #heisenbug Jenkinsfile для библиотеки • Jenkinsfile вызывает PipelineUnit • Результаты публикуются в JUnit Что дальше? CI/CD для библиотек

Slide 109

Slide 109 text

109 @oleg_nenashev, #heisenbug Jenkinsfile для библиотеки • Jenkinsfile вызывает PipelineUnit • Результаты публикуются в JUnit Pull Request Builder Что дальше? CI/CD для библиотек

Slide 110

Slide 110 text

110 @oleg_nenashev, #heisenbug Jenkinsfile для библиотеки • Jenkinsfile вызывает PipelineUnit • Результаты публикуются в JUnit Pull Request Builder НО: Конфликты библиотек? Folders! Что дальше? CI/CD для библиотек

Slide 111

Slide 111 text

111 @oleg_nenashev, #heisenbug И что, оно того стоит?

Slide 112

Slide 112 text

112 @oleg_nenashev, #heisenbug И что, оно того стоит? TL;DR: Да, стоит

Slide 113

Slide 113 text

113 @oleg_nenashev, #heisenbug Библиотеки… • Упрощают использование и поддержку фреймворков • Уменьшают сложность Jenkinsfile • Сложны, но только для разработчиков

Slide 114

Slide 114 text

114 @oleg_nenashev, #heisenbug Что делать? 1. Jenkins? Переводить автоматизацию на Pipeline

Slide 115

Slide 115 text

115 @oleg_nenashev, #heisenbug Что делать? 1. Jenkins? Переводить автоматизацию Jenkins на Pipeline 2. Использовать библиотеки и минимизировать Jenkinsfile

Slide 116

Slide 116 text

116 @oleg_nenashev, #heisenbug Что делать? 1. Jenkins? Переводить автоматизацию Jenkins на Pipeline 2. Использовать библиотеки и минимизировать Jenkinsfile 3. Документировать и тестировать библиотеки

Slide 117

Slide 117 text

117 @oleg_nenashev, #heisenbug Ссылки Cлайды • http://bit.ly/heisenbug2017-nenashev-slides Демо • https://github.com/oleg-nenashev/heisenbug2017-demo Документация • https://jenkins.io/doc/book/pipeline/ • https://go.cloudbees.com

Slide 118

Slide 118 text

118 @oleg_nenashev, #heisenbug Вопросы? Контакты: E-mail: [email protected] GitHub: oleg-nenashev Twitter: @oleg_nenashev https://go.cloudbees.com

Slide 119

Slide 119 text

Software at the speed of ideas СПАСИБО! www.cloudbees.com