gitlab+jenkins自动发布Python包到私有仓储
背景
- 有个私有仓储,地址为
https://your.repo.com/pypi/
- 代码存储在gitlab, 地址为
https://gitlab.company.com/software.git
- CI为jenkins
常规解决手法
jenkins有一个特定的节点,节点里面已经配置好了%HOMEPATH%/.pypirc
[distutils]
index-servers =
deploy
[deploy]
repository=https://your.repo.com/pypi/
username=youraccmount
password=yourpwd
然后直接使用
python setup.py sdist upload -r deploy
问题
权限控制
私有仓储存在一个权限, 只有高级别的账号才能push. 而所有人都可以pull包. 那么就存在一个问题. 绝对不能将leader的账户密码直接记录在jenkins节点的配置中.这样很容易就暴露权限.
如果换了台节点
常用方法需要在节点配置.pypirc
文件. 如果我想换台节点,还需要登陆到新节点进行配置.这样非常不方便.
需求
- 绝对不能暴露高级别的账号密码
- 对节点无特殊需求, CI任务换哪个节点都可以
- 希望能够自定义包的版本. 而不是每次都是某个固定的版本
- 我提交代码到gitlab. 然后就自动发布到仓储
解决
我新打了一个tag0.1.1
, 然后我的私有仓储就有一个client0.1.1的包
- 通过jenkins password injection解决权限控制的问题
- 通过expect解决需要交互式输入用户名密码的问题
- 通过gitlab push解决自动发布的问题
- 通过设置环境变量解决tag转化为包版本的问题
设置仓储名, 指定分支为refs/tags/*
. 这样只会编译tag分支
增加jenkins自动触发
gitlab 配置事件推送
注入密码到环境变量
手动添加凭据
shell脚本
这里有一个难题要解决, 首先jenkins shell执行相当于在目标机器下发了一个文件. 如果要用expect
都是只能采用#!/usr/bin/expect
头来执行. 可是使用#!/usr/bin/expect
作为shell脚本执行器,很多命令又没办法用. 所以采用#!/usr/bin/expect -c "command"
来执行
#!/bin/bash
# 注入环境变量
set -e
# 将Tag版本传到环境变量,Setup.py会读取这个环境变量
version=`basename $GIT_BRANCH`
export VERSION=$version
here=`pwd`
# 安装打包辅助库twine到默认python环境
pip install twine
# 打包
python setup.py sdist
# 使用expect进行交互式用户名,密码输入, 这里需要将yourpackagename改成python包名
/usr/bin/expect -c "spawn twine upload --repository-url https://your.repo.com/pypi/ "$here"/dist/yourpackage-"$version".tar.gz; expect "*username:" ; send ${ADMIN_USER}\r; expect "*password:"; send ${ADMIN_PWD}\r; expect eof"
而在setup.py
中,使用环境变量作为当前版本
setuptools.setup(
...
version=os.getenv("VERSION", "0.1.0")
...
)