diff --git a/jenkinsfiles/Jenkinsfile_release_tag b/jenkinsfiles/Jenkinsfile_release_tag index ec4f230..8f14715 100644 --- a/jenkinsfiles/Jenkinsfile_release_tag +++ b/jenkinsfiles/Jenkinsfile_release_tag @@ -4,32 +4,42 @@ import groovy.json.JsonOutput def PROJECT_URL_DEFAULT = "https://github.com/dseeley/esxifree_guest" def PROJECT_BRANCH_DEFAULT = "master" //Set the default git branch to use if we're not running an SCM job (e.g. if we're copying/pasting into a pipeline script) +def pypi_ansible = ["curl", "-s", "-H", "Accept: application/json", "-H", "Content-type: application/json", "GET", "https://pypi.org/pypi/ansible/json"].execute().text +def pypi_ansible_latest = new groovy.json.JsonSlurper().parseText(pypi_ansible).releases.keySet()[-1] + //This allows us to create our own Docker image for this specific use-case. Once it is built, it will not be rebuilt, so only adds delay the first time we use it. -def create_custom_image(image_name, params = "") { +def create_custom_image(image_name, build_opts = "") { // Create a lock to prevent building the same image in parallel - lock('IMAGEBUILDLOCK__' + env.NODE_NAME) { + lock('IMAGEBUILDLOCK__' + image_name + '__' + env.NODE_NAME) { def jenkins_username = sh(script: 'whoami', returnStdout: true).trim() def jenkins_uid = sh(script: "id -u ${jenkins_username}", returnStdout: true).trim() def jenkins_gid = sh(script: "id -g ${jenkins_username}", returnStdout: true).trim() def dockerfile = """ - FROM ubuntu:20.04 + FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive ENV JENKINS_HOME=${env.JENKINS_HOME} ENV HOME=${env.JENKINS_HOME} ENV PIPENV_VENV_IN_PROJECT=true ENV TZ=Europe/London + SHELL ["/bin/bash", "-c"] + RUN groupadd -g ${jenkins_gid} ${jenkins_username} && useradd -m -u ${jenkins_uid} -g ${jenkins_gid} -s /bin/bash ${jenkins_username} ### Note: use pip to install pipenv (not apt) to avoid pypa/pipenv#2196 (when using PIPENV_VENV_IN_PROJECT) RUN apt-get update \ - && apt-get install -y git iproute2 \ - python3-boto python3-boto3 python3-botocore python3-dev python3-distutils python3-dnspython python3-google-auth python3-googleapi python3-libcloud python3-jinja2 python3-jmespath python3-netaddr python3-paramiko python3-pip python3-ruamel.yaml python3-setuptools python3-wheel python3-xmltodict \ - && pip3 install pipenv ansible>=5.2.0 \ - && pip3 install -r \$(pip3 show ansible | grep ^Location | sed 's/Location: \\(.*\\)/\\1/')/ansible_collections/azure/azcollection/requirements-azure.txt + && apt-get install -y git iproute2 python3-boto python3-boto3 python3-dev python3-distutils python3-docker python3-dnspython python3-google-auth python3-googleapi python3-jinja2 python3-jmespath python3-libcloud python3-libvirt python3-lxml python3-netaddr python3-paramiko python3-passlib python3-pip python3-pyvmomi python3-ruamel.yaml python3-setuptools python3-wheel python3-xmltodict \ + && pip3 --no-cache-dir install pycdlib pipenv ansible==${params.ANSIBLE_VERSION} + + ### Install community.libvirt:==1.2.0 if our Ansible version is < 6.3.0 (it is otherwise included in the pypi release) and azure.azcollection:==1.13.0 if our Ansible version is <= 6.0.0 (it is otherwise included in the pypi release) + RUN if [ \$(echo -e "\$(pip3 --no-cache-dir show ansible | grep ^Version | sed -r 's/^Version: (.*)/\\1/')\\n6.4.0"|sort|head -1) != "6.4.0" ]; then ansible-galaxy collection install community.libvirt:==1.2.0 -p \$(pip3 --no-cache-dir show ansible | grep ^Location | sed 's/Location: \\(.*\\)/\\1/') --force && chown -R jenkins.jenkins ~/.ansible; fi \ + && if [ \$(echo -e "\$(pip3 --no-cache-dir show ansible | grep ^Version | sed -r 's/^Version: (.*)/\\1/')\\n6.1.0"|sort|head -1) != "6.1.0" ]; then ansible-galaxy collection install azure.azcollection:==1.13.0 -p \$(pip3 --no-cache-dir show ansible | grep ^Location | sed -r 's/Location: (.*)/\\1/') --force && chown -R jenkins.jenkins ~/.ansible; fi + + ### Install the azcollection/requirements-azure.txt dependencies (in the default python library location) + RUN pip3 --no-cache-dir install -r \$(pip3 --no-cache-dir show ansible | grep ^Location | sed -r 's/^Location: (.*)/\\1/')/ansible_collections/azure/azcollection/requirements-azure.txt """.stripIndent() - writeFile(file: "Dockerfile", text: dockerfile, encoding: "UTF-8") - custom_build = docker.build(image_name, params + "--network host .") + writeFile(file: "Dockerfile_${image_name}", text: dockerfile, encoding: "UTF-8") + custom_build = docker.build(image_name, build_opts + "--network host -f Dockerfile_${image_name} .") return (custom_build) } @@ -40,12 +50,13 @@ properties([ parameters([ string(name: 'NEW_VERSION', defaultValue: "", description: "Specify either the version to be created (e.g.: v1.0.0), or 'next' to apply the next patch version."), credentials(name: 'GIT_CREDS', credentialType: 'com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl', defaultValue: 'GITHUB_SVC_USER', description: 'Jenkins username/password credentials for GitHub', required: false), + string(name: 'ANSIBLE_VERSION', defaultValue: pypi_ansible_latest, description: "Ansible version."), booleanParam(name: 'UPDATE_GALAXY', defaultValue: true, description: 'Tick the box to also update Ansible-Galaxy repo') ]) ]) node { - if (params.NEW_VERSION != "") { + if (params.NEW_VERSION && params.NEW_VERSION != "") { stage('Setup Environment') { sh 'printenv | sort' echo "Params: $params" @@ -63,13 +74,13 @@ node { def docker_parent_net_str = "" if (sh(script: 'grep -sq "docker\\|lxc" /proc/1/cgroup', returnStatus: true) == 0) { println("Running in docker. Getting network to pass to docker-in-docker containers...") - def docker_parent_net_id = sh(script: 'docker inspect $(basename $(cat /proc/1/cpuset)) -f "{{ range .NetworkSettings.Networks }}{{println .NetworkID}}{{end}}" | head -n 1', returnStdout: true).trim() + def docker_parent_net_id = sh(script: 'docker inspect $(grep -oP \'(?<=docker-)[a-f0-9]+(?=\\.scope)\' /proc/1/cgroup | head -1) -f "{{ range .NetworkSettings.Networks }}{{println .NetworkID}}{{end}}" | head -n 1', returnStdout: true).trim() docker_parent_net_str = "--network ${docker_parent_net_id}" println("docker_parent_net_str: ${docker_parent_net_str}") } /*** Create a custom docker image within this Jenkinsfile ***/ - create_custom_image("ubuntu_ansible", "").inside("--init ${docker_parent_net_str}") { + create_custom_image("ubuntu_ansible${params.ANSIBLE_VERSION}", "").inside("--init ${docker_parent_net_str}") { def new_tag_version = params.NEW_VERSION stage('Create new version') { withCredentials([usernamePassword(credentialsId: params.GIT_CREDS, usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PASS')]) { diff --git a/jenkinsfiles/Jenkinsfile_release_tag__auto b/jenkinsfiles/Jenkinsfile_release_tag__auto index 54159d1..5cb2270 100644 --- a/jenkinsfiles/Jenkinsfile_release_tag__auto +++ b/jenkinsfiles/Jenkinsfile_release_tag__auto @@ -1,7 +1,10 @@ #!groovy +def pypi_ansible = ["curl", "-s", "-H", "Accept: application/json", "-H", "Content-type: application/json", "GET", "https://pypi.org/pypi/ansible/json"].execute().text +def pypi_ansible_latest = new groovy.json.JsonSlurper().parseText(pypi_ansible).releases.keySet()[-1] + node { stage('Call ansible/esxifree_guest-release-tag') { - build job: 'ansible/esxifree_guest-release-tag', parameters: [string(name: 'NEW_VERSION', value: "next")] + build job: 'ansible/esxifree_guest-release-tag', parameters: [string(name: 'NEW_VERSION', value: "next"), string(name: 'ANSIBLE_VERSION', value: pypi_ansible_latest)] } } \ No newline at end of file