gct 0.3.4 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/gct/command.rb +36 -7
- data/lib/gct/command/autotag.rb +161 -0
- data/lib/gct/command/config.rb +2 -29
- data/lib/gct/command/config/get.rb +1 -1
- data/lib/gct/command/config/set.rb +1 -1
- data/lib/gct/command/create/third.rb +1 -1
- data/lib/gct/command/init/gitlab-ci.rb +12 -1
- data/lib/gct/command/robot.rb +14 -0
- data/lib/gct/command/robot/finish.rb +54 -0
- data/lib/gct/command/robot/start.rb +48 -0
- data/lib/gct/command/spec/lint.rb +2 -1
- data/lib/gct/command/update.rb +9 -0
- data/lib/gct/command/update/tag.rb +84 -16
- data/lib/gct/command/update/version.rb +8 -13
- data/lib/gct/file_base.rb +51 -21
- data/lib/gct/gct_version.rb +1 -1
- data/lib/gct/generator/gct_file.rb +7 -4
- data/lib/gct/specification.rb +8 -3
- data/lib/gct/temp_local_file.rb +14 -3
- metadata +6 -3
- data/lib/gct/command/analyze.rb +0 -127
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3916a6b218a57f70b55c78f86fc05ab29bd9c0db6718ba525249a62b6f92b514
|
4
|
+
data.tar.gz: bffb1a3d12eba75d4ee371c95c1a0145027d75c5d50e399520a4d7d6b9ac16e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3e6420ec4067f11b7a72f6406949739abce31b8e0772ecede4dda7653385154dce1e89cb3bc2dc9d0707c8a15c1ff8dfd0639bb84d18d8a2e17f79b235a2c02
|
7
|
+
data.tar.gz: 2e8d40284080f8a079137afe3e3c44c336d7294603549811608f33e24c91e016ebbff240c0db30a1db3c0c67ad164c74c8f77f9c0251981057a000a0f177f22c
|
data/lib/gct/command.rb
CHANGED
@@ -19,13 +19,14 @@ module Gct
|
|
19
19
|
require 'gct/command/create'
|
20
20
|
require 'gct/command/init'
|
21
21
|
require 'gct/command/config'
|
22
|
-
|
22
|
+
require 'gct/command/autotag'
|
23
23
|
require 'gct/command/op'
|
24
24
|
require 'gct/command/build'
|
25
25
|
require 'gct/command/spec'
|
26
26
|
require 'gct/command/repo'
|
27
27
|
require 'gct/command/setup'
|
28
28
|
require 'gct/command/update'
|
29
|
+
require 'gct/command/robot'
|
29
30
|
|
30
31
|
self.abstract_command = true
|
31
32
|
self.command = 'gct'
|
@@ -51,7 +52,7 @@ module Gct
|
|
51
52
|
String.send(:define_method, :colorize) { |string, _| string }
|
52
53
|
end
|
53
54
|
|
54
|
-
config_gitlab
|
55
|
+
config_gitlab
|
55
56
|
end
|
56
57
|
|
57
58
|
def file_contents(project_id, file, branch)
|
@@ -61,14 +62,19 @@ module Gct
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def config_gitlab
|
64
|
-
token
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
if FileBase.exist_root and token and Gitlab.endpoint.nil?
|
66
|
+
Gitlab.configure do |config|
|
67
|
+
config.endpoint = 'https://gi-dev.ccrgt.com/api/v4'
|
68
|
+
config.private_token = token
|
69
|
+
end
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
73
|
+
def gitlab_error
|
74
|
+
FileBase.root_err
|
75
|
+
token_err
|
76
|
+
end
|
77
|
+
|
72
78
|
def get_project
|
73
79
|
proj = nil
|
74
80
|
Dir.entries(Dir.pwd).each do |subfile|
|
@@ -98,5 +104,28 @@ module Gct
|
|
98
104
|
end
|
99
105
|
tag_points.join('.')
|
100
106
|
end
|
107
|
+
|
108
|
+
def current_branch
|
109
|
+
branch = "#{`git branch | awk '$1 == "*" {print $2}'`}".rstrip
|
110
|
+
raise "该文件夹不是一个git仓库".red if branch.empty?
|
111
|
+
branch
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_branch_can_be_update(branch)
|
115
|
+
can_be_update = current_branch.include?(branch)
|
116
|
+
|
117
|
+
puts "当前不是#{branch}分支".red if !can_be_update
|
118
|
+
|
119
|
+
can_be_update
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
def token
|
124
|
+
FileBase.get_config("token")
|
125
|
+
end
|
126
|
+
|
127
|
+
def token_err
|
128
|
+
raise "请先运行命令:gct config set token GITLAB_TOKEN,参考文档:http://febase.crgt.xyz/docs/app_ios/base".red if token.nil?
|
129
|
+
end
|
101
130
|
end
|
102
131
|
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'parallel'
|
4
|
+
|
5
|
+
module Gct
|
6
|
+
class Command
|
7
|
+
class Autotag < Command
|
8
|
+
self.summary = '分析podfile完整依赖链'
|
9
|
+
self.description = <<-DESC
|
10
|
+
分析podfile完整依赖链,并输出json文件.
|
11
|
+
DESC
|
12
|
+
|
13
|
+
self.arguments = [
|
14
|
+
CLAide::Argument.new('PROJECT_ID', true),
|
15
|
+
CLAide::Argument.new('BRANCH', true),
|
16
|
+
]
|
17
|
+
|
18
|
+
def initialize(argv)
|
19
|
+
gitlab_error
|
20
|
+
@update_ci = argv.flag?('update-ci', false)
|
21
|
+
@project_id = "ios/#{argv.shift_argument}"
|
22
|
+
@branch = argv.shift_argument
|
23
|
+
@file = 'Podfile'
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.options
|
28
|
+
[
|
29
|
+
['--update-ci', '是否更新CI']
|
30
|
+
].concat(super)
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate!
|
34
|
+
super
|
35
|
+
help! '请输入项目名.' unless @project_id
|
36
|
+
help! '请输入分支名.' unless @branch
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
FileBase.root_err
|
41
|
+
analyze_dependencies
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_branch(branch)
|
45
|
+
ret = @branch.include?(branch)
|
46
|
+
raise "当前不是发布分支".red if !ret
|
47
|
+
end
|
48
|
+
|
49
|
+
def podfile
|
50
|
+
# if check_branch_can_be_update('zeus')
|
51
|
+
if check_branch('ft/tag') # TODO: Test branch
|
52
|
+
contents = file_contents(@project_id, @file, @branch)
|
53
|
+
contents.force_encoding('UTF-8')
|
54
|
+
puts contents
|
55
|
+
temp_local_file = TempLocalFile.new(contents, @file)
|
56
|
+
temp_local_file.write
|
57
|
+
full_path = temp_local_file.full_path
|
58
|
+
|
59
|
+
@podfile ||= begin
|
60
|
+
podfile = Pod::Podfile.from_ruby(full_path, contents)
|
61
|
+
podfile
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def analyze_dependencies
|
67
|
+
untagged_git_dependencies = podfile.dependencies.select { |dependency| dependency.external? && dependency.external_source[:tag].nil? && dependency.external_source[:branch] == Constant.DefaultTagBranch}
|
68
|
+
|
69
|
+
untagged_specs = Parallel.map(untagged_git_dependencies, in_threads: 1) do |dep|
|
70
|
+
file_name = "#{dep.name}.podspec"
|
71
|
+
podspec_contents = file_contents("#{Constant.NameSpace}#{dep.name}", file_name, Constant.DefaultTagBranch)
|
72
|
+
temp_local_spec_file = TempLocalFile.new(podspec_contents, file_name)
|
73
|
+
temp_local_spec_file.write
|
74
|
+
spec_file = temp_local_spec_file.full_path
|
75
|
+
|
76
|
+
# 创建podspec对象
|
77
|
+
spec = Pod::Specification.from_file(spec_file)
|
78
|
+
gct_spec = Specification.new()
|
79
|
+
gct_spec.name = spec.name
|
80
|
+
gct_spec.priority = 1000
|
81
|
+
gct_spec.status = SpecPublishStatus::CREATED
|
82
|
+
gct_spec.tag = "0"
|
83
|
+
dependencySpecs = Array.new()
|
84
|
+
if spec.subspecs.length == 0
|
85
|
+
dependencySpecs = spec.dependencies.map do |dep|
|
86
|
+
sub_spec = Specification.new()
|
87
|
+
sub_spec.name = dep.root_name
|
88
|
+
sub_spec.priority = 1000
|
89
|
+
sub_spec.status = SpecPublishStatus::CREATED
|
90
|
+
sub_spec.tag = "0"
|
91
|
+
sub_spec
|
92
|
+
end
|
93
|
+
else
|
94
|
+
temp_arr = Array.new()
|
95
|
+
spec.subspecs.map do |subspec|
|
96
|
+
arr = subspec.dependencies.map do |dep|
|
97
|
+
sub_spec = Specification.new()
|
98
|
+
sub_spec.name = dep.root_name
|
99
|
+
sub_spec.priority = 1000
|
100
|
+
sub_spec.status = SpecPublishStatus::CREATED
|
101
|
+
sub_spec.tag = "0"
|
102
|
+
sub_spec
|
103
|
+
end
|
104
|
+
temp_arr.concat(arr)
|
105
|
+
end
|
106
|
+
dependencySpecs = temp_arr
|
107
|
+
end
|
108
|
+
gct_spec.dependencySpecs = dependencySpecs
|
109
|
+
gct_spec
|
110
|
+
end
|
111
|
+
|
112
|
+
priority_rank(untagged_specs)
|
113
|
+
end
|
114
|
+
|
115
|
+
def eqlBetweenHash(hash1, hash2)
|
116
|
+
iseql = true
|
117
|
+
if hash1.empty? || hash2.empty?
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
hash1.keys.map do |key|
|
121
|
+
if hash1[key].priority != hash2[key].priority
|
122
|
+
iseql = false
|
123
|
+
return iseql
|
124
|
+
end
|
125
|
+
end
|
126
|
+
!hash2.empty?
|
127
|
+
end
|
128
|
+
|
129
|
+
# 优先级排序
|
130
|
+
def priority_rank(specs)
|
131
|
+
temp_spec_map = Hash.new()
|
132
|
+
specs.map do |spec|
|
133
|
+
temp_spec_map[spec.name] = spec
|
134
|
+
end
|
135
|
+
temp_spec_map_copy = Hash.new()
|
136
|
+
count = 1
|
137
|
+
|
138
|
+
while !(eqlBetweenHash(temp_spec_map, temp_spec_map_copy)) do
|
139
|
+
# 深拷贝
|
140
|
+
temp_spec_map_copy = Marshal.load(Marshal.dump(temp_spec_map))
|
141
|
+
puts "--- times == #{count} ---"
|
142
|
+
specs.map do |spec|
|
143
|
+
temp_spec = temp_spec_map[spec.name]
|
144
|
+
spec.dependencySpecs.map do |subspec|
|
145
|
+
temp_sub_spec = temp_spec_map[subspec.name]
|
146
|
+
if temp_sub_spec && temp_sub_spec.name != temp_spec.name
|
147
|
+
if temp_spec.priority >= temp_sub_spec.priority - 1
|
148
|
+
temp_spec.priority = temp_sub_spec.priority - 1
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
count += 1
|
154
|
+
temp_spec_map.each { |key, value|
|
155
|
+
puts "#{key} => #{value.priority}"
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/gct/command/config.rb
CHANGED
@@ -4,39 +4,12 @@ require 'gct/command/config/get'
|
|
4
4
|
module Gct
|
5
5
|
class Command
|
6
6
|
class Config < Command
|
7
|
+
self.abstract_command = true
|
7
8
|
self.summary = 'gct 配置'
|
8
9
|
self.description = <<-DESC
|
9
10
|
配置全局链接等
|
10
11
|
DESC
|
11
|
-
|
12
|
-
def initialize(argv)
|
13
|
-
@list = argv.flag?('list', false)
|
14
|
-
super
|
15
|
-
end
|
16
|
-
|
17
|
-
def run
|
18
|
-
# get_all_config if @list
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.options
|
22
|
-
[
|
23
|
-
['--list', '打印config所有信息'],
|
24
|
-
].concat(super)
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.get_config(key)
|
28
|
-
file_base = FileBase.new(config_path)
|
29
|
-
file_base.yaml_read(key)
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.set_config(key, value)
|
33
|
-
file_base = FileBase.new(config_path)
|
34
|
-
file_base.yaml_write(key, value)
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.config_path
|
38
|
-
"#{Generator::GctFile.config_file_path}"
|
39
|
-
end
|
12
|
+
|
40
13
|
end
|
41
14
|
end
|
42
15
|
end
|
@@ -52,7 +52,7 @@ module Gct
|
|
52
52
|
puts "git命令为:<-- git clone #{branch} #{@url} -->".green
|
53
53
|
`git clone #{branch} #{@url}`
|
54
54
|
Dir.chdir(path) do
|
55
|
-
git_url = "#{Constant.
|
55
|
+
git_url = "#{Constant.GitThirdURL}#{dir}"
|
56
56
|
`git init`
|
57
57
|
`git remote set-url origin #{git_url}.git`
|
58
58
|
`git add .`
|
@@ -1,13 +1,24 @@
|
|
1
1
|
stages:
|
2
2
|
- push
|
3
|
+
- failure
|
3
4
|
|
4
5
|
push_pod:
|
5
6
|
stage: push
|
6
7
|
script:
|
8
|
+
- gct robot start
|
7
9
|
- echo "开始lint 和 push podspec"
|
8
10
|
- gct repo update
|
9
11
|
- gct repo push
|
12
|
+
- gct robot finish true
|
10
13
|
only:
|
11
|
-
-
|
14
|
+
- tags
|
15
|
+
tags:
|
16
|
+
- iOS
|
17
|
+
|
18
|
+
on_failure:
|
19
|
+
stage: failure
|
20
|
+
script:
|
21
|
+
- gct robot finish false
|
22
|
+
when: on_failure
|
12
23
|
tags:
|
13
24
|
- iOS
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'gct/command/robot/start'
|
2
|
+
require 'gct/command/robot/finish'
|
3
|
+
|
4
|
+
module Gct
|
5
|
+
class Command
|
6
|
+
class Robot < Command
|
7
|
+
self.abstract_command = true
|
8
|
+
self.summary = '企微机器人相关操作'
|
9
|
+
self.description = <<-DESC
|
10
|
+
发送jenkins和gitlab机器人消息
|
11
|
+
DESC
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Gct
|
5
|
+
class Command
|
6
|
+
class Robot < Command
|
7
|
+
class Finish < Robot
|
8
|
+
|
9
|
+
self.summary = 'jenkins 企微机器人通知'
|
10
|
+
self.description = <<-DESC
|
11
|
+
jenkins 企微机器人通知
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('BUILD_STATUS', true),
|
16
|
+
]
|
17
|
+
|
18
|
+
def initialize(argv)
|
19
|
+
@project_name = ENV['CI_PROJECT_NAME']
|
20
|
+
@user_name = ENV['GITLAB_USER_NAME']
|
21
|
+
@tag = ENV['CI_COMMIT_REF_NAME']
|
22
|
+
@build_status = argv.shift_argument
|
23
|
+
@commit_sha = ENV['CI_COMMIT_SHA']
|
24
|
+
@ci_url = ENV['CI_PIPELINE_URL']
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
build_text = @build_status ? "<font color=\"info\">CI运行成功</font>" : "<font color=\"comment\">CI运行失败</font>,请相关人员注意"
|
30
|
+
ci_text = "[点击跳转](#{@ci_url})"
|
31
|
+
|
32
|
+
webhook = FileBase.get_config("gitlab-robot-webhook")
|
33
|
+
url = URI(webhook)
|
34
|
+
|
35
|
+
http = Net::HTTP.new(url.host, url.port)
|
36
|
+
if url.scheme == "https"
|
37
|
+
http.use_ssl = true
|
38
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
39
|
+
end
|
40
|
+
|
41
|
+
data = {
|
42
|
+
"msgtype": "markdown",
|
43
|
+
"markdown": {
|
44
|
+
"content": "**#{@project_name} #{build_text}**\n\n\n>触发人:#{@user_name}\n\n>tag:#{@tag}\n\n>commitid:#{@commit_sha}\n\n>流水线地址:#{ci_text}"
|
45
|
+
}
|
46
|
+
}.to_json
|
47
|
+
|
48
|
+
header = {'content-type':'application/json'}
|
49
|
+
response = http.post(url, data, header)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Gct
|
5
|
+
class Command
|
6
|
+
class Robot < Command
|
7
|
+
class Start < Robot
|
8
|
+
|
9
|
+
self.summary = '开始通知'
|
10
|
+
self.description = <<-DESC
|
11
|
+
开始通知
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
]
|
16
|
+
|
17
|
+
def initialize(argv)
|
18
|
+
@project_name = ENV['CI_PROJECT_NAME']
|
19
|
+
@tag = ENV['CI_COMMIT_REF_NAME']
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
webhook = FileBase.get_config("gitlab-robot-webhook")
|
25
|
+
raise "请先设置webhook --> gct config set gitlab-robot-webhook WEBHOOK_URL" if webhook.nil? || webhook.empty?
|
26
|
+
url = URI(webhook)
|
27
|
+
|
28
|
+
http = Net::HTTP.new(url.host, url.port)
|
29
|
+
if url.scheme == "https"
|
30
|
+
http.use_ssl = true
|
31
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
32
|
+
end
|
33
|
+
|
34
|
+
message = " <font color=\"info\">#{@tag}</font> 开始打tag"
|
35
|
+
data = {
|
36
|
+
"msgtype": "markdown",
|
37
|
+
"markdown": {
|
38
|
+
"content": "**#{@project_name}** #{message}"
|
39
|
+
}
|
40
|
+
}.to_json
|
41
|
+
|
42
|
+
header = {'content-type':'application/json'}
|
43
|
+
response = http.post(url, data, header)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -22,7 +22,8 @@ module Gct
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def run
|
25
|
-
|
25
|
+
system "pod lib lint --sources=#{Constant.GitURL}iOSCRGTPodSource.git --allow-warnings --verbose --skip-import-validation --use-libraries", exception: true
|
26
|
+
# lint_spec
|
26
27
|
end
|
27
28
|
|
28
29
|
def generate_podfile(pod_name, spec_path)
|
data/lib/gct/command/update.rb
CHANGED
@@ -9,41 +9,109 @@ module Gct
|
|
9
9
|
DESC
|
10
10
|
|
11
11
|
self.arguments = [
|
12
|
+
CLAide::Argument.new('NAME', false),
|
12
13
|
CLAide::Argument.new('TAG', false),
|
13
14
|
]
|
14
15
|
|
16
|
+
def self.options
|
17
|
+
[
|
18
|
+
['--skip-tag', '是否忽略tag,直接触发ci'],
|
19
|
+
['--update-ci', '是否更新CI'],
|
20
|
+
].concat(super)
|
21
|
+
end
|
22
|
+
|
15
23
|
def initialize(argv)
|
24
|
+
@update_version_branch = 'develop'
|
25
|
+
@skip_tag = argv.flag?('skip-tag', false)
|
26
|
+
@update_ci = argv.flag?('update-ci', false)
|
27
|
+
@file = get_spec_file
|
28
|
+
name = argv.shift_argument
|
29
|
+
@name = name.nil? ? @spec.name : name
|
16
30
|
@tag = argv.shift_argument
|
31
|
+
@project_id = "#{Constant.NameSpace}#{@name}"
|
17
32
|
super
|
18
33
|
end
|
19
34
|
|
20
|
-
def
|
21
|
-
|
35
|
+
def run
|
36
|
+
update_ci_method if @update_ci
|
37
|
+
if @skip_tag
|
38
|
+
skip_tag_method
|
39
|
+
else
|
40
|
+
update_podspec_version
|
41
|
+
end
|
22
42
|
end
|
23
43
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
44
|
+
def skip_tag_method
|
45
|
+
@new_tag = @spec.version
|
46
|
+
puts "tag == #{@new_tag}"
|
47
|
+
delete_tag # remove tag
|
48
|
+
create_tag # create tag
|
27
49
|
end
|
28
50
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
51
|
+
def update_ci_method
|
52
|
+
puts "更新ci文件".green
|
53
|
+
temp_local_file = TempLocalFile.new()
|
54
|
+
path = File.expand_path("../../init", __FILE__)
|
55
|
+
ci_content = temp_local_file.read_path_file(path, "gitlab-ci.rb")
|
56
|
+
edit_file('.gitlab-ci.yml', ci_content, 'update ci')
|
57
|
+
mr_to_master
|
58
|
+
accept_merge_request
|
32
59
|
end
|
33
60
|
|
34
|
-
def
|
61
|
+
def get_spec_file
|
35
62
|
spec_file = Pathname.glob('*.podspec').first
|
36
63
|
raise "在 #{Dir.pwd} 目录下找不到podspec文件".red if spec_file.nil?
|
37
64
|
|
38
|
-
spec = Pod::Specification.from_file(spec_file)
|
39
|
-
|
65
|
+
@spec = Pod::Specification.from_file(spec_file)
|
66
|
+
spec_file
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_podspec_version
|
70
|
+
puts "开始读取podspec文件...".green
|
71
|
+
podspec_content = file_contents(@project_id, @file, @update_version_branch)
|
72
|
+
version_regex = /.*version.*/
|
73
|
+
version_match = version_regex.match(podspec_content).to_s
|
74
|
+
tag_regex = /(?<=')\w.*(?=')/
|
75
|
+
tag = tag_regex.match(version_match)
|
76
|
+
@now_tag = tag
|
77
|
+
@new_tag = @tag || auto_add_tag(tag.to_s)
|
78
|
+
replace_string = version_match.gsub(tag_regex, @new_tag)
|
79
|
+
updated_podspec_content = podspec_content.gsub(version_match, replace_string)
|
80
|
+
puts "修改podpsec版本号成功!版本号为:#{@new_tag}".green
|
81
|
+
edit_file(@file, updated_podspec_content, "@config 更新版本号:#{@new_tag}")
|
82
|
+
mr_to_master
|
83
|
+
accept_merge_request
|
84
|
+
create_tag
|
85
|
+
end
|
86
|
+
|
87
|
+
def edit_file(file, content, commit_message)
|
88
|
+
Gitlab.edit_file(@project_id, file, @update_version_branch, content, commit_message)
|
89
|
+
end
|
90
|
+
|
91
|
+
def mr_to_master
|
92
|
+
puts "正在创建MR请求将develop分支合并到master!".green
|
93
|
+
mr = Gitlab.create_merge_request("#{Constant.NameSpace}#{@name}", "更新版本podpesc版本号", { source_branch: "#{@update_version_branch}", target_branch: 'master' })
|
94
|
+
@id = mr.iid
|
95
|
+
puts mr.merge_status
|
96
|
+
if mr.merge_status == 'cannot_be_merged'
|
97
|
+
raise "Merge有冲突,请前往 https://gi-dev.ccrgt.com/#{Constant.NameSpace}#{@name}/merge_requests/#{@id} 解决".red
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def accept_merge_request
|
102
|
+
mr_result = Gitlab.accept_merge_request("#{@project_id}", @id)
|
103
|
+
if mr_result.state == 'merged'
|
104
|
+
puts "成功合并到master分支".green
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def delete_tag
|
109
|
+
Gitlab.delete_tag("#{@project_id}", "#{@new_tag}")
|
40
110
|
end
|
41
111
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
`git tag #{@new_tag}`
|
46
|
-
`git push origin #{@new_tag} || { exit 1; }`
|
112
|
+
def create_tag
|
113
|
+
Gitlab.create_tag("#{@project_id}", "#{@new_tag}", "master")
|
114
|
+
puts "打tag成功,开始上传podspec...".green
|
47
115
|
end
|
48
116
|
end
|
49
117
|
end
|
@@ -9,8 +9,8 @@ module Gct
|
|
9
9
|
DESC
|
10
10
|
|
11
11
|
self.arguments = [
|
12
|
-
CLAide::Argument.new('NAME', false),
|
13
12
|
CLAide::Argument.new('VERSION', false),
|
13
|
+
CLAide::Argument.new('NAME', false),
|
14
14
|
]
|
15
15
|
|
16
16
|
def initialize(argv)
|
@@ -19,7 +19,6 @@ module Gct
|
|
19
19
|
name = @name ||= "iLife"
|
20
20
|
@project_id = "#{Constant.NameSpace}#{name}"
|
21
21
|
@file = "#{name}.xcodeproj/project.pbxproj"
|
22
|
-
@branch = current_branch.rstrip
|
23
22
|
super
|
24
23
|
end
|
25
24
|
|
@@ -28,11 +27,17 @@ module Gct
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def run
|
30
|
+
@branch = current_branch
|
31
31
|
update_version
|
32
32
|
end
|
33
33
|
|
34
34
|
def update_version
|
35
|
-
|
35
|
+
puts @project_id
|
36
|
+
puts @file
|
37
|
+
puts @branch
|
38
|
+
content = file_contents(@project_id, @file, @branch)
|
39
|
+
puts content
|
40
|
+
if check_branch_can_be_update('release')
|
36
41
|
content = file_contents(@project_id, @file, @branch)
|
37
42
|
version_var_name = 'MARKETING_VERSION = '
|
38
43
|
version_regex = /(?<=#{version_var_name})\w.*(?=;)/
|
@@ -40,22 +45,12 @@ module Gct
|
|
40
45
|
version = @version ||= auto_add_tag(version_match)
|
41
46
|
updated_content = content.gsub(version_regex, version)
|
42
47
|
edit_file(updated_content, version)
|
43
|
-
else
|
44
|
-
puts "当前不是release分支".red
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
51
|
def edit_file(content, version)
|
49
52
|
Gitlab.edit_file(@project_id, @file, @branch, content, "@config 更新版本号:#{version}")
|
50
53
|
end
|
51
|
-
|
52
|
-
def check_branch_can_be_update
|
53
|
-
current_branch.include?('release')
|
54
|
-
end
|
55
|
-
|
56
|
-
def current_branch
|
57
|
-
"#{`git branch | awk '$1 == "*" {print $2}'`}"
|
58
|
-
end
|
59
54
|
end
|
60
55
|
end
|
61
56
|
end
|
data/lib/gct/file_base.rb
CHANGED
@@ -1,29 +1,59 @@
|
|
1
1
|
module Gct
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
module FileBase
|
3
|
+
class << self
|
4
|
+
attr_reader :path
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
def yaml_write(key, value)
|
11
|
+
begin
|
12
|
+
config_map = YAML.load(File.open(@path, "r"))
|
13
|
+
config_map[key] = value
|
14
|
+
yaml_file = File.open(@path, "w")
|
15
|
+
YAML::dump(config_map, yaml_file)
|
16
|
+
rescue IOError => e
|
17
|
+
raise e.message
|
18
|
+
ensure
|
19
|
+
yaml_file.close unless yaml_file.nil?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def yaml_read(key)
|
24
|
+
begin
|
25
|
+
yaml_file = YAML.load(File.open(@path, "r"))
|
26
|
+
if yaml_file
|
27
|
+
yaml_file[key]
|
28
|
+
end
|
29
|
+
rescue IOError => e
|
30
|
+
raise e.message
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_config(key)
|
35
|
+
root_err
|
36
|
+
@path = config_path
|
37
|
+
yaml_read(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_config(key, value)
|
41
|
+
root_err
|
42
|
+
@path = config_path
|
43
|
+
yaml_write(key, value)
|
44
|
+
end
|
45
|
+
|
46
|
+
def config_path
|
47
|
+
"#{Generator::GctFile.config_file_path}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def exist_root
|
51
|
+
root_exist = File.exist?(Generator::GctFile.root_folder_path)
|
52
|
+
root_exist
|
18
53
|
end
|
19
|
-
end
|
20
54
|
|
21
|
-
|
22
|
-
|
23
|
-
yaml_file = YAML.load(File.open(@path, "r"))
|
24
|
-
yaml_file[key]
|
25
|
-
rescue IOError => e
|
26
|
-
raise e.message
|
55
|
+
def root_err
|
56
|
+
raise "请先运行命令:gct setup".red if !exist_root
|
27
57
|
end
|
28
58
|
end
|
29
59
|
end
|
data/lib/gct/gct_version.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
module Gct
|
2
2
|
module Generator
|
3
3
|
class GctFile
|
4
|
-
|
5
4
|
def self.root_folder_path
|
6
|
-
"
|
5
|
+
"#{get_system_home_path.rstrip}/.gct"
|
7
6
|
end
|
8
7
|
|
9
8
|
def self.temp_folder_path
|
10
|
-
"
|
9
|
+
"#{get_system_home_path.rstrip}/.gct/tmp"
|
11
10
|
end
|
12
11
|
|
13
12
|
def self.config_file_path
|
14
|
-
"
|
13
|
+
"#{get_system_home_path.rstrip}/.gct/config"
|
15
14
|
end
|
16
15
|
|
17
16
|
# 获取系统用户名
|
@@ -27,6 +26,10 @@ module Gct
|
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
29
|
+
def self.get_system_home_path
|
30
|
+
"#{`echo ~`}"
|
31
|
+
end
|
32
|
+
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
data/lib/gct/specification.rb
CHANGED
@@ -3,8 +3,6 @@ module Gct
|
|
3
3
|
# attr_reader only get
|
4
4
|
# attr_writer only set
|
5
5
|
class Specification
|
6
|
-
# Pod::Dependency
|
7
|
-
attr_accessor :specification
|
8
6
|
|
9
7
|
# 优先级
|
10
8
|
attr_accessor :priority
|
@@ -15,11 +13,18 @@ module Gct
|
|
15
13
|
# 发布状态
|
16
14
|
attr_accessor :status
|
17
15
|
|
16
|
+
# 依赖specs
|
17
|
+
attr_accessor :dependencySpecs
|
18
|
+
|
19
|
+
# spec name
|
20
|
+
attr_accessor :name
|
21
|
+
|
18
22
|
def initialize()
|
19
|
-
@specification = specification
|
20
23
|
@priority = priority
|
21
24
|
@status = status
|
22
25
|
@tag = tag
|
26
|
+
@dependencySpecs = dependencySpecs
|
27
|
+
@name = name
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
data/lib/gct/temp_local_file.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Gct
|
2
2
|
class TempLocalFile
|
3
|
-
|
3
|
+
attr_accessor :content
|
4
4
|
|
5
|
-
|
5
|
+
attr_accessor :file_name
|
6
6
|
|
7
|
-
def initialize(content, file_name)
|
7
|
+
def initialize(content = '', file_name = '')
|
8
8
|
@content = content
|
9
9
|
@file_name = file_name
|
10
10
|
end
|
@@ -31,6 +31,17 @@ module Gct
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
def read_path_file(path, file)
|
35
|
+
begin
|
36
|
+
file = File.new(File.join(path, file), "r")
|
37
|
+
file.read
|
38
|
+
rescue IOError => e
|
39
|
+
raise e.message
|
40
|
+
ensure
|
41
|
+
file.close unless file.nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
34
45
|
def full_path
|
35
46
|
tmp_folder
|
36
47
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jieming
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -146,7 +146,7 @@ files:
|
|
146
146
|
- bin/gct
|
147
147
|
- lib/gct.rb
|
148
148
|
- lib/gct/command.rb
|
149
|
-
- lib/gct/command/
|
149
|
+
- lib/gct/command/autotag.rb
|
150
150
|
- lib/gct/command/build.rb
|
151
151
|
- lib/gct/command/build/r.rb
|
152
152
|
- lib/gct/command/config.rb
|
@@ -169,6 +169,9 @@ files:
|
|
169
169
|
- lib/gct/command/repo/add.rb
|
170
170
|
- lib/gct/command/repo/push.rb
|
171
171
|
- lib/gct/command/repo/update.rb
|
172
|
+
- lib/gct/command/robot.rb
|
173
|
+
- lib/gct/command/robot/finish.rb
|
174
|
+
- lib/gct/command/robot/start.rb
|
172
175
|
- lib/gct/command/setup.rb
|
173
176
|
- lib/gct/command/spec.rb
|
174
177
|
- lib/gct/command/spec/lint.rb
|
data/lib/gct/command/analyze.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'tmpdir'
|
3
|
-
require 'parallel'
|
4
|
-
|
5
|
-
module Gct
|
6
|
-
class Command
|
7
|
-
class Analyze < Command
|
8
|
-
self.summary = '分析podfile完整依赖链'
|
9
|
-
self.description = <<-DESC
|
10
|
-
分析podfile完整依赖链,并输出json文件.
|
11
|
-
DESC
|
12
|
-
|
13
|
-
self.arguments = [
|
14
|
-
CLAide::Argument.new('PROJECT_ID', true),
|
15
|
-
CLAide::Argument.new('FILE', true),
|
16
|
-
CLAide::Argument.new('BRANCH', true),
|
17
|
-
]
|
18
|
-
|
19
|
-
def initialize(argv)
|
20
|
-
@project_id = argv.shift_argument
|
21
|
-
@file = argv.shift_argument
|
22
|
-
@branch = argv.shift_argument
|
23
|
-
super
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.options
|
27
|
-
[
|
28
|
-
].concat(super)
|
29
|
-
end
|
30
|
-
|
31
|
-
def validate!
|
32
|
-
help! '必须输入项目名.' unless @project_id
|
33
|
-
help! '必须输入读取文件的相对路径.' unless @file
|
34
|
-
help! '必须输入读取文件的项目分支.' unless @branch
|
35
|
-
super
|
36
|
-
end
|
37
|
-
|
38
|
-
def run
|
39
|
-
analyze_dependencies
|
40
|
-
# update_podspec_version()
|
41
|
-
end
|
42
|
-
|
43
|
-
def podfile
|
44
|
-
contents = file_contents(@project_id, @file, @branch)
|
45
|
-
contents.force_encoding('UTF-8')
|
46
|
-
|
47
|
-
temp_local_file = TempLocalFile.new(contents, @file)
|
48
|
-
temp_local_file.write
|
49
|
-
full_path = temp_local_file.full_path
|
50
|
-
|
51
|
-
@podfile ||= begin
|
52
|
-
podfile = Pod::Podfile.from_ruby(full_path, contents)
|
53
|
-
podfile
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def analyze_dependencies
|
58
|
-
untagged_git_dependencies = podfile.dependencies.select { |dependency| dependency.external? && dependency.external_source[:tag].nil? && dependency.external_source[:branch] == Constant.DefaultTagBranch}
|
59
|
-
puts untagged_git_dependencies
|
60
|
-
# untagged_specs = Parallel.map(untagged_git_dependencies, in_threads: 1) do |dep|
|
61
|
-
# require 'json'
|
62
|
-
# puts "#{Constant.NameSpace}#{dep.name}"
|
63
|
-
# puts "#{dep.name}.podspec"
|
64
|
-
# puts Constant.DefaultTagBranch
|
65
|
-
|
66
|
-
# contents_json = file_contents("#{Constant.NameSpace}#{dep.name}", "#{dep.name}.podspec", Constant.DefaultTagBranch)
|
67
|
-
# podspec = system contents_json
|
68
|
-
# puts podspec.class
|
69
|
-
# puts podspec
|
70
|
-
# podspec = from_string("", contents_json)
|
71
|
-
# podspec = Pod::Spec.new do |spec|
|
72
|
-
|
73
|
-
# end
|
74
|
-
|
75
|
-
|
76
|
-
# puts podspec.class.to_s
|
77
|
-
# puts podspec.to_s
|
78
|
-
# gct_spec = Specification.new()
|
79
|
-
# gct_spec.specification = podspec
|
80
|
-
# gct_spec.priority = 1000
|
81
|
-
# gct_spec.status = SpecPublishStatus::CREATED
|
82
|
-
# gct_spec.tag = "0"
|
83
|
-
|
84
|
-
# update_podspec_version(spec)
|
85
|
-
# gct_spec
|
86
|
-
# end
|
87
|
-
end
|
88
|
-
|
89
|
-
def update_podspec_version(spec)
|
90
|
-
content = file_contents("#{Constant.NameSpace}#{dep.name}", "#{spec.name}.podspec", Constant.DefaultTagBranch)
|
91
|
-
now_version = spec.version
|
92
|
-
version = auto_add_tag(now_version)
|
93
|
-
require_variable_prefix = true
|
94
|
-
version_var_name = 'version'
|
95
|
-
variable_prefix = require_variable_prefix ? /\w\./ : //
|
96
|
-
version_regex = /^(?<begin>[^#]*#{variable_prefix}#{version_var_name}\s*=\s*['"])(?<value>(?<major>[0-9]+)(\.(?<minor>[0-9]+))?(\.(?<patch>[0-9]+))?(?<appendix>(\.[0-9]+)*)?(-(?<prerelease>(.+)))?)(?<end>['"])/i
|
97
|
-
version_match = version_regex.match(content)
|
98
|
-
updated_podspec_content = content.gsub(version_regex, "#{version_match[:begin]}#{version}#{version_match[:end]}")
|
99
|
-
updated_podspec_content
|
100
|
-
|
101
|
-
edit_file(spec, updated_podspec_content, version)
|
102
|
-
mr_to_master(spec)
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
def edit_file(spec, content, version)
|
108
|
-
Gitlab.edit_file("#{Constant.NameSpace}#{dep.name}", "#{spec.name}.podspec", Constant.DefaultTagBranch, content, "@config 升级版本号:#{version}")
|
109
|
-
end
|
110
|
-
|
111
|
-
def mr_to_master(spec)
|
112
|
-
mr = Gitlab.create_merge_request("#{Constant.NameSpace}#{dep.name}", "podpesc修改", { source_branch: 'develop', target_branch: 'master' })
|
113
|
-
id = mr.iid
|
114
|
-
puts mr.to_hash
|
115
|
-
if mr.merge_status == 'cannot_be_merged'
|
116
|
-
raise "Merge有冲突,请前往 https://gi-dev.ccrgt.com/#{Constant.NameSpace}#{spec.name}/merge_requests/#{id} 解决".red
|
117
|
-
end
|
118
|
-
|
119
|
-
accept_merge_request(spec, id)
|
120
|
-
end
|
121
|
-
|
122
|
-
def accept_merge_request(spec, id)
|
123
|
-
Gitlab.accept_merge_request("#{Constant.NameSpace}#{dep.name}", id)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|