pod-binary-pack 1.0.0

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.
@@ -0,0 +1,312 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require_relative 'provider'
5
+ require_relative 'gitee_client'
6
+ require_relative '../push'
7
+ require_relative '../git_helper'
8
+
9
+ module Build
10
+ # Gitee 平台实现(适用于 gitee.com 个人标准版)
11
+ # 仓库标识统一使用 owner/repo(full_name),不使用数字ID
12
+ class GiteeProvider < Hosting::Provider
13
+ include Singleton
14
+
15
+ DEFAULT_ENDPOINT = 'https://gitee.com/api/v5'
16
+
17
+ def initialize
18
+ super
19
+ @api = nil
20
+ @user_login = nil
21
+ end
22
+
23
+ def available?
24
+ true
25
+ end
26
+
27
+ # 创建gitee仓库 如果不存在的话
28
+ def create_project_if_need(project_name, http_url, private: true, description: nil)
29
+ unless gitee_url?(http_url)
30
+ Build.log.info('不使用gitee接口检查和创建项目')
31
+ return
32
+ end
33
+
34
+ Build.log.detail("检查gitee仓库(#{http_url})是否存在")
35
+
36
+ info = find_project(project_name, http_url, false)
37
+ if info
38
+ Build.log.info("已存在 仓库: #{info.full_name} 命名空间: #{info.namespace_path} 无需新建")
39
+ info.full_name
40
+ else
41
+ Build.log.info("不存在 需要创建仓库,仓库描述: #{description}")
42
+ do_create_project(project_name, http_url, description, private)
43
+ end
44
+ end
45
+
46
+ def find_project(pod_name, http_url, can_raise = true)
47
+ unless gitee_url?(http_url)
48
+ Build.log.info('不使用gitee接口查询仓库')
49
+ return nil
50
+ end
51
+
52
+ _host, owner, repo = split_url(http_url)
53
+
54
+ data = api.get("/repos/#{escape(owner)}/#{escape(repo)}")
55
+ build_info(data)
56
+ rescue GiteeClient::NotFound
57
+ if can_raise
58
+ error = "当前配置access_token检索不到#{owner}/#{repo},可能是如下原因:\n"
59
+ error += "1、该组件在gitee仓库中的名字和#{pod_name}不一致\n"
60
+ error += "2、当前令牌账号对 #{owner}/#{repo} 没有权限,请用仓库管理员账号生成令牌"
61
+ pusher.push('❌ 打包失败', error)
62
+ Process.exit(-1)
63
+ end
64
+ nil
65
+ end
66
+
67
+ # 标准版保护分支: 保护后仅仓库管理员可推送/合并
68
+ def lock_branch(repo_info, branch, page_url)
69
+ owner, repo = split_full_name(repo_info.full_name)
70
+ branch_path = "#{escape(owner)}/#{escape(repo)}/branches/#{escape(branch)}/protection"
71
+
72
+ # 先取消已有的保护(404说明本来就没保护,忽略)
73
+ begin
74
+ api.delete("/repos/#{branch_path}")
75
+ rescue GiteeClient::NotFound
76
+ # 未保护,无需先取消
77
+ end
78
+
79
+ # 重新保护
80
+ api.put("/repos/#{branch_path}", {})
81
+
82
+ "#{page_url}/branches"
83
+ rescue GiteeClient::Error => e
84
+ pusher.push('❌ 打包失败', "锁死分支#{branch}失败: #{e.message}")
85
+ Process.exit(-1)
86
+ end
87
+
88
+ # 判断分支是否已经包含某次提交(分页拉取分支提交列表)
89
+ def branch_contain_commit?(repo_info, branch, commit_sha)
90
+ owner, repo = split_full_name(repo_info.full_name)
91
+ current_page = 1
92
+ per_page = 100
93
+
94
+ loop do
95
+ commits = api.get(
96
+ "/repos/#{escape(owner)}/#{escape(repo)}/commits",
97
+ sha: branch,
98
+ page: current_page,
99
+ per_page: per_page
100
+ )
101
+
102
+ commits.each do |obj|
103
+ return true if obj['sha'] == commit_sha
104
+ end
105
+
106
+ break if commits.size < per_page
107
+
108
+ current_page += 1
109
+ end
110
+
111
+ false
112
+ rescue GiteeClient::Error => e
113
+ pusher.push('❌ 打包失败', "查询gitee提交记录失败: #{e.message}")
114
+ Process.exit(-1)
115
+ end
116
+
117
+ # 本地 fast-forward 方式合并分支到目标分支并推送
118
+ # 等价于GitLab端 ff 合并: 目标分支直接快进到源分支HEAD,不产生merge commit
119
+ def merge_branch(repo_module, target_branch)
120
+ Build.log.step("开始合并分支到#{target_branch}(#{File.basename(repo_module.path)})")
121
+
122
+ return unless check_merge_branch(repo_module, target_branch)
123
+
124
+ path = repo_module.path
125
+ source_branch = repo_module.branch
126
+
127
+ # 丢弃保护可能的残留,拉取所有远端最新引用
128
+ GitHelper.fetch(path)
129
+
130
+ if GitHelper.remote_branch?(path, target_branch)
131
+ # 基于远端目标分支创建/重置本地目标分支
132
+ GitHelper.checkout_tracking(path, target_branch)
133
+
134
+ # 快进到源分支,非ff情况check_merge_branch已拦截,这里失败直接退出
135
+ GitHelper.merge_ff_only(path, "origin/#{source_branch}")
136
+
137
+ # 推送目标分支
138
+ GitHelper.push(path, target_branch)
139
+ else
140
+ # 远端目标分支不存在,直接把源分支推送为目标分支
141
+ Build.log.info("远端不存在#{target_branch}分支,将当前源分支推送创建该分支")
142
+ GitHelper.push_head_as(path, target_branch)
143
+ end
144
+
145
+ # 切回源分支,后续打tag等流程依赖当前分支
146
+ GitHelper.checkout(path, source_branch)
147
+
148
+ Build.log.detail("自动合并完毕 #{source_branch} => #{target_branch}")
149
+ pusher.push("【✅组件合并到#{target_branch}成功】")
150
+ end
151
+
152
+ private
153
+
154
+ # 合并前置校验
155
+ def check_merge_branch(repo_module, target_branch)
156
+ unless repo_module.build_item.merge_master
157
+ Build.log.info('本次构建 merge_master = false 不执行自动合并')
158
+ return false
159
+ end
160
+
161
+ source_branch = repo_module.branch
162
+ if target_branch == source_branch
163
+ Build.log.warn("源分支#{source_branch}和目标分支#{target_branch}指定名字一样, 无需执行合并")
164
+ return false
165
+ end
166
+
167
+ path = repo_module.path
168
+ GitHelper.fetch(path)
169
+
170
+ # 目标分支远端不存在,直接允许(后续推送创建)
171
+ unless GitHelper.remote_branch?(path, target_branch)
172
+ return true
173
+ end
174
+
175
+ target_ref = "origin/#{target_branch}"
176
+ source_ref = "origin/#{source_branch}"
177
+
178
+ target_last_commit = GitHelper.revision(path, target_ref)
179
+ source_last_commit = GitHelper.revision(path, source_ref)
180
+
181
+ unless target_last_commit
182
+ return true
183
+ end
184
+
185
+ # 源分支和目标分支最新提交一致
186
+ if target_last_commit == source_last_commit
187
+ Build.log.warn("源分支#{source_branch}和目标分支#{target_branch}最新提交一致, 无需执行合并")
188
+ return false
189
+ end
190
+
191
+ # 目标分支最新提交是源分支的祖先 => 可以ff快进合并
192
+ if GitHelper.ancestor?(path, target_ref, source_ref)
193
+ return true
194
+ end
195
+
196
+ error = "当前分支#{source_branch}落后于(或分叉于)#{target_branch}, 无法fast-forward合并, 请先手动合并分支后再打包并执行自动合并分支"
197
+ pusher.push('❌ 打包失败', error)
198
+ Process.exit(-1)
199
+ end
200
+
201
+ def do_create_project(pod_name, http_url, description, is_private)
202
+ _host, owner, _repo = split_url(http_url)
203
+
204
+ params = {
205
+ name: pod_name,
206
+ path: pod_name,
207
+ description: description,
208
+ # gitee无私有/公开之外的internal级别: true私有 false公开
209
+ private: is_private ? true : false,
210
+ auto_init: true
211
+ }
212
+
213
+ data =
214
+ if owner == user_login
215
+ # 个人空间建仓
216
+ api.post('/user/repos', params)
217
+ else
218
+ # 组织空间建仓,先校验令牌对组织有权限
219
+ begin
220
+ api.get("/orgs/#{escape(owner)}")
221
+ rescue GiteeClient::Error
222
+ error = "命名空间#{owner}不存在,或当前令牌账号无权在其下创建仓库。请先在Gitee创建组织/空间#{owner},并使用该组织管理员的令牌"
223
+ pusher.push('❌ 打包失败', error)
224
+ Process.exit(-1)
225
+ end
226
+ api.post("/orgs/#{escape(owner)}/repos", params)
227
+ end
228
+
229
+ full_name = data.is_a?(Hash) ? data['full_name'] : nil
230
+ unless full_name
231
+ pusher.push('❌ 打包失败', '创建gitee仓库失败,接口未返回仓库信息')
232
+ Process.exit(-1)
233
+ end
234
+ full_name
235
+ rescue GiteeClient::Error => e
236
+ pusher.push('❌ 打包失败', "创建gitee仓库失败: #{e.message}")
237
+ Process.exit(-1)
238
+ end
239
+
240
+ # 令牌所属用户的login(用于区分个人空间建仓还是组织建仓)
241
+ def user_login
242
+ @user_login ||= api.get('/user')['login']
243
+ end
244
+
245
+ def build_info(data)
246
+ namespace = data['namespace'] || {}
247
+ Hosting::RepoInfo.new(
248
+ id: data['id'],
249
+ full_name: data['full_name'],
250
+ namespace_path: namespace['path']
251
+ )
252
+ end
253
+
254
+ def split_full_name(full_name)
255
+ full_name.to_s.split('/', 2)
256
+ end
257
+
258
+ # 从ssh/http地址解析 host/owner/repo
259
+ # git@gitee.com:owner/repo.git -> [gitee.com, owner, repo]
260
+ # https://gitee.com/owner/repo(.git) -> [gitee.com, owner, repo]
261
+ def split_url(url)
262
+ url = url.to_s
263
+ if url.start_with?('git@')
264
+ tail = url.split('@', 2).last
265
+ host, path = tail.split(':', 2)
266
+ else
267
+ u = URI(url)
268
+ host = u.host
269
+ path = u.path
270
+ end
271
+
272
+ path = path.to_s.sub(/\A\//, '').sub(/\.git\z/, '')
273
+ parts = path.split('/')
274
+ [host.to_s, parts[0], parts[1]]
275
+ end
276
+
277
+ def gitee_url?(url)
278
+ Hosting.host_of(url).to_s.downcase.include?('gitee')
279
+ end
280
+
281
+ def escape(value)
282
+ GiteeClient.escape_segment(value)
283
+ end
284
+
285
+ def api
286
+ @api ||= GiteeClient.new(endpoint, access_token)
287
+ end
288
+
289
+ def endpoint
290
+ value = ENV['GITEE_API_URL'].to_s.strip
291
+ value = read_git_config('gitee.apiurl') if value.empty?
292
+ value.empty? ? DEFAULT_ENDPOINT : value
293
+ end
294
+
295
+ def access_token
296
+ value = ENV['GITEE_ACCESS_TOKEN'].to_s.strip
297
+ value = read_git_config('gitee.accesstoken') if value.empty?
298
+ if value.empty?
299
+ error = "未读取到gitee令牌,请通过以下任一方式配置(优先级从高到低):\n"
300
+ error += "1、Jenkins环境变量 GITEE_ACCESS_TOKEN(推荐)\n"
301
+ error += "2、git config --global gitee.accesstoken \"xxx\""
302
+ pusher.push('❌ 打包失败', error)
303
+ Process.exit(-1)
304
+ end
305
+ value
306
+ end
307
+
308
+ def read_git_config(key)
309
+ %x(git config --global #{key}).to_s.strip
310
+ end
311
+ end
312
+ end
@@ -0,0 +1,342 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require_relative 'provider'
5
+
6
+ module Build
7
+ # GitLab 平台实现,保留原有基于 Merge Request API 的行为
8
+ # gitlab gem 为懒加载:未安装/未配置时,只有真正操作GitLab仓库才会报错,不影响Gitee流程
9
+ class GitlabProvider < Hosting::Provider
10
+ include Singleton
11
+
12
+ attr_accessor :endpoint
13
+
14
+ def initialize
15
+ super
16
+ @endpoint = nil
17
+ @private_token = nil
18
+ @ready = false
19
+ end
20
+
21
+ def available?
22
+ true
23
+ end
24
+
25
+ # 创建gitlab项目 如果不存在的话(固定创建为私有项目)
26
+ def create_project_if_need(project_name, http_url, private: true, description: nil)
27
+ unless gitlab_url?(http_url)
28
+ Build.log.info('不使用gitlab接口检查和创建项目')
29
+ return
30
+ end
31
+
32
+ Build.log.detail("检查gitlab项目(#{http_url})是否存在")
33
+
34
+ # 检查是否已经存在
35
+ project_obj = find_project(project_name, http_url, false)
36
+ if project_obj
37
+ Build.log.info("已存在 项目ID: #{project_obj.id} 群组:#{project_obj.namespace_path} 无需新建")
38
+ project_obj.full_name
39
+ else
40
+ Build.log.info("不存在 需要创建项目,项目描述: #{description}")
41
+ do_create_project(project_name, http_url, description, private)
42
+ end
43
+ end
44
+
45
+ def find_project(pod_name, http_url, can_raise: true)
46
+ ensure_client
47
+
48
+ unless gitlab_url?(http_url)
49
+ Build.log.info('不使用gitlab接口查询项目ID')
50
+ return nil
51
+ end
52
+
53
+ # 搜索
54
+ project_obj = nil
55
+ projects = Gitlab.project_search(pod_name)
56
+ projects.each do |project|
57
+ project_hash = project.to_hash
58
+ if project.name == pod_name
59
+ if http_url == project_hash['http_url_to_repo'] ||
60
+ http_url == project_hash['ssh_url_to_repo'] ||
61
+ http_url == project_hash['web_url']
62
+ project_obj = project
63
+ break
64
+ end
65
+ end
66
+ end
67
+
68
+ if project_obj.nil? && can_raise
69
+ error = "当前配置private_token检索不到#{pod_name},可能是如下原因:\n"
70
+ error += "1、该组件在git仓库中的名字和#{pod_name}不一致\n"
71
+ error += "2、当前账号在该链接下#{http_url}没有权限,注:需要Maintainer权限"
72
+ pusher.push('❌ 打包失败', error)
73
+ Process.exit(-1)
74
+ end
75
+
76
+ return nil unless project_obj
77
+
78
+ Hosting::RepoInfo.new(
79
+ id: project_obj.id,
80
+ full_name: project_obj.to_hash['path_with_namespace'],
81
+ namespace_path: project_obj.namespace.id.to_s
82
+ )
83
+ end
84
+
85
+ # 锁死对应的分支
86
+ def lock_branch(repo_info, branch, page_url)
87
+ ensure_client
88
+ project_id = repo_info.id
89
+
90
+ # 先取消锁死
91
+ res = Gitlab.protected_branches(project_id)
92
+ res.each do |obj|
93
+ if obj.name == branch
94
+ Gitlab.unprotect_branch(project_id, branch)
95
+ break
96
+ end
97
+ end
98
+
99
+ # 锁死
100
+ Gitlab.protect_branch(project_id, branch, { allow_force_push: false, push_access_level: 0, merge_access_level: 0 })
101
+
102
+ "#{page_url}/-/settings/repository#js-protected-branches-settings"
103
+ end
104
+
105
+ # 判断分支是否已经包含某次提交
106
+ def branch_contain_commit?(repo_info, branch, commit_sha)
107
+ ensure_client
108
+ project_id = repo_info.id
109
+ current_page = 1
110
+ per_page = 20
111
+
112
+ # 获取某个分支的提交
113
+ commits = Gitlab.commits(project_id, { ref_name: branch, page: current_page, per_page: per_page })
114
+ commits.each do |obj|
115
+ return true if obj.to_hash['id'] == commit_sha
116
+ end
117
+
118
+ while commits.size == per_page
119
+ current_page += 1
120
+ commits = Gitlab.repo_commits(project_id, { ref_name: branch, page: current_page, per_page: per_page })
121
+ commits.each do |obj|
122
+ return true if obj.to_hash['id'] == commit_sha
123
+ end
124
+ end
125
+
126
+ false
127
+ end
128
+
129
+ # 通过Merge Request API合并分支(保留原GitLab实现)
130
+ def merge_branch(repo_module, target_branch)
131
+ ensure_client
132
+
133
+ Build.log.step("开始合并分支到#{target_branch}(#{File.basename(repo_module.path)})")
134
+
135
+ unless gitlab_url?(repo_module.ssh_url)
136
+ Build.log.info('非gitlab项目, 不支持此功能')
137
+ return
138
+ end
139
+
140
+ return unless check_merge_branch(repo_module, target_branch)
141
+
142
+ # 合并前需要修改合并方法为快进式 防止拿到的提交者是错误的
143
+ project_id = repo_module.repo_info.id
144
+
145
+ Gitlab.edit_project(project_id, { merge_method: 'ff' })
146
+ sleep 1
147
+
148
+ message = "[merge] #{repo_module.branch} => #{target_branch}"
149
+ merge_request = Gitlab.create_merge_request(project_id, message, { source_branch: repo_module.branch, target_branch: target_branch })
150
+ merge_url = "#{endpoint}/projects/#{project_id}/merge_requests/#{merge_request.iid}/merge"
151
+ Build.log.detail("合并请求的ID: #{merge_request.iid} 链接: #{merge_url}")
152
+
153
+ merge_request = Gitlab.merge_request(project_id, merge_request.iid)
154
+ merge_status = merge_request.to_hash['merge_status']
155
+ state = merge_request.to_hash['state']
156
+ can_be_merged = (merge_status == 'can_be_merged')
157
+ retry_count = 0
158
+ while retry_count <= 60 && !can_be_merged
159
+ Build.log.detail("合并请求检查中...(当前状态: #{state} #{merge_status})")
160
+ merge_request = Gitlab.merge_request(project_id, merge_request.iid)
161
+ merge_status = merge_request.to_hash['merge_status']
162
+ can_be_merged = (merge_status == 'can_be_merged')
163
+ retry_count += 1
164
+ sleep 2
165
+ end
166
+
167
+ # 请求状态错误
168
+ if state != 'opened'
169
+ error = "自动合并失败, 合并请求状态错误:#{state} #{merge_url}"
170
+ pusher.push("【❌ 组件分支合并到#{target_branch}失败】", error)
171
+ Process.exit(-1)
172
+ end
173
+
174
+ # 超时
175
+ unless can_be_merged
176
+ error = "自动合并失败, 检查状态超时: #{merge_status} #{merge_url}"
177
+ pusher.push("【❌ 组件分支合并到#{target_branch}失败】", error)
178
+ Process.exit(-1)
179
+ end
180
+
181
+ Build.log.detail("merge_request检查完毕,当前状态:#{state} #{merge_status}")
182
+ res = Gitlab.accept_merge_request(project_id, merge_request.iid, { merge_commit_message: message })
183
+
184
+ if res.state == 'merged'
185
+ Build.log.detail("自动合并完毕 #{repo_module.branch} => #{target_branch}")
186
+ pusher.push("【✅组件合并到#{target_branch}成功】")
187
+ else
188
+ error = "自动合并失败, 请检查:#{merge_url}"
189
+ pusher.push("【❌ 组件分支合并到#{target_branch}失败】", error)
190
+ Process.exit(-1)
191
+ end
192
+ end
193
+
194
+ private
195
+
196
+ def check_merge_branch(repo_module, target_branch)
197
+ unless repo_module.build_item.merge_master
198
+ Build.log.info('本次构建 merge_master = false 不执行自动合并')
199
+ return false
200
+ end
201
+
202
+ if target_branch == repo_module.branch
203
+ Build.log.warn("源分支#{repo_module.branch}和目标分支#{target_branch}指定名字一样, 无需执行合并")
204
+ return false
205
+ end
206
+
207
+ unless repo_module.repo_info
208
+ error = '仓库信息为空,无法执行自动合并'
209
+ pusher.push('❌ 打包失败', error)
210
+ Process.exit(-1)
211
+ end
212
+
213
+ project_id = repo_module.repo_info.id
214
+ current_page = 1
215
+ per_page = 20
216
+
217
+ # 获取目标分支的最新提交
218
+ target_commits = Gitlab.commits(project_id, { ref_name: target_branch, page: current_page, per_page: per_page })
219
+ target_last_commit = target_commits.size > 0 ? target_commits[0].to_hash['id'] : nil
220
+
221
+ return true unless target_last_commit
222
+
223
+ # 获取源分支的提交
224
+ source_commits = Gitlab.commits(project_id, { ref_name: repo_module.branch, page: current_page, per_page: per_page })
225
+ source_last_commit = source_commits.size > 0 ? source_commits[0].to_hash['id'] : nil
226
+
227
+ if target_last_commit == source_last_commit
228
+ Build.log.warn("源分支#{repo_module.branch}和目标分支#{target_branch}最新提交一致, 无需执行合并")
229
+ return false
230
+ end
231
+
232
+ # 包含目标分支的提交
233
+ source_commits.each do |obj|
234
+ return true if target_last_commit == obj.to_hash['id']
235
+ end
236
+
237
+ # 往前翻页 包含目标分支的提交
238
+ while source_commits.size == per_page
239
+ current_page += 1
240
+ source_commits = Gitlab.repo_commits(project_id, { ref_name: repo_module.branch, page: current_page, per_page: per_page })
241
+ source_commits.each do |obj|
242
+ return true if target_last_commit == obj.to_hash['id']
243
+ end
244
+ end
245
+
246
+ error = "当前分支#{repo_module.branch}落后于#{target_branch}, 请先手动合并分支后再打包并执行自动合并分支"
247
+ pusher.push('❌ 打包失败', error)
248
+ Process.exit(-1)
249
+ end
250
+
251
+ def do_create_project(pod_name, http_url, description, is_private)
252
+ ensure_client
253
+
254
+ # 读取路径
255
+ url = URI(http_url)
256
+ repo_path = url.path.gsub("/#{pod_name}.git", '')
257
+ repo_path = repo_path.gsub(pod_name.to_s, '')
258
+
259
+ # 获取群组ID
260
+ namespace_id = get_project_namespace_id(repo_path)
261
+ if namespace_id.nil?
262
+ error = '获取namespace_id失败, 无法创建项目'
263
+ pusher.push('❌ 打包失败', error)
264
+ Process.exit(-1)
265
+ end
266
+
267
+ # 可见性 private/internal(仅自托管实例支持)
268
+ visibility = is_private ? 'private' : 'internal'
269
+ Build.log.debug("创建的项目在群组ID:#{namespace_id}")
270
+ res = Gitlab.create_project(pod_name, {
271
+ description: description,
272
+ initialize_with_readme: true,
273
+ default_branch: 'master',
274
+ namespace_id: namespace_id,
275
+ 'merge_method' => 'ff',
276
+ visibility: visibility
277
+ })
278
+
279
+ unless res.id
280
+ error = '创建项目失败'
281
+ pusher.push('❌ 打包失败', error)
282
+ Process.exit(-1)
283
+ end
284
+
285
+ res.id
286
+ end
287
+
288
+ # 根据仓库路径获取命名空间ID
289
+ def get_project_namespace_id(repo_path)
290
+ Build.log.debug("仓库命名空间路径:#{repo_path}")
291
+ group_name = repo_path.split('/').last
292
+ Build.log.debug("组名:#{group_name}")
293
+ groups = Gitlab.group_search(group_name)
294
+ groups.each do |group|
295
+ return group.id if repo_path.include? group.full_path
296
+ end
297
+ nil
298
+ end
299
+
300
+ def gitlab_url?(http_url)
301
+ Hosting.host_of(http_url).to_s.downcase.include?('gitlab')
302
+ end
303
+
304
+ def ensure_client
305
+ return if @ready
306
+
307
+ begin
308
+ require 'gitlab'
309
+ rescue LoadError
310
+ error = '操作GitLab仓库需要 gitlab gem,请在Gemfile中添加 gem "gitlab" 后 bundle install'
311
+ pusher.push('❌ 打包失败', error)
312
+ Process.exit(-1)
313
+ end
314
+
315
+ @endpoint = read_required_config(
316
+ 'gitlab.apiurl',
317
+ '未读取到配置的gitlabAPI, 请先执行命令配置:git config --global gitlab.apiurl "xxx" 示例:https://gitlab.xxx.com/api/v4'
318
+ )
319
+ @private_token = read_required_config(
320
+ 'gitlab.privatetoken',
321
+ '未读取到配置的private_token, 请执行命令配置:git config --global gitlab.privatetoken "xxx"'
322
+ )
323
+ Build.log.debug("读取配置的gitlabAPI地址是:#{@endpoint}")
324
+
325
+ Gitlab.configure do |config|
326
+ config.endpoint = @endpoint
327
+ config.private_token = @private_token
328
+ end
329
+
330
+ @ready = true
331
+ end
332
+
333
+ def read_required_config(key, error_message)
334
+ res = %x(git config --global #{key}).to_s.strip
335
+ if res.empty?
336
+ pusher.push('❌ 打包失败', error_message)
337
+ Process.exit(-1)
338
+ end
339
+ res
340
+ end
341
+ end
342
+ end