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,70 @@
1
+ #
2
+ # invocation.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ module Highway
7
+ module Compiler
8
+ module Build
9
+ module Output
10
+
11
+ # This class represents a step invocation in the build manifest. It
12
+ # contains information about step definition class, parameters and
13
+ # execution policy.
14
+ class Invocation
15
+
16
+ public
17
+
18
+ # Initialize an instance.
19
+ #
20
+ # @param index [Integer] Index of invocation, 1-based.
21
+ # @param step_class [Class] Definition class of the step.
22
+ # @param parameters [Highway::Compiler::Analyze::Tree::Values::Hash] Hash value of step parameters.
23
+ # @param policy [Symbol] Execution policy of the step invocation.
24
+ # @param keypath [Array<String>] A keypath used for debugging purposes.
25
+ def initialize(index:, step_class:, parameters:, policy:, keypath:)
26
+ @index = index
27
+ @step_class = step_class
28
+ @parameters = parameters
29
+ @policy = policy
30
+ @keypath = keypath
31
+ end
32
+
33
+ # Index of invocation, 1-based.
34
+ #
35
+ # @return [Integer]
36
+ attr_reader :index
37
+
38
+ # Definition class of the step.
39
+ #
40
+ # @return [Class]
41
+ attr_reader :step_class
42
+
43
+ # Hash value of step parameters.
44
+ #
45
+ # @return [Highway::Compiler::Analyze::Tree::Values::Hash]
46
+ attr_reader :parameters
47
+
48
+ # Execution policy of the step invocation.
49
+ #
50
+ # @return [Symbol]
51
+ attr_reader :policy
52
+
53
+ # A keypath used for debugging purposes.
54
+ #
55
+ # @return [Array<String>]
56
+ attr_reader :keypath
57
+
58
+ # An identifier of the invocation, joined by index and step name.
59
+ #
60
+ # @return [String]
61
+ def identifier
62
+ return "#{index}-#{step_class.name}"
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,52 @@
1
+ #
2
+ # manifest.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/compiler/build/output/invocation"
7
+
8
+ module Highway
9
+ module Compiler
10
+ module Build
11
+ module Output
12
+
13
+ # This class represents a build manifest. It contains compiled step
14
+ # invocations.
15
+ class Manifest
16
+
17
+ public
18
+
19
+ # Initialize an instance.
20
+ def initialize()
21
+ @invocations = Array.new()
22
+ end
23
+
24
+ # The preset.
25
+ #
26
+ # @return [String]
27
+ attr_accessor :preset
28
+
29
+ # Invocations in the manifest.
30
+ #
31
+ # @return [Array<Highway::Compiler::Build::Output::Invocation>]
32
+ attr_reader :invocations
33
+
34
+ # Add an invocation to the manifest.
35
+ #
36
+ # @param index [Integer] Index of invocation, 1-based.
37
+ # @param step_class [Class] Definition class of the step.
38
+ # @param parameters [Highway::Compiler::Analyze::Tree::Values::Hash] Hash value of step parameters.
39
+ # @param policy [:normal, :always] Execution policy of the step invocation.
40
+ # @param keypath [Array<String>] A keypath used for debugging purposes.
41
+ #
42
+ # @return [Void]
43
+ def add_invocation(index:, step_class:, parameters:, policy:, keypath:)
44
+ @invocations << Invocation.new(index: index, step_class: step_class, parameters: parameters, policy: policy, keypath: keypath)
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,92 @@
1
+ #
2
+ # parser.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "yaml"
7
+
8
+ require "highway/compiler/parse/versions/v1"
9
+
10
+ module Highway
11
+ module Compiler
12
+ module Parse
13
+
14
+ # This class is responsible for syntactic analysis of a configuration
15
+ # file. This is the first phase of the compiler.
16
+ class Parser
17
+
18
+ public
19
+
20
+ # Initialize an instance.
21
+ #
22
+ # @param interface [Highway::Interface] The interface.
23
+ def initialize(interface:)
24
+ @interface = interface
25
+ end
26
+
27
+ # Parse the configuration file.
28
+ #
29
+ # The parser is backwards compatible with previous versions of
30
+ # configuration files.
31
+ #
32
+ # This method only loads the file, searches for the version declaration
33
+ # and then delegates the wotk to parser of a particular version.
34
+ #
35
+ # The parser produces a parse tree which is then used by semantic
36
+ # analysis phase to produce semantic tree.
37
+ #
38
+ # @param path [String] Path to configuration file.
39
+ #
40
+ # @return [Highway::Compiler::Parse::Tree::Root]
41
+ def parse(path:)
42
+
43
+ # Load the file.
44
+
45
+ unless File.exist?(path)
46
+ @interface.fatal!("The configuration file '#{path}' does not exist.")
47
+ end
48
+
49
+ begin
50
+ raw = YAML.load_file(path)
51
+ rescue StandardError => error
52
+ @interface.fatal!("The configuration file '#{path}' is not a valid YAML file.")
53
+ end
54
+
55
+ # Make sure it contains a hash.
56
+
57
+ unless raw.is_a?(Hash)
58
+ @interface.fatal!("The configuration file does not contain a top-level dictionary.")
59
+ end
60
+
61
+ # Specify the known versions and their corresponding subparsers.
62
+
63
+ known = {
64
+ 1 => Parse::Versions::V1,
65
+ }
66
+
67
+ # Find and validate the version.
68
+
69
+ unless version = (Integer(raw.fetch("version", nil)) rescue nil)
70
+ @interface.fatal!("Missing or invalid value of: 'version'.")
71
+ end
72
+
73
+ unless known.keys.include?(version)
74
+ expected_versions = known.keys.map { |v| "'#{v}'" }.join(", ")
75
+ @interface.fatal!("Invalid value of: 'version'. Expected one of: [#{expected_versions}], got: '#{version}'.")
76
+ end
77
+
78
+ # Delegate the work to parser of a specific version.
79
+
80
+ subparser = known[version].new(interface: @interface)
81
+
82
+ # Parse and return the tree.
83
+
84
+ subparser.parse(raw: raw)
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,73 @@
1
+ #
2
+ # root.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/compiler/parse/tree/step"
7
+ require "highway/compiler/parse/tree/variable"
8
+
9
+ module Highway
10
+ module Compiler
11
+ module Parse
12
+ module Tree
13
+
14
+ # This class represents a root node of a parse tree. It contains other
15
+ # nodes, such as variables and steps.
16
+ class Root
17
+
18
+ public
19
+
20
+ # Initialize an instance.
21
+ #
22
+ # @param version [Integer] Version of the parse tree.
23
+ def initialize(version:)
24
+ @version = version
25
+ @variables = Array.new()
26
+ @steps = Array.new()
27
+ end
28
+
29
+ # Version of the parse tree.
30
+ #
31
+ # @return [Integer]
32
+ attr_reader :version
33
+
34
+ # Variables in the tree.
35
+ #
36
+ # @return [Array<Highway::Compiler::Parse::Tree::Variable>]
37
+ attr_reader :variables
38
+
39
+ # Steps in the tree.
40
+ #
41
+ # @return [Array<Highway::Compiler::Parse::Tree::Step>]
42
+ attr_reader :steps
43
+
44
+ # Add a variable to the tree.
45
+ #
46
+ # @param name [String] Name of the variable.
47
+ # @param value [String] Raw value of the variable.
48
+ # @param preset [String] Parent preset of the variable.
49
+ #
50
+ # @return [Void]
51
+ def add_variable(name:, value:, preset:)
52
+ @variables << Variable.new(name: name, value: value, preset: preset)
53
+ end
54
+
55
+ # Add a step to the tree.
56
+ #
57
+ # @param index [Integer] Index of step in its scope.
58
+ # @param name [String] Name of the step.
59
+ # @param parameters [Hash] Parameters of the step.
60
+ # @param preset [String] Parent preset of the step.
61
+ # @param stage [String] Parent stage of the step.
62
+ #
63
+ # @return [Void]
64
+ def add_step(name:, parameters:, preset:, stage:, index:)
65
+ @steps << Step.new(index: index, name: name, parameters: parameters, preset: preset, stage: stage)
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,62 @@
1
+ #
2
+ # step.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ module Highway
7
+ module Compiler
8
+ module Parse
9
+ module Tree
10
+
11
+ # This class represents a step node in a parse tree. It contains
12
+ # information about a single step and its parameters.
13
+ class Step
14
+
15
+ public
16
+
17
+ # Initialize an instance.
18
+ #
19
+ # @param index [Integer] Index of step in its scope.
20
+ # @param name [String] Name of the step.
21
+ # @param parameters [Hash] Parameters of the step.
22
+ # @param preset [String] Parent preset of the step.
23
+ # @param stage [String] Parent stage of the step.
24
+ def initialize(index:, name:, parameters:, preset:, stage:)
25
+ @name = name
26
+ @parameters = parameters
27
+ @preset = preset
28
+ @stage = stage
29
+ @index = index
30
+ end
31
+
32
+ # Name of the step.
33
+ #
34
+ # @return [String]
35
+ attr_reader :name
36
+
37
+ # Parameters of the step.
38
+ #
39
+ # @return [Hash]
40
+ attr_reader :parameters
41
+
42
+ # Parent preset of the step.
43
+ #
44
+ # @return [String]
45
+ attr_reader :preset
46
+
47
+ # Parent stage of the step.
48
+ #
49
+ # @return [String]
50
+ attr_reader :stage
51
+
52
+ # Index of step in its scope.
53
+ #
54
+ # @return [Integer]
55
+ attr_reader :index
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,48 @@
1
+ #
2
+ # variable.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ module Highway
7
+ module Compiler
8
+ module Parse
9
+ module Tree
10
+
11
+ # This class represents a variable node in a parse tree. It contains
12
+ # information about a single variable.
13
+ class Variable
14
+
15
+ public
16
+
17
+ # Initialize an instance.
18
+ #
19
+ # @param name [String] Name of the variable.
20
+ # @param value [String] Raw value of the variable.
21
+ # @param preset [String] Parent preset of the variable.
22
+ def initialize(name:, value:, preset:)
23
+ @name = name
24
+ @value = value
25
+ @preset = preset
26
+ end
27
+
28
+ # Name of the variable.
29
+ #
30
+ # @return [String]
31
+ attr_reader :name
32
+
33
+ # Raw value of the variable.
34
+ #
35
+ # @return [String]
36
+ attr_reader :value
37
+
38
+ # Parent preset of the variable.
39
+ #
40
+ # @return [String]
41
+ attr_reader :preset
42
+
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,110 @@
1
+ #
2
+ # v1.rb
3
+ # Copyright © 2019 Netguru S.A. All rights reserved.
4
+ #
5
+
6
+ require "highway/compiler/parse/tree/root"
7
+
8
+ module Highway
9
+ module Compiler
10
+ module Parse
11
+ module Versions
12
+
13
+ # This class is responsible for parsing a configuration file v1.
14
+ class V1
15
+
16
+ public
17
+
18
+ # Initialize an instance.
19
+ #
20
+ # @param reporter [Highway::Interface] The interface.
21
+ def initialize(interface:)
22
+ @interface = interface
23
+ end
24
+
25
+ # Parse the configuration file v1.
26
+ #
27
+ # @param raw [Hash] Raw content of configuration file.
28
+ #
29
+ # @return [Highway::Compiler::Parse::Tree::Root]
30
+ def parse(raw:)
31
+
32
+ parse_tree = Parse::Tree::Root.new(version: 1)
33
+
34
+ validate_toplevel_keys(raw: raw)
35
+
36
+ parse_variables(raw: raw, parse_tree: parse_tree)
37
+ parse_steps(raw: raw, parse_tree: parse_tree)
38
+
39
+ parse_tree
40
+
41
+ end
42
+
43
+ private
44
+
45
+ def validate_toplevel_keys(raw:)
46
+ expected = %w(version variables bootstrap test deploy report)
47
+ raw.each_key do |key|
48
+ assert_toplevel_key_valid(key, expected: expected)
49
+ end
50
+ end
51
+
52
+ def parse_variables(raw:, parse_tree:)
53
+ variables = raw.fetch("variables", {})
54
+ assert_value_type(variables, expected: Hash, keypath: ["variables"])
55
+ variables.each_pair do |preset, names_and_values|
56
+ assert_value_type(names_and_values, expected: Hash, keypath: ["variables", preset])
57
+ names_and_values.each_pair do |name, value|
58
+ parse_tree.add_variable(name: name, value: value, preset: preset)
59
+ end
60
+ end
61
+ end
62
+
63
+ def parse_steps(raw:, parse_tree:)
64
+ %w(bootstrap test deploy report).each do |stage|
65
+ presets = raw.fetch(stage, {})
66
+ assert_value_type(presets, expected: Hash, keypath: [stage])
67
+ presets.each_pair do |preset, steps|
68
+ assert_value_type(steps, expected: Array, keypath: [stage, preset])
69
+ steps.each_with_index do |step, step_index|
70
+ assert_value_type(step, expected: Hash, keypath: [stage, preset, step_index])
71
+ assert_value_length(step, expected: 1, keypath: [stage, preset, step_index])
72
+ assert_value_type(step.values.first, expected: Hash, keypath: [stage, preset, step.keys.first])
73
+ parse_tree.add_step(index: step_index, name: step.keys.first, parameters: step.values.first, preset: preset, stage: stage)
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def assert_toplevel_key_valid(actual, expected:)
80
+ unless expected.include?(actual)
81
+ expected_keys = expected.map { |key| "'#{key}'" }.join(", ")
82
+ @interface.fatal!("Invalid top-level key: '#{actual}'. Expected one of: [#{expected_keys}].")
83
+ end
84
+ end
85
+
86
+ def assert_value_type(actual, expected:, keypath:)
87
+ if expected.is_a?(Class)
88
+ unless actual.is_a?(expected)
89
+ @interface.fatal!("Invalid type of value: '#{actual}' at: '#{keypath}'. Expected: '#{expected}', got: '#{actual.class}'.")
90
+ end
91
+ elsif expected.is_a?(Array)
92
+ unless (expected.any? { |klass| actual.is_a?(klass) })
93
+ expected_types = expected.map { |klass| "'#{klass}'"}.join(", ")
94
+ @interface.fatal!("Invalid type of value: '#{actual}' at: '#{keypath}'. Expected one of: [#{expected_types}], got: '#{actual.class}'.")
95
+ end
96
+ end
97
+ end
98
+
99
+ def assert_value_length(actual, expected:, keypath:)
100
+ unless actual.length == expected
101
+ @interface.fatal!("Invalid length of value at: '#{keypath}'. Expected: #{expected}, got: #{actual}.")
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+ end
109
+ end
110
+ end