escalator_ios 1.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f81824c1303fd2e05669bbbe309bcd5885f032e41a78beab761d0f2424adf6cf
4
+ data.tar.gz: 20b0f11fcb8942604669eb0db268d192dc4e1a548169890705a3890d3db2b8e9
5
+ SHA512:
6
+ metadata.gz: 4eadf4fc8f5b55a2a6d6599afae552f05edef2397b149df3e018a6643703d2617cd08bc1c6b0821a885144f902ab9ad3836993182d2c718eb7e577c6b851cc46
7
+ data.tar.gz: 49593084775555eceadd1297743ade7d9d9ff927915b2c28ce569da3e3e4471f9a3cd3f9bd4c19259e16a760824ed9b9d55709c5fcf8e45adbf3632a4145786b
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # EscalatorIos
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/escalator_ios`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'escalator_ios'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install escalator_ios
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/escalator_ios.
data/bin/escalator ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ if $PROGRAM_NAME == __FILE__
5
+ $:.unshift File.expand_path("../../lib", __FILE__)
6
+ end
7
+
8
+ require "escalator"
9
+
10
+ Escalator::Command.run ARGV
@@ -0,0 +1,27 @@
1
+ # $: = $LOAD_PATH
2
+
3
+ $:.unshift File.expand_path("../lib", __FILE__)
4
+
5
+ require "escalator"
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'escalator_ios'
9
+ s.version = Escalator::VERSION
10
+ s.summary = "escalator!"
11
+ s.description = "For xcode project: confuse, archive, resign, upload"
12
+ s.authors = ["🔥起飞吧🔥"]
13
+ s.email = ["developer@gmail.com"]
14
+ s.homepage = 'https://rubygems.org/gems/escalator_ios'
15
+ s.license = 'MIT'
16
+ s.executables = Dir["bin/**/*"].map { |f| File.basename(f) }
17
+ s.files = Dir["lib/**/*"] + Dir["resources/**/*"] + ["README.md", "escalator_ios.gemspec"]
18
+ s.add_dependency "json", "~> 2.6.1"
19
+ # s.add_dependency "openssl", "~> 2.2.1"
20
+ s.add_dependency "ostruct", "~> 0.5.0"
21
+ s.add_dependency "fileutils", "~> 1.6.0"
22
+ s.add_dependency "xcodeproj", "~> 1.21.0"
23
+ s.add_dependency "fastlane", "~> 2.199.0"
24
+ s.add_dependency "colored2", "~> 3.1.2"
25
+ s.add_dependency "claide", "~> 1.0.3"
26
+ s.add_dependency "CFPropertyList", "~> 3.0.5"
27
+ end
@@ -0,0 +1,122 @@
1
+ module Escalator
2
+
3
+ class Archive
4
+
5
+ class << self
6
+
7
+ def run command
8
+ @command = command
9
+ Throw.note "Begin archive #{File.basename File.dirname command.project_path} ..."
10
+ prepareContext
11
+ buildProject
12
+ archiveProject
13
+ exportAssets
14
+ exportCoverInfo
15
+ if command.show_output?
16
+ system "open #{command.output_path}"
17
+ end
18
+ Throw.note "Archive Success!"
19
+ "#{output_path}/#{product_name}.ipa"
20
+ end
21
+
22
+ private
23
+
24
+ attr_accessor :command
25
+
26
+ attr_accessor :scheme
27
+
28
+ attr_accessor :assets_paths
29
+
30
+ attr_accessor :archive_path
31
+
32
+ attr_accessor :plist_path
33
+
34
+ attr_accessor :coverInfo_path
35
+
36
+ attr_accessor :cmd_source
37
+
38
+ attr_accessor :output_path
39
+
40
+ attr_accessor :product_name
41
+
42
+ def prepareContext
43
+ Throw.note "Prepare archive context ..."
44
+ tmpdir = ENV["TMPDIR"] + "escalator/archive"
45
+ if File.exist? tmpdir
46
+ FileUtils.rm_rf Dir["#{tmpdir}/*"]
47
+ else
48
+ FileUtils.mkdir_p tmpdir
49
+ end
50
+ @plist_path = "#{tmpdir}/ExportOptions.plist"
51
+ @scheme = Xcodeproj::Project.schemes(command.project_path).first
52
+ project = Xcodeproj::Project.open command.project_path
53
+ target = project.targets.first
54
+ @assets_paths = target.resources_build_phase.files.select { |f|
55
+ f.file_ref.real_path.extname == ".xcassets"
56
+ }.map { |f| f.file_ref.real_path.to_s }
57
+ build_settings = target.build_settings "Release"
58
+ enableBitCode = build_settings["ENABLE_BITCODE"] == "YES"
59
+ @product_name = build_settings["PRODUCT_NAME"]
60
+ if product_name == "$(TARGET_NAME)"
61
+ @product_name = target.name
62
+ end
63
+ @archive_path = "#{tmpdir}/#{product_name}.xcarchive"
64
+ base_path = File.dirname command.project_path
65
+ @coverInfo_path = base_path + "/CoverInfo.plist"
66
+ project_name = File.basename(command.project_path).split(".").first
67
+ workspace_path = "#{base_path}/#{project_name}.xcworkspace"
68
+ @cmd_source = "-project #{command.project_path}"
69
+ if File.exist? workspace_path
70
+ @cmd_source = "-workspace #{workspace_path}"
71
+ end
72
+ @output_path = File.expand_path "./#{File.basename base_path}", command.output_path
73
+ FileUtils.rm_rf output_path
74
+ options_path = File.expand_path "../../../resources/ExportOptions.plist", __FILE__
75
+ plist = CFPropertyList::List.new :file => options_path
76
+ data = CFPropertyList.native_types plist.value
77
+ data["method"] = command.method
78
+ data["uploadBitcode"] = enableBitCode
79
+ plist.value = CFPropertyList::guess data
80
+ plist.save plist_path
81
+ end
82
+
83
+ def buildProject
84
+ Throw.note "Begin build project ..."
85
+ cmd = "xcodebuild archive #{cmd_source} -scheme #{scheme} \
86
+ -configuration Release -arch arm64 -archivePath #{archive_path}"
87
+ system cmd
88
+ if !$?.success?
89
+ Throw.error "Build faild with #{cmd}"
90
+ end
91
+ end
92
+
93
+ def archiveProject
94
+ Throw.note "Begin export ipa ..."
95
+ cmd = "xcodebuild -exportArchive -archivePath #{archive_path} \
96
+ -exportPath #{output_path} -exportOptionsPlist #{plist_path} \
97
+ -allowProvisioningUpdates"
98
+ system cmd
99
+ if !$?.success?
100
+ Throw.error "Export faild with #{cmd}"
101
+ end
102
+ end
103
+
104
+ def exportAssets
105
+ Throw.note "Begin export assets ..."
106
+ assets_paths.each { |path|
107
+ FileUtils.cp_r path, output_path
108
+ }
109
+ end
110
+
111
+ def exportCoverInfo
112
+ Throw.note "Begin export CoverInfo.plist ..."
113
+ if File.exist? coverInfo_path
114
+ FileUtils.cp_r coverInfo_path, output_path
115
+ end
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,116 @@
1
+ module Escalator
2
+
3
+ class Combine
4
+
5
+ class << self
6
+
7
+ def run command
8
+ @command = command
9
+ prepareContext
10
+ excuteCommands
11
+ end
12
+
13
+ private
14
+
15
+ attr_accessor :command
16
+
17
+ attr_accessor :arguments
18
+
19
+ def prepareContext
20
+ Throw.note "Prepare combine context ..."
21
+ plist = CFPropertyList::List.new :file => command.config_path
22
+ @arguments = CFPropertyList.native_types plist.value
23
+ end
24
+
25
+ def excuteCommands
26
+ Throw.note "Begin excute commands ..."
27
+ outputPath = command.work_path + "/_confuses"
28
+ if File.exist? outputPath
29
+ FileUtils.rm_rf outputPath
30
+ end
31
+ projectPaths = nil
32
+ if command.commands.include? "confuse"
33
+ projectPaths = Dir["#{command.input_path}/*/*.xcodeproj"]
34
+ args = ["confuse"] + arguments["keywords"]
35
+ projectPaths = projectPaths.map { |path|
36
+ Command.run args + [
37
+ "--project-path=#{path}",
38
+ "--output-path=#{outputPath}"
39
+ ]
40
+ }
41
+ end
42
+
43
+ ipaPaths = nil
44
+ if command.commands.include? "archive"
45
+ outputPath = command.work_path + "/_packges"
46
+ if File.exist? outputPath
47
+ FileUtils.rm_rf outputPath
48
+ end
49
+ if !projectPaths
50
+ projectPaths = Dir["#{command.input_path}/*/*.xcodeproj"]
51
+ end
52
+ args = ["archive", arguments["method"]]
53
+ ipaPaths = projectPaths.map { |path|
54
+ Command.run args + [
55
+ "--project-path=#{path}",
56
+ "--output-path=#{outputPath}"
57
+ ]
58
+ }
59
+ end
60
+
61
+ if command.commands.include? "resign"
62
+ if !ipaPaths
63
+ ipaPaths = Dir["#{command.input_path}/*/*.ipa"]
64
+ end
65
+ args = ["resign"] + ipaPaths + [
66
+ "--key-id=#{arguments["key_id"]}",
67
+ "--issuer-id=#{arguments["issuer_id"]}",
68
+ "--keyfile-path=#{arguments["keyfile_path"]}",
69
+ "--user-password=#{arguments["user_password"]}",
70
+ "--bundle-identifier=#{arguments["CFBundleIdentifier"]}",
71
+ "--short-version=#{arguments["CFBundleShortVersionString"]}",
72
+ "--bundle-version=#{arguments["CFBundleVersion"]}"
73
+ ]
74
+ arg = arguments["apple_id"]
75
+ if arg
76
+ args << "--apple-id=#{arg}"
77
+ end
78
+ arg = arguments["CFBundleName"]
79
+ if arg
80
+ args << "--bundle-name=#{arg}"
81
+ end
82
+ arg = arguments["CFBundleDisplayName"]
83
+ if arg
84
+ args << "--display-name=#{arg}"
85
+ end
86
+ arg = arguments["CFBundleExecutable"]
87
+ if arg
88
+ args << "--executable-name=#{arg}"
89
+ end
90
+ arg = arguments["iconAssets_path"]
91
+ if arg
92
+ args << "--iconAssets-path=#{arg}"
93
+ end
94
+ ipaPaths = Command.run args
95
+ end
96
+
97
+ if command.commands.include? "upload"
98
+ if !ipaPaths
99
+ ipaPaths = Dir["#{command.input_path}/*/*.ipa"]
100
+ end
101
+ Command.run ["upload"] + ipaPaths + [
102
+ "--key-id=#{arguments["key_id"]}",
103
+ "--issuer-id=#{arguments["issuer_id"]}",
104
+ "--keyfile-path=#{arguments["keyfile_path"]}",
105
+ "--bundle-identifier=#{arguments["CFBundleIdentifier"]}"
106
+ ]
107
+ end
108
+
109
+ Throw.note "==========================End!=========================="
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,84 @@
1
+ module Escalator
2
+
3
+ class Command
4
+
5
+ class Archive < Command
6
+
7
+ class Help < CLAide::Help
8
+
9
+ def message
10
+ [
11
+ formatted_error_message,
12
+ "请执行: escalator archive --help".ansi.green
13
+ ].compact.join("\n\n").insert 0, "\n"
14
+ end
15
+
16
+ end
17
+
18
+ attr_reader :method
19
+
20
+ attr_reader :project_path
21
+
22
+ attr_reader :output_path
23
+
24
+ attr_reader :show_output
25
+ alias_method :show_output?, :show_output
26
+
27
+ self.command = "archive"
28
+
29
+ self.summary = "打包 Xcode 工程"
30
+
31
+ self.description = <<-DESC
32
+ 利用 Xcode 工程的配置的编译选项, 和自定义参数, 自动打包 ipa 并导出
33
+
34
+ `METHOD` 为 ipa 包导出类型: #{"app-store".ansi.green}, #{"ad-hoc".ansi.green}
35
+ DESC
36
+
37
+ self.arguments = [
38
+ CLAide::Argument.new('METHOD', true, false)
39
+ ]
40
+
41
+ def self.options
42
+ [
43
+ ["--project-path=path", "path 为 .xcproject 源路径"],
44
+ ["--output-path=path", "path 为 .ipa 以及部分重签资源的存放路径"],
45
+ ["--show-output", "文件管理中展示输出文件夹, 默认: 否"]
46
+ ].concat super
47
+ end
48
+
49
+ def initialize argv
50
+ @method = argv.arguments!.first
51
+ @project_path = argv.option "project-path", ""
52
+ @output_path = argv.option "output-path", ""
53
+ @show_output = argv.flag? "show-output", false
54
+ super
55
+ end
56
+
57
+ def validate!
58
+ super
59
+ if !method
60
+ help! "未检测到 METHOD 参数"
61
+ elsif !%w(app-store ad-hoc).include? method
62
+ help! "METHOD 参数只能为 #{"app-store".ansi.green}, #{"ad-hoc".ansi.green}"
63
+ end
64
+ if project_path.empty?
65
+ help! "未检测到 --project-path 参数"
66
+ end
67
+ if output_path.empty?
68
+ help! "未检测到 --output-path 参数"
69
+ end
70
+ end
71
+
72
+ def help!(error_message = nil)
73
+ invoked_command_class.help!(error_message, Help)
74
+ end
75
+
76
+ def run
77
+ Escalator::Archive.run self
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,116 @@
1
+ module Escalator
2
+
3
+ class Command
4
+
5
+ class Combine < Command
6
+
7
+ class Help < CLAide::Help
8
+
9
+ def message
10
+ [
11
+ formatted_error_message,
12
+ "请执行: escalator combine --help".ansi.green
13
+ ].compact.join("\n\n").insert 0, "\n"
14
+ end
15
+
16
+ end
17
+
18
+ attr_reader :commands
19
+
20
+ attr_reader :config_path
21
+
22
+ attr_reader :input_path
23
+
24
+ attr_reader :work_path
25
+
26
+ self.command = "combine"
27
+
28
+ self.summary = "组合 命令: confuse archive resign upload"
29
+
30
+ self.description = <<-DESC
31
+ 可选择组合相关命令, 创建执行自定义任务流
32
+
33
+ `COMMAND` 要组合的命令, 支持 #{"confuse archive resign upload".ansi.green} 命令, 进行选择组合执行
34
+
35
+ 注意命令的功能之间, 是否具备组合粘性:
36
+
37
+ #{"上一条命令的输出预期 => 下一条命令的输入预期 匹配".ansi.yellow}
38
+
39
+ `--input-path=path` 参数下目录结构要求:
40
+
41
+ 1. #{"confuse archive".ansi.green} 为初始命令
42
+
43
+ --input-path
44
+ |
45
+ | --- 工程名 (支持多个)
46
+ | |
47
+ | ----- | --- .xcodeproj 文件
48
+ | |
49
+ | ----- | --- CoverInfo.plist 文件 (可缺省: 执行 #{"escalator setup".ansi.green} 获取配置模版)
50
+
51
+ 2. #{"resign upload".ansi.green} 为初始命令
52
+
53
+ --input-path
54
+ |
55
+ | --- 工程名 (支持多个)
56
+ | |
57
+ | ----- | --- .ipa 文件
58
+ | | |
59
+ | ----- | --- .xcassets 文件 (ipa 对应工程下所有被引用的的 .xcassets)
60
+ | | |
61
+ | ----- | --- CoverInfo.plist 文件 (可缺省: 执行 #{"escalator setup".ansi.green} 获取配置模版)
62
+ DESC
63
+
64
+ self.arguments = [
65
+ CLAide::Argument.new('COMMAND', true, true)
66
+ ]
67
+
68
+ def self.options
69
+ [
70
+ ["--config-path=path", "path 为任务流需要的配置参数 ConfigInfo.plist 文件路径, 执行 #{"escalator setup".ansi.green} 获取配置模版"],
71
+ ["--input-path=path", "path 为初始命令需要的输入根目录, 会自动检测需要的输入文件"],
72
+ ["--work-path=path", "path 为脚本工作的根目录"]
73
+ ].concat super
74
+ end
75
+
76
+ def initialize argv
77
+ @commands = argv.arguments!
78
+ @config_path = argv.option "config-path", ""
79
+ @input_path = argv.option "input-path", ""
80
+ @work_path = argv.option "work-path", ""
81
+ super
82
+ end
83
+
84
+ def validate!
85
+ super
86
+ if commands.empty?
87
+ help! "未检测到 COMMAND 参数"
88
+ end
89
+ cmds = (commands - (%w(confuse archive resign upload) & commands))
90
+ if !cmds.empty?
91
+ help! "检测到 非法参数: #{cmds.join ", "}"
92
+ end
93
+ if config_path.empty?
94
+ help! "未检测到 --config-path 参数"
95
+ end
96
+ if input_path.empty?
97
+ help! "未检测到 --input-path 参数"
98
+ end
99
+ if work_path.empty?
100
+ help! "未检测到 --work-path 参数"
101
+ end
102
+ end
103
+
104
+ def help!(error_message = nil)
105
+ invoked_command_class.help!(error_message, Help)
106
+ end
107
+
108
+ def run
109
+ Escalator::Combine.run self
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,86 @@
1
+ module Escalator
2
+
3
+ class Command
4
+
5
+ class Confuse < Command
6
+
7
+ class Help < CLAide::Help
8
+
9
+ def message
10
+ [
11
+ formatted_error_message,
12
+ "请执行: escalator confuse --help".ansi.green
13
+ ].compact.join("\n\n").insert 0, "\n"
14
+ end
15
+
16
+ end
17
+
18
+ attr_reader :keywords
19
+
20
+ attr_reader :project_path
21
+
22
+ attr_reader :output_path
23
+
24
+ attr_reader :show_output
25
+ alias_method :show_output?, :show_output
26
+
27
+ self.command = "confuse"
28
+
29
+ self.summary = "混淆 Xcode 工程"
30
+
31
+ self.description = <<-DESC
32
+ 使用置换关键词的方式混淆项目内容和文件名
33
+
34
+ `KEYWORD` 要置换的关键词, 关键词个数不限
35
+
36
+ 支持混淆的文件类型: #{"h, hpp, pch, c, m, mm, cpp, swift, xib, storyboard".ansi.yellow}
37
+
38
+ 支持 #{"Swift".ansi.yellow}, #{"OC".ansi.yellow} 混编模式
39
+ DESC
40
+
41
+ self.arguments = [
42
+ CLAide::Argument.new('KEYWORD', true, true)
43
+ ]
44
+
45
+ def self.options
46
+ [
47
+ ["--project-path=path", "path 为 .xcodeproj 源路径"],
48
+ ["--output-path=path", "path 为混淆工程存放路径"],
49
+ ["--show-output", "文件管理中展示输出文件夹, 默认: 否"]
50
+ ].concat super
51
+ end
52
+
53
+ def initialize argv
54
+ @keywords = argv.arguments!.select { |arg| !arg.empty? }
55
+ @project_path = argv.option "project-path", ""
56
+ @output_path = argv.option "output-path", ""
57
+ @show_output = argv.flag? "show-output", false
58
+ super
59
+ end
60
+
61
+ def validate!
62
+ super
63
+ if keywords.empty?
64
+ help! "未检测到 KEYWORD 参数"
65
+ end
66
+ if project_path.empty?
67
+ help! "未检测到 --project-path 参数"
68
+ end
69
+ if output_path.empty?
70
+ help! "未检测到 --output-path 参数"
71
+ end
72
+ end
73
+
74
+ def help!(error_message = nil)
75
+ invoked_command_class.help!(error_message, Help)
76
+ end
77
+
78
+ def run
79
+ Escalator::Confuse.run self
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end