fir-cli-xsl 1.0.3 → 1.0.4

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +8 -0
  3. data/.dockerignore +2 -0
  4. data/.flow-plugin.yml +14 -0
  5. data/.gitignore +27 -0
  6. data/.travis.yml +23 -0
  7. data/CHANGELOG +194 -0
  8. data/Dockerfile +12 -0
  9. data/Gemfile +10 -0
  10. data/LICENSE.txt +22 -0
  11. data/README.md +67 -0
  12. data/Rakefile +10 -0
  13. data/bin/console +11 -0
  14. data/bin/fir +14 -0
  15. data/bin/setup +7 -0
  16. data/doc/help.md +34 -0
  17. data/doc/info.md +44 -0
  18. data/doc/install.md +67 -0
  19. data/doc/login.md +19 -0
  20. data/doc/publish.md +35 -0
  21. data/doc/upgrade.md +7 -0
  22. data/fir-cli.gemspec +52 -0
  23. data/fir.sh +46 -0
  24. data/install.sh +210 -0
  25. data/lib/fir-cli.rb +3 -0
  26. data/lib/fir.rb +28 -0
  27. data/lib/fir/api.yml +7 -0
  28. data/lib/fir/cli.rb +192 -0
  29. data/lib/fir/patches.rb +10 -0
  30. data/lib/fir/patches/blank.rb +131 -0
  31. data/lib/fir/patches/concern.rb +146 -0
  32. data/lib/fir/patches/default_headers.rb +9 -0
  33. data/lib/fir/patches/hash.rb +79 -0
  34. data/lib/fir/patches/instance_variables.rb +30 -0
  35. data/lib/fir/patches/native_patch.rb +28 -0
  36. data/lib/fir/patches/os_patch.rb +28 -0
  37. data/lib/fir/patches/try.rb +102 -0
  38. data/lib/fir/util.rb +86 -0
  39. data/lib/fir/util/build_apk.rb +77 -0
  40. data/lib/fir/util/build_common.rb +93 -0
  41. data/lib/fir/util/build_ipa.rb +11 -0
  42. data/lib/fir/util/config.rb +43 -0
  43. data/lib/fir/util/http.rb +23 -0
  44. data/lib/fir/util/info.rb +38 -0
  45. data/lib/fir/util/login.rb +17 -0
  46. data/lib/fir/util/mapping.rb +98 -0
  47. data/lib/fir/util/me.rb +19 -0
  48. data/lib/fir/util/parser/apk.rb +46 -0
  49. data/lib/fir/util/parser/bin/pngcrush +0 -0
  50. data/lib/fir/util/parser/common.rb +24 -0
  51. data/lib/fir/util/parser/ipa.rb +188 -0
  52. data/lib/fir/util/parser/pngcrush.rb +23 -0
  53. data/lib/fir/util/publish.rb +293 -0
  54. data/lib/fir/version.rb +5 -0
  55. data/lib/fir/xcode_wrapper.sh +29 -0
  56. data/lib/fir_cli.rb +3 -0
  57. data/test/build_ipa_test.rb +17 -0
  58. data/test/cases/test_apk.apk +0 -0
  59. data/test/cases/test_apk_txt +1 -0
  60. data/test/cases/test_ipa.ipa +0 -0
  61. data/test/cases/test_ipa_dsym +0 -0
  62. data/test/info_test.rb +36 -0
  63. data/test/login_test.rb +12 -0
  64. data/test/mapping_test.rb +18 -0
  65. data/test/me_test.rb +17 -0
  66. data/test/publish_test.rb +44 -0
  67. data/test/test_helper.rb +98 -0
  68. metadata +84 -4
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+ # This file exists for backward compatbility with require 'fir-cli'
3
+ require_relative './fir'
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'logger'
5
+ require 'yaml'
6
+ require 'rest-client'
7
+ require 'json'
8
+ require 'securerandom'
9
+ require 'fileutils'
10
+ require 'cfpropertylist'
11
+ require 'tempfile'
12
+ require 'rqrcode'
13
+
14
+ # TODO: remove rescue when https://github.com/tajchert/ruby_apk/pull/4 merged
15
+ begin
16
+ require 'ruby_android'
17
+ rescue LoadError
18
+ require 'ruby_apk'
19
+ end
20
+
21
+ require 'fir/patches'
22
+ require 'fir/util'
23
+ require 'fir/version'
24
+ require 'fir/cli'
25
+
26
+ module FIR
27
+ include Util
28
+ end
@@ -0,0 +1,7 @@
1
+ fir:
2
+ domain: 'http://fir.im'
3
+ base_url: 'http://api.fir.im'
4
+ user_url: 'http://api.fir.im/user'
5
+ app_url: 'http://api.fir.im/apps'
6
+ udids_url: 'http://api.fir.im/devices/multi_udid'
7
+
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FIR
4
+ class CLI < Thor
5
+ class_option :token, type: :string, aliases: '-T', desc: "User's API Token at fir.im"
6
+ class_option :logfile, type: :string, aliases: '-L', desc: 'Path to writable logfile'
7
+ class_option :verbose, type: :boolean, aliases: '-V', desc: 'Show verbose', default: true
8
+ class_option :quiet, type: :boolean, aliases: '-q', desc: 'Silence commands'
9
+ class_option :help, type: :boolean, aliases: '-h', desc: 'Show this help message and quit'
10
+
11
+ desc '(EXPIRED, PLEASE use fastlane instead) build_ipa BUILD_DIR [options] [settings]', 'Build iOS app (alias: `bi`).'
12
+ long_desc <<-LONGDESC
13
+ `build_ipa` command will auto build your project/workspace to an ipa package
14
+ and it also can auto publish your built ipa to fir.im if use `-p` option.
15
+ Internally, it use `xcodebuild` to accomplish these things, use `man xcodebuild` to get more information.
16
+
17
+ Example:
18
+
19
+ $ fir bi <project dir> [-C <configuration>] [-t <target name>] [-o <ipa output dir>] [settings] [-c <changelog>] [-p -Q -T <your api token>]
20
+
21
+ $ fir bi <project dir> [-c <changelog> -P <bughd project id> -M -p -Q -T <your api token>]
22
+
23
+ $ fir bi <git ssh url> [-B develop -c <changelog> -f <profile> -P <bughd project id> -M -p -Q -T <your api token>]
24
+
25
+ $ fir bi <workspace dir> -w -S <scheme name> [-C <configuration>] [-t <target name>] [-o <ipa output dir>] [settings] [-c <changelog>] [-p -Q -T <your api token>]
26
+ LONGDESC
27
+ map %w[b bi] => :build_ipa
28
+ method_option :branch, type: :string, aliases: '-B', desc: 'Set branch if project is a git repo, the default is `master`'
29
+ method_option :workspace, type: :boolean, aliases: '-w', desc: 'true/false if build workspace'
30
+ method_option :scheme, type: :string, aliases: '-S', desc: 'Set the scheme NAME if build workspace'
31
+ method_option :configuration, type: :string, aliases: '-C', desc: 'Use the build configuration NAME for building each target'
32
+ method_option :destination, type: :string, aliases: '-d', desc: 'Set the destination specifier'
33
+ method_option :target, type: :string, aliases: '-t', desc: 'Build the target specified by target name'
34
+ method_option :export_method, type: :string, aliases: '-E', desc: 'for exportOptionsPlist method, ad-hoc as default'
35
+ method_option :optionPlistPath, type: :string, aliases: '-O', desc: 'User defined exportOptionsPlist path'
36
+ method_option :profile, type: :string, aliases: '-f', desc: 'Set the export provisioning profile'
37
+ method_option :output, type: :string, aliases: '-o', desc: 'IPA output path, the default is: BUILD_DIR/fir_build_ipa'
38
+ method_option :publish, type: :boolean, aliases: '-p', desc: 'true/false if publish to fir.im'
39
+ method_option :short, type: :string, aliases: '-s', desc: 'Set custom short link if publish to fir.im'
40
+ method_option :name, type: :string, aliases: '-n', desc: 'Set custom ipa name when built'
41
+ method_option :changelog, type: :string, aliases: '-c', desc: 'Set changelog if publish to fir.im'
42
+ method_option :qrcode, type: :boolean, aliases: '-Q', desc: 'Generate qrcode'
43
+ method_option :mapping, type: :boolean, aliases: '-M', desc: 'true/false if upload app mapping file to BugHD.com'
44
+ method_option :proj, type: :string, aliases: '-P', desc: 'Project id in BugHD.com if upload app mapping file'
45
+ method_option :open, type: :boolean, desc: 'true/false if open for everyone'
46
+ method_option :password, type: :string, desc: 'Set password for app'
47
+ method_option :content, type: :string, aliases: '-ct', desc: 'Set Dtalk robot message'
48
+ def build_ipa(*args)
49
+ prepare :build_ipa
50
+
51
+ FIR.build_ipa(*args, options)
52
+ end
53
+
54
+ desc 'build_apk BUILD_DIR', 'Build Android app (alias: `ba`).'
55
+ long_desc <<-LONGDESC
56
+ `build_apk` command will auto build your project to an apk package
57
+ and it also can auto publish your built apk to fir.im if use `-p` option.
58
+ Internally, it use `gradle` to accomplish these things, use `gradle --help` to get more information.
59
+
60
+ Example:
61
+
62
+ $ fir ba <project dir> [-o <apk output dir> -c <changelog> -p -Q -T <your api token>]
63
+
64
+ $ fir ba <project dir> [-f <flavor> -o <apk output dir> -c <changelog> -p -Q -T <your api token>]
65
+
66
+ $ fir ba <git ssh url> [-B develop -o <apk output dir> -c <changelog> -p -Q -T <your api token>]
67
+ LONGDESC
68
+ map ['ba'] => :build_apk
69
+ method_option :branch, type: :string, aliases: '-B', desc: 'Set branch if project is a git repo, the default is `master`'
70
+ method_option :output, type: :string, aliases: '-o', desc: 'APK output path, the default is: BUILD_DIR/build/outputs/apk'
71
+ method_option :publish, type: :boolean, aliases: '-p', desc: 'true/false if publish to fir.im'
72
+ method_option :flavor, type: :string, aliases: '-f', desc: 'Set flavor if have productFlavors'
73
+ method_option :short, type: :string, aliases: '-s', desc: 'Set custom short link if publish to fir.im'
74
+ method_option :name, type: :string, aliases: '-n', desc: 'Set custom apk name when builded'
75
+ method_option :changelog, type: :string, aliases: '-c', desc: 'Set changelog if publish to fir.im, support string/file'
76
+ method_option :qrcode, type: :boolean, aliases: '-Q', desc: 'Generate qrcode'
77
+ method_option :open, type: :boolean, desc: 'true/false if open for everyone, the default is: true', default: true
78
+ method_option :password, type: :string, desc: 'Set password for app'
79
+ method_option :content, type: :string, aliases: '-ct', desc: 'Set Dtalk robot message'
80
+ def build_apk(*args)
81
+ prepare :build_apk
82
+
83
+ FIR.build_apk(*args, options)
84
+ end
85
+
86
+ desc 'info APP_FILE_PATH', 'Show iOS/Android app info, support ipa/apk file (aliases: `i`).'
87
+ map 'i' => :info
88
+ method_option :all, type: :boolean, aliases: '-a', desc: 'Show all information in application'
89
+ def info(*args)
90
+ prepare :info
91
+
92
+ FIR.info(*args, options)
93
+ end
94
+
95
+ desc 'publish APP_FILE_PATH', 'Publish iOS/Android app to fir.im, support ipa/apk file (aliases: `p`).'
96
+ long_desc <<-LONGDESC
97
+ `publish` command will publish your app file to fir.im, also the command support to publish app's short & changelog.
98
+
99
+
100
+ Example:
101
+
102
+ $ fir p <app file path> [-c <changelog> -s <custom short link> -Q -T <your api token>]
103
+
104
+ $ fir p <app file path> [-c <changelog> -s <custom short link> --password=123456 --open=false -Q -T <your api token>]
105
+
106
+ $ fir p <app file path> [-c <changelog> -s <custom short link> -m <mapping file path> -P <bughd project id> -Q -T <your api token>]
107
+ LONGDESC
108
+ map 'p' => :publish
109
+ method_option :short, type: :string, aliases: '-s', desc: 'Set custom short link'
110
+ method_option :changelog, type: :string, aliases: '-c', desc: 'Set changelog'
111
+ method_option :qrcode, type: :boolean, aliases: '-Q', desc: 'Generate qrcode'
112
+ method_option :need_release_id, type: :boolean, aliases: '-R', desc: 'Add release id with fir url (WARNING: FIR ONLY SAVED 30 releases recently per app'
113
+
114
+ method_option :mappingfile, type: :string, aliases: '-m', desc: 'App mapping file'
115
+ method_option :dingtalk_access_token, type: :string, aliases: '-D', desc: 'Send msg to dingtalk, only need access_token, not whole url'
116
+
117
+ method_option :open, type: :boolean, desc: 'true/false if open for everyone'
118
+ method_option :password, type: :string, desc: 'Set password for app'
119
+ method_option :content, type: :string, aliases: '-ct', desc: 'Set Dtalk robot message'
120
+ map 'dt' => :dingtalk
121
+
122
+ def dingtalk(*args)
123
+ prepare :dingtalk
124
+
125
+ FIR.dingtalk(*args, options)
126
+ end
127
+
128
+ def publish(*args)
129
+ prepare :publish
130
+
131
+ FIR.publish(*args, options)
132
+ end
133
+
134
+ desc 'login', 'Login fir.im (aliases: `l`).'
135
+ map 'l' => :login
136
+ def login(*args)
137
+ prepare :login
138
+
139
+ token = options[:token] || args.first || ask('Please enter your fir.im API Token:', :white, echo: true)
140
+ FIR.login(token)
141
+ end
142
+
143
+ desc 'me', 'Show current user info if user is logined.'
144
+ def me
145
+ prepare :me
146
+
147
+ FIR.me
148
+ end
149
+
150
+ desc 'upgrade', 'Upgrade fir-cli and quit (aliases: `u`).'
151
+ map 'u' => :upgrade
152
+ def upgrade
153
+ prepare :upgrade
154
+
155
+ say '✈ Upgrade fir-cli (use `gem install fir-cli --no-ri --no-rdoc`)'
156
+ say `gem install fir-cli --no-ri --no-rdoc`
157
+ end
158
+
159
+ desc 'version', 'Show fir-cli version number and quit (aliases: `v`).'
160
+ map ['v', '-v', '--version'] => :version
161
+ def version
162
+ say "✈ fir-cli #{FIR::VERSION}"
163
+ end
164
+
165
+ desc 'help', 'Describe available commands or one specific command (aliases: `h`).'
166
+ map Thor::HELP_MAPPINGS => :help
167
+ def help(command = nil, subcommand = false)
168
+ super
169
+ end
170
+
171
+ no_commands do
172
+ def invoke_command(command, *args)
173
+ logfile = options[:logfile].blank? ? STDOUT : options[:logfile]
174
+ logfile = '/dev/null' if options[:quiet]
175
+
176
+ FIR.logger = Logger.new(logfile)
177
+ FIR.logger.level = options[:verbose] ? Logger::INFO : Logger::ERROR
178
+ super
179
+ end
180
+ end
181
+
182
+ private
183
+
184
+ def prepare(task)
185
+ if options.help?
186
+ help(task.to_s)
187
+ raise SystemExit
188
+ end
189
+ $DEBUG = true if ENV['DEBUG']
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative './patches/blank'
4
+ require_relative './patches/concern'
5
+ require_relative './patches/hash'
6
+ require_relative './patches/instance_variables'
7
+ require_relative './patches/native_patch'
8
+ require_relative './patches/os_patch'
9
+ require_relative './patches/try'
10
+ require_relative './patches/default_headers'
@@ -0,0 +1,131 @@
1
+ # encoding: utf-8
2
+
3
+ class Object
4
+ # An object is blank if it's false, empty, or a whitespace string.
5
+ # For example, '', ' ', +nil+, [], and {} are all blank.
6
+ #
7
+ # This simplifies
8
+ #
9
+ # address.nil? || address.empty?
10
+ #
11
+ # to
12
+ #
13
+ # address.blank?
14
+ #
15
+ # @return [true, false]
16
+ def blank?
17
+ respond_to?(:empty?) ? !!empty? : !self
18
+ end
19
+
20
+ # An object is present if it's not blank.
21
+ #
22
+ # @return [true, false]
23
+ def present?
24
+ !blank?
25
+ end
26
+
27
+ # Returns the receiver if it's present otherwise returns +nil+.
28
+ # <tt>object.presence</tt> is equivalent to
29
+ #
30
+ # object.present? ? object : nil
31
+ #
32
+ # For example, something like
33
+ #
34
+ # state = params[:state] if params[:state].present?
35
+ # country = params[:country] if params[:country].present?
36
+ # region = state || country || 'US'
37
+ #
38
+ # becomes
39
+ #
40
+ # region = params[:state].presence || params[:country].presence || 'US'
41
+ #
42
+ # @return [Object]
43
+ def presence
44
+ self if present?
45
+ end
46
+ end
47
+
48
+ class NilClass
49
+ # +nil+ is blank:
50
+ #
51
+ # nil.blank? # => true
52
+ #
53
+ # @return [true]
54
+ def blank?
55
+ true
56
+ end
57
+ end
58
+
59
+ class FalseClass
60
+ # +false+ is blank:
61
+ #
62
+ # false.blank? # => true
63
+ #
64
+ # @return [true]
65
+ def blank?
66
+ true
67
+ end
68
+ end
69
+
70
+ class TrueClass
71
+ # +true+ is not blank:
72
+ #
73
+ # true.blank? # => false
74
+ #
75
+ # @return [false]
76
+ def blank?
77
+ false
78
+ end
79
+ end
80
+
81
+ class Array
82
+ # An array is blank if it's empty:
83
+ #
84
+ # [].blank? # => true
85
+ # [1,2,3].blank? # => false
86
+ #
87
+ # @return [true, false]
88
+ alias_method :blank?, :empty?
89
+ end
90
+
91
+ class Hash
92
+ # A hash is blank if it's empty:
93
+ #
94
+ # {}.blank? # => true
95
+ # { key: 'value' }.blank? # => false
96
+ #
97
+ # @return [true, false]
98
+ alias_method :blank?, :empty?
99
+ end
100
+
101
+ class String
102
+ BLANK_RE = /\A[[:space:]]*\z/
103
+
104
+ # A string is blank if it's empty or contains whitespaces only:
105
+ #
106
+ # ''.blank? # => true
107
+ # ' '.blank? # => true
108
+ # "\t\n\r".blank? # => true
109
+ # ' blah '.blank? # => false
110
+ #
111
+ # Unicode whitespace is supported:
112
+ #
113
+ # "\u00a0".blank? # => true
114
+ #
115
+ # @return [true, false]
116
+ def blank?
117
+ BLANK_RE === self
118
+ end
119
+ end
120
+
121
+ class Numeric #:nodoc:
122
+ # No number is blank:
123
+ #
124
+ # 1.blank? # => false
125
+ # 0.blank? # => false
126
+ #
127
+ # @return [false]
128
+ def blank?
129
+ false
130
+ end
131
+ end
@@ -0,0 +1,146 @@
1
+ # encoding: utf-8
2
+
3
+ module ActiveSupport
4
+ # A typical module looks like this:
5
+ #
6
+ # module M
7
+ # def self.included(base)
8
+ # base.extend ClassMethods
9
+ # base.class_eval do
10
+ # scope :disabled, -> { where(disabled: true) }
11
+ # end
12
+ # end
13
+ #
14
+ # module ClassMethods
15
+ # ...
16
+ # end
17
+ # end
18
+ #
19
+ # By using <tt>ActiveSupport::Concern</tt> the above module could instead be
20
+ # written as:
21
+ #
22
+ # require 'active_support/concern'
23
+ #
24
+ # module M
25
+ # extend ActiveSupport::Concern
26
+ #
27
+ # included do
28
+ # scope :disabled, -> { where(disabled: true) }
29
+ # end
30
+ #
31
+ # class_methods do
32
+ # ...
33
+ # end
34
+ # end
35
+ #
36
+ # Moreover, it gracefully handles module dependencies. Given a +Foo+ module
37
+ # and a +Bar+ module which depends on the former, we would typically write the
38
+ # following:
39
+ #
40
+ # module Foo
41
+ # def self.included(base)
42
+ # base.class_eval do
43
+ # def self.method_injected_by_foo
44
+ # ...
45
+ # end
46
+ # end
47
+ # end
48
+ # end
49
+ #
50
+ # module Bar
51
+ # def self.included(base)
52
+ # base.method_injected_by_foo
53
+ # end
54
+ # end
55
+ #
56
+ # class Host
57
+ # include Foo # We need to include this dependency for Bar
58
+ # include Bar # Bar is the module that Host really needs
59
+ # end
60
+ #
61
+ # But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
62
+ # could try to hide these from +Host+ directly including +Foo+ in +Bar+:
63
+ #
64
+ # module Bar
65
+ # include Foo
66
+ # def self.included(base)
67
+ # base.method_injected_by_foo
68
+ # end
69
+ # end
70
+ #
71
+ # class Host
72
+ # include Bar
73
+ # end
74
+ #
75
+ # Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
76
+ # is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
77
+ # module dependencies are properly resolved:
78
+ #
79
+ # require 'active_support/concern'
80
+ #
81
+ # module Foo
82
+ # extend ActiveSupport::Concern
83
+ # included do
84
+ # def self.method_injected_by_foo
85
+ # ...
86
+ # end
87
+ # end
88
+ # end
89
+ #
90
+ # module Bar
91
+ # extend ActiveSupport::Concern
92
+ # include Foo
93
+ #
94
+ # included do
95
+ # self.method_injected_by_foo
96
+ # end
97
+ # end
98
+ #
99
+ # class Host
100
+ # include Bar # It works, now Bar takes care of its dependencies
101
+ # end
102
+ module Concern
103
+ class MultipleIncludedBlocks < StandardError #:nodoc:
104
+ def initialize
105
+ super "Cannot define multiple 'included' blocks for a Concern"
106
+ end
107
+ end
108
+
109
+ def self.extended(base) #:nodoc:
110
+ base.instance_variable_set(:@_dependencies, [])
111
+ end
112
+
113
+ def append_features(base)
114
+ if base.instance_variable_defined?(:@_dependencies)
115
+ base.instance_variable_get(:@_dependencies) << self
116
+ return false
117
+ else
118
+ return false if base < self
119
+ @_dependencies.each { |dep| base.send(:include, dep) }
120
+ super
121
+ base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
122
+ base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
123
+ end
124
+ end
125
+
126
+ def included(base = nil, &block)
127
+ if base.nil?
128
+ fail MultipleIncludedBlocks if instance_variable_defined?(:@_included_block)
129
+
130
+ @_included_block = block
131
+ else
132
+ super
133
+ end
134
+ end
135
+
136
+ def class_methods(&class_methods_module_definition)
137
+ if const_defined?(:ClassMethods, false)
138
+ mod = const_get(:ClassMethods)
139
+ else
140
+ mod = const_set(:ClassMethods, Module.new)
141
+ end
142
+
143
+ mod.module_eval(&class_methods_module_definition)
144
+ end
145
+ end
146
+ end