kookeeper 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +20 -0
  3. data/.gitignore +50 -0
  4. data/.travis.yml +19 -0
  5. data/CODE_OF_CONDUCT.md +46 -0
  6. data/CONTRIBUTING.md +70 -0
  7. data/Gemfile +10 -0
  8. data/Gemfile.lock +125 -0
  9. data/LICENSE +21 -0
  10. data/README.md +113 -0
  11. data/Rakefile +2 -0
  12. data/big_keeper.gemspec +49 -0
  13. data/bin/big +14 -0
  14. data/bin/setup +8 -0
  15. data/docs/en-US/FEATURE.md +0 -0
  16. data/docs/en-US/README.md +54 -0
  17. data/docs/zh-CN/BIGKEEPER_FILE.md +84 -0
  18. data/docs/zh-CN/FEATURE&HOTFIX.md +88 -0
  19. data/docs/zh-CN/IMAGE.md +0 -0
  20. data/docs/zh-CN/PODFILE.md +43 -0
  21. data/docs/zh-CN/README.md +113 -0
  22. data/docs/zh-CN/RECOMMEND.md +22 -0
  23. data/docs/zh-CN/RELEASE.md +60 -0
  24. data/docs/zh-CN/SPEC.md +39 -0
  25. data/lib/big_keeper/command/client.rb +50 -0
  26. data/lib/big_keeper/command/feature&hotfix/delete.rb +40 -0
  27. data/lib/big_keeper/command/feature&hotfix/finish.rb +54 -0
  28. data/lib/big_keeper/command/feature&hotfix/list.rb +63 -0
  29. data/lib/big_keeper/command/feature&hotfix/publish.rb +56 -0
  30. data/lib/big_keeper/command/feature&hotfix/pull.rb +26 -0
  31. data/lib/big_keeper/command/feature&hotfix/push.rb +27 -0
  32. data/lib/big_keeper/command/feature&hotfix/rebase.rb +32 -0
  33. data/lib/big_keeper/command/feature&hotfix/start.rb +74 -0
  34. data/lib/big_keeper/command/feature&hotfix/switch.rb +46 -0
  35. data/lib/big_keeper/command/feature&hotfix/update.rb +66 -0
  36. data/lib/big_keeper/command/feature&hotfix.rb +167 -0
  37. data/lib/big_keeper/command/image/image.rb +0 -0
  38. data/lib/big_keeper/command/image.rb +28 -0
  39. data/lib/big_keeper/command/init.rb +36 -0
  40. data/lib/big_keeper/command/pod/podfile.rb +72 -0
  41. data/lib/big_keeper/command/pod.rb +55 -0
  42. data/lib/big_keeper/command/release/finish.rb +36 -0
  43. data/lib/big_keeper/command/release/home.rb +92 -0
  44. data/lib/big_keeper/command/release/module.rb +65 -0
  45. data/lib/big_keeper/command/release/publish.rb +4 -0
  46. data/lib/big_keeper/command/release/start.rb +78 -0
  47. data/lib/big_keeper/command/release.rb +100 -0
  48. data/lib/big_keeper/command/spec/add.rb +9 -0
  49. data/lib/big_keeper/command/spec/analyze.rb +88 -0
  50. data/lib/big_keeper/command/spec/delete.rb +9 -0
  51. data/lib/big_keeper/command/spec/list.rb +19 -0
  52. data/lib/big_keeper/command/spec/search.rb +9 -0
  53. data/lib/big_keeper/command/spec/sync.rb +12 -0
  54. data/lib/big_keeper/command/spec.rb +78 -0
  55. data/lib/big_keeper/dependency/dep_gradle_operator.rb +74 -0
  56. data/lib/big_keeper/dependency/dep_operator.rb +48 -0
  57. data/lib/big_keeper/dependency/dep_pod_operator.rb +130 -0
  58. data/lib/big_keeper/dependency/dep_service.rb +14 -0
  59. data/lib/big_keeper/dependency/dep_type.rb +33 -0
  60. data/lib/big_keeper/model/gitflow_type.rb +43 -0
  61. data/lib/big_keeper/model/library_model.rb +116 -0
  62. data/lib/big_keeper/model/operate_type.rb +30 -0
  63. data/lib/big_keeper/model/podfile_model.rb +33 -0
  64. data/lib/big_keeper/service/git_service.rb +211 -0
  65. data/lib/big_keeper/service/module_service.rb +224 -0
  66. data/lib/big_keeper/service/stash_service.rb +45 -0
  67. data/lib/big_keeper/util/bigkeeper_parser.rb +260 -0
  68. data/lib/big_keeper/util/cache_operator.rb +118 -0
  69. data/lib/big_keeper/util/code_operator.rb +37 -0
  70. data/lib/big_keeper/util/command_line_util.rb +9 -0
  71. data/lib/big_keeper/util/file_operator.rb +33 -0
  72. data/lib/big_keeper/util/git_operator.rb +242 -0
  73. data/lib/big_keeper/util/gitflow_operator.rb +51 -0
  74. data/lib/big_keeper/util/gradle_content_generator.rb +26 -0
  75. data/lib/big_keeper/util/gradle_file_operator.rb +339 -0
  76. data/lib/big_keeper/util/gradle_module_operator.rb +70 -0
  77. data/lib/big_keeper/util/info_plist_operator.rb +46 -0
  78. data/lib/big_keeper/util/leancloud_logger.rb +84 -0
  79. data/lib/big_keeper/util/list_generator.rb +101 -0
  80. data/lib/big_keeper/util/lockfile_parser.rb +143 -0
  81. data/lib/big_keeper/util/logger.rb +47 -0
  82. data/lib/big_keeper/util/pod_operator.rb +70 -0
  83. data/lib/big_keeper/util/podfile_detector.rb +102 -0
  84. data/lib/big_keeper/util/podfile_module.rb +63 -0
  85. data/lib/big_keeper/util/podfile_operator.rb +125 -0
  86. data/lib/big_keeper/util/verify_operator.rb +17 -0
  87. data/lib/big_keeper/util/version_config_operator.rb +29 -0
  88. data/lib/big_keeper/util/xcode_operator.rb +15 -0
  89. data/lib/big_keeper/version.rb +3 -0
  90. data/lib/big_keeper.rb +81 -0
  91. data/resources/banner.png +0 -0
  92. data/resources/command.png +0 -0
  93. data/resources/keynote/big-keeper-readme-analyze.key +0 -0
  94. data/resources/keynote/big-keeper-readme-example.key +0 -0
  95. data/resources/keynote/big-keeper-readme-feature.key +0 -0
  96. data/resources/keynote/big-keeper-readme-release.key +0 -0
  97. data/resources/readme/big-keeper-readme.001.png +0 -0
  98. data/resources/template/Bigkeeper +23 -0
  99. metadata +354 -0
@@ -0,0 +1,84 @@
1
+ # Bigkeeper 文件
2
+
3
+ 首先,我们在主项目 Podfile 所在的目录加入 **Bigkeeper** 文件。
4
+
5
+ ## 配置版本
6
+
7
+ ```
8
+ version '2.8.8'
9
+ ```
10
+
11
+ 版本号的用途有:
12
+
13
+ - feature 和 hotfix 流程里面做为分支名前缀的一部分,方便后期通过版本号匹配分支;
14
+ - release 流程里面做为发布版本号,影响范围包括业务模块和主项目。
15
+
16
+ ## 配置主项目
17
+
18
+ ```
19
+ home 'BigKeeperMain', :git => 'git@github.com:BigKeeper/BigKeeperMain.git', :pulls => 'https://github.com/BigKeeper/BigKeeperMain/pulls'
20
+ ```
21
+
22
+ 这个配置包含三个部分:
23
+
24
+ - 主项目的名字;
25
+ - 主项目的 git 远程仓库地址;
26
+ - 主项目的 pull request / merge request 页面地址,完成某个 feature / hotfix 时,会自动打开这个页面,让开发者提交 pull request / merge request。
27
+
28
+ ## 配置模块源
29
+
30
+ ```
31
+ source 'git@git.elenet.me:LPD-iOS/LPDSpecs.git, elenet-lpdspecs' do
32
+ modules do
33
+ ...
34
+ end
35
+ end
36
+
37
+ source ...
38
+ ...
39
+ end
40
+ ```
41
+
42
+ 考虑到我们的业务模块可能属于不同的源,所以配置业务模块之前,要先在最外层配置源信息:
43
+
44
+ - 源 git 地址;
45
+ - 源名称。
46
+
47
+ 配置这个主要是方便对我们关心的源执行 `pod repo update`,从而节省命令执行的时间。
48
+
49
+ ## 配置业务模块
50
+
51
+ ```
52
+ modules do
53
+ mod 'BigKeeperModular', :git => 'git@github.com:BigKeeper/BigKeeperModular.git', :pulls => 'https://github.com/BigKeeper/BigKeeperModular/pulls'
54
+ mod ...
55
+ end
56
+ ```
57
+
58
+ 这个配置包含可以配置多个业务模块,建议是把当前所有非第三方库都加入到这个配置里面:
59
+
60
+ - 业务模块在 Podfile 中的名字;
61
+ - 业务模块的 git 远程仓库地址;
62
+ - 业务模块的 pull request / merge request 页面地址,完成某个 feature / hotfix 时,会自动打开这个页面,让开发者提交 pull request / merge request。
63
+
64
+ ## 配置用户自定义信息
65
+
66
+ ```
67
+ user 'perry' do
68
+ mod 'BigKeeperModular', :path => '../BigKeeperModular'
69
+ end
70
+ ```
71
+
72
+ 如果用户需要配置一些自定义信息,比如业务模块在本地的路径,就可以增加一个这样的配置。
73
+
74
+ 这个配置同样支持对指定的用户名(上述配置用户名为 perry)配置多个业务模块,目前支持的是:
75
+
76
+ - 配置业务模块的本地路径,通过这个路径,我们就可以在主工程直接对业务模块做一些 CocoaPods 和 git 相关的操作。
77
+
78
+ > 注:
79
+ >
80
+ > 1. 默认用户名是 git global config 的 user.name;
81
+ >
82
+ > 2. 默认我们会把本地路径配置成 `../{业务模块在 Podfile 中的名字}` 的形式,因为大部分情况下,我们会把项目都放在同级目录下,这也是我们推荐的;
83
+ >
84
+ > 3. 另外,在使用 bigkeeper 相关功能时,如果某些业务模块并没有 clone 到本地,bigkeeper 会根据之前配置的业务模块远程 git 地址 clone 业务模块仓库到**主项目同级目录下**。
@@ -0,0 +1,88 @@
1
+ # feature - 功能开发流程 & hotfix - 线上修复流程
2
+
3
+ > 注:hotfix 除了基础分支是 **master**,其他操作和 feature 一致,所以我们这里以 feature 为例说明。
4
+
5
+ 直接在命令行执行 `big feature --help` 可以查看其提供的所有功能:
6
+
7
+ ```
8
+ NAME
9
+ feature - Gitflow feature operations
10
+
11
+ SYNOPSIS
12
+ big [global options] feature delete
13
+ big [global options] feature finish
14
+ big [global options] feature list
15
+ big [global options] feature publish
16
+ big [global options] feature pull
17
+ big [global options] feature push
18
+ big [global options] feature rebase
19
+ big [global options] feature start
20
+ big [global options] feature switch
21
+ big [global options] feature update
22
+
23
+ COMMANDS
24
+ delete - Delete feature with name
25
+ finish - Finish current feature
26
+ list - List all the features
27
+ publish - Publish current feature
28
+ pull - Pull remote changes for current feature
29
+ push - Push local changes to remote for current feature
30
+ rebase - Rebase 'develop' to current feature
31
+ start - Start a new feature with name for given modules and main project
32
+ switch - Switch to the feature with name
33
+ update - Update modules for the feature with name
34
+ ```
35
+
36
+ 功能列表如下:
37
+
38
+ - start:
39
+ 开始一个新的 feature,输入参数依次为:
40
+ - feature 的名字;
41
+ - 开发该 feature 需要改动的业务模块名。可以多个,用空格隔开;如果不指定,取 **Bigkeeper 文件中所有的业务模块名**。
42
+ - finish:结束当前 feature;
43
+ - publish:发布当前 feature;
44
+ - switch:切换到一个已经存在的 feature,输入参数为 feature 名;
45
+ - update:
46
+ 更新一个 feature 需要改动的业务模块,输入参数依次为:
47
+ - feature 的名字;
48
+ - 开发该 feature 需要改动的业务模块名。可以多个,用空格隔开;如果不指定,取 **Bigkeeper 文件中所有的业务模块名**。
49
+ - pull:拉取当前 feature 主项目和业务模块的远程 git 仓库更新;
50
+ - push:提交并推送当前 feature 主项目和业务模块的本地变更到远程 git 仓库,输入参数为提交信息;
51
+ - rebase:rebase 主项目和业务模块 `develop` 分支到当前 feature;
52
+ - delete:根据 featue 名删除主项目和业务模块所有相关分支;(PS:慎用,因为会删除本地和远程所有相关分支)
53
+ - list:显示当前的 feature 列表。
54
+
55
+ ## 各个指令的使用场景
56
+
57
+ - 如果需要开发新的功能,使用 big feature start;
58
+ - 开发功能过程中如果发现某个模块其实不用改动,使用 big feature update 来把这个模块从这个 feature 移除;
59
+ - 使用 big feature pull 来同步主项目和相关业务模块远端变更;
60
+ - 使用 big feature push 来推送主项目和相关业务模块变更到远端;
61
+ - 使用 big feature rebase 来 rebase 主项目和业务模块 `develop` 分支到当前 feature;
62
+ - 使用 big feature switch 来切换 feature,比如:两个功能并行开发的时候,就可以用这个命令互相切换了;
63
+ - 功能开发完成,需要单独打包提交测试时,使用 big feature finish 结束开发;
64
+ - 开始进行集成测试,需要将代码 PR 到 develop 分支时,使用 big feature publish;
65
+ - 如果开发过程中突然有新的功能需要紧急开发,直接使用 big feature start 进行新功能开发,旧功能未提交的内容我们会保存在 stash 中。
66
+
67
+ ## 各个指令执行结束后工程的状态
68
+
69
+ ### feature 的工作区
70
+
71
+ 在开始了解各条指令执行后工程的状态之前,我们先了解一下 bigkeeper feature 流程的工作区。
72
+
73
+ ![](../../resources/readme/big-keeper-readme.001.png)
74
+
75
+ feature 的工作区主要由两部分组成:
76
+
77
+ - 主项目;
78
+ - 相关业务模块,我们把 Podfile 中引用方式为 `:path => {业务模块本地路径}` 的模块做为相关业务模块。
79
+
80
+ 主项目和每个相关业务模块又有各自的工作区,由三个部分组成:
81
+
82
+ - 当前代码区改动;
83
+ - stash 缓存区,当用户需要切换新的 feature 时,对于用户来不及提交的改动,我们会缓存到各个项目的 stash 中,(PS:所以代码突然不见了不要担心,都在 git 的 stash 里面),而当用户切换回某个 feature 时,我们会把和该 feature 分支同名的 stash 恢复回来,从而使用户可以继续开发之前未完成的部分,因为需要通过 feature 的分支名来匹配 stash,而 git stash 又没有提供给 stash 命名的功能,所以我们实现了 [bigstash](https://github.com/BigKeeper/bigstash) 来完成这个功能;
84
+ - git。
85
+
86
+ > 注:
87
+ > 1. 所有的指令我们都做了良好的出错提示和异常恢复机制,当某个步骤报错时,只需要根据提示的错误手动修复问题,重新输入指令,bigkeeper 会继续执行接下来的流程。
88
+ > 2. 所有的代码都会保存在工作区中,除了 delete 操作,bigkeeper 不会删除任何工作区的代码,也就是说:你总是可以在变更区、Stash 中或者远端找到你变更的代码。
File without changes
@@ -0,0 +1,43 @@
1
+ # podfile - podfile版本控制流程
2
+
3
+ 直接在命令行执行 `big podfile --help` 可以查看其提供的所有功能
4
+
5
+ ```
6
+ NAME
7
+ podfile - Podfile operation
8
+
9
+ SYNOPSIS
10
+ big [global options] podfile [command options] detect
11
+ big [global options] podfile [command options] lock
12
+ big [global options] podfile [command options] upgrade
13
+
14
+ COMMAND OPTIONS
15
+ --pod, --podfile=arg - (default: none)
16
+
17
+ COMMANDS
18
+ detect - Detect podname should be locked.
19
+ lock - Lock podname should be locked.
20
+ upgrade - Update module version
21
+
22
+ ```
23
+
24
+ 全局参数如下:
25
+
26
+ - -pod --podfile :podfile文件路径
27
+
28
+ 功能列表如下:
29
+
30
+ - detect:
31
+ 检测当前同步到本地的项目工程中podfile,得到未锁定的第三方库。
32
+ 如果存在,提示需要指定版本。
33
+ 如果不存在,提示无需指定版本的第三方库。
34
+
35
+ - lock:
36
+ 检测到存在需指定代版本的三方库后,执行lock指令对所有需要锁定的库进行锁定。
37
+
38
+ - upgrade:
39
+ 检测配置文件中指定业务库,有无最新可更新版本。
40
+
41
+ ## podfile lock 流程
42
+
43
+ ![](../../resources/readme/big-keeper-readme.011.png)
@@ -0,0 +1,113 @@
1
+ [English](../en-US/README.md)
2
+
3
+ ---
4
+
5
+ # bigkeeper
6
+
7
+ ![](../../resources/banner.png)
8
+
9
+ [![Build Status](https://travis-ci.org/BigKeeper/bigkeeper.svg?branch=master)](https://travis-ci.org/BigKeeper/bigkeeper)
10
+ [![Maintainability](https://api.codeclimate.com/v1/badges/c6dc4161e84fcec9a890/maintainability)](https://codeclimate.com/github/BigKeeper/big-keeper/maintainability)
11
+ [![Gem Version](https://badge.fury.io/rb/bigkeeper.svg)](https://rubygems.org/gems/bigkeeper)
12
+ [![Language: Ruby](https://img.shields.io/badge/language-Ruby-da212f.svg)](https://www.ruby-lang.org/)
13
+ [![License](https://img.shields.io/badge/license-MIT-000000.svg)](https://github.com/BigKeeper/big-keeper/blob/master/LICENSE)
14
+ [![Gitter](https://img.shields.io/gitter/room/BigKeeper/BigKeeper.svg)](https://gitter.im/Big-Keeper/Lobby)
15
+
16
+ bigkeeper 是一个 **iOS&Android 模块化项目**效率提升工具,旨在帮助有模块化需求的团队更轻松的渡过“半模块化”尴尬期。
17
+
18
+ 使用这个工具后,开发者**在主项目内**即可完成**包括其他业务模块在内**所有代码的编写和管理。
19
+
20
+ 我们借鉴 CocoaPods 的做法,开发团队只需要在主项目中加入一个 Bigkeeper 文件,然后利用我们提供的 `big` 命令,即可更便捷的实现**代码分支**和**业务模块**的管理;另外,通过 `big` 命令提供的流程,也能帮助开发者养成更规范的日常开发习惯,减轻项目管理者的负担。
21
+
22
+ ## 应用场景
23
+
24
+ 在模块化项目的过渡阶段,我们往往会碰到业务拆分不是那么彻底的情况(PS:比如主项目中仍然存在业务相关代码),这样就会导致一系列问题:
25
+
26
+ - 开发流程方面:开发者在开发一个 feature 时需要维护多个项目的分支,同时还要频繁修改主项目的 `Podfile`;
27
+ - 项目管理者需要花很大精力去和团队成员同步项目管理规范流程,尤其对于新人,挑战很大;
28
+ - 开发过程中如果碰到突发情况需要开新分支处理问题时对当前工作区的保存操作会很繁琐(PS:因为涉及到多个项目);
29
+ - 日常开发过程中类似 commit、pull、push 等操作比较繁琐(PS:因为涉及到多个项目);
30
+ - 资源(比如图片)散落在各个业务模块,可能存在重名、重复等问题,难以管理;
31
+ - 业务模块可能存在横向依赖的问题,导致业务模块间耦合严重,不能单独编译运行。
32
+ - 各模块依赖的版本没有统一的同步更新方式,导致各个模块的开发环境不一致,问题百出。
33
+
34
+ bigkeeper 的出现就是为了解决这些问题。
35
+
36
+ > 注:也有很多人认为直接做一个完整的组件化项目更合理,而不需要采用这样曲折的方案,但是很多时候我们并没有这么多的精力直接去做这些事情,bigkeeper 存在的价值也是为了帮助开发团队在** iOS&Android 模块化项目过渡阶段**能更轻松的往前走。
37
+
38
+ ## 安装
39
+
40
+ - 当作 Ruby Gem 使用:
41
+ 在项目的 Gemfile 中加入下面这行:
42
+
43
+ ```ruby
44
+ gem 'bigkeeper'
45
+ ```
46
+
47
+ 然后执行:
48
+
49
+ $ bundle
50
+
51
+ - 直接安装:
52
+
53
+ $ gem install bigkeeper
54
+
55
+ ## 使用方法
56
+
57
+ - [Bigkeeper 文件配置](BIGKEEPER_FILE.md)
58
+ - `bigkeeper` 工具使用:
59
+
60
+ 直接在命令行执行 `bigkeeper` 可以查看其提供的所有功能:
61
+
62
+ ```
63
+ NAME
64
+ big - Efficiency improvement for iOS&Android module development, iOSer&Android using this tool can make module development easier.
65
+
66
+ SYNOPSIS
67
+ big [global options] command [command options] [arguments...]
68
+
69
+
70
+ GLOBAL OPTIONS
71
+ --help - Show this message
72
+ -p, --path=arg - (default: ./)
73
+ -u, --user=arg - (default: mmoaay)
74
+ -v, --ver=arg - (default: Version in Bigkeeper file)
75
+
76
+ COMMANDS
77
+ feature - Gitflow feature operations
78
+ help - Shows a list of commands or help for one command
79
+ hotfix - Gitflow hotfix operations
80
+ image - Image operations
81
+ podfile - Podfile operation
82
+ release - Gitflow release operations
83
+ spec - Spec operations
84
+ version - Show version of bigkeeper
85
+ ```
86
+
87
+ 全局参数如下:
88
+
89
+ - -p, --path:主项目所在的目录,默认是执行 bigkeeper 命令的当前目录;
90
+ - -v, --ver:版本号,如果没有指定的话,会以主项目 [Bigkeeper 文件](BIGKEEPER_FILE.md)中指定的版本为准。
91
+ - -u, --user:用户名,默认是 git global config 的 user.name,会显示在命令提示信息中,比如上述提示信息中的默认用户名是 mmoaay
92
+
93
+ 功能列表如下:
94
+
95
+ - [feature](FEATURE&HOTFIX.md):功能开发流程;
96
+ - [hotfix](FEATURE&HOTFIX.md):线上 Bug 修复流程;
97
+ - [release](RELEASE.md):发布流程;
98
+ - [podfile](PODFILE.md):Podfile 管理;
99
+ - [image](IMAGE.md):图片管理;
100
+ - [spec](SPEC.md):spec 管理;
101
+ - version:查看 bigkeeper 当前版本号;
102
+ - help:查看 bigkeeper 帮助文档。
103
+
104
+ ## 其他
105
+
106
+ - [一些建议](RECOMMEND.md)
107
+ - [一些思考]()
108
+
109
+ ## 协议
110
+
111
+ ![](https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/License_icon-mit-88x31-2.svg/128px-License_icon-mit-88x31-2.svg.png)
112
+
113
+ bigkeeper 基于 MIT 协议进行分发和使用,更多信息参见协议文件。
@@ -0,0 +1,22 @@
1
+ # 代码管理规范
2
+
3
+ ## 基本原则
4
+
5
+ - master 分支保证是线上最新包的代码。
6
+ - develop 分支保证是下一个发布包的代码,随时支持发布。
7
+
8
+ ### 开发和测试流程
9
+
10
+ feature 分支为 feature 开发和提测分支,提测前需要 rebase/merge develop 的代码,测试完成后,pr 到 develop 分支,确定下个版本发布才 accept pr。
11
+
12
+ ### develop 分支 bug 修复流程
13
+
14
+ 单独开分支,fix 完成后,pr 到 develop 分支。
15
+
16
+ ### 发布流程
17
+
18
+ develop->release->master 瞬间操作,release 不能长期存在。
19
+
20
+ ### hotfix 流程
21
+
22
+ master 拉出 hotfix,fix 完成后分别 pr 到 master、develop 两个分支,完成后新建发布版本。
@@ -0,0 +1,60 @@
1
+ 饿了么物流模块化效率提升思考 - 发布流程篇
2
+ ### 背景
3
+ bigkeeper 的目的是为了在项目的模块化过渡阶段提升效率,在过渡到模块化的过程中要做很多的代码抽离,而越来越多的 Pod依赖(假设用Cocoapods做包管理)对项目管理者的负担越来越大.
4
+ 移动端完成一个需求迭代,除了代码开发外,还需要有模块发版,集成,打包,回归这些步骤,而往往在回归到发版的时候,研发同学要花较多时间在发版,这严重影响了开发效率.
5
+ ### 解决方案
6
+ 为了提高要提高发布流程的发布效率,我们开发了big release 功能是来提升发布效率.首先说明,bigkeeper的开发以及发布流程是完全遵循[git-flow 流程](https://jeffkreeftmeijer.com/git-flow/).
7
+ 我们建议直接把`Pods`和`Podfile.lock`移出版本控制系统,因为模块化的操作会频繁进行 `Pods`的增删以及更新,但是这会带来版本锁定的困扰,我们建议把版本锁定的工作从 `Podfile.lock`移到`Podfile`中,为此我们做了一个功能 [big pod](---.).
8
+ `bigkeeper`提供了`release module`模块发版和`release home`主工程发版,每种发版方式分为` start`和` finish`, 这两种方式的最大区别是` start`没有`git push`,不会因为可能存在的问题而污染`origin`仓库,这也留一个口子给研发人员进行二次确认.
9
+ #### 模块发版
10
+ 在过渡到模块化和已经模块化的项目中, 会存在很多依赖库, 一般会分为:
11
+ * 业务模块库
12
+ * 业务基础库
13
+ * 二方库(公司内部库)
14
+ * 三方库
15
+ 一般来说,二方库和三方库的版本稳定,而每次业务迭代频繁改动往往就是业务模块库与业务基础库,这这两种类型的库在发布的时候往往因为会因为依赖库的原因而导致发版失败,浪费开发人员的时间.
16
+ 所以,模块发布提供了两种解决方案:
17
+ ```
18
+ big release module finish ExampleModule
19
+ Options:
20
+ -s, --spec : 模块需要发布版本
21
+ ```
22
+ `--spec`指令决定模块需要发版,如果不需要,那仅会在`master`分支打上`tag`.
23
+ 而在`start`指令中我们也做了一些安全性检查:
24
+ * 根据开发流程的分支命名规范(branch: feature/x.x.x),检查当前是否有分支还没有合并到`develop`分支;
25
+ * 检查`master`分支相较于`develop`分支是否有超前的` commit`,防止有不规范的操作导致污染` master`分支代码.
26
+ ```
27
+ big release module start ExampleModule
28
+ Options:
29
+ -i, --ignore : 忽略安全性检查(默认开启)
30
+ ```
31
+ #### 主工程发版
32
+ 在模块化完成之后,主工程基本上是个壳工程,只会有`Podfile`和配置文件的改动, 根据`git-flow`的规则`bigkeeper`在发布主工程时会从`develop`切出` release/x.x.x`分支,`release`分支是一个暂时性分支,在代码已经并入`master`之后会删除`release`分支.
33
+ `release home start`中有两种模块的引用方式:
34
+ ```
35
+ pod 'ExampleModule', '0.1.0'
36
+ or
37
+ pod 'ExampleModule', :git => 'ExampleModule.git', :tag => '0.1.0'
38
+ ```
39
+ 如果模块没有发布,` bigkeeper`会根据在根据仓库里的最新`tag`和`.cocoapods/repos` 里的已发布版本去找到合适的依赖方式.
40
+ 在` release home finish`中有一个需要注意的地方就是` release`分支合并到` develop`之前`reset`掉对` Podfile`的操作,这样保持了不会有在` Podfile`文件不会有冲突.
41
+ ### 举个例子
42
+ 模块发版:
43
+ ```
44
+ big -v 0.1.0 release module start ExampleModule
45
+ big -v 0.1.0 release module finish ExampleModule
46
+ Options:
47
+ -v : 发布是指定版本号,如未指定,则用bigkeeper文件中的vesion
48
+ ```
49
+ 主工程发版:
50
+ ```
51
+ big -v 0.1.0 release home start
52
+ big -v 0.1.0 release home finish
53
+ Options:
54
+ -v : 发布是指定版本号,如未指定,则用bigkeeper文件中的vesion
55
+ ```
56
+ ### 展望
57
+ 对于很多中大型公司来说都是自己的CI系统,可以把发版本这种耗时而且占内存的工作放在CI机器上,所以我们也有计划把`release module`最后一步的发版本的步骤留个口子,研发同学可以在这里去触发各自CI系统的发版流程.
58
+ ### 结束语
59
+ `bigkeeper`在饿了么物流已经实践了半年多了,从数个模块到现在40+的模块数量,仅`release`流程节省项目管理者非常多的时间,提升了效率而且规范化了开发流程,也希望大家在使用中有` issue`反馈给到我们.
60
+
@@ -0,0 +1,39 @@
1
+ # spec - spec 管理
2
+
3
+ ## 背景
4
+
5
+ 模块化推进过程中势必存在业务模块间的横向依赖,原则上这种依赖我们都需要通过 router 进行解耦,不能直接源码依赖其他业务模块,因为这样的依赖会导致如下的问题:
6
+
7
+ - 因为直接横向依赖业务模块,导致业务模块无法独立编译运行。
8
+ - 各个业务模块如果存在大量类似依赖,必将导致后期模块代码依赖错综复杂,难以维护。
9
+
10
+ ## 功能简介
11
+
12
+ 直接在命令行执行 `big spec --help` 可以查看其提供的所有功能:
13
+
14
+ ```
15
+ NAME
16
+ spec - Spec operations
17
+
18
+ SYNOPSIS
19
+ big [global options] spec [command options] add
20
+ big [global options] spec [command options] analyze
21
+ big [global options] spec [command options] delete
22
+ big [global options] spec [command options] list
23
+ big [global options] spec [command options] search
24
+
25
+ COMMAND OPTIONS
26
+ -a, --[no-]all -
27
+
28
+ COMMANDS
29
+ add - Add a spec (Coming soon).
30
+ analyze - Analyze spec dependency infomation.
31
+ delete - Delete a spec (Coming soon).
32
+ list - List all the specs.
33
+ search - Search a spec with name (Coming soon).
34
+ ```
35
+
36
+ 功能列表如下:
37
+
38
+ - analyze:分析所有指定模块之间的依赖,通常为业务模块。
39
+ - list:显示当前所有的业务 spec。
@@ -0,0 +1,50 @@
1
+ require 'big_keeper/util/leancloud_logger'
2
+ require 'big_keeper/command/pod/podfile'
3
+ require 'big_keeper/command/spec/list'
4
+ require 'big_keeper/util/list_generator'
5
+
6
+ module BigKeeper
7
+
8
+ def self.client_command
9
+ desc 'API for bigkeeper-client.'
10
+ command :client do | c |
11
+ c.desc 'Commands about operate modules.'
12
+ c.command :modules do |modules|
13
+ modules.desc 'Get modules list from Bigkeeper file.'
14
+ modules.command :list do |list|
15
+ list.action do |global_options, options, args|
16
+ LeanCloudLogger.instance.set_command("spec/list")
17
+ path = File.expand_path(global_options[:path])
18
+ version = global_options[:ver]
19
+ user = global_options[:user].gsub(/[^0-9A-Za-z]/, '').downcase
20
+ spec_list(path, user, options)
21
+ end
22
+ end
23
+ modules.desc 'Update modules.'
24
+ modules.command :update do |update|
25
+ update.action do |global_options, options, args|
26
+ LeanCloudLogger.instance.set_command("spec/list")
27
+ path = File.expand_path(global_options[:path])
28
+ version = global_options[:ver]
29
+ user = global_options[:user].gsub(/[^0-9A-Za-z]/, '').downcase
30
+ spec_list(path, user, options)
31
+ end
32
+ end
33
+ end
34
+ c.desc 'Commands about features.'
35
+ c.command :feature do |feature|
36
+ feature.desc "List all the features including origin."
37
+ feature.command :list do | list |
38
+ list.flag %i[v version] , default_value: 'all versions'
39
+ list.action do |global_options, options, args|
40
+ LeanCloudLogger.instance.set_command("feature/list/json")
41
+ options[:json] = true
42
+ path = File.expand_path(global_options[:path])
43
+ user = global_options[:user].gsub(/[^0-9A-Za-z]/, '').downcase
44
+ list(path, user, GitflowType::FEATURE, options)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'big_keeper/util/podfile_operator'
4
+ require 'big_keeper/util/gitflow_operator'
5
+ require 'big_keeper/util/bigkeeper_parser'
6
+ require 'big_keeper/util/logger'
7
+ require 'big_keeper/util/pod_operator'
8
+
9
+ require 'big_keeper/dependency/dep_service'
10
+
11
+ require 'big_keeper/dependency/dep_type'
12
+
13
+ require 'big_keeper/service/stash_service'
14
+ require 'big_keeper/service/module_service'
15
+
16
+
17
+ module BigKeeper
18
+ def self.delete(path, user, name, type)
19
+ begin
20
+ # Parse Bigkeeper file
21
+ BigkeeperParser.parse("#{path}/Bigkeeper")
22
+ branch_name = "#{GitflowType.name(type)}/#{name}"
23
+ version = 'all version'
24
+
25
+ modules = BigkeeperParser.module_names
26
+ modules.each do |module_name|
27
+ module_full_path = BigkeeperParser.module_full_path(path, user, module_name)
28
+
29
+ if FileOperator.definitely_exists?(module_full_path)
30
+ StashService.new.pop_stash(module_full_path, branch_name, module_name)
31
+ GitService.new.verify_del(module_full_path, branch_name, module_name, type)
32
+ end
33
+ end
34
+
35
+ StashService.new.pop_stash(path, branch_name, 'Home')
36
+ GitService.new.verify_del(path, branch_name, 'Home', type)
37
+ ensure
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'big_keeper/util/podfile_operator'
4
+ require 'big_keeper/util/logger'
5
+ require 'big_keeper/util/pod_operator'
6
+ require 'big_keeper/util/xcode_operator'
7
+ require 'big_keeper/util/cache_operator'
8
+ require 'big_keeper/util/bigkeeper_parser'
9
+ require 'big_keeper/model/operate_type'
10
+ require 'big_keeper/dependency/dep_service'
11
+
12
+ require 'big_keeper/dependency/dep_type'
13
+
14
+
15
+ module BigKeeper
16
+
17
+ def self.finish(path, user, type)
18
+ begin
19
+ # Parse Bigkeeper file
20
+ BigkeeperParser.parse("#{path}/Bigkeeper")
21
+
22
+ branch_name = GitOperator.new.current_branch(path)
23
+ Logger.error("Not a #{GitflowType.name(type)} branch, exit.") unless branch_name.include? GitflowType.name(type)
24
+
25
+ # Cache git modules
26
+ if ModuleCacheOperator.new(path).all_path_modules.empty?
27
+ Logger.error("Branch '#{branch_name}' is already finished, exit.")
28
+ end
29
+
30
+ ModuleCacheOperator.new(path).cache_git_modules(ModuleCacheOperator.new(path).all_path_modules)
31
+
32
+ modules = ModuleCacheOperator.new(path).remain_git_modules
33
+ # Rebase modules and modify module as git
34
+ modules.each do |module_name|
35
+ ModuleService.new.finish(path, user, module_name, branch_name, type)
36
+ end
37
+
38
+ Logger.highlight("Finish branch '#{branch_name}' for 'Home'")
39
+
40
+ # Delete all path modules
41
+ ModuleCacheOperator.new(path).cache_path_modules([], [], [])
42
+
43
+ # Install
44
+ DepService.dep_operator(path, user).install(modules, OperateType::FINISH, false)
45
+
46
+ # Open home workspace
47
+ DepService.dep_operator(path, user).open
48
+
49
+ # Push home changes to remote
50
+ GitService.new.verify_push(path, "finish branch #{branch_name}", branch_name, 'Home')
51
+ ensure
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/ruby
2
+ require 'big_keeper/util/bigkeeper_parser'
3
+ require 'big_keeper/util/list_generator'
4
+ require 'big_keeper/service/module_service'
5
+
6
+
7
+ module BigKeeper
8
+ def self.list(path, user, type, options)
9
+ BigkeeperParser.parse("#{path}/Bigkeeper")
10
+ home_path = File.expand_path(path)
11
+ #get home project branches
12
+ branches = GitService.new.branchs_with_type(home_path, type)
13
+ #get modules list
14
+ is_print_log = false if options[:json]
15
+ #get search version
16
+ version = options[:version]
17
+ cache_path = File.expand_path("#{path}/.bigkeeper")
18
+ json_path = "#{cache_path}/branches.json"
19
+ begin
20
+ #get cache file path
21
+ FileUtils.mkdir_p(cache_path) unless File.exist?(cache_path)
22
+ file = File.new(json_path, 'w', :encoding => 'UTF-8')
23
+ begin
24
+ #get all modules info
25
+ module_list_dic = get_module_info(path, user, type, version, branches, is_print_log)
26
+ file << module_list_dic.to_json
27
+ file.close
28
+ end
29
+ #print list
30
+ generate_list_with_option(options, json_path, version, branches)
31
+ ensure
32
+ file.close
33
+ end
34
+ end
35
+
36
+ def self.get_module_info(path, user, type, version, home_branches, is_print_log)
37
+ #get module list
38
+ modules = BigkeeperParser.module_names
39
+ git_operator = GitOperator.new
40
+ module_info_list = []
41
+ modules.each do |module_name|
42
+ module_full_path = BigkeeperParser.module_full_path(path, user, module_name)
43
+ #local project verify
44
+ if !File.exist? module_full_path
45
+ Logger.default("No local repository for module '#{module_name}', clone it...") if is_print_log
46
+ module_git = BigkeeperParser.module_git(module_name)
47
+ git_operator.clone(File.expand_path("#{module_full_path}/../"), module_git)
48
+ end
49
+ #每个模块详细信息
50
+ module_branch_info = ModuleService.new.module_info(module_full_path, home_branches, user, type, module_name, version)
51
+ module_info_list << module_branch_info
52
+ end
53
+ module_info_list
54
+ end
55
+
56
+ def self.generate_list_with_option(options, file_path, version, home_branches)
57
+ if options[:json]
58
+ ListGenerator.generate_json(file_path, home_branches, version)
59
+ else
60
+ ListGenerator.generate_tree(file_path, home_branches, version)
61
+ end
62
+ end
63
+ end