pod-pipeline 0.1.6
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 +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: []
|