highway 0.0.1 → 1.0.1

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/lib/highway.rb +8 -4
  3. data/lib/highway/compiler/analyze/analyzer.rb +249 -0
  4. data/lib/highway/compiler/analyze/tree/root.rb +95 -0
  5. data/lib/highway/compiler/analyze/tree/segments/text.rb +36 -0
  6. data/lib/highway/compiler/analyze/tree/segments/variable.rb +43 -0
  7. data/lib/highway/compiler/analyze/tree/stage.rb +48 -0
  8. data/lib/highway/compiler/analyze/tree/step.rb +69 -0
  9. data/lib/highway/compiler/analyze/tree/values/array.rb +45 -0
  10. data/lib/highway/compiler/analyze/tree/values/base.rb +67 -0
  11. data/lib/highway/compiler/analyze/tree/values/hash.rb +45 -0
  12. data/lib/highway/compiler/analyze/tree/values/primitive.rb +43 -0
  13. data/lib/highway/compiler/analyze/tree/variable.rb +48 -0
  14. data/lib/highway/compiler/build/builder.rb +154 -0
  15. data/lib/highway/compiler/build/output/invocation.rb +70 -0
  16. data/lib/highway/compiler/build/output/manifest.rb +52 -0
  17. data/lib/highway/compiler/parse/parser.rb +92 -0
  18. data/lib/highway/compiler/parse/tree/root.rb +73 -0
  19. data/lib/highway/compiler/parse/tree/step.rb +62 -0
  20. data/lib/highway/compiler/parse/tree/variable.rb +48 -0
  21. data/lib/highway/compiler/parse/versions/v1.rb +110 -0
  22. data/lib/highway/compiler/suite.rb +56 -0
  23. data/lib/highway/environment.rb +282 -0
  24. data/lib/highway/fastlane/action.rb +67 -0
  25. data/lib/highway/interface.rb +135 -0
  26. data/lib/highway/main.rb +173 -0
  27. data/lib/highway/runtime/context.rb +229 -0
  28. data/lib/highway/runtime/report.rb +80 -0
  29. data/lib/highway/runtime/runner.rb +286 -0
  30. data/lib/highway/steps/infrastructure.rb +20 -0
  31. data/lib/highway/steps/library/action.rb +42 -0
  32. data/lib/highway/steps/library/appcenter.rb +106 -0
  33. data/lib/highway/steps/library/appstore.rb +137 -0
  34. data/lib/highway/steps/library/carthage.rb +67 -0
  35. data/lib/highway/steps/library/cocoapods.rb +76 -0
  36. data/lib/highway/steps/library/copy_artifacts.rb +36 -0
  37. data/lib/highway/steps/library/lane.rb +42 -0
  38. data/lib/highway/steps/library/sh.rb +36 -0
  39. data/lib/highway/steps/library/slack.rb +381 -0
  40. data/lib/highway/steps/library/testflight.rb +105 -0
  41. data/lib/highway/steps/library/xcode_archive.rb +162 -0
  42. data/lib/highway/steps/library/xcode_test.rb +264 -0
  43. data/lib/highway/steps/parameters/base.rb +52 -0
  44. data/lib/highway/steps/parameters/compound.rb +141 -0
  45. data/lib/highway/steps/parameters/single.rb +74 -0
  46. data/lib/highway/steps/registry.rb +92 -0
  47. data/lib/highway/steps/step.rb +52 -0
  48. data/lib/highway/steps/types/any.rb +65 -0
  49. data/lib/highway/steps/types/anyof.rb +64 -0
  50. data/lib/highway/steps/types/array.rb +44 -0
  51. data/lib/highway/steps/types/bool.rb +36 -0
  52. data/lib/highway/steps/types/enum.rb +44 -0
  53. data/lib/highway/steps/types/hash.rb +45 -0
  54. data/lib/highway/steps/types/number.rb +38 -0
  55. data/lib/highway/steps/types/set.rb +39 -0
  56. data/lib/highway/steps/types/string.rb +47 -0
  57. data/lib/highway/steps/types/url.rb +35 -0
  58. data/lib/highway/utilities.rb +51 -0
  59. data/lib/highway/version.rb +9 -1
  60. metadata +194 -22
  61. data/.gitignore +0 -4
  62. data/Gemfile +0 -4
  63. data/Rakefile +0 -1
  64. data/highway.gemspec +0 -24
@@ -0,0 +1,56 @@
1
+ #
2
+ # suite.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/compiler/analyze/analyzer"
7
+ require "highway/compiler/build/builder"
8
+ require "highway/compiler/parse/parser"
9
+
10
+ module Highway
11
+ module Compiler
12
+
13
+ # This class is responsible for executing all compiler stages, including
14
+ # syntactic analysis, semantic analysis and manifest generation.
15
+ class Suite
16
+
17
+ public
18
+
19
+ # Initialize an instance.
20
+ #
21
+ # @param registry [Highway::Steps::Registry] The registry of steps.
22
+ # @param interface [Highway::Inteface] The interface.
23
+ def initialize(registry:, interface:)
24
+ @registry = registry
25
+ @interface = interface
26
+ end
27
+
28
+ # Run the compiler suite.
29
+ #
30
+ # @param path [String] Path to the configuration file.
31
+ # @param preset [String] Preset to compile.
32
+ #
33
+ # @return [Highway::Compiler::Build::Output::Manifest]
34
+ def compile(path:, preset:)
35
+
36
+ @interface.header_success("Compiling the configuration file...")
37
+
38
+ parser = Parse::Parser.new(interface: @interface)
39
+ parse_tree = parser.parse(path: path)
40
+
41
+ analyzer = Analyze::Analyzer.new(registry: @registry, interface: @interface)
42
+ sema_tree = analyzer.analyze(parse_tree: parse_tree)
43
+
44
+ builder = Build::Builder.new(interface: @interface)
45
+ manifest = builder.build(sema_tree: sema_tree, preset: preset)
46
+
47
+ @interface.success("Successfully compiled the configuration file.")
48
+
49
+ manifest
50
+
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,282 @@
1
+ #
2
+ # environment.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "fastlane"
7
+ require "uri/ssh_git"
8
+
9
+ module Highway
10
+
11
+ # This class wraps `ENV` and additionaly provides wrappers and shortcuts
12
+ # to the most interesting values in the runtime environment.
13
+ class Environment
14
+
15
+ # Get value for given key in the `ENV`.
16
+ #
17
+ # @param key [String] A key.
18
+ #
19
+ # @return [String, nil]
20
+ def [](key)
21
+ ENV[key]
22
+ end
23
+
24
+ # Set value for given key in the `ENV`.
25
+ #
26
+ # @param key [String] A key.
27
+ # @param value [String, nil] A value.
28
+ #
29
+ # @return [Void]
30
+ def []=(key, value)
31
+ ENV[key] = value
32
+ end
33
+
34
+ # Find value for any of the given keys.
35
+ #
36
+ # @param *keys [String] Keys to look for.
37
+ #
38
+ # @return [String, nil]
39
+ def find(*keys)
40
+ keys.reduce(nil) { |memo, key| memo || self[key] }
41
+ end
42
+
43
+ # Find a non-empty value for any of the given keys.
44
+ #
45
+ # @param *keys [String] Keys to look for.
46
+ #
47
+ # @return [String, nil]
48
+ def find_nonempty(*keys)
49
+ result = find(*keys)
50
+ result if result != nil && !result.empty?
51
+ end
52
+
53
+ # Check whether any of the given keys exists.
54
+ #
55
+ # @param *keys [String] Keys to look for.
56
+ #
57
+ # @param [Boolean]
58
+ def include?(*keys)
59
+ find(*keys) != nil
60
+ end
61
+
62
+ # Check whether any of the given keys exists and is not empty.
63
+ #
64
+ # @param *keys [String] Keys to look for.
65
+ #
66
+ # @param [Boolean]
67
+ def include_nonempty?(*keys)
68
+ result = find(*keys)
69
+ result != nil && !result.empty?
70
+ end
71
+
72
+ # Whether environment specifies running in verbose mode.
73
+ #
74
+ # @return [Boolean]
75
+ def verbose?
76
+ FastlaneCore::Globals::verbose?
77
+ end
78
+
79
+ # Whether environment is running on a supported CI service.
80
+ #
81
+ # @return [Boolean]
82
+ def ci?
83
+ ci_service != nil
84
+ end
85
+
86
+ # Detected CI service. One of: `:bitrise`, `:circle`, `:travis`.
87
+ #
88
+ # @return [Symbol, nil].
89
+ def ci_service
90
+ return :bitrise if include?("BITRISE_IO")
91
+ return :circle if include?("CIRCLECI")
92
+ return :travis if include?("TRAVIS")
93
+ end
94
+
95
+ # Build number on CI.
96
+ #
97
+ # @return [String, nil]
98
+ def ci_build_number
99
+ case ci_service
100
+ when :bitrise then find_nonempty("BITRISE_BUILD_NUMBER")
101
+ when :circle then find_nonempty("CIRCLE_BUILD_NUM")
102
+ when :travis then find_nonempty("TRAVIS_BUILD_NUMBER")
103
+ end
104
+ end
105
+
106
+ # Build URL on CI.
107
+ #
108
+ # @return [String, nil]
109
+ def ci_build_url
110
+ case ci_service
111
+ when :bitrise then find_nonempty("BITRISE_BUILD_URL")
112
+ when :circle then find_nonempty("CIRCLE_BUILD_URL")
113
+ when :travis then find_nonempty("TRAVIS_BUILD_WEB_URL")
114
+ end
115
+ end
116
+
117
+ # Detected trigger type on CI. One of: `:tag`, `:pr`, `:push`.
118
+ #
119
+ # @return [Symbol, nil]
120
+ def ci_trigger
121
+ if ci_service == :bitrise
122
+ return :tag if include_nonempty?("BITRISE_GIT_TAG")
123
+ return :pr if include_nonempty?("BITRISE_PULL_REQUEST")
124
+ return :push if include_nonempty?("BITRISE_GIT_BRANCH")
125
+ return :manual
126
+ elsif ci_service == :circle
127
+ return :tag if include_nonempty?("CIRCLE_TAG")
128
+ return :push if include_nonempty?("CIRCLE_BRANCH")
129
+ return :manual
130
+ elsif ci_service == :travis
131
+ return :tag if include_nonempty?("TRAVIS_TAG")
132
+ return :pr if find_nonempty("TRAVIS_EVENT_TYPE") == "pull_request"
133
+ return :push if find_nonempty("TRAVIS_EVENT_TYPE") == "push"
134
+ return :manual
135
+ end
136
+ end
137
+
138
+ # Git tag that is triggeting CI or value from local repository.
139
+ #
140
+ # @return [String, nil]
141
+ def git_tag
142
+ case ci_service
143
+ when :bitrise then find_nonempty("BITRISE_GIT_TAG")
144
+ when :circle then find_nonempty("CIRCLE_TAG")
145
+ when :travis then find_nonempty("TRAVIS_TAG")
146
+ else safe_sh("git", "describe --exact-match --tags HEAD")
147
+ end
148
+ end
149
+
150
+ # Git branch that is triggeting CI or value from local repository.
151
+ #
152
+ # @return [String, nil]
153
+ def git_branch
154
+ case ci_service
155
+ when :bitrise then find_nonempty("BITRISE_GIT_BRANCH")
156
+ when :circle then find_nonempty("CIRCLE_BRANCH")
157
+ when :travis then find_nonempty("TRAVIS_PULL_REQUEST_BRANCH", "TRAVIS_BRANCH")
158
+ else safe_sh("git", "rev-parse --abbrev-ref HEAD")
159
+ end
160
+ end
161
+
162
+ # Git commit hash that is triggeting CI or value from local repository.
163
+ #
164
+ # @return [String, nil]
165
+ def git_commit_hash
166
+ case ci_service
167
+ when :bitrise then find_nonempty("GIT_CLONE_COMMIT_HASH")
168
+ when :circle then find_nonempty("CIRCLE_SHA1")
169
+ when :travis then find_nonempty("TRAVIS_COMMIT")
170
+ else safe_sh("git", "rev-parse HEAD")
171
+ end
172
+ end
173
+
174
+ # Git commit hash that is triggeting CI or value from local repository.
175
+ #
176
+ # @return [String, nil]
177
+ def git_commit_message
178
+ case ci_service
179
+ when :bitrise then find_nonempty("GIT_CLONE_COMMIT_MESSAGE_SUBJECT").split("\n").first
180
+ when :travis then find_nonempty("TRAVIS_COMMIT_MESSAGE").split("\n").first
181
+ else safe_sh("git", "log -1 --pretty=%B").split("\n").first
182
+ end
183
+ end
184
+
185
+ # Git remote repository URL that is triggering CI.
186
+ #
187
+ # @return [String, nil]
188
+ def git_repo_url
189
+ case ci_service
190
+ when :bitrise then normalize_git_url(find_nonempty("GIT_REPOSITORY_URL"))
191
+ when :circle then normalize_git_url(find_nonempty("CIRCLE_REPOSITORY_URL"))
192
+ else normalize_git_url(safe_sh("git", "remote get-url origin"))
193
+ end
194
+ end
195
+
196
+ # Source Git repository URL of the Pull Request that is triggering CI.
197
+ #
198
+ # @return [String, nil]
199
+ def git_pr_source_repo_url
200
+ case ci_service
201
+ when :bitrise then normalize_git_url(find_nonempty("BITRISEIO_PULL_REQUEST_REPOSITORY_URL"))
202
+ end
203
+ end
204
+
205
+ # Source Git branch of the Pull Request that is triggering CI.
206
+ #
207
+ # @return [String, nil]
208
+ def git_pr_source_branch
209
+ case ci_service
210
+ when :bitrise then find_nonempty("BITRISE_GIT_BRANCH")
211
+ when :travis then find_nonempty("TRAVIS_PULL_REQUEST_BRANCH")
212
+ end
213
+ end
214
+
215
+ # Target Git branch of the Pull Request that is triggering CI.
216
+ #
217
+ # @return [String, nil]
218
+ def git_pr_target_branch
219
+ case ci_service
220
+ when :bitrise then find_nonempty("BITRISEIO_GIT_BRANCH_DEST")
221
+ when :travis then find_nonempty("TRAVIS_BRANCH")
222
+ end
223
+ end
224
+
225
+ # Number of the Pull Request that is triggering CI.
226
+ #
227
+ # @return [String, nil]
228
+ def git_pr_number
229
+ case ci_service
230
+ when :bitrise then find_nonempty("BITRISE_PULL_REQUEST")
231
+ when :travis then find_nonempty("TRAVIS_PULL_REQUEST")
232
+ end
233
+ end
234
+
235
+ # Title of the Pull Request that is triggering CI.
236
+ #
237
+ # @return [String, nil]
238
+ def git_pr_title
239
+ case ci_service
240
+ when :bitrise then find_nonempty("BITRISE_GIT_MESSAGE")
241
+ end
242
+ end
243
+
244
+ # URL of the Pull Request that is triggering CI.
245
+ #
246
+ # @return [String, nil]
247
+ def git_pr_url
248
+ normalize_git_url(git_repo_url, git_pr_number)
249
+ end
250
+
251
+ private
252
+
253
+ def safe_sh(executable, *command)
254
+ result = `which #{executable} > /dev/null && #{executable} #{command.join(" ")} 2> /dev/null`.strip
255
+ result if !result.empty?
256
+ end
257
+
258
+ def normalize_git_url(uri_string, pr_number = nil)
259
+
260
+ return nil unless uri_string
261
+
262
+ uri = URI.parse(uri_string) if uri_string.start_with?("https://")
263
+ uri = URI::SshGit.parse(uri_string) if uri_string.start_with?("git@")
264
+
265
+ return nil unless uri
266
+
267
+ host = uri.host
268
+ repo_path = File.join(File.dirname(uri.path), File.basename(uri.path, ".git"))
269
+
270
+ return File.join("https://#{host}", repo_path) unless pr_number
271
+
272
+ pr_path = "pull/#{pr_number}" if host == "github.com"
273
+ pr_path = "merge_requests/#{pr_number}" if host == "gitlab.com"
274
+ pr_path = "pull-requests/#{pr_number}" if host == "bitbucket.org"
275
+
276
+ return File.join("https://#{host}", repo_path, pr_path) if pr_path
277
+
278
+ end
279
+
280
+ end
281
+
282
+ end
@@ -0,0 +1,67 @@
1
+ #
2
+ # action.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "fastlane"
7
+ require "highway"
8
+
9
+ module Fastlane
10
+ module Actions
11
+
12
+ # The `run_highway` action that can be used inside Fastline.
13
+ class RunHighwayAction < Action
14
+
15
+ # Available options of `run_highway` action.
16
+ #
17
+ # Use the same behavior of computing option values as in lane entry point.
18
+ # First, get the actual values, then fall back to env variables, then fall
19
+ # back to default values.
20
+ #
21
+ # @return [Array<FastlaneCore::ConfigItem>]
22
+ def self.available_options
23
+ [
24
+ FastlaneCore::ConfigItem.new(
25
+ key: :highwayfile,
26
+ description: "Path to Highway configuration file",
27
+ type: String,
28
+ optional: false,
29
+ env_name: "HIGHWAY_HIGHWAYFILE",
30
+ default_value: "Highwayfile.yml",
31
+ ),
32
+ FastlaneCore::ConfigItem.new(
33
+ key: :preset,
34
+ description: "Highway preset to run",
35
+ type: String,
36
+ optional: false,
37
+ env_name: "HIGHWAY_PRESET",
38
+ default_value: "default",
39
+ ),
40
+ ]
41
+ end
42
+
43
+ # Execute the `run_highway` action.
44
+ #
45
+ # This is the main entry point of Highway.
46
+ #
47
+ # @param options [Hash<String, Object>]
48
+ def self.run(options)
49
+
50
+ # Run Highway from `:action` entry point.
51
+
52
+ main = Highway::Main.new(
53
+ entrypoint: :action,
54
+ path: options[:highwayfile],
55
+ preset: options[:preset],
56
+ fastlane_runner: runner,
57
+ fastlane_lane_context: lane_context,
58
+ )
59
+
60
+ main.run()
61
+
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,135 @@
1
+ #
2
+ # interface.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "fastlane"
7
+ require "terminal-table"
8
+
9
+ module Highway
10
+
11
+ # This class is responsible for interfacing with the user (e.g. displaying
12
+ # error messages), using Fastlane UI mechanism underneath.
13
+ class Interface
14
+
15
+ public
16
+
17
+ # Initialize an instance.
18
+ def initialize()
19
+ @history = []
20
+ end
21
+
22
+ # Display a raw unformatted message.
23
+ #
24
+ # @param message [String] The raw message.
25
+ #
26
+ # @return [Void]
27
+ def raw(message)
28
+ puts(message.to_s)
29
+ @history << message.to_s
30
+ end
31
+
32
+ # Display a whitespace, unless it's already displayed.
33
+ #
34
+ # @return [Void]
35
+ def whitespace()
36
+ unless (@history.last || "").end_with?("\n")
37
+ raw("\n")
38
+ end
39
+ end
40
+
41
+ # Display a success message.
42
+ #
43
+ # @param message [String] The success message.
44
+ #
45
+ # @return [Void]
46
+ def success(message)
47
+ message.to_s.strip.split("\n").each { |line| FastlaneCore::UI.success(line) }
48
+ @history << message.to_s.strip
49
+ end
50
+
51
+ # Display an error message and abort.
52
+ #
53
+ # @param message [String] The error message.
54
+ #
55
+ # @return [Void]
56
+ def fatal!(message)
57
+ FastlaneCore::UI.user_error!(message.to_s)
58
+ end
59
+
60
+ # Display an error message.
61
+ #
62
+ # @param message [String] The error message.
63
+ #
64
+ # @return [Void]
65
+ def error(message)
66
+ message.to_s.strip.split("\n").each { |line| FastlaneCore::UI.error(line) }
67
+ @history << message.to_s.strip
68
+ end
69
+
70
+ # Display a warning message.
71
+ #
72
+ # @param message [String] The warning message.
73
+ #
74
+ # @return [Void]
75
+ def warning(message)
76
+ message.to_s.strip.split("\n").each { |line| FastlaneCore::UI.important(line) }
77
+ @history << message.to_s.strip
78
+ end
79
+
80
+ # Display a note message.
81
+ #
82
+ # @param message [String] The note message.
83
+ #
84
+ # @return [Void]
85
+ def note(message)
86
+ message.to_s.strip.split("\n").each { |line| FastlaneCore::UI.message(line) }
87
+ @history << message.to_s.strip
88
+ end
89
+
90
+ # Display a success header message.
91
+ #
92
+ # @param message [String] The header message.
93
+ #
94
+ # @return [Void]
95
+ def header_success(message)
96
+ whitespace()
97
+ success("--- #{message}".bold)
98
+ end
99
+
100
+ # Display a warning header message.
101
+ #
102
+ # @param message [String] The header message.
103
+ #
104
+ # @return [Void]
105
+ def header_warning(message)
106
+ whitespace()
107
+ warning("--- #{message}".bold)
108
+ end
109
+
110
+ # Display a table padded with whitespace.
111
+ #
112
+ # @param title [String] Table title.
113
+ # @param headings [Array<String>] Heading titles.
114
+ # @param rows [Array<String>] Row values.
115
+ #
116
+ # @return [Void]
117
+ def table(title: nil, headings: [], rows:)
118
+
119
+ whitespace()
120
+
121
+ table = Terminal::Table.new(
122
+ title: title,
123
+ headings: headings,
124
+ rows: FastlaneCore::PrintTable.transform_output(rows)
125
+ )
126
+
127
+ raw(table)
128
+
129
+ whitespace()
130
+
131
+ end
132
+
133
+ end
134
+
135
+ end