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,52 @@
1
+ #
2
+ # base.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ module Highway
7
+ module Steps
8
+ module Parameters
9
+
10
+ # This class is a base abstract class for other classes in this
11
+ # module. You should not use it directly.
12
+ class Base
13
+
14
+ public
15
+
16
+ # Initialize an instance.
17
+ def initialize()
18
+ raise NotImplementedError.new("You must not call `#{__method__.to_s}` on `#{self.class.to_s}`.")
19
+ end
20
+
21
+ # Name of the parameter.
22
+ #
23
+ # @return [String]
24
+ attr_reader :name
25
+
26
+ # Whether the parameter is required.
27
+ #
28
+ # @return [Boolean]
29
+ def is_required?
30
+ @required
31
+ end
32
+
33
+ # Typecheck and validate a value of the parameter.
34
+ #
35
+ # This method returns typechecked, coerced and validated value or raises
36
+ # a fatal error if value has invalid type, can't be coerced or is
37
+ # othweriwse invalid.
38
+ #
39
+ # @param value [Object] A value.
40
+ # @param interface [Highway::Interface] An interface instance.
41
+ # @param keypath [Array<String>] A keypath to be used for debugging purposes.
42
+ #
43
+ # @return [Object]
44
+ def typecheck_and_validate(value, interface:, keypath: [])
45
+ raise NotImplementedError.new("You must override `#{__method__.to_s}` in `#{self.class.to_s}`.")
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,141 @@
1
+ #
2
+ # compound.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/steps/parameters/base"
7
+
8
+ module Highway
9
+ module Steps
10
+ module Parameters
11
+
12
+ # This class is used in step definition classes to represent a compound
13
+ # parameter of a step that consists of other parameters.
14
+ class Compound < Parameters::Base
15
+
16
+ # Initialize an instance.
17
+ #
18
+ # @param name [String] Name of the parameter.
19
+ # @param required [Boolean] Whether parametr is required.
20
+ # @param defaults [Boolean] Whether to construct default value from child parameters.
21
+ # @param children [Array<Highway::Steps::Parameters::*>] Child parameters.
22
+ def initialize(name:, required:, defaults: false, children:)
23
+ @name = name
24
+ @required = required
25
+ @defaults = defaults
26
+ @children = children
27
+ end
28
+
29
+ # Child parameters.
30
+ #
31
+ # @return [Array<Highway::Steps::Parameters::*>]
32
+ attr_reader :children
33
+
34
+ # Find a child parameter definition by name.
35
+ #
36
+ # @param name [String] Name of the parameter
37
+ #
38
+ # @return [Highway::Steps::Parameters::*]
39
+ def find_child_for_name(name)
40
+ @children.find { |child| child.name == name }
41
+ end
42
+
43
+ # Default value of the parameter.
44
+ #
45
+ # @return [Hash, nil]
46
+ def default
47
+ if @defaults
48
+ Utilities::hash_map(@children) { |child| [child.name, child.default] }
49
+ end
50
+ end
51
+
52
+ # Typecheck and validate a value of the parameter.
53
+ #
54
+ # This method returns typechecked, coerced and validated value or raises
55
+ # a fatal error if value has invalid type, can't be coerced or is
56
+ # othweriwse invalid.
57
+ #
58
+ # @param value [Object] A value.
59
+ # @param interface [Highway::Interface] An interface instance.
60
+ # @param keypath [Array<String>] A keypath to be used for debugging purposes.
61
+ #
62
+ # @return [Object]
63
+ def typecheck_and_validate(values, interface:, keypath: [])
64
+
65
+ unless values.is_a?(Hash)
66
+ interface.fatal!("Invalid type of value for parameter: '#{Utilities::keypath_to_s(keypath)}'.")
67
+ end
68
+
69
+ @children.each { |child|
70
+ if child.is_required? && !values.keys.include?(child.name) && child.default == nil
71
+ interface.fatal!("Missing value for required parameter: '#{Utilities::keypath_to_s(keypath + [child.name])}'.")
72
+ end
73
+ }
74
+
75
+ values.keys.each { |name|
76
+ unless find_child_for_name(name)
77
+ expected = @children.map { |child| "'#{child.name}'" }.join(", ")
78
+ interface.fatal!("Unknown parameter: '#{Utilities::keypath_to_s(keypath + [name])}'. Expected one of: [#{expected}].")
79
+ end
80
+ }
81
+
82
+ typechecked = Utilities::hash_map(values) { |name, value|
83
+ child = find_child_for_name(name)
84
+ [name, child.typecheck_and_validate(value, interface: interface, keypath: keypath + [name])]
85
+ }
86
+
87
+ (default || {}).merge(typechecked)
88
+
89
+ end
90
+
91
+ # Typecheck and prevalidate a value of the parameter. This method is
92
+ # used during the initial prevalidation of step parameter values before
93
+ # evaluating all the values.
94
+ #
95
+ # This method works in a similar way to `typecheck_and_validate` with
96
+ # one difference: if it encounters a single parameter whose value
97
+ # is (or contains) `:ignore` symbol, it doesn't perform any typechecking
98
+ # and validation on it. That way, the caller can specify which values
99
+ # should be fully validated and which should be ignored.
100
+ #
101
+ # @param value [Object] A value.
102
+ # @param interface [Highway::Interface] An interface instance.
103
+ # @param keypath [Array<String>] A keypath to be used for debugging purposes.
104
+ #
105
+ # @return [Void]
106
+ def typecheck_and_prevalidate(values, interface:, keypath: [])
107
+
108
+ unless values.is_a?(Hash)
109
+ interface.fatal!("Invalid type of value for parameter: '#{Utilities::keypath_to_s(keypath)}'.")
110
+ end
111
+
112
+ @children.each { |child|
113
+ if child.is_required? && !values.keys.include?(child.name) && child.default == nil
114
+ interface.fatal!("Missing value for required parameter: '#{Utilities::keypath_to_s(keypath + [child.name])}'.")
115
+ end
116
+ }
117
+
118
+ values.keys.each { |name|
119
+ unless find_child_for_name(name)
120
+ expected = @children.map { |child| "'#{child.name}'" }.join(", ")
121
+ interface.fatal!("Unknown parameter: '#{Utilities::keypath_to_s(keypath + [name])}'. Expected one of: [#{expected}].")
122
+ end
123
+ }
124
+
125
+ values.each_pair { |name, value|
126
+ if (child = find_child_for_name(name))
127
+ if child.is_a?(Parameters::Compound)
128
+ child.typecheck_and_prevalidate(value, interface: interface, keypath: keypath + [name])
129
+ elsif !Utilities::recursive_include?(value, :ignore)
130
+ child.typecheck_and_validate(value, interface: interface, keypath: keypath + [name])
131
+ end
132
+ end
133
+ }
134
+
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,74 @@
1
+ #
2
+ # single.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/steps/parameters/base"
7
+
8
+ module Highway
9
+ module Steps
10
+ module Parameters
11
+
12
+ # This class is used in step definition classes to represent a single
13
+ # parameter of a step.
14
+ class Single < Parameters::Base
15
+
16
+ public
17
+
18
+ # Initialize an instance.
19
+ #
20
+ # @param name [String] Name of the parameter.
21
+ # @param type [Highway::Steps::Types::*] Type of the parameter.
22
+ # @param required [Boolean] Whether parametr is required.
23
+ # @param default [Object, nil] Default value of the parameter.
24
+ def initialize(name:, type:, required:, default: nil)
25
+ @name = name
26
+ @required = required
27
+ @type = type
28
+ @default = default
29
+ assert_default_value_valid()
30
+ end
31
+
32
+ # Type of the parameter.
33
+ #
34
+ # @return [Highway::Steps::Types::*]
35
+ attr_reader :type
36
+
37
+ # Default value of the parameter.
38
+ #
39
+ # @return [Object, nil]
40
+ attr_reader :default
41
+
42
+ # Typecheck and validate a value of the parameter.
43
+ #
44
+ # This method returns typechecked, coerced and validated value or raises
45
+ # a fatal error if value has invalid type, can't be coerced or is
46
+ # othweriwse invalid.
47
+ #
48
+ # @param value [Object] A value.
49
+ # @param interface [Highway::Interface] An interface instance.
50
+ # @param keypath [Array<String>] A keypath to be used for debugging purposes.
51
+ #
52
+ # @return [Object]
53
+ def typecheck_and_validate(value, interface:, keypath: [])
54
+ typechecked = @type.typecheck_and_validate(value)
55
+ if typechecked != nil
56
+ typechecked
57
+ else
58
+ interface.fatal!("Invalid value: '#{value}' for parameter: '#{Utilities::keypath_to_s(keypath)}'.")
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def assert_default_value_valid()
65
+ if @default != nil && @type.typecheck_and_validate(@default) == nil
66
+ raise ArgumentError.new("Default value: '#{@default}' is not a valid value for parameter: '#{@name}'.")
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,92 @@
1
+ #
2
+ # registry.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/steps/step"
7
+
8
+ module Highway
9
+ module Steps
10
+
11
+ # This class is responsible for keeping track of available steps.
12
+ class Registry
13
+
14
+ public
15
+
16
+ # Initialize an instance.
17
+ def initialize()
18
+ @classes = Set.new()
19
+ end
20
+
21
+ # Initialize an instance and automatically load all steps in the default
22
+ # library.
23
+ #
24
+ # @return [Highway::Steps::Registry]
25
+ def self.new_and_load_default_library()
26
+
27
+ registry = self.new()
28
+
29
+ Dir[File.expand_path('library/*.rb', File.dirname(__FILE__))].each do |file|
30
+ require(file)
31
+ end
32
+
33
+ unless Highway::Steps.const_defined?("Library")
34
+ return
35
+ end
36
+
37
+ Highway::Steps::Library.constants.each do |step_symbol|
38
+ step_class = Highway::Steps::Library.const_get(step_symbol)
39
+ if step_class_valid?(step_class)
40
+ registry.register(step_class)
41
+ end
42
+ end
43
+
44
+ registry
45
+
46
+ end
47
+
48
+ # Add a new step definition class to the registry. Is it is already
49
+ # registered, this does nothing.
50
+ #
51
+ # @param step_class [Class] The step definition class.
52
+ #
53
+ # @raise [ArgumentError] If trying to register an invalid step class.
54
+ #
55
+ # @return [Void]
56
+ def register(step_class)
57
+ if self.class.step_class_valid?(step_class)
58
+ @classes.add(step_class)
59
+ else
60
+ raise ArgumentError.new("Step class `#{step_class}` is invalid.")
61
+ end
62
+ end
63
+
64
+ # Remove a step definition class from the registry. If it is not
65
+ # registered, this does nothing.
66
+ #
67
+ # @param step_class [Class] The step definition class.
68
+ #
69
+ # @return [Void]
70
+ def unregister(step_class)
71
+ @classes.remove(step_class)
72
+ end
73
+
74
+ # Get a step definition class by its name.
75
+ #
76
+ # @param step_name [String] The step name.
77
+ #
78
+ # @return [Class, nil]
79
+ def get_by_name(step_name)
80
+ @classes.find { |step_class| step_class.name == step_name }
81
+ end
82
+
83
+ private
84
+
85
+ def self.step_class_valid?(step_class)
86
+ step_class.is_a?(Class) && step_class < Highway::Steps::Step
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,52 @@
1
+ #
2
+ # step.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/steps/parameters/compound"
7
+
8
+ module Highway
9
+ module Steps
10
+
11
+ # This class serves as a base class for all step definition classes. It
12
+ # contains a common API and some useful utilities.
13
+ class Step
14
+
15
+ public
16
+
17
+ # Name of the step as it appears in configuration file.
18
+ #
19
+ # @return [String]
20
+ def self.name
21
+ raise NotImplementedError.new("You must override `#{__method__.to_s}` in `#{self.class.to_s}`.")
22
+ end
23
+
24
+ # Parameters that this step recognizes.
25
+ #
26
+ # @return [Array<Highway::Steps::Parameters::*>]
27
+ def self.parameters
28
+ raise NotImplementedError.new("You must override `#{__method__.to_s}` in `#{self.class.to_s}`.")
29
+ end
30
+
31
+ # The root parameter that nests all parameters of the step.
32
+ #
33
+ # @return [Highway::Steps::Parameters::Compound]
34
+ def self.root_parameter
35
+ return Parameters::Compound.new(name: "root", required: true, defaults: true, children: parameters)
36
+ end
37
+
38
+ # Run the step in given context containing inputs and Fastlane runner.
39
+ #
40
+ # @param parameters [Hash] Parameters of the step.
41
+ # @param context [Highway::Runtime::Context] The runtime context.
42
+ # @param report [Highway::Runtime::Report] The current runtime report.
43
+ #
44
+ # @return [Void]
45
+ def self.run(parameters:, context:, report:)
46
+ raise NotImplementedError.new("You must override `#{__method__.to_s}` in `#{self.class.to_s}`.")
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,65 @@
1
+ #
2
+ # any.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ module Highway
7
+ module Steps
8
+ module Types
9
+
10
+ # This class represents any parameter type. It can be used in parameters
11
+ # which should not perform any type checking.
12
+ class Any
13
+
14
+ public
15
+
16
+ # Initialize an instance.
17
+ #
18
+ # @param validate [Proc] A custom value validation block.
19
+ def initialize(validate: nil)
20
+ @validate = validate
21
+ end
22
+
23
+ # Typecheck and coerce a value if possible.
24
+ #
25
+ # This method returns a typechecked and coerced value or `nil` if value
26
+ # has invalid type and can't be coerced.
27
+ #
28
+ # @param value [Object] A value.
29
+ #
30
+ # @return [Object, nil]
31
+ def typecheck(value)
32
+ value
33
+ end
34
+
35
+ # Validate the typechecked value against a custom validation block.
36
+ #
37
+ # This method returns `true` if value is valid or `false` if value is
38
+ # invalid.
39
+ #
40
+ # @param value [Object] A value.
41
+ #
42
+ # @return [Boolean]
43
+ def validate(value)
44
+ return true if @validate == nil
45
+ @validate.call(value)
46
+ end
47
+
48
+ # Typecheck and validate the value at the same time.
49
+ #
50
+ # This method returns typechecked, coerced and validated value or `nil`
51
+ # if value has invalid type, can't be coerced or is invalid.
52
+ #
53
+ # @param value [Object] A value.
54
+ #
55
+ # @return [Object, nil]
56
+ def typecheck_and_validate(value)
57
+ typechecked = typecheck(value)
58
+ typechecked if !typechecked.nil? && validate(typechecked)
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end