From 3890c6760c2e980dcd95fd04f16e956cffae1b0e Mon Sep 17 00:00:00 2001 From: chengli3 Date: Thu, 24 Oct 2019 18:44:36 +0800 Subject: [PATCH] Install private jenkins for CD jobs This patch is to create ansible playbook for jenkins installation. The private jenkins is for CD jobs. So it needs vagrant/libvirt to create VMs. Also this patch covers the jjb scripts. Signed-off-by: chengli3 Change-Id: I5a2f050a269842aa9cb6258c0039ae2573553087 --- Jenkinsfile | 30 ------- Vagrantfile | 14 +++ ci/README.md | 39 +++++--- ci/gerrit.groovy | 34 ------- ci/icn_check.xml | 105 ---------------------- ci/{setup_jenkins.sh => install_ansible.sh} | 0 ci/jjb/akraino-icn-macros.yaml | 52 +++++++++++ ci/jjb/akraino-icn-templates.yaml | 63 +++++++++++++ ci/jjb/defaults.yaml | 20 +++++ ci/jjb/project.yaml | 11 +++ ci/jjb/shell/org-logs-deploy.sh | 45 ++++++++++ ci/jjb/shell/verify.sh | 23 +++++ ci/roles/jenkins-config/defaults/main.yaml | 2 + ci/roles/jenkins-config/tasks/jenkins_gerrit.yaml | 75 ++++++++++++++++ ci/roles/jenkins-config/tasks/main.yaml | 50 +++++++++++ ci/site_jenkins.yaml | 86 +----------------- ci/vars.yaml | 9 ++ 17 files changed, 395 insertions(+), 263 deletions(-) delete mode 100644 Jenkinsfile create mode 100644 Vagrantfile delete mode 100644 ci/gerrit.groovy delete mode 100644 ci/icn_check.xml rename ci/{setup_jenkins.sh => install_ansible.sh} (100%) create mode 100644 ci/jjb/akraino-icn-macros.yaml create mode 100644 ci/jjb/akraino-icn-templates.yaml create mode 100644 ci/jjb/defaults.yaml create mode 100644 ci/jjb/project.yaml create mode 100644 ci/jjb/shell/org-logs-deploy.sh create mode 100644 ci/jjb/shell/verify.sh create mode 100644 ci/roles/jenkins-config/defaults/main.yaml create mode 100644 ci/roles/jenkins-config/tasks/jenkins_gerrit.yaml create mode 100644 ci/roles/jenkins-config/tasks/main.yaml create mode 100644 ci/vars.yaml diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 895065a..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,30 +0,0 @@ -pipeline { - agent any - options { - skipDefaultCheckout() - } - environment { - changeBranch = "change-${GERRIT_CHANGE_NUMBER}-${GERRIT_PATCHSET_NUMBER}" - } - stages { - stage("Build ISO Image") { - steps { - sh "sudo rm -rf icn build/ubuntu icn-ubuntu-18.04.iso" - sh "git clone https://gerrit.akraino.org/r/icn" - dir("icn") { - sh "git fetch origin ${GERRIT_REFSPEC}:${changeBranch}" - sh "git checkout ${changeBranch}" - sh "git rebase origin/${GERRIT_BRANCH}" - } - sh "sudo icn/tools/setup_build_machine.sh" - // sh "sudo icn/tools/collect.sh" - sh "sudo icn/tools/create_usb_bootable.sh" - } - } - } - post { - always { - archiveArtifacts artifacts: "icn-ubuntu-18.04.iso", onlyIfSuccessful: true - } - } -} diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..6cde8df --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,14 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure("2") do |config| + config.vm.box = "generic/ubuntu1804" + config.vm.hostname = "ubuntu18" + config.vm.synced_folder ".", "/vagrant" + config.vm.provider :libvirt do |libvirt| + libvirt.graphics_ip = '0.0.0.0' + libvirt.cpus = 16 + libvirt.memory = 32768 + libvirt.machine_virtual_size = 400 + end +end diff --git a/ci/README.md b/ci/README.md index c368dc3..5e3e444 100644 --- a/ci/README.md +++ b/ci/README.md @@ -1,24 +1,41 @@ -# Setup a private Jenkins server from a refresh ubuntu +# Setup a private Jenkins server from a refresh ubuntu 18.04 - -**Note:** As we don't support that downloading packages in sandbox for now, -it means that the packages are all downloaded directely from the jenkins -server. So that the jenkins server must have the same OS version with ICN -nodes. Currently, it's ubuntu 18.04 with kernel version 4.15.0-45-generic. +Akraino community has a publich jenkins cluster, we run CI jobs there. +But the CD jobs, we need to run them in our private Jenkins cluster. +For now, we support only one node private jenkins deployment. +The only supported OS is ubuntu 18.04 ## How to setup jenkins server -Put the gerrit ssh key under `icn/ci/gerrit.key` +We define vars in `vars.yaml` to customize the deployment. The default listening address is the default ip address of the Jenkins server. -To override the listening address/domain name, use variable `jenkins_hostname`. -The default Jenkins username/password is `admin/admin`. To overrides it, use variables +To override the listening address/domain name, please set `jenkins_hostname`. +The default Jenkins username/password is `admin/admin`. To overrides it, please set `jenkins_admin_username` and `jenkins_admin_password`. ```bash git clone "https://gerrit.akraino.org/r/icn" # may need to switch the branch based on your case cd icn/ci -sudo ./setup_jenkins.sh -sudo ansible-playbook site_jenkins.yaml -v +sudo ./install_ansible.sh +sudo ansible-playbook site_jenkins.yaml --extra-vars "@vars.yaml" -v ``` Once the playbook is successful, we can visite the jenkins server at http://:8080. + +## What to do next + +1. Add the gerrit ssh key as jenkins credential, so that our jobs can pull code from the gerrit. +The credential ID field must be `jenkins-ssh`. As this is hard coded in the jobs. +2. To push the logs to Akraino Nexus server, we need to create the authentication file for lftools. +The file path is `/var/lib/jenkins/.netrc` and the content should be one line +`machine nexus.akraino.org login the_name password the_pass` +3. The last step is to deploy our CD jobs by jenkins-job-builder tool. + +``` +git clone "https://gerrit.akraino.org/r/ci-management" +git clone "https://gerrit.akraino.org/r/icn" +# create the jjb config file before moving on +# https://docs.releng.linuxfoundation.org/en/latest/jenkins-sandbox.html +jenkins-jobs test ci-management/jjb:icn/ci/jjb icn-master-verify +jenkins-jobs update ci-management/jjb:icn/ci/jjb icn-master-verify +``` diff --git a/ci/gerrit.groovy b/ci/gerrit.groovy deleted file mode 100644 index 38d3076..0000000 --- a/ci/gerrit.groovy +++ /dev/null @@ -1,34 +0,0 @@ -import jenkins.* -import jenkins.model.* -import hudson.* -import hudson.model.* -import com.sonyericsson.hudson.plugins.gerrit.trigger.config.Config -import com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer -import com.sonyericsson.hudson.plugins.gerrit.trigger.PluginImpl - - -def gerrit_server_name = 'gerrit.akraino.org' -def gerrit_hostname = 'gerrit.akraino.org' -def gerrit_key_path = '/var/lib/jenkins/.ssh/gerrit.key' -def gerrit_url = 'https://gerrit.akraino.org/' -def gerrit_username = 'icn.jenkins' - -if (PluginImpl.getInstance().getServer(gerrit_server_name) == null) { - GerritServer defaultServer = new GerritServer(gerrit_server_name) - Config config = defaultServer.getConfig() - PluginImpl.getInstance().addServer(defaultServer) - defaultServer.start() - // setting properties - config.setGerritHostName(gerrit_hostname) - config.setGerritFrontEndURL(gerrit_url) - config.setGerritUserName(gerrit_username) - config.setGerritAuthKeyFile(new File(gerrit_key_path)) -} else { - Config config = PluginImpl.getInstance().getServer(gerrit_server_name).getConfig() - config.setGerritHostName(gerrit_hostname) - config.setGerritFrontEndURL(gerrit_url) - config.setGerritUserName(gerrit_username) - config.setGerritAuthKeyFile(new File(gerrit_key_path)) - PluginImpl.getInstance().save() -} -return "success" diff --git a/ci/icn_check.xml b/ci/icn_check.xml deleted file mode 100644 index 668f711..0000000 --- a/ci/icn_check.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - skipDefaultCheckout - - - - ICN CI job - false - - - - - - - - PLAIN - icn - - - ANT - ** - - - false - - - - - false - false - false - false - - 0 - 1 - 0 - -1 - 0 - -1 - false - - false - true - PLAIN - - BASE64 - PLAIN - BASE64 - - ci failed - ci pass - - - - - gerrit.akraino.org - - - false - false - false - false - false - - - false - - - - - - - - - 2 - - - origin - https://gerrit.akraino.org/r/icn.git - - - - - origin/${GERRIT_BRANCH} - - - false - - - - - - Jenkinsfile - true - - - false - \ No newline at end of file diff --git a/ci/setup_jenkins.sh b/ci/install_ansible.sh similarity index 100% rename from ci/setup_jenkins.sh rename to ci/install_ansible.sh diff --git a/ci/jjb/akraino-icn-macros.yaml b/ci/jjb/akraino-icn-macros.yaml new file mode 100644 index 0000000..e18951a --- /dev/null +++ b/ci/jjb/akraino-icn-macros.yaml @@ -0,0 +1,52 @@ +--- +- publisher: + name: icn-infra-publish + # lf-infra macro to finish up a build. + # + # Handles the following: + # - Shipping logs to Nexus logs site repository + # - Cleanup workspace + publishers: + - postbuildscript: + builders: + - role: BOTH + build-on: + - ABORTED + - FAILURE + - NOT_BUILT + - SUCCESS + - UNSTABLE + build-steps: + - lf-infra-sysstat + - lf-infra-package-listing + - icn-infra-ship-logs + mark-unstable-if-failed: true + - workspace-cleanup: + exclude: + # Do not clean up *.jenkins-trigger files for jobs that use a + # properties file as input for triggering another build. + - "**/*.jenkins-trigger" + fail-build: false + +- builder: + name: icn-infra-ship-logs + builders: + # Ensure no pre-existing .netrc files are overriding logs config + #- lf-provide-maven-settings-cleanup + #- config-file-provider: + # files: + # - file-id: "jenkins-log-archives-settings" + # variable: "SETTINGS_FILE" + #- lf-infra-create-netrc: + # server-id: logs + - shell: !include-raw: + # Ensure python-tools are installed in case job template does not + # call the lf-infra-pre-build macro. + - ../../../ci-management/jjb/global-jjb/shell/python-tools-install.sh + - shell: !include-raw: + - shell/org-logs-deploy.sh + #- shell: !include-raw: + # - ../../../ci-management/jjb/global-jjb/shell/logs-clear-credentials.sh + - description-setter: + regexp: "^Build logs: .*" + diff --git a/ci/jjb/akraino-icn-templates.yaml b/ci/jjb/akraino-icn-templates.yaml new file mode 100644 index 0000000..f610a88 --- /dev/null +++ b/ci/jjb/akraino-icn-templates.yaml @@ -0,0 +1,63 @@ +--- +- job-template: + id: icn-stream-verify + name: 'icn-{stream}-verify' + defaults: icn + archive-artifacts: > + **/*.log + build-days-to-keep: 30 + build-timeout: 60 + stream: master + project-type: freestyle + submodule-recursive: true + #node: '{build-node}' + + properties: + - lf-infra-properties: + build-days-to-keep: '{build-days-to-keep}' + + parameters: + - lf-infra-parameters: + project: '{project}' + stream: '{stream}' + branch: '{branch}' + lftools-version: '{lftools-version}' + + - string: + name: ARCHIVE_ARTIFACTS + default: '{archive-artifacts}' + description: Artifacts to archive to the logs server. + + - string: + name: NEXUS_LOG_SUBDIR + default: '{nexus_log_subdir}' + description: Organization sub dir on Akraino Nexus server. + + wrappers: + - lf-infra-wrappers: + build-timeout: '{build-timeout}' + jenkins-ssh-credential: '{jenkins-ssh-credential}' + + scm: + - lf-infra-gerrit-scm: + jenkins-ssh-credential: '{jenkins-ssh-credential}' + git-url: '{git-url}/{project}.git' + refspec: '$GERRIT_REFSPEC' + branch: '$GERRIT_BRANCH' + submodule-recursive: '{submodule-recursive}' + submodule-timeout: '{submodule-timeout}' + submodule-disable: false + choosing-strategy: 'gerrit' + + triggers: + - timed: "@midnight" + + builders: + - shell: !include-raw-escape: + - shell/verify.sh + + publishers: + - icn-infra-publish +# - email: +# recipients: icn.jenkins@intel.com + diff --git a/ci/jjb/defaults.yaml b/ci/jjb/defaults.yaml new file mode 100644 index 0000000..cc17382 --- /dev/null +++ b/ci/jjb/defaults.yaml @@ -0,0 +1,20 @@ +--- +- defaults: + name: icn + + gerrit-server-name: Primary + git-url: 'ssh://icn.jenkins@gerrit.akraino.org:29418' + jenkins-ssh-credential: jenkins-ssh + lftools-version: '<1.0.0' + submodule-timeout: 10 + + # Nexus 2 for jars + mvn-snapshot-id: snapshots + mvn-staging-id: staging + mvn-site-id: site + nexus-snapshot-repo: snapshots + staging-profile-id: a7925c009cb5d + + # Sonarcloud + sonarcloud_project_organization: akraino-edge-stack + sonarcloud_api_token: 6864256050596cb8f0cb689d599687f5de46f414 diff --git a/ci/jjb/project.yaml b/ci/jjb/project.yaml new file mode 100644 index 0000000..e1aa2de --- /dev/null +++ b/ci/jjb/project.yaml @@ -0,0 +1,11 @@ +--- +- project: + name: icn-private + project: icn + project-name: icn + nexus_log_subdir: intel/ICN_CD_logs + stream: + - master: + branch: master + jobs: + - icn-stream-verify diff --git a/ci/jjb/shell/org-logs-deploy.sh b/ci/jjb/shell/org-logs-deploy.sh new file mode 100644 index 0000000..ca828cb --- /dev/null +++ b/ci/jjb/shell/org-logs-deploy.sh @@ -0,0 +1,45 @@ +#!/bin/bash -l +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2017 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +echo "---> logs-deploy.sh" + +# Ensure we fail the job if any steps fail +# Disable 'globbing' +set -euf -o pipefail + +JENKINS_HOSTNAME=pod14-node2 +NEXUS_URL=https://nexus.akraino.org +LOGS_SERVER=https://logs.akraino.org + +NEXUS_LOG_SUBDIR=${NEXUS_LOG_SUBDIR:-$SILO} + +source ~/.local/bin/activate +if [[ -z $"${LOGS_SERVER:-}" ]]; then + echo "WARNING: Logging server not set" +else + nexus_url="${NEXUSPROXY:-$NEXUS_URL}" + nexus_path="${NEXUS_LOG_SUBDIR}/${JENKINS_HOSTNAME}/${JOB_NAME}/${BUILD_NUMBER}" + + if [[ -n ${ARCHIVE_ARTIFACTS:-} ]] ; then + # Handle multiple search extensions as separate values to '-p|--pattern' + # "arg1 arg2" -> (-p arg1 -p arg2) + pattern_opts=() + for arg in $ARCHIVE_ARTIFACTS; do + pattern_opts+=("-p" "$arg") + done + lftools deploy archives "${pattern_opts[@]}" \ + "$nexus_url" "$nexus_path" "$WORKSPACE" + else + lftools deploy archives "$nexus_url" "$nexus_path" "$WORKSPACE" + fi + lftools deploy logs "$nexus_url" "$nexus_path" "${BUILD_URL:-}" + + echo "Build logs: $LOGS_SERVER/$nexus_path" +fi diff --git a/ci/jjb/shell/verify.sh b/ci/jjb/shell/verify.sh new file mode 100644 index 0000000..4b3016f --- /dev/null +++ b/ci/jjb/shell/verify.sh @@ -0,0 +1,23 @@ +#!/bin/bash -l +echo "---> verify.sh" + +# Ensure we fail the job if any steps fail +# Disable 'globbing' +set -exuf -o pipefail + +function clean_vm { + vagrant destroy -f +} +trap clean_vm EXIT + +vagrant destroy -f +vagrant up +vagrant ssh -c " +set -exuf +sudo parted -a optimal /dev/sda ---pretend-input-tty resizepart 3 yes 100% +sudo resize2fs /dev/sda3 +sudo apt update +sudo apt install -y make +cd /vagrant +sudo make verifier +" diff --git a/ci/roles/jenkins-config/defaults/main.yaml b/ci/roles/jenkins-config/defaults/main.yaml new file mode 100644 index 0000000..aebea32 --- /dev/null +++ b/ci/roles/jenkins-config/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +enable_vagrant: true diff --git a/ci/roles/jenkins-config/tasks/jenkins_gerrit.yaml b/ci/roles/jenkins-config/tasks/jenkins_gerrit.yaml new file mode 100644 index 0000000..e19173e --- /dev/null +++ b/ci/roles/jenkins-config/tasks/jenkins_gerrit.yaml @@ -0,0 +1,75 @@ +--- +- name: restart jenkins to use new installed plugins + meta: flush_handlers + +- name: Wait for Jenkins to start up before proceeding. + command: > + curl -D - --silent --max-time 5 http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}/cli/ + args: + warn: false + register: result + until: > + (result.stdout.find("403 Forbidden") != -1) + or (result.stdout.find("200 OK") != -1) + and (result.stdout.find("Please wait while") == -1) + retries: "{{ jenkins_connection_retries | default(60) }}" + delay: "{{ jenkins_connection_delay | default(5) }}" + changed_when: false + check_mode: false + +- name: create directory /var/lib/jenkins/.ssh + file: + path: /var/lib/jenkins/.ssh + owner: jenkins + group: jenkins + state: directory + +- name: place gerrit ssh key + copy: + src: "{{ gerrit_key_path | default('gerrit.key') }}" + dest: /var/lib/jenkins/.ssh/gerrit.key + owner: jenkins + group: jenkins + mode: '0600' + tags: [gerrit] + +- name: grant jenkins user sudo + copy: + content: "jenkins ALL=(ALL) NOPASSWD: ALL" + dest: /etc/sudoers.d/jenkins + owner: root + group: root + mode: '0660' + tags: [gerrit] + +- name: add gerrit server + jenkins_script: + script: "{{lookup('file', 'gerrit.groovy')}}" + url: "http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}" + user: "{{ jenkins_admin_username }}" + password: "{{ jenkins_admin_password }}" + validate_certs: no + register: result + failed_when: "'Result: success\n' != result.output" + tags: [gerrit] + +- name: Install python-pip + apt: + name: python-pip + tags: [jobs] + +- name: Install python-jenkins and lxml(required by jenkins_job module) + pip: + name: + - python-jenkins + - lxml + tags: [jobs] + +- name: Add pipeline job for ICN CI + jenkins_job: + name: icn_check + config: "{{lookup('file', 'icn_check.xml')}}" + url: "http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}" + user: "{{ jenkins_admin_username }}" + password: "{{ jenkins_admin_password }}" + tags: [jobs] diff --git a/ci/roles/jenkins-config/tasks/main.yaml b/ci/roles/jenkins-config/tasks/main.yaml new file mode 100644 index 0000000..008b4ec --- /dev/null +++ b/ci/roles/jenkins-config/tasks/main.yaml @@ -0,0 +1,50 @@ +--- +- name: grant jenkins user sudo + copy: + content: "jenkins ALL=(ALL) NOPASSWD: ALL" + dest: /etc/sudoers.d/jenkins + owner: root + group: root + mode: '0660' + +- name: install and configure vagrant + block: + - name: install libvirt and vagrant + package: + name: "{{ item }}" + with_items: + - libvirt-bin + - vagrant + + - name: add jenkins user to libvirt and vagrant group + user: + name: jenkins + append: yes + groups: + - libvirt + + - name: setup vagrant-libvirt plugin + shell: vagrant plugin install vagrant-libvirt + become_user: jenkins + when: enable_vagrant + tags: [vagrant] + +- name: install packages for lftools log + package: + name: "{{ item }}" + with_items: + - python3-pip + - python3-venv + - facter + - sysstat + +- name: enable sysstat + lineinfile: + path: /etc/default/sysstat + regexp: '^ENABLED=' + line: ENABLED="true" + +- name: start sysstat service + service: + name: sysstat + state: restarted diff --git a/ci/site_jenkins.yaml b/ci/site_jenkins.yaml index 1510fc8..b76c8a2 100644 --- a/ci/site_jenkins.yaml +++ b/ci/site_jenkins.yaml @@ -1,89 +1,9 @@ - hosts: localhost - vars: - jenkins_hostname: "{{ ansible_default_ipv4.address }}" - jenkins_version: 2.192 - jenkins_plugin_timeout: 360 - jenkins_plugins: - - gerrit-trigger - - workflow-aggregator - - git roles: - role: geerlingguy.java become: yes - role: geerlingguy.jenkins become: yes - tasks: - - name: restart jenkins to use new installed plugins - meta: flush_handlers - - - name: Wait for Jenkins to start up before proceeding. - command: > - curl -D - --silent --max-time 5 http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}/cli/ - args: - warn: false - register: result - until: > - (result.stdout.find("403 Forbidden") != -1) - or (result.stdout.find("200 OK") != -1) - and (result.stdout.find("Please wait while") == -1) - retries: "{{ jenkins_connection_retries | default(60) }}" - delay: "{{ jenkins_connection_delay | default(5) }}" - changed_when: false - check_mode: false - - - name: create directory /var/lib/jenkins/.ssh - file: - path: /var/lib/jenkins/.ssh - owner: jenkins - group: jenkins - state: directory - - - name: place gerrit ssh key - copy: - src: "{{ gerrit_key_path | default('gerrit.key') }}" - dest: /var/lib/jenkins/.ssh/gerrit.key - owner: jenkins - group: jenkins - mode: '0600' - tags: [gerrit] - - - name: grant jenkins user sudo - copy: - content: "jenkins ALL=(ALL) NOPASSWD: ALL" - dest: /etc/sudoers.d/jenkins - owner: root - group: root - mode: '0660' - tags: [gerrit] - - - name: add gerrit server - jenkins_script: - script: "{{lookup('file', 'gerrit.groovy')}}" - url: "http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}" - user: "{{ jenkins_admin_username }}" - password: "{{ jenkins_admin_password }}" - validate_certs: no - register: result - failed_when: "'Result: success\n' != result.output" - tags: [gerrit] - - - name: Install python-pip - apt: - name: python-pip - tags: [jobs] - - - name: Install python-jenkins and lxml(required by jenkins_job module) - pip: - name: - - python-jenkins - - lxml - tags: [jobs] - - - name: Add pipeline job for ICN CI - jenkins_job: - name: icn_check - config: "{{lookup('file', 'icn_check.xml')}}" - url: "http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}" - user: "{{ jenkins_admin_username }}" - password: "{{ jenkins_admin_password }}" - tags: [jobs] + - role: jenkins-config + become: yes + tags: [jenkins-config] diff --git a/ci/vars.yaml b/ci/vars.yaml new file mode 100644 index 0000000..ea35d08 --- /dev/null +++ b/ci/vars.yaml @@ -0,0 +1,9 @@ +--- +jenkins_hostname: "{{ ansible_default_ipv4.address }}" +jenkins_version: 2.192 +jenkins_plugin_timeout: 360 +jenkins_plugins: + - gerrit-trigger + - git + - postbuildscript + - config-file-provider -- 2.16.6