我有一个 FastAPI 应用程序,我已经为其配置了 Jenkins 管道。当我在启用代码覆盖率的情况下执行单元测试时,它们失败并出现以下错误:
Started by user gold
Obtained Jenkinsfile from git https://github.com/edtshuma/devsecops-labs.git
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/Python-DevSecOps
....
....
[Pipeline] sh
+ pip install -r requirements.txt
....
Requirement already satisfied: uvicorn==0.20.0 in ./.pyenv-usr-bin-python3.8/lib/python3.8/site-packages (from -r requirements.txt (line 41)) (0.20.0)
Requirement already satisfied: watchfiles==0.18.1 in ./.pyenv-usr-bin-python3.8/lib/python3.8/site-packages (from -r requirements.txt (line 42)) (0.18.1)
Requirement already satisfied: websockets==10.4 in ./.pyenv-usr-bin-python3.8/lib/python3.8/site-packages (from -r requirements.txt (line 43)) (10.4)
+ sudo chown -R jenkins:jenkins ./docs/unit-tests/htmlcoverage
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
[Pipeline] }
[Pipeline] // withPythonEnv
詹金斯文件
pipeline {
agent any
triggers {
githubPush()
}
stages {
stage('Setup'){
steps{
withPythonEnv('/usr/bin/python3.8') {
sh 'echo "Job is starting" '
}
}
}
stage('Unit Tests'){
steps{
withPythonEnv('/usr/bin/python3.8') {
sh '''pip install -r requirements.txt
sudo chown -R jenkins:jenkins ./docs/unit-tests/htmlcoverage
pytest -v --junitxml=docs/unit-tests/htmlcoverage/coverage.xml --cov-report xml --cov app.main
'''
}
}
}
stage('Publish Test Report'){
steps{
cobertura autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: 'coverage*.xml', conditionalCoverageTargets: '70, 0, 0', failUnhealthy: false, failUnstable: false, lineCoverageTargets: '80, 0, 0', maxNumberOfBuilds: 0, methodCoverageTargets: '80, 0, 0', onlyStable: false, sourceEncoding: 'ASCII', zoomCoverageChart: false
archiveArtifacts artifacts: 'docs/unit-tests/htmlcoverage/*.*'
}
}
}
}
我添加了行 sudo chown -R jenkins:jenkins ./docs/unit-tests/htmlcoverage 因为我面临覆盖文件的权限错误:
INTERNALERROR> PermissionError: [Errno 13] Permission denied: 'coverage.xml'
我还验证了 coverage.xml 在 root 用户下,而不是普通的 jenkins 用户(甚至是什么原因造成的?):
我尝试过的:
echo “jenkins ALL=(ALL) NOPASSWD: ALL” >> /etc/sudoers
这导致相同的错误
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
echo “jenkins ALL= NOPASSWD: ALL” >> /etc/sudoers
这也会导致同样的错误
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
在这两种情况下,我都重新启动了 jenkins 服务。 jenkins 用户也已经添加到 sudo 组。
我到底错过了什么?
docs
文件夹是root权限的,需要root权限清理,可以添加一个临时stage来清理,如下所示,一旦你确定你的管道不会使用root,你可以删除临时stage
stage('Clean Test Report') {
steps {
sh '''
docker run -t \
-u root \
-v "$(pwd)":/"$(pwd)" \
--entrypoint='' \
<what ever a docker image> \
rm -rf docs
'''
}
}
stage('Unit Tests'){
steps{
withPythonEnv('/usr/bin/python3.8') {
sh '''
ls -al
pip install -r requirements.txt
pytest -v \
--junitxml=docs/unit-tests/htmlcoverage/coverage.xml \
--cov-report xml \
--cov app.main
'''
}
}
}
要防止管道以 root 身份运行容器,您可以执行以下操作
# run container in sh step
docker run \
-u $(id -u):$(id -g) \
-v /etc/passwd:/etc/passwd \
<other options as you need>
# run container by docker global variable
container = docker.image(<image>).run('-u $(id -u):$(id -g) -v /etc/passwd:/etc/passwd -t', 'cat')
# specify agent to docker container, it runs container as current host user by default
agent {
docker {
args: '-v/etc/passwd:/etc/passwd'
}
}
agent {
dockerfile {
args: '-v/etc/passwd:/etc/passwd'
}
}