Class: Gct::Command::Autotag

Inherits:
Gct::Command show all
Defined in:
lib/gct/command/autotag.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Gct::Command

#auto_add_tag, #check_branch_can_be_update, #config_gitlab, #current_branch, #file_contents, #get_project, #gitlab_error, run

Constructor Details

#initialize(argv) ⇒ Autotag

Returns a new instance of Autotag.



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/gct/command/autotag.rb', line 20

def initialize(argv)
  gitlab_error
  config_gitlab
  @update_ci = argv.flag?('update-ci', false)
  @pre = argv.flag?('pre', false)
  name = argv.shift_argument
  @project_id = "ios/#{name}"
  @project_name = name
  @branch = argv.shift_argument
  @version = argv.shift_argument
  @file = 'Podfile'
  super
end

Class Method Details

.optionsObject



34
35
36
37
38
39
# File 'lib/gct/command/autotag.rb', line 34

def self.options
  [
    ['--update-ci', '是否更新CI'],
    ['--pre', '是否为预发tag'],
  ].concat(super)
end

Instance Method Details

#analyze_dependenciesObject



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/gct/command/autotag.rb', line 176

def analyze_dependencies 
  untagged_specs = tmp_podspecs.map do |spec_file| 
    # 创建podspec对象
    spec = Pod::Specification.from_file(spec_file)
    gct_spec = Specification.new()
    gct_spec.name = spec.name
    gct_spec.priority = 1000
    gct_spec.status = SpecPublishStatus::WAITING
    gct_spec.tag = "0"
    dependencySpecs = Array.new()
    if spec.subspecs.length == 0
      dependencySpecs = spec.dependencies.map do |dep|
        sub_spec = Specification.new()
        sub_spec.name = dep.root_name
        sub_spec.priority = 1000
        sub_spec.status = SpecPublishStatus::WAITING
        sub_spec.tag = "0"
        sub_spec
      end 
    else 
      temp_arr = Array.new()
      spec.subspecs.map do |subspec|
        arr = subspec.dependencies.map do |dep|
          sub_spec = Specification.new()
          sub_spec.name = dep.root_name
          sub_spec.priority = 1000
          sub_spec.status = SpecPublishStatus::WAITING
          sub_spec.tag = "0"
          sub_spec
        end 
        temp_arr.concat(arr)
      end
      dependencySpecs = temp_arr
    end
    gct_spec.dependencySpecs = dependencySpecs
    gct_spec
  end
  untagged_specs
end

#check_remote_branchObject



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/gct/command/autotag.rb', line 83

def check_remote_branch
  remote_branches = Gitlab.branches(@project_id, per_page: 1000)
  branches = Array.new()
  remote_branches.each do |item|
    hash_branch = item.to_hash
    branch_name = hash_branch["name"]
    branches.push(branch_name)
  end
  is_exist_branch = branches.include?(@branch)
  is_exist_branch
end

#create_pre_branch(branch, project_name) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/gct/command/autotag.rb', line 140

def create_pre_branch(branch, project_name)
  puts "正在创建#{project_name}预发分支!".green
  bs = Gitlab.branches(project_name)
  to_b = Constant.DefaultTagToBranch
  pre_to_b = Constant.PreTagToBranch
  from_b = Constant.DefaultTagFromBranch
  bs.each do |b|
    if b["name"].eql?(branch)
      Gitlab.delete_branch(project_name, branch)
    end
    if b["name"].eql?(pre_to_b)
      Gitlab.delete_branch(project_name, pre_to_b)
    end
  end
  Gitlab.create_branch(project_name, branch, from_b)
  Gitlab.create_branch(project_name, pre_to_b, to_b)
end

#create_tag_by_priorityObject

按优先级打tag, 触发第一个优先级,其他的上一优先级打完之后自动触发



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/gct/command/autotag.rb', line 276

def create_tag_by_priority()
  db = Database::Data.new
  # 查询优先级最高的为完成打tag的数据
  where_statement = "and is_pre = " + (@pre ? "1" : "0")
  sql = "select * from tag where priority = (select MAX(priority) from tag where tag_status != '#{SpecPublishStatus::SUCCESS}' #{where_statement}) and project_version = '#{@version}'" 
  result = db.query(sql)
  vals = ""
  ins = ""
  if !result.nil? && result.count > 0
    result.each do |row|
      if row["tag_status"].eql?(SpecPublishStatus::WAITING) || row["tag_status"].eql?(SpecPublishStatus::CANCELED) || row["tag_status"].eql?(SpecPublishStatus::FAILED)
        status = SpecPublishStatus::PENDING
        name = row["pod_name"]
        vals.concat("when pod_name = '#{name}' then '#{status}' ")     
        ins.concat("'#{name}',")
        system "gct update dependency #{name} tag_status #{status}"
        skip_tag = ""
        if row["is_tag"].to_i == 1 
          skip_tag = "--skip-tag"
        end
        pre = ""
        if row["is_pre"].to_i == 1
          pre = "--pre"
        end
        system "gct update tag #{name} --auto-tag --update-ci #{skip_tag} #{pre}"
      end
    end
    f_ins = ins[0, ins.length - 1]
    sql = "update tag set tag_status = (
    case 
    #{vals}
    end
    ) where pod_name in (#{f_ins}) and project_version = '#{@version}'"
    update_db = Database::Data.new
    update_db.query(sql)
  end
end

#eqlBetweenHash(hash1, hash2) ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/gct/command/autotag.rb', line 216

def eqlBetweenHash(hash1, hash2) 
  iseql = true
  if hash1.empty? || hash2.empty?
    return false
  end
  hash1.keys.map do |key|
    if hash1[key].priority != hash2[key].priority
      iseql = false
      return iseql
    end
  end
  !hash2.empty?
end

#podfileObject



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/gct/command/autotag.rb', line 95

def podfile
  contents = file_contents(@project_id, @file, @branch)
  contents.force_encoding('UTF-8')
  temp_local_file = TempLocalFile.new(contents, @file)
  temp_local_file.write
  full_path = temp_local_file.full_path

  @podfile ||= begin
    podfile = Pod::Podfile.from_ruby(full_path, contents)
    podfile
  end
end

#priority_rank(specs) ⇒ Object

优先级排序



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/gct/command/autotag.rb', line 231

def priority_rank(specs)
  temp_spec_map = Hash.new()
  specs.map do |spec| 
    temp_spec_map[spec.name] = spec
  end
  temp_spec_map_copy = Hash.new()

  while !(eqlBetweenHash(temp_spec_map, temp_spec_map_copy)) do
    # 深拷贝
    temp_spec_map_copy = Marshal.load(Marshal.dump(temp_spec_map))
    specs.map do |spec| 
      temp_spec = temp_spec_map[spec.name]
      spec.dependencySpecs.map do |subspec| 
        temp_sub_spec = temp_spec_map[subspec.name]
        if temp_sub_spec && temp_sub_spec.name != temp_spec.name
          if temp_spec.priority >= temp_sub_spec.priority - 1
            temp_spec.priority = temp_sub_spec.priority - 1
          end
        end
      end
    end
  end
  # 写入project
  write_project
  # 写入tag
  values = ""
  temp_spec_map.each do |key, value| 
    values.concat("('#{@version}', '#{key}', '#{@project_name}', '#{value.tag}', '#{value.status}', #{value.priority}" + (@pre ? ", 1)," : "),"))
  end
  val = values[0, values.length - 1]
  keys = "(project_version, pod_name, project_name, tag_version, tag_status, priority" + (@pre ? ", is_pre)" : ")")
  sql = "insert into tag #{keys} values #{val}"
  db = Database::Data.new
  db.query(sql)
end

#remove_tag(tag, name) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/gct/command/autotag.rb', line 158

def remove_tag(tag, name)
  # 判断是否有这个tag
  tag = "#{tag}#{Constant.PreHuffix}"
  command = `git rev-parse --is-inside-work-tree`
  if command.eql?("true")
    `git tag -d #{tag}`
    `git push origin :refs/tags/#{tag}`  
  else
    tags = Gitlab.tags("#{name}")
    tags.each do |t|
      if t["name"].eql?("#{tag}")
        Gitlab.delete_tag("#{name}", "#{tag}")
        break
      end
    end
  end
end

#runObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/gct/command/autotag.rb', line 48

def run
  FileBase.root_err

  # 检查远端是否存在分支
  is_exist_branch = check_remote_branch
  if !is_exist_branch
    raise "远端未找到 #{@branch} 分支".red
  end

  puts "开始分析podfile文件".green
  puts ""
  where_statement = "and is_pre = #{@pre ? 1 : 0}"
  p_db = Database::Data.new
  p_sql = "select * from project where version = '#{@version}' #{where_statement}"
  p_res = p_db.query(p_sql)
  
  if !p_res.nil? && p_res.count > 0 
    res_first = nil
    p_res.each do |row|
      res_first = row
      break
    end
    if res_first["is_done"].to_i == 0
      tmp_podspecs
      create_tag_by_priority()
    else
      raise "#{@project_name} #{@version} 版本已经打完tag了!!!".red
    end
  else
    untagged_specs = analyze_dependencies
    priority_rank(untagged_specs)
    create_tag_by_priority()
  end
end

#tmp_podspecsObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/gct/command/autotag.rb', line 108

def tmp_podspecs
  untagged_git_dependencies = podfile.dependencies.select { |dependency| dependency.external? && dependency.external_source[:tag].nil? && dependency.external_source[:branch] == Constant.DefaultTagFromBranch}
  raise "没有需要打tag的库".red if untagged_git_dependencies.count == 0

  spec_files = Parallel.map(untagged_git_dependencies, in_threads: 1) do |dep| 
    # 取出组名
    source = dep.external_source[:git]
    left1 = "https://gi-dev.ccrgt.com/"
    left2 = "http://gi-dev.ccrgt.com/"
    right = "/"
    source_regex = /(?<=#{left1}|#{left2}).*(?=#{right})/
    group_name = source_regex.match(source).to_s
    raise "gitlab中找不到#{dep.name}所在的group".red if group_name.nil? || group_name.empty?

    project_name = "#{group_name}/#{dep.name}"
    branch = Constant.DefaultTagFromBranch
    if @pre
      branch = Constant.PreTagFromBranch
      create_pre_branch(branch, project_name)
    end
    file_name = "#{dep.name}.podspec"
    podspec_contents = file_contents(project_name, file_name, branch)
    temp_local_spec_file = TempLocalFile.new(podspec_contents, file_name)
    temp_local_spec_file.write
    path = temp_local_spec_file.full_path
    spec = Pod::Specification.from_file(path)
    remove_tag(auto_add_tag(spec.version.to_s), project_name)
    path
  end
  spec_files
end

#validate!Object



41
42
43
44
45
46
# File 'lib/gct/command/autotag.rb', line 41

def validate!
  super
  help! '请输入项目名.' unless @project_id
  help! '请输入分支名.' unless @branch
  help! '请输入版本号.' unless @version
end

#write_projectObject



267
268
269
270
271
272
273
# File 'lib/gct/command/autotag.rb', line 267

def write_project
  keys = "(version, name, branch" + (@pre ? ", is_pre)" : ")")
  values = "('#{@version}', '#{@project_name}', '#{@branch}'" + (@pre ? ", 1)" : ")")
  db = Database::Data.new
  sql = "insert into project #{keys} values #{values}"
  res = db.query(sql)
end