提供简单发布过程的发布助手脚本
项目描述
摘要
安装
下载并解压缩此包到您的本地svn文件夹结构中您的其他包旁边。之后,在Linux上运行以下命令安装p01.releaser包:
python bootstrap.py
bin/buildout
Windows
python bootstrap.py
binbuildout.exe
发布
您可以使用以下命令使用发布方法进行新版本或下一个版本的发布:
nix
bin/release <package-name>
Windows
binrelease.exe <package-name>
使用此命令,发布脚本将对给定名称的包执行以下操作:
检查挂起的本地修改
查找现有版本
根据选项获取下一个版本(-n,–next-version)
如果选项中未定义,则猜测下一个版本
确认猜测的版本或设置显式/初始版本
如果已存在,则请求确认CHANGES.txt的发布文本
如果确认为空,则提供原地编辑CHANGES.txt
之后,该脚本将启动自动化构建过程,并在任何错误时终止。请注意,错误可能导致部分提交的SVN数据或缺失的发布文件。但这应该很容易检查和纠正。步骤如下
如果编辑期间未更新,则在CHANGES.txt中更新版本
在setup.py中更新版本
提交版本更改(本地包目录)
基于setup.py创建发布版本(本地包目录)
如果新包获得发布,则确保tags文件夹
标记包(svn cp tags/pkgName/version)
猜测下一个发布版本
在CHANGES.txt中添加下一个版本和未发布标记
在setup.py中添加包括开发标记的下一个版本
提交setup.py和CHANGES.txt开发标记更新
现在你已经完成了,发布应该已经准备好了。
简要说明
简要来说,发布脚本应该仅执行以下步骤
请求确认猜测的新版本
请求确认CHANGES.txt或提供编辑
然后发布应该就可以开始了。
致谢
本包是一种简单的keas.build版本,用于单个包。keas.build包提供基于配置文件构建多个发布的支持。如果你需要基于不同包创建多个发布,这很有用,但不是用于发布包本身。
README
本包提供了一个发布辅助脚本,可用于基于SVN的存储库开发。该脚本将执行发布包所需的所有步骤,并在完成后添加开发标记。新包发布将根据包URL上传到正确的pypi。如果需要身份验证,脚本将在你的HOME/.pypirc配置文件中查找它们。这意味着如果你的包元数据定义正确,且“python setup.py sdist upload”命令正常工作,则无需进行任何配置。
需求
在使用脚本之前,请确保以下需求正常
- correct <HOME>/.pypirc setup - pypi package server tweaks in setup.py (see Server Lock below) - working "python setup.py sdist upload" command - correct meta data (url, version) in <package>/setup.py - existing CHANGES.txt file in your package
设置
您可以使用提供的entry_point将p01.releaser设置为buildout的一部分。请参阅setup.py。但我建议不要将脚本用作包的buildout部分,因为它会将该部分包含在你的部署中。
使用脚本的建议方法是将其作为SVN外部链接到你的包<root>旁边的p01.releaser包。无论你使用哪种SVN布局结构都无关紧要。发布脚本将自动检测SVN存储库布局并找到相关文件夹。在这种设置下,你可以进入p01.releaser包并调用发布命令。当然,在可以使用此方法之前,你必须运行
python bootstrap.py bin/buildout
before you can use the method
bin/release
发布脚本将根据你的SVN布局找到正确的包和标记文件夹。下面将提供更多有关常见SVN存储库布局结构的信息。
注意
发布方法仅在自上次发布以来有更改时才会发布包。如果包中有挂起的(未提交)代码,发布方法也不会启动发布过程。发布方法还通过在CHANGES.txt中添加注释来支持你。
SVN
我们支持两种SVN布局。第一种布局是用于独立Python库的默认布局。每个包提供自己的分支、标签和trunk文件夹
- <root> (svn layout detection rule: can't use trunk as name) | |- p01.releaser (cwd location) | | | - bin | | | - releaser.py (releaser.exe) | |- package1 | | | - branches | | | - tags | | | | | - 0.5.0 (version) | | | |- trunk | | | - src ... | - package1 | - branches | - tags | | | - 0.5.0 (version) | |- trunk | - src ...
第二种svn布局用于框架或其他一组包。每个包位于同一个trunk文件夹中,并且它们共享分支和标签文件夹。这种布局提供了一步完成所有包的简单打标签选项。
- <root> | - branches | - tags | | | - package1 | | | - 0.5.0 (version) | - trunk | |- p01.releaser (cwd location) | | | - bin | | | - releaser.py (releaser.exe) | |- package1 | | | - src .. | - package2 | - src ..
服务器锁定
p01.releaser脚本将根据
我们用于私有包的解决方案如下。我们在每个私有包中使用mypypi服务器和locker.py脚本。此脚本提供以下内容
import sys import os.path from ConfigParser import ConfigParser #---[ repository locking ]----------------------------------------------------- def getRepository(name): """Return repository server defined in .pypirc file""" server = None # find repository in .pypirc file rc = os.path.join(os.path.expanduser('~'), '.pypirc') if os.path.exists(rc): config = ConfigParser() config.read(rc) if 'distutils' in config.sections(): # let's get the list of servers index_servers = config.get('distutils', 'index-servers') _servers = [s.strip() for s in index_servers.split('\n') if s.strip() != ''] for srv in _servers: if srv == name: repos = config.get(srv, 'repository') print "Found repository %s for %s in '%s'" % (repos,name,rc) server = repos break if not server: print "No repository for %s found in '%s'" % (name, rc) sys.exit(1) else: return server def lockRelease(name): """Lock repository if we use the register or upload command""" COMMANDS_WATCHED = ('register', 'upload') changed = False server = None for command in COMMANDS_WATCHED: if command in sys.argv: # now get the server from pypirc if server is None: server = getRepository(name) # found one command, check for -r or --repository commandpos = sys.argv.index(command) i = commandpos+1 repo = None while i<len(sys.argv) and sys.argv[i].startswith('-'): # check all following options (not commands) if (sys.argv[i] == '-r') or (sys.argv[i] == '--repository'): #next one is the repository itself try: repo = sys.argv[i+1] if repo.lower() != server.lower(): print "You tried to %s to %s, while this package "\ "is locked to %s" % (command, repo, server) sys.exit(1) else: #repo OK pass except IndexError: #end of args pass i += 1 if repo is None: #no repo found for the command print "Adding repository %s to the command %s" % ( server, command ) sys.argv[commandpos+1:commandpos+1] = ['-r', server] changed = True if changed: print "Final command: %s" % (' '.join(sys.argv))
使用此locker.py脚本,您可以在setup.py文件中执行以下命令,简单地将发布锁定到自己的pypi服务器
import locker locker.lockRelease("projekt01")
单个lockRelease方法参数必须是您在
[distutils] index-servers = pypi mypypi [pypi] repository: http://pypi.python.org/pypi username:<username> password:<password> [mypypi] repository: http://pypi.domain.tld username:<username> password:<password>
此locker.py脚本概念是一种安全带,可以防止任何发布文件错误地上传到错误的pypi服务器,无论是否使用p01.releaser脚本。请记住,如果没有此脚本,releaser脚本将能够找到正确的服务器。但如果你有重要的库,始终备份这个概念是个好主意。
问题
想要提醒一下,distutils由于一个不良的正则表达式而损坏。在Windows上,无法包含以build开头的buildout.cfg或其他文件。这仅在您需要包含带有include_package_data=True的附加包数据时才相关。修复您的python安装后,应可以包含带有MANIFST.in文件的
包含buildout.cfg
参见
变更记录
0.6.0 (2012-11-16)
增加了关于distutils问题的注释
增加了严格的连接错误处理
实现了外部检查
实现了更好的编辑选项
改进测试,修复测试条件
修复了更改标记
用更简单的实现和API替换了CHANGES.txt包装类ChangeDoc
0.5.4 (2011-08-27)
发布前未将新版本添加到CHANGES.txt中
0.5.3 (2011-08-27)
修复了bugfix返回到开发步骤的问题
0.5.2 (2011-08-27)
改进了版本/日期解析。例如,window.open(‘’)被解析为版本标题
跳过内联编辑,只需打开CHANGES.txt文件并中止。如果我发现一种方法在编辑器中打开文件并阻塞子进程直到编辑器关闭,我可能还会将CHANGES.txt文件编辑功能恢复。这并不简单,因为如果在已打开的编辑器中打开文件,则不会阻塞子进程.call
0.5.1 (2011-08-25)
在setup.py调用中增加了缺少的register参数。似乎pypi索引需要此选项,否则包将不会显示在索引中
0.5.0 (2011-08-25)
使用p01.releaser完成了初始发布