2016年10月25日 星期二

Git 自動版本號

以前公司都是使用SVN,產品都是自已先取一個名字,再加上流水號
然後在 Release Note 上註名 SVN REV (版本號)

前些日子突然想要自已寫一個自動產生版本號的腳本
利用 Git 實作一個簡單的版本管理

網路上有不少作法,要使用 Git 指令也有些差異
我試了幾種後,決定了一個最順手的方式
  1. # [tag]-[rev]-g[hash]
  2. git describe --tags --long --always

Git Tag 使用方式可以參考這一篇
加上--always 可以保證一定會有值產生

Python寫一個腳本
  1. # Coding=UTF-8
  2. """
  3.  
  4. @author 小安
  5. @date 2016/10/21
  6. """
  7. import datetime
  8. from subprocess import check_output
  9.  
  10. VERSION_FILE = 'version.py'
  11.  
  12. _Version_FMT = '''# Coding=UTF-8
  13. """WARNING
  14. This file is automatically generated by GitVersion.py
  15. DO NOT EDIT IT!
  16. """
  17. PKG_NAME = '{pkg_name}'
  18.  
  19. # This file create timestamp
  20. create_time = '{create_time}'
  21.  
  22. # Git Version
  23. full_version_string = '{full_version_string}'
  24. __version__ = '{version}'
  25. __rev__ = '{rev}'
  26. __hash_short = '{hash_short}'
  27.  
  28. '''
  29.  
  30.  
  31. def git_version_parser(full_version_string):
  32. """
  33. If tag exist, it will get a string : v0.0.1-rc0-15-g6c11093
  34. otherwise, get a string : 6c11093 (hash only)
  35.  
  36. :param full_version_string:
  37. :return: (version, rev, hash_short)
  38. """
  39. # Default value
  40. pkg_version = 'v0'
  41. pkg_rev_commit = 0
  42.  
  43. # Parser full_version_string
  44. tag_version = full_version_string.split('-dirty')[0].split('-')
  45.  
  46. # hash
  47. pkg_hash_short = tag_version.pop() if len(tag_version) == 1 else tag_version.pop().split('g')[1]
  48.  
  49. # rev
  50. if len(tag_version) != 0:
  51. pkg_rev_commit = tag_version.pop()
  52.  
  53. # version
  54. if len(tag_version) != 0:
  55. pkg_version = '-'.join(tag_version)
  56.  
  57. return pkg_version, pkg_rev_commit, pkg_hash_short
  58.  
  59.  
  60. def generate_version(pkg_name, output_filename, dirty=None):
  61. """[NOTE] I want to update this function to a class or xml format.
  62. $> git describe --tags --long --always
  63. It will get a string : v0.0.1-rc0-15-g6c11093
  64.  
  65. The means,
  66. last tag : v0.0.1-rc
  67. number of commits since last tag : 15
  68. SHA of HEAD : 6c11093
  69. (g is the git's feature)
  70.  
  71. :param pkg_name: APP name/Package name
  72. :param output_filename: 'version.py' for example
  73. :param dirty: If generate in local/beta, set dirty
  74. :return:
  75. """
  76. cmd_version = 'git describe --tags --long --always'
  77.  
  78. if dirty:
  79. cmd_version += " --dirty"
  80.  
  81. # Get git version string
  82. # [NOTE] In Python3, it will return results in bytes string
  83. full_version_string = check_output(cmd_version, shell=True).rstrip()
  84. full_version_string = full_version_string.decode(encoding="utf-8")
  85.  
  86. # parser
  87. pkg_version, pkg_rev_commit, pkg_hash_short = git_version_parser(full_version_string)
  88.  
  89. # output, includes create time
  90. with open(output_filename, 'w') as out_file:
  91. out_file.write(_Version_FMT.format(pkg_name=pkg_name,
  92. create_time=datetime.datetime.now().isoformat(),
  93. # --- Git Version ---
  94. full_version_string=full_version_string,
  95. version=pkg_version,
  96. rev=pkg_rev_commit,
  97. hash_short=pkg_hash_short, ))
  98.  
產生出的結果如下
  1. # Coding=UTF-8
  2. """WARNING
  3. This file is automatically generated by GitVersion.py
  4. DO NOT EDIT IT!
  5. """
  6. PKG_NAME = 'APP'
  7.  
  8. # This file create timestamp
  9. create_time = '2016-10-25T15:29:26.975873'
  10.  
  11. # Git Version
  12. full_version_string = 'v0.0.1-rc0-29-g8032766-dirty'
  13. __version__ = 'v0.0.1-rc0'
  14. __rev__ = '29'
  15. __hash_short = '8032766'
  16.  
想在程式內引用時
  1. # 記得給一個正確路徑,這裡是輸出version.py
  2. from version import PKG_NAME, full_version_string, create_time

丟到 Release 流程中,就可以保證 release 後的版本號是正確的了

沒有留言:

張貼留言