Jenkins CICD Pipeline for Python

文章目录

  • Jenkins CICD Pipeline for Python
    • 配置Jenkins Node server
      • 安装Git
      • 安装Python工具和依赖
    • 配置Jenkins Node
    • Jenkins CICD Pipeline for Python
      • agent
      • options
      • stages
        • stage - Initialize
        • stage - Checkout
        • stage - Prepare Build Env
        • stage - Unit Test
        • stage - Code Quality Check
        • stage - Packaging

Jenkins CICD Pipeline for Python

本文描述了使用Ubuntu 18.04和Python 3.6.8作为Jenkins Node来对Python项目做CICD Pipeline。

配置Jenkins Node server

安装Git

一般地Ubuntu 18.04已经自带Git,可以运行git --version来检查是否已经安装Git。

如果还未安装,可以运行以下命令来安装:

sudo apt-get update
sudo apt-get install git -y

安装Python工具和依赖

一般地Ubuntu 18.04已经自带Python 3.6.8。

运行以下命令安装Python工具和依赖:

sudo apt-get update
sudo apt-get install python3-pip python3-venv python3-dev gcc libmysqlclient-dev -y

python3 --version
pip3 --version

配置Jenkins Node

参考下面的文章以SSH方式配置Jenkins Node:

  • https://blog.csdn.net/nklinsirui/article/details/96485501

Jenkins CICD Pipeline for Python

Pipeline用的工具列表如下:

分类 工具
版本控制工具 GitLab + Git
流水线 Jenkins Pipeline
依赖管理 pip3 + venv + requirements.txt
单元测试 nosetests
测试覆盖率检查 coverage + Jenkins Cobertura插件
代码质量分析 pylint + Jenkins Warnings插件
应用打包 pyinstaller

agent

让Pipeline运行在指定label的Jenkins Node上:

agent {label 'ubuntu-python3'}

options

options {
	// Keep max num of recent builds
	buildDiscarder(logRotator(numToKeepStr: "15"))
	// Add timestamps on console output
	timestamps()
    // Set GitLab connection
	gitLabConnection('GitlabAccess')
    // Disable concurrent builds
	disableConcurrentBuilds()
}

stages

stage - Initialize

在构建前清空对应的workspace:

stage('Initialize') {
    steps {
	    sh "env"
		sh "pwd && ls -ltra"
		cleanWs()
		sh "pwd && ls -ltra"
    }
}

stage - Checkout

从GitLab上拉取代码:

stage('Checkout') {
    steps {
        git branch: "${GIT_REPO_BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}", url: "${GIT_REPO_URL}"
    }
}

stage - Prepare Build Env

准备Python的构建环境,包括:

  • 检查Python版本
  • 创建venv (使得后面的CICD步骤都在这个隔离的venv中进行,免得污染Jenkins Node服务器全局的Python环境)
  • 激活该venv
  • 安装CI/CD的依赖(比如单元测试、测试覆盖率检查和代码质量检查)
  • 安装项目的依赖
stage('Prepare Build Env') {
	steps {
		sh """
			python3 --version
			python3 -m venv .venv
			. .venv/bin/activate
			pip3 install wheel
			pip3 install nose
			pip3 install coverage
			pip3 install pylint
			pip3 install -r requirements.txt
			pip3 list
		"""
	}
}

说明:

  • . .venv/bin/activate 如果写成source .venv/bin/activate,需要打开Manage Jenkins -> Configure System -> Shell -> Shell executable, 设置该值为 /bin/bash,但是不建议修改Jenkins的该项设置,会导致其它非Linux的Jenkins Node可能出现"script.sh: not found"的错误。
  • pip3的缺省缓存目录为~/.cache/pip, ~是Jenkins Node的Home目录
  • Install “wheel” firstly to fix “error: invalid command ‘bdist_wheel’” error when install requirements

stage - Unit Test

在venv上运行单元测试和代码测试覆盖率检查:

stage('Unit Test') {
    steps {
	    echo "Run unit test and coverage check"
		sh """
			. .venv/bin/activate
			nosetests -v --with-xunit --xunit-file=${UNIT_TEST_REPORT} --with-coverage --cover-xml --cover-xml-file="${COVERAGE_REPORT}" --cover-package=${COVER_PACKAGE} --cover-erase
		"""
	}
	post { 
        always { 
            echo "Archive test results"
            junit allowEmptyResults: true, testResults: "${UNIT_TEST_REPORT}"
			
			// Requires Cobertura plugin to archive and display converage report
			// https://wiki.jenkins.io/display/JENKINS/Cobertura+Plugin
			echo "Archive coverage report"
			cobertura autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: "${COVERAGE_REPORT}", failNoReports: false, failUnhealthy: false, failUnstable: false, maxNumberOfBuilds: 0, onlyStable: false, zoomCoverageChart: false
        }
    }
}

说明:

  • 上面的nosetests以verbose模式运行(-v),生成xunit格式的单元测试报告(--with-unit),并可指定单元测试报告生成的位置(--xunit-file);调用coverage插件(--with-coverage)生成xml格式的代码测试覆盖率报告(--cover-xml),并可指定代码测试覆盖率报告生成的位置(--cover-xml-file),并可指定对哪些代码目录进行测试覆盖率检查(--cover-package);并清除上一次的代码测试覆盖率报告(--cover-erase)。
  • 需要安装Jenkins Cobertura插件才能归档和展示代码测试覆盖率报告

stage - Code Quality Check

在venv上运行代码质量检查:

stage('Code Quality Check') {
    steps {
	    echo "Run pylint code style check"
		// Ignore pylint comments via "-d C"
		sh """
			. .venv/bin/activate
			pylint -d C -f parseable ${SOURCE_ROOT} --exit-zero | tee ${PYLINT_REPORT}
		"""
	}
	post { 
        always { 
            // Requires Warnings plugin since Violations plugin is deprecated
			// http://wiki.jenkins-ci.org/x/G4CGAQ
			warnings canComputeNew: false, canResolveRelativePaths: false, canRunOnFailed: true, categoriesPattern: '', defaultEncoding: '', excludePattern: '', healthy: '', includePattern: '', messagesPattern: '', parserConfigurations: [[parserName: 'PyLint', pattern: "${PYLINT_REPORT}"]], unHealthy: ''
        }
    }
}

说明:

  • pylint可以忽略对某些警告级别,比如通过-d C忽略Comment级别的警告,可以通过--exit-zero参数让pylint总是返回成功代码0,并可以指定生成的报告文件

stage - Packaging

在venv上做应用打包:

stage('Packaging') {
	steps {
	    echo "Run packaging Python program"
		// Requires to run pyinstaller in each kind of machine
		
		script {
			PACKAGE_NAME = "${PACKAGE_ID}"
			if ("${params.PACKAGE_VERSION}" != "") {
				PACKAGE_NAME = "${PACKAGE_NAME}-${params.PACKAGE_VERSION}"
			}
			PACKAGE_PATH = "./dist/${PACKAGE_NAME}"
		}

		sh """
		    . .venv/bin/activate
			pip3 install pyinstaller
			pyinstaller ${ENTRYPOINT_SCRIPT} --onefile --name ${PACKAGE_NAME}
			pwd && ls -ltra
			echo "Package: ${PACKAGE_PATH}"
			du -sh ${PACKAGE_PATH}
			sha256sum ${PACKAGE_PATH}
		"""
	}
}

说明:

  • pyinstaller对应用的入口脚本(entrypoint script)进行打包,可以生成一个目录;也可以通过--onefile参数来生成一个应用二进制包,并通过--name指定应用二进制包的名称
  • 使用pyinstaller为Python应用打包,使得Python应用的分发和部署更为简单,不用再去另外安装相关依赖
  • 由于pyinstaller的限制,应用要部署的机器应该要和运行pyinstaller打包的机器一致,比如应用部署的服务器是Ubuntu,对应打包的Jenkins Node最好也是Ubuntu

你可能感兴趣的:(Jenkins,Python)