Python CI流程踩坑
编辑背景
由于最近开始做毕业设计,准备是先做一个轻量级的爬虫框架(类似Scrapy),接触了一下Python的CI流程。
需求概述
正好最近实习也在研究单元测试的内容,所以单元测试是一定要做的,同时要算出单元测试的覆盖率,再同时需要保证代码里面没有smell或者安全隐患。
因此选用的框架如下
- 单元测试:pytest
- 单元测试覆盖率:coverage
- 代码质量检查、可视化:SonarQube
其他工具的话,git和CI/CD依然使用OneDev。
总的项目可以看medusa。CI/CD相关的文件在.onedev-buildspec.yml。
最终方案(tl;dr)
首先肯定还是先给项目上git,这部分轻车熟路不多解释了。完事以后我们得给他准备一个CI流程用的docker镜像,这部分是踩坑重点,先简单讲讲最终的方案,后面再补上踩坑的流程。最后代码检查的部分也比较简单,会简单略过。
最终效果:
CI流程docker镜像构建
简单分析一下这个镜像需要干些什么:
- 提供一个python环境
- 安装好项目的依赖
- 提供单元测试工具
众所周知Python的环境是个非常让人蛋疼的事情,根本没有完美的迁移方案(docker除外)。现在介绍一下我摸索出来的这么一个方法。
- 在Docker Hub 找到心水的python版本镜像,例如我这里选择
3.7.11
; - 手工写一份
requirements.txt
,只包含最需要的依赖并指明版本(例如这里的pytest==6.2.4
),一些比较通用(就是版本上下兼容很好,或者其实你无所谓他什么版本的包))可以不写版本号; pip install -r requirements.txt
写成Dockerfile是这个样子
FROM python:3.7.11
COPY requirements.txt .
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
完事以后因为Windows上docker操作不方便,写个流程让OneDev自己去构建、推送镜像。
单元测试、覆盖率计算
这部分就颇为简单,确保依赖中有pytest-cov
就可以直接运行py.test --cov=src
,就可以同时运行单元测试和计算覆盖率。后续再运行coverage xml -o coverage.xml
即可输出覆盖率计算结果(这一步输出的xml后面SonarQube会用到)。
SonarQube扫描
这一步非常方便,直接使用SonarQube提供的sonar-scanner-cli
即可。直接就有镜像(sonarsource/sonar-scanner-cli
)可以用。
sonar-scanner \
-Dsonar.projectKey=medusa \
-Dsonar.sources=. \
-Dsonar.host.url=xxx \
-Dsonar.login=xxx \
-Dsonar.branch.name=@branch@ \
-Dsonar.language=python \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.python.version=3 \
-Dsonar.python.coverage.reportPaths=coverage.xml
几个字段说明一下
- sonar.branch.name:配合社区插件,实现社区版也能分branch
- sonar.python.coverage.reportPaths:填上面输出
coverage.xml
的路径,给SonarQube分析覆盖率用
目前的CI流程就是这样,后续还有待完善。
踩坑流程
坑点1:Anaconda环境迁移
之前专门写过一篇博客讲Anaconda环境的配置,以为一劳永逸解决99.99%的Python环境问题了,没想到在这里还是翻了车。
原来的方案是:
# 在源机器上运行下面的命令
conda env export > environment.yml
# 在目标机器上运行下面的命令
conda env create -f environment.yml
一般来说就能原封不动把环境迁移过去了,一般指的是windows往windows里迁移,linux往linux里迁移。以上方式适合导出同操作系统和架构的环境,能够保证依赖能原封不动安装。在不同操作系统/架构间迁移时,可能会由于系统/架构原因导致依赖有所不同,不能使用该方式导入。
当然对应这种情况也有勉强能用的方案,也是推荐的方式——手动创建environment.yml
,手动输入需要的主要依赖和其版本(如tensorflow、python和其版本号)。例子如下:
name: medusa
channels:
- defaults
dependencies:
- coverage=5.5
- pytest=6.2.4
- pytest-cov=3.0.0
- python=3.7.11
- requests=2.27.1
坑点2 :Anaconda在OneDev里不能用
好不容易解决依赖问题,发现在OneDev里面不能切换环境,只好改用pip的方案
- 0
- 0
-
赞助
微信赞赏码 -
分享