pod-pipeline 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/ppl +16 -0
- data/lib/pod-pipeline.rb +3 -0
- data/lib/pod-pipeline/command.rb +119 -0
- data/lib/pod-pipeline/command/build.rb +184 -0
- data/lib/pod-pipeline/command/publish.rb +69 -0
- data/lib/pod-pipeline/command/scan.rb +37 -0
- data/lib/pod-pipeline/command/update.rb +91 -0
- data/lib/pod-pipeline/extension/dir-ppl.rb +6 -0
- data/lib/pod-pipeline/extension/git-ppl.rb +9 -0
- data/lib/pod-pipeline/extension/linter-ppl.rb +14 -0
- data/lib/pod-pipeline/extension/validator-ppl.rb +24 -0
- data/lib/pod-pipeline/extension/version-ppl.rb +23 -0
- data/lib/pod-pipeline/extension/workspace-ppl.rb +13 -0
- data/lib/pod-pipeline/util/binary.rb +72 -0
- data/lib/pod-pipeline/util/bundle.rb +21 -0
- data/lib/pod-pipeline/util/scanner.rb +114 -0
- data/lib/pod-pipeline/util/xcodebuild.rb +28 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 675d0ddaa029cc0b8945f68529698c99774c5345b60da818ea827d18134d5972
|
4
|
+
data.tar.gz: 0a9afea692777250dceaa4e2f13facb714a91641699c662f3023568368d347be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: df852956c2047496a99e5c5d081ce42eaa3fc83b0492a5199a6fd6f75c1cd393273a3987a2a194860deba484ccdc9d34a1acf9f00dbf1bcf27b4716835ad463f
|
7
|
+
data.tar.gz: 4bdb21e4ca1eb50a57c2b2ddfd7941d2f16966699d3ab6b152fdee910a431df47d91430b33f8a8b905c5f0f953f12aa92fc6320e14975d56ba0941619899e429
|
data/bin/ppl
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pod-pipeline'
|
3
|
+
|
4
|
+
if Encoding.default_external != Encoding::UTF_8
|
5
|
+
|
6
|
+
STDERR.puts <<-DOC
|
7
|
+
\e[33mWARNING: Pod-Pipeline requires your terminal to be using UTF-8 encoding.
|
8
|
+
Consider adding the following to ~/.profile:
|
9
|
+
|
10
|
+
export LANG=en_US.UTF-8
|
11
|
+
\e[0m
|
12
|
+
DOC
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
PPL::Command.run(ARGV)
|
data/lib/pod-pipeline.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'claide'
|
2
|
+
|
3
|
+
module PPL
|
4
|
+
class Command < CLAide::Command
|
5
|
+
require 'pod-pipeline/command/scan'
|
6
|
+
require 'pod-pipeline/command/build'
|
7
|
+
require 'pod-pipeline/command/update'
|
8
|
+
require 'pod-pipeline/command/publish'
|
9
|
+
|
10
|
+
self.abstract_command = true
|
11
|
+
self.command = 'ppl'
|
12
|
+
self.description = 'Pod-Pipeline 是 CocoaPods 的流水线工具.'
|
13
|
+
|
14
|
+
def self.options
|
15
|
+
[
|
16
|
+
['--help', '展示改命令的介绍面板'],
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.options_extension
|
21
|
+
options = Array.new
|
22
|
+
options_extension_hash.each { |_key, _options_extension|
|
23
|
+
_options_extension.each { |_option_extension|
|
24
|
+
options << [_option_extension.first.gsub(/(--)(.*)/,"\\1#{_key}-\\2"), _option_extension.last]
|
25
|
+
}
|
26
|
+
}
|
27
|
+
options
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.options_extension_hash
|
31
|
+
Hash[
|
32
|
+
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.run(argv)
|
37
|
+
ensure_not_root_or_allowed! argv
|
38
|
+
verify_minimum_git_version!
|
39
|
+
verify_xcode_license_approved!
|
40
|
+
|
41
|
+
super(argv)
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# 确保root用户
|
46
|
+
#
|
47
|
+
# @return [void]
|
48
|
+
#
|
49
|
+
def self.ensure_not_root_or_allowed!(argv, uid = Process.uid, is_windows = Gem.win_platform?)
|
50
|
+
root_allowed = argv.include?('--allow-root') || !ENV['COCOAPODS_ALLOW_ROOT'].nil?
|
51
|
+
help! 'You cannot run Pod-Pipeline as root.' unless root_allowed || uid != 0 || is_windows
|
52
|
+
end
|
53
|
+
|
54
|
+
# 读取Git版本号,返回一个新的 {Gem::Version} 实例
|
55
|
+
#
|
56
|
+
# @return [Gem::Version]
|
57
|
+
#
|
58
|
+
def self.git_version
|
59
|
+
raw_version = `git version`
|
60
|
+
unless match = raw_version.scan(/\d+\.\d+\.\d+/).first
|
61
|
+
raise "Failed to extract git version from `git --version` (#{raw_version.inspect})"
|
62
|
+
end
|
63
|
+
Gem::Version.new(match)
|
64
|
+
end
|
65
|
+
|
66
|
+
# 检查Git版本号是否低于 1.8.5
|
67
|
+
#
|
68
|
+
# @raise Git版本号低于 1.8.5
|
69
|
+
#
|
70
|
+
# @return [void]
|
71
|
+
#
|
72
|
+
def self.verify_minimum_git_version!
|
73
|
+
if git_version < Gem::Version.new('1.8.5')
|
74
|
+
raise 'You need at least git version 1.8.5 to use Pod-Pipeline'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# 检查xcode许可是否被批准
|
80
|
+
#
|
81
|
+
# @return [void]
|
82
|
+
#
|
83
|
+
def self.verify_xcode_license_approved!
|
84
|
+
if `/usr/bin/xcrun clang 2>&1` =~ /license/ && !$?.success?
|
85
|
+
raise 'You have not agreed to the Xcode license, which ' \
|
86
|
+
'you must do to use CocoaPods. Agree to the license by running: ' \
|
87
|
+
'`xcodebuild -license`.'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize(argv)
|
92
|
+
@argv_extension = Hash.new
|
93
|
+
self.class.options_extension_hash.each_key { |key|
|
94
|
+
@argv_extension[key] = Array.new
|
95
|
+
self.class.options.each do |option|
|
96
|
+
name = option.first
|
97
|
+
if name.include?(key)
|
98
|
+
is_option = name.include? '='
|
99
|
+
if is_option
|
100
|
+
option = name.gsub(/(--)(.*)(=.*)/,"\\2")
|
101
|
+
value = argv.option(option, '')
|
102
|
+
@argv_extension[key] << name.gsub(/(--.*=)(.*)/,"\\1#{value}").gsub("#{key}-",'') unless value.empty?
|
103
|
+
else
|
104
|
+
flag = name.gsub(/(--)(.*)/,'\\2')
|
105
|
+
value = argv.flag?(flag)
|
106
|
+
@argv_extension[key] << name.gsub("#{key}-",'') if value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
}
|
111
|
+
|
112
|
+
super
|
113
|
+
end
|
114
|
+
|
115
|
+
def argv_extension
|
116
|
+
@argv_extension
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'pod-pipeline/util/scanner'
|
4
|
+
require 'pod-pipeline/util/xcodebuild'
|
5
|
+
require 'pod-pipeline/util/binary'
|
6
|
+
require 'pod-pipeline/util/bundle'
|
7
|
+
|
8
|
+
require 'pod-pipeline/extension/dir-ppl'
|
9
|
+
|
10
|
+
module PPL
|
11
|
+
class Command
|
12
|
+
class Build < Command
|
13
|
+
self.summary = '项目构建'
|
14
|
+
self.description = <<-DESC
|
15
|
+
构建项目代码、资源文件和依赖库,生成Framework包和Bundle包
|
16
|
+
DESC
|
17
|
+
self.arguments = [
|
18
|
+
CLAide::Argument.new('项目根目录(默认使用当前目录)', false),
|
19
|
+
]
|
20
|
+
def self.options
|
21
|
+
[
|
22
|
+
['--output=./', '项目构建的输出目录。(默认使用项目根目录)'],
|
23
|
+
['--configuration=Release', '项目构建的环境。(默认为Release)'],
|
24
|
+
['--arch=arm64,armv7,x86_64', '项目构建的架构。(默认为 arm64,armv7,x86_64)'],
|
25
|
+
['--combine=local,pod', '项目构建后合并依赖库的二进制文件,local为本地依赖库,pod为CocoaPods依赖库。(默认为 local)'],
|
26
|
+
['--bundle-merge=merge', '是否合并所有资源包,参数为合并后的资源包名。(默认为 不合并)'],
|
27
|
+
].concat(super)
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(argv)
|
31
|
+
@path = argv.arguments!
|
32
|
+
@output = argv.option('output', '').split(',').first
|
33
|
+
@configuration = argv.option('configuration', '').split(',').first
|
34
|
+
@archs = argv.option('arch', '').split(',')
|
35
|
+
@combines = argv.option('combine', '').split(',')
|
36
|
+
@bundle_merge = argv.option('bundle-merge', '').split(',').first
|
37
|
+
|
38
|
+
@projectPath = @path.count.zero? ? Pathname.pwd.to_s : @path.first
|
39
|
+
@output = @output ? @output : @projectPath
|
40
|
+
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def run
|
45
|
+
PPL::Scanner.new(@projectPath, ["pod", "workspace"]).run
|
46
|
+
|
47
|
+
@podspec = PPL::Scanner.podspec
|
48
|
+
@workspace = PPL::Scanner.workspace
|
49
|
+
puts "Pod: #{@podspec}"
|
50
|
+
puts "Workspace: #{@workspace.path}"
|
51
|
+
|
52
|
+
#初始化 构建目录
|
53
|
+
reset_dir
|
54
|
+
|
55
|
+
#构建
|
56
|
+
puts "\n[构建 #{@configuration} 环境的 #{@archs.join(", ")} 架构项目]"
|
57
|
+
@archs.each do |arch|
|
58
|
+
XCodebuild.build(@workspace.path, @podspec.name, arch, @configuration, @build_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
#添加头文件
|
62
|
+
puts "\n[添加Framework头文件]"
|
63
|
+
add_headers
|
64
|
+
|
65
|
+
#合并二进制文件
|
66
|
+
puts "\n[合并 #{@combines.join(", ")} 的二进制文件]"
|
67
|
+
combine_binarys(@combines.include?('local'), @combines.include?('pod'))
|
68
|
+
|
69
|
+
#拷贝资源包
|
70
|
+
puts "\n[拷贝 #{@combines.join(", ")} 的资源包 到输出目录]"
|
71
|
+
copy_bundles(@combines.include?('local'), @combines.include?('pod'))
|
72
|
+
|
73
|
+
#合并资源包
|
74
|
+
if @bundle_merge
|
75
|
+
puts "\n[合并的资源包内容 到 #{@bundle_merge}.bundle]"
|
76
|
+
merge_bundles
|
77
|
+
end
|
78
|
+
|
79
|
+
#拷贝构建内容到Pod目录
|
80
|
+
puts "\n[拷贝内容到Pod目录]"
|
81
|
+
copy_pod
|
82
|
+
end
|
83
|
+
|
84
|
+
def reset_dir
|
85
|
+
#初始化 构建目录
|
86
|
+
@build_path = "#{@output}/#{@podspec.name}-#{@podspec.version}"
|
87
|
+
Dir.reset(@build_path)
|
88
|
+
#初始化 Framework目录
|
89
|
+
@framework_path = "#{@build_path}/#{@podspec.name}.framework"
|
90
|
+
Dir.reset(@framework_path)
|
91
|
+
@framework_headers_path = "#{@framework_path}/Headers"
|
92
|
+
Dir.reset(@framework_headers_path)
|
93
|
+
#初始化 SDK目录
|
94
|
+
@sdk_path = "#{@output}/#{@podspec.name}/#{@podspec.name}SDK"
|
95
|
+
Dir.reset(@sdk_path)
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_headers
|
99
|
+
header_stands = "#{@output}/Example/Pods/Headers/Public/#{@podspec.name}/*.h"
|
100
|
+
Dir[header_stands].each do |header_stand|
|
101
|
+
if File.ftype(header_stand).eql? 'link'
|
102
|
+
puts File.basename(header_stand)
|
103
|
+
|
104
|
+
header = "#{File.dirname(header_stand)}/#{File.readlink(header_stand)}"
|
105
|
+
FileUtils.cp(header, @framework_headers_path)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def combine_binarys(local_dependency, pod_dependency)
|
111
|
+
binary = "#{@framework_path}/#{@podspec.name}"
|
112
|
+
#添加 构建生成的二进制文件
|
113
|
+
inputs = ["#{@build_path}/**/lib#{@podspec.name}.a"]
|
114
|
+
if local_dependency
|
115
|
+
#添加 本地依赖的二进制文件
|
116
|
+
inputs << "#{@output}/#{@podspec.name}/Libraries/**/*.a"
|
117
|
+
inputs << "#{@output}/#{@podspec.name}/Frameworks/**/*.framework/*"
|
118
|
+
end
|
119
|
+
if pod_dependency
|
120
|
+
#添加 Pod依赖库构建生成的二进制文件
|
121
|
+
inputs << "#{@build_path}/**/lib*.a";
|
122
|
+
#添加 Pod依赖库预先构建的二进制文件
|
123
|
+
inputs << "#{@output}/Example/Pods/**/*SDK/*.framework/*"
|
124
|
+
#添加 Pod依赖库本地依赖的二进制文件
|
125
|
+
inputs << "#{@output}/Example/Pods/**/Libraries/**/*.a"
|
126
|
+
inputs << "#{@output}/Example/Pods/**/Frameworks/**/*.framework/*"
|
127
|
+
end
|
128
|
+
|
129
|
+
Binary.combine(binary, inputs)
|
130
|
+
Binary.thin(binary, @archs)
|
131
|
+
end
|
132
|
+
|
133
|
+
def copy_bundles(local_dependency, pod_dependency)
|
134
|
+
#添加 构建生成的资源包
|
135
|
+
inputs = ["#{@output}/**/#{@podspec.name}/*.bundle"]
|
136
|
+
if local_dependency
|
137
|
+
#添加 本地依赖的资源包
|
138
|
+
inputs << "#{@output}/#{@podspec.name}/Libraries/**/*.bundle"
|
139
|
+
inputs << "#{@output}/#{@podspec.name}/Frameworks/**/*.bundle"
|
140
|
+
end
|
141
|
+
if pod_dependency
|
142
|
+
#添加 Pod依赖库构建生成的资源包
|
143
|
+
inputs << "#{@build_path}/**/*.bundle"
|
144
|
+
#添加 Pod依赖库预先构建的资源包
|
145
|
+
inputs << "#{@output}/Example/Pods/**/*SDK/*.bundle"
|
146
|
+
#添加 Pod依赖库本地依赖的资源包
|
147
|
+
inputs << "#{@output}/Example/Pods/**/Libraries/**/*.bundle"
|
148
|
+
inputs << "#{@output}/Example/Pods/**/Frameworks/**/*.bundle"
|
149
|
+
end
|
150
|
+
|
151
|
+
Bundle.cp(inputs, @build_path)
|
152
|
+
end
|
153
|
+
|
154
|
+
def merge_bundles
|
155
|
+
#初始化资源文件夹
|
156
|
+
bundle_path = "#{@build_path}/#{@bundle_merge}"
|
157
|
+
Dir.reset(bundle_path)
|
158
|
+
|
159
|
+
#合并资源文件
|
160
|
+
Dir["#{@build_path}/*.bundle/*"].each do |asset|
|
161
|
+
`cp -fr "#{asset}" "#{bundle_path}"`
|
162
|
+
end
|
163
|
+
|
164
|
+
#删除bundle
|
165
|
+
Dir["#{@build_path}/*.bundle/"].each do |bundle|
|
166
|
+
`rm -fr "#{bundle}"`
|
167
|
+
end
|
168
|
+
|
169
|
+
#将资源文件夹命名为 .bundle 格式
|
170
|
+
`mv "#{bundle_path}" "#{bundle_path}.bundle"`
|
171
|
+
end
|
172
|
+
|
173
|
+
def copy_pod
|
174
|
+
Dir["#{@framework_path}"].each do |framework|
|
175
|
+
`cp -fr "#{framework}" "#{@sdk_path}"`
|
176
|
+
end
|
177
|
+
Dir["#{@build_path}/*.bundle"].each do |bundle|
|
178
|
+
`cp -fr "#{bundle}" "#{@sdk_path}"`
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'cocoapods-core'
|
3
|
+
|
4
|
+
require 'pod/command/trunk'
|
5
|
+
|
6
|
+
require 'pod-pipeline/util/scanner'
|
7
|
+
|
8
|
+
require 'pod-pipeline/extension/version-ppl.rb'
|
9
|
+
require 'pod-pipeline/extension/linter-ppl'
|
10
|
+
require 'pod-pipeline/extension/validator-ppl'
|
11
|
+
|
12
|
+
module PPL
|
13
|
+
class Command
|
14
|
+
class Publish < Command
|
15
|
+
self.summary = '项目发布'
|
16
|
+
self.description = <<-DESC
|
17
|
+
整合项目发布流程
|
18
|
+
DESC
|
19
|
+
self.arguments = [
|
20
|
+
CLAide::Argument.new('项目根目录(默认使用当前目录)', false),
|
21
|
+
]
|
22
|
+
def self.options
|
23
|
+
[
|
24
|
+
['--repo=master', 'Pod库所属的repo。(默认使用官方repo:master)'],
|
25
|
+
].concat(super).concat(options_extension)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.options_extension_hash
|
29
|
+
Hash[
|
30
|
+
'build' => PPL::Command::Build.options,
|
31
|
+
'update' => PPL::Command::Update.options,
|
32
|
+
'trunk-push' => Pod::Command::Trunk::Push.options,
|
33
|
+
'repo-push' => Pod::Command::Repo::Push.options
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(argv)
|
38
|
+
@path = argv.arguments!
|
39
|
+
@repo = argv.option('repo', '').split(',').first
|
40
|
+
|
41
|
+
@projectPath = @path.count.zero? ? Pathname.pwd.to_s : @path.first
|
42
|
+
@is_master = false
|
43
|
+
unless @repo
|
44
|
+
@repo = 'master'
|
45
|
+
@is_master = true
|
46
|
+
end
|
47
|
+
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def run
|
52
|
+
PPL::Command::Build.run([@projectPath] + argv_extension['build'])
|
53
|
+
PPL::Command::Update.run([@projectPath] + argv_extension['update'])
|
54
|
+
|
55
|
+
PPL::Scanner.new(@projectPath, ['pod']).run
|
56
|
+
|
57
|
+
podspec_file = PPL::Scanner.linter.file
|
58
|
+
|
59
|
+
if @is_master
|
60
|
+
push_argv = [podspec_file] + argv_extension['trunk-push']
|
61
|
+
Pod::Command::Trunk::Push.run(push_argv)
|
62
|
+
else
|
63
|
+
push_argv = [@repo, podspec_file] + argv_extension['repo-push']
|
64
|
+
Pod::Command::Repo::Push.run(push_argv)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'pod-pipeline/util/scanner'
|
2
|
+
|
3
|
+
module PPL
|
4
|
+
class Command
|
5
|
+
class Scan < Command
|
6
|
+
self.summary = '项目扫描'
|
7
|
+
self.description = <<-DESC
|
8
|
+
获取项目的关键参数
|
9
|
+
DESC
|
10
|
+
self.arguments = [
|
11
|
+
CLAide::Argument.new('项目根目录(默认使用当前目录)', false),
|
12
|
+
]
|
13
|
+
def self.options
|
14
|
+
[
|
15
|
+
['--channel=pod,git,workspace', '扫描内容。(默认扫描所有内容)']
|
16
|
+
].concat(super)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(argv)
|
20
|
+
@path = argv.arguments!
|
21
|
+
@channels = argv.option('channel', '').split(',')
|
22
|
+
|
23
|
+
@projectPath = @path.count.zero? ? Pathname.pwd.to_s : @path.first
|
24
|
+
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
PPL::Scanner.new(@projectPath, @channels).run
|
30
|
+
|
31
|
+
puts "Pod: #{PPL::Scanner.podspec}" if PPL::Scanner.podspec
|
32
|
+
puts "Git: remote = #{PPL::Scanner.git.remote}, branch = #{PPL::Scanner.git.branches.current.first}" if PPL::Scanner.git
|
33
|
+
puts "Workspace: #{PPL::Scanner.workspace.path}" if PPL::Scanner.workspace
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'cocoapods-core'
|
3
|
+
|
4
|
+
require 'pod/command/trunk'
|
5
|
+
|
6
|
+
require 'pod-pipeline/util/scanner'
|
7
|
+
|
8
|
+
require 'pod-pipeline/extension/version-ppl.rb'
|
9
|
+
require 'pod-pipeline/extension/linter-ppl'
|
10
|
+
require 'pod-pipeline/extension/validator-ppl'
|
11
|
+
|
12
|
+
module PPL
|
13
|
+
class Command
|
14
|
+
class Update < Command
|
15
|
+
self.summary = '项目扫描'
|
16
|
+
self.description = <<-DESC
|
17
|
+
更新项目内容
|
18
|
+
DESC
|
19
|
+
self.arguments = [
|
20
|
+
CLAide::Argument.new('项目根目录(默认使用当前目录)', false),
|
21
|
+
]
|
22
|
+
def self.options
|
23
|
+
[
|
24
|
+
['--channel=version,git', '更新内容。(默认更新所有内容)'],
|
25
|
+
['--version=x.x.x', '新版本号。(默认使用patch+1)']
|
26
|
+
].concat(super)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(argv)
|
30
|
+
@path = argv.arguments!
|
31
|
+
@channels = argv.option('channel', '').split(',')
|
32
|
+
@new_version = argv.option('version', '').split(',').first
|
33
|
+
|
34
|
+
@projectPath = @path.count.zero? ? Pathname.pwd.to_s : @path.first
|
35
|
+
@is_master = false
|
36
|
+
unless @repo
|
37
|
+
@repo = 'master'
|
38
|
+
@is_master = true
|
39
|
+
end
|
40
|
+
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def run
|
45
|
+
PPL::Scanner.new(@projectPath, ['pod', 'git']).run
|
46
|
+
|
47
|
+
@channels = ["all"] if @channels.count.zero?
|
48
|
+
|
49
|
+
puts "\n[更新 #{@channels.join(", ")} 内容]"
|
50
|
+
|
51
|
+
@channels.each do |channel|
|
52
|
+
case channel
|
53
|
+
when "all"
|
54
|
+
update_version
|
55
|
+
update_git
|
56
|
+
when "version"
|
57
|
+
update_version
|
58
|
+
when "git"
|
59
|
+
update_git
|
60
|
+
else
|
61
|
+
raise "暂不支持#{channel}内容扫描"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_version
|
67
|
+
version = PPL::Scanner.podspec.version
|
68
|
+
raise "版本号异常,无法更新" unless version
|
69
|
+
if @new_version
|
70
|
+
version.archiving(@new_version)
|
71
|
+
else
|
72
|
+
version.increase_patch
|
73
|
+
end
|
74
|
+
|
75
|
+
PPL::Scanner.linter.write_to_file('version', version.version)
|
76
|
+
end
|
77
|
+
|
78
|
+
def update_git
|
79
|
+
git = PPL::Scanner.git
|
80
|
+
new_tag = PPL::Scanner.podspec.version.version
|
81
|
+
git.tags.each do |tag|
|
82
|
+
raise "当前版本 #{new_tag} 已发布,请尝试其他版本号" if tag.name.eql? new_tag
|
83
|
+
end
|
84
|
+
git.add('.')
|
85
|
+
git.commit_all(new_tag)
|
86
|
+
git.add_tag(new_tag)
|
87
|
+
git.push(git.remote, git.branches.current.first, true)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Pod
|
2
|
+
class Specification
|
3
|
+
class Linter
|
4
|
+
def write_to_file(property, value)
|
5
|
+
puts "[写入 #{property} = #{value}]"
|
6
|
+
file_content = File.read file
|
7
|
+
file_content.gsub!(/(.*.#{property}.*=.*)('.*')/,"\\1'#{value}'")
|
8
|
+
File.open(file, "w") { |f|
|
9
|
+
f.puts file_content
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Validator
|
5
|
+
def xcodebuild(action, scheme, configuration, deployment_target:)
|
6
|
+
require 'fourflusher'
|
7
|
+
command = %W(clean #{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
|
8
|
+
command += %w(--help)
|
9
|
+
|
10
|
+
if analyze
|
11
|
+
command += %w(CLANG_ANALYZER_OUTPUT=html CLANG_ANALYZER_OUTPUT_DIR=analyzer)
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
_xcodebuild(command, true)
|
16
|
+
rescue => e
|
17
|
+
message = 'Returned an unsuccessful exit code.'
|
18
|
+
message += ' You can use `--verbose` for more information.' unless config.verbose?
|
19
|
+
error('xcodebuild', message)
|
20
|
+
e.message
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pod
|
2
|
+
class Version
|
3
|
+
def increase_major
|
4
|
+
numeric_segments[0] = numeric_segments[0].to_i + 1
|
5
|
+
archiving(numeric_segments.join('.'))
|
6
|
+
end
|
7
|
+
|
8
|
+
def increase_minor
|
9
|
+
numeric_segments[1] = numeric_segments[1].to_i + 1
|
10
|
+
archiving(numeric_segments.join('.'))
|
11
|
+
end
|
12
|
+
|
13
|
+
def increase_patch
|
14
|
+
numeric_segments[2] = numeric_segments[2].to_i + 1
|
15
|
+
archiving(numeric_segments.join('.'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def archiving(new_version)
|
19
|
+
puts "[修改版本号:#{version} => #{new_version}]"
|
20
|
+
@version = new_version
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module PPL
|
2
|
+
class Binary
|
3
|
+
def self.combine(output, inputs, ignore="")
|
4
|
+
puts "\n目标文件:#{output}\n"
|
5
|
+
|
6
|
+
#获取合并文件的路径序列
|
7
|
+
input_file_queue=""
|
8
|
+
inputs.each do |input|
|
9
|
+
puts "\n合并路径:#{input}"
|
10
|
+
|
11
|
+
Dir[input].each do |input_file|;
|
12
|
+
#若 input_file 为目录 则跳过
|
13
|
+
next if Dir.exists? input_file
|
14
|
+
#若 input_file 为被忽略标记的文件 则跳过
|
15
|
+
unless ignore.empty?
|
16
|
+
next if File.basename(input_file).include? File.basename(ignore)
|
17
|
+
end
|
18
|
+
#若 input_file 为非二进制文件 则跳过
|
19
|
+
info_log = `lipo -info "#{input_file}" > /dev/null 2>&1
|
20
|
+
echo result:$?`
|
21
|
+
next unless info_log.include? 'result:0'
|
22
|
+
#若 input_file 为序列中已存在的文件 则跳过
|
23
|
+
next if input_file_queue.include? input_file
|
24
|
+
|
25
|
+
#合并
|
26
|
+
puts "=> #{input_file}"
|
27
|
+
input_file_queue += " \"#{input_file}\""
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#若合并文件序列不为空,执行合并
|
32
|
+
unless input_file_queue.empty?
|
33
|
+
if File.exists? output
|
34
|
+
output_temp = output+'.temp'
|
35
|
+
File.rename(output, output_temp)
|
36
|
+
|
37
|
+
combine_log =
|
38
|
+
`libtool -static -o "#{output}" "#{output_temp}" #{input_file_queue} > /dev/null 2>&1
|
39
|
+
echo result:$?`
|
40
|
+
raise "\ncombine log:\n#{combine_log}" unless combine_log.include? 'result:0'
|
41
|
+
|
42
|
+
File.delete(output_temp)
|
43
|
+
else
|
44
|
+
combine_log =
|
45
|
+
`libtool -static -o "#{output}" #{input_file_queue} > /dev/null 2>&1
|
46
|
+
echo result:$?`
|
47
|
+
raise "\ncombine log:\n#{combine_log}" unless combine_log.include? 'result:0'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.thin(binary, archs)
|
53
|
+
archs.each do |arch|
|
54
|
+
thin_log =
|
55
|
+
`lipo "#{binary}" -thin #{arch} -output "#{binary}-#{arch}" > /dev/null 2>&1
|
56
|
+
echo result:$?`
|
57
|
+
unless thin_log.include? 'result:0'
|
58
|
+
puts "lipo -thin 异常"
|
59
|
+
return
|
60
|
+
end
|
61
|
+
end
|
62
|
+
File.delete(binary)
|
63
|
+
|
64
|
+
binary_pieces = "#{binary}-*"
|
65
|
+
combine(binary, [binary_pieces])
|
66
|
+
|
67
|
+
Dir[binary_pieces].each do |binary_piece|
|
68
|
+
File.delete(binary_piece)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PPL
|
2
|
+
class Bundle
|
3
|
+
def self.cp(inputs, output)
|
4
|
+
puts "\n目标文件:#{output}\n"
|
5
|
+
|
6
|
+
#获取合并文件的路径序列
|
7
|
+
inputs.each do |input|
|
8
|
+
puts "\n合并路径:#{input}"
|
9
|
+
|
10
|
+
Dir[input].each do |input_bundle|;
|
11
|
+
#若 input_bundle 为输出目录 则跳过
|
12
|
+
next if input_bundle.eql? output
|
13
|
+
|
14
|
+
#合并
|
15
|
+
puts "合并资源包:" + input_bundle
|
16
|
+
FileUtils.cp_r(input_bundle, output, :preserve => true)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'cocoapods-core'
|
2
|
+
require 'git'
|
3
|
+
require 'xcodeproj'
|
4
|
+
|
5
|
+
require 'pod-pipeline/extension/git-ppl.rb'
|
6
|
+
require 'pod-pipeline/extension/workspace-ppl.rb'
|
7
|
+
|
8
|
+
module PPL
|
9
|
+
class Scanner
|
10
|
+
@@linter = nil
|
11
|
+
@@podspec = nil
|
12
|
+
@@git = nil
|
13
|
+
@@workspace = nil
|
14
|
+
|
15
|
+
def initialize(projectPath, channels)
|
16
|
+
@projectPath = projectPath
|
17
|
+
@channels = channels
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
@channels = ["all"] if @channels.count.zero?
|
22
|
+
|
23
|
+
puts "\n[扫描 #{@channels.join(", ")} 内容]"
|
24
|
+
|
25
|
+
@channels.each do |channel|
|
26
|
+
case channel
|
27
|
+
when "all"
|
28
|
+
@@linter = scan_pod @projectPath
|
29
|
+
@@podspec = @@linter.spec
|
30
|
+
@@git = scan_git @projectPath
|
31
|
+
@@workspace = scan_workspace @projectPath
|
32
|
+
when "pod"
|
33
|
+
@@linter = scan_pod @projectPath
|
34
|
+
@@podspec = @@linter.spec
|
35
|
+
when "git"
|
36
|
+
@@git = scan_git @projectPath
|
37
|
+
when "workspace"
|
38
|
+
@@workspace = scan_workspace @projectPath
|
39
|
+
else
|
40
|
+
raise "暂不支持#{channel}内容扫描"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#----------------------------------------#
|
46
|
+
|
47
|
+
def self.linter
|
48
|
+
@@linter
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.podspec
|
52
|
+
@@podspec
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.git
|
56
|
+
@@git
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.workspace
|
60
|
+
@@workspace
|
61
|
+
end
|
62
|
+
|
63
|
+
#----------------------------------------#
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
#
|
68
|
+
# 检查项目的 podspec 文件
|
69
|
+
#
|
70
|
+
# @param [String] projectPath 项目根目录
|
71
|
+
#
|
72
|
+
# @return [Pod::Specification] 新 {Pod::Specification} 实例
|
73
|
+
#
|
74
|
+
def scan_pod(projectPath)
|
75
|
+
podspec_files = Pathname.glob(projectPath + '/*.podspec{.json,}')
|
76
|
+
if podspec_files.count.zero? || podspec_files.count > 1
|
77
|
+
raise '未找到或存在多个 *.podspec 文件'
|
78
|
+
end
|
79
|
+
podspec_file = podspec_files.first
|
80
|
+
linter = Pod::Specification::Linter.new(podspec_file)
|
81
|
+
unless linter.spec
|
82
|
+
raise 'podspec文件异常'
|
83
|
+
end
|
84
|
+
linter
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# 检查项目的 Git 库
|
89
|
+
#
|
90
|
+
# @param [String] projectPath 项目根目录
|
91
|
+
#
|
92
|
+
# @return [Git::Base] 新 {Git::Base} 实例
|
93
|
+
#
|
94
|
+
def scan_git(projectPath)
|
95
|
+
Git.open(projectPath)
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# 检查项目的 workspace
|
100
|
+
#
|
101
|
+
# @param [String] projectPath 项目根目录
|
102
|
+
#
|
103
|
+
# @return [Xcodeproj::Workspace] 新的 {Xcodeproj::Workspace} 实例
|
104
|
+
#
|
105
|
+
def scan_workspace(projectPath)
|
106
|
+
workspace_files = Dir[projectPath + '/Example/*.xcworkspace']
|
107
|
+
if workspace_files.count.zero? || workspace_files.count > 1
|
108
|
+
raise '未找到或存在多个 *.xcworkspace 文件'
|
109
|
+
end
|
110
|
+
workspace_file = workspace_files.first
|
111
|
+
Xcodeproj::Workspace.open(workspace_file)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PPL
|
2
|
+
class XCodebuild
|
3
|
+
def self.build(workspace, scheme, arch, configuration, output)
|
4
|
+
puts "Building #{arch} ..."
|
5
|
+
|
6
|
+
sdk =
|
7
|
+
case
|
8
|
+
when arch.include?("arm") then 'iphoneos'
|
9
|
+
when arch.include?("86") then 'iphonesimulator'
|
10
|
+
else raise "暂时不支持 #{arch} 架构" unless sdk
|
11
|
+
end
|
12
|
+
|
13
|
+
build_log =
|
14
|
+
`xcodebuild\
|
15
|
+
-workspace "#{workspace}"\
|
16
|
+
-scheme #{scheme}\
|
17
|
+
-sdk #{sdk}\
|
18
|
+
-arch #{arch}\
|
19
|
+
-configuration #{configuration}\
|
20
|
+
-UseModernBuildSystem=NO\
|
21
|
+
-quiet\
|
22
|
+
MACH_O_TYPE=staticlib\
|
23
|
+
BUILD_DIR="#{output}/#{arch}"
|
24
|
+
echo result:$?`
|
25
|
+
raise "\nbuild log:\n#{build_log}" unless build_log.include? 'result:0'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pod-pipeline
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- 郑贤达
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-03-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cocoapods-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.10.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.10.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: cocoapods-trunk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.0
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '2.0'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.4.0
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: git
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.8.1
|
54
|
+
- - "<"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '2.0'
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.8.1
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '2.0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: xcodeproj
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.19.0
|
74
|
+
- - "<"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 1.19.0
|
84
|
+
- - "<"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '2.0'
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: claide
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.0.2
|
94
|
+
- - "<"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
type: :runtime
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.0.2
|
104
|
+
- - "<"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '2.0'
|
107
|
+
description: 为组件化开发设计的集项目构建、发布为一体的强大工具
|
108
|
+
email: zhengxianda0512@gmail.com
|
109
|
+
executables:
|
110
|
+
- ppl
|
111
|
+
extensions: []
|
112
|
+
extra_rdoc_files: []
|
113
|
+
files:
|
114
|
+
- bin/ppl
|
115
|
+
- lib/pod-pipeline.rb
|
116
|
+
- lib/pod-pipeline/command.rb
|
117
|
+
- lib/pod-pipeline/command/build.rb
|
118
|
+
- lib/pod-pipeline/command/publish.rb
|
119
|
+
- lib/pod-pipeline/command/scan.rb
|
120
|
+
- lib/pod-pipeline/command/update.rb
|
121
|
+
- lib/pod-pipeline/extension/dir-ppl.rb
|
122
|
+
- lib/pod-pipeline/extension/git-ppl.rb
|
123
|
+
- lib/pod-pipeline/extension/linter-ppl.rb
|
124
|
+
- lib/pod-pipeline/extension/validator-ppl.rb
|
125
|
+
- lib/pod-pipeline/extension/version-ppl.rb
|
126
|
+
- lib/pod-pipeline/extension/workspace-ppl.rb
|
127
|
+
- lib/pod-pipeline/util/binary.rb
|
128
|
+
- lib/pod-pipeline/util/bundle.rb
|
129
|
+
- lib/pod-pipeline/util/scanner.rb
|
130
|
+
- lib/pod-pipeline/util/xcodebuild.rb
|
131
|
+
homepage: https://github.com/TokiGems/pod-pipeline
|
132
|
+
licenses:
|
133
|
+
- MIT
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubygems_version: 3.0.3
|
151
|
+
signing_key:
|
152
|
+
specification_version: 3
|
153
|
+
summary: Cocoapods流水线工具
|
154
|
+
test_files: []
|