floe 0.9.0 → 0.10.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 +4 -4
- data/CHANGELOG.md +15 -1
- data/Gemfile +0 -6
- data/exe/floe +2 -1
- data/floe.gemspec +7 -0
- data/lib/floe/version.rb +1 -1
- data/lib/floe/workflow/context.rb +14 -10
- data/lib/floe/workflow/reference_path.rb +2 -2
- data/lib/floe/workflow/runner/docker_mixin.rb +4 -3
- data/lib/floe/workflow/runner/kubernetes.rb +1 -1
- data/lib/floe/workflow/state.rb +7 -2
- data/lib/floe/workflow/states/choice.rb +3 -3
- data/lib/floe/workflow/states/fail.rb +4 -6
- data/lib/floe/workflow/states/pass.rb +3 -5
- data/lib/floe/workflow/states/succeed.rb +3 -3
- data/lib/floe/workflow/states/task.rb +8 -6
- data/lib/floe/workflow/states/wait.rb +7 -2
- data/lib/floe/workflow.rb +2 -1
- metadata +86 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2b158e514e08902a1138c7b2878bb8633ca7c1abb59d4b77b6d9ce568c65710b
         | 
| 4 | 
            +
              data.tar.gz: 32d053bba54e8c35645a636771964692e435ad72ee38e03c8c22b4da5bce25ec
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e39301eed1de9189b66f07a7ecdda807974bf47495b4906bd57f6f8ed862fab38448668155f79e12c87da8935f4054d14dbcd08e292429b194768d2234fa7c46
         | 
| 7 | 
            +
              data.tar.gz: 5cf0476521a1cd4fc0dcc4edeccdd00c6c72ee88bf7428103b86f5f30097608f934f19e75499a61b5d7e7380f2e1451dccfd82f796eee6bcef041dd6f3db8664
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -4,6 +4,19 @@ This project adheres to [Semantic Versioning](http://semver.org/). | |
| 4 4 |  | 
| 5 5 | 
             
            ## [Unreleased]
         | 
| 6 6 |  | 
| 7 | 
            +
            ## [0.10.0] - 2024-04-05
         | 
| 8 | 
            +
            ### Fixed
         | 
| 9 | 
            +
            - Fix rubocops ([#164](https://github.com/ManageIQ/floe/pull/164))
         | 
| 10 | 
            +
            - Output should contain errors ([#165](https://github.com/ManageIQ/floe/pull/165))
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ### Added
         | 
| 13 | 
            +
            - Add simplecov ([#162](https://github.com/ManageIQ/floe/pull/162))
         | 
| 14 | 
            +
            - Add ability to pass context on the command line ([#161](https://github.com/ManageIQ/floe/pull/161))
         | 
| 15 | 
            +
            - Add specs for `Workflow#wait_until`, `#waiting?` ([#166](https://github.com/ManageIQ/floe/pull/166))
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ### Changed
         | 
| 18 | 
            +
            - Drop non-standard Error/Cause fields ([#167](https://github.com/ManageIQ/floe/pull/167))
         | 
| 19 | 
            +
             | 
| 7 20 | 
             
            ## [0.9.0] - 2024-02-19
         | 
| 8 21 | 
             
            ### Changed
         | 
| 9 22 | 
             
            - Default to wait indefinitely ([#157](https://github.com/ManageIQ/floe/pull/157))
         | 
| @@ -136,7 +149,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). | |
| 136 149 | 
             
            ### Added
         | 
| 137 150 | 
             
            - Initial release
         | 
| 138 151 |  | 
| 139 | 
            -
            [Unreleased]: https://github.com/ManageIQ/floe/compare/v0. | 
| 152 | 
            +
            [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.10.0...HEAD
         | 
| 153 | 
            +
            [0.10.0]: https://github.com/ManageIQ/floe/compare/v0.9.0...v0.10.0
         | 
| 140 154 | 
             
            [0.9.0]: https://github.com/ManageIQ/floe/compare/v0.8.0...v0.9.0
         | 
| 141 155 | 
             
            [0.8.0]: https://github.com/ManageIQ/floe/compare/v0.7.0...v0.8.0
         | 
| 142 156 | 
             
            [0.7.0]: https://github.com/ManageIQ/floe/compare/v0.6.1...v0.7.0
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/exe/floe
    CHANGED
    
    | @@ -10,6 +10,7 @@ opts = Optimist.options do | |
| 10 10 |  | 
| 11 11 | 
             
              opt :workflow, "Path to your workflow json (legacy)",         :type => :string
         | 
| 12 12 | 
             
              opt :input, "JSON payload to input to the workflow (legacy)", :type => :string
         | 
| 13 | 
            +
              opt :context, "JSON payload of the Context",                  :type => :string
         | 
| 13 14 | 
             
              opt :credentials, "JSON payload with credentials",            :type => :string
         | 
| 14 15 | 
             
              opt :credentials_file, "Path to a file with credentials",     :type => :string
         | 
| 15 16 | 
             
              opt :docker_runner, "Type of runner for docker images",       :type => :string, :short => 'r'
         | 
| @@ -49,7 +50,7 @@ credentials = | |
| 49 50 |  | 
| 50 51 | 
             
            workflows =
         | 
| 51 52 | 
             
              args.each_slice(2).map do |workflow, input|
         | 
| 52 | 
            -
                context = Floe::Workflow::Context.new(:input => input || opts[:input] || "{}")
         | 
| 53 | 
            +
                context = Floe::Workflow::Context.new(opts[:context], :input => input || opts[:input] || "{}")
         | 
| 53 54 | 
             
                Floe::Workflow.load(workflow, context, credentials)
         | 
| 54 55 | 
             
              end
         | 
| 55 56 |  | 
    
        data/floe.gemspec
    CHANGED
    
    | @@ -34,4 +34,11 @@ Gem::Specification.new do |spec| | |
| 34 34 | 
             
              spec.add_dependency "jsonpath", "~>1.1"
         | 
| 35 35 | 
             
              spec.add_dependency "kubeclient", "~>4.7"
         | 
| 36 36 | 
             
              spec.add_dependency "optimist", "~>3.0"
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              spec.add_development_dependency "manageiq-style"
         | 
| 39 | 
            +
              spec.add_development_dependency "rake", "~> 13.0"
         | 
| 40 | 
            +
              spec.add_development_dependency "rspec"
         | 
| 41 | 
            +
              spec.add_development_dependency "rubocop"
         | 
| 42 | 
            +
              spec.add_development_dependency "simplecov", ">= 0.21.2"
         | 
| 43 | 
            +
              spec.add_development_dependency "timecop"
         | 
| 37 44 | 
             
            end
         | 
    
        data/lib/floe/version.rb
    CHANGED
    
    
| @@ -3,19 +3,19 @@ | |
| 3 3 | 
             
            module Floe
         | 
| 4 4 | 
             
              class Workflow
         | 
| 5 5 | 
             
                class Context
         | 
| 6 | 
            +
                  # @param context [Json|Hash] (default, create another with input and execution params)
         | 
| 7 | 
            +
                  # @param input [Hash] (default: {})
         | 
| 6 8 | 
             
                  def initialize(context = nil, input: {})
         | 
| 7 9 | 
             
                    context = JSON.parse(context) if context.kind_of?(String)
         | 
| 8 10 | 
             
                    input = JSON.parse(input) if input.kind_of?(String)
         | 
| 9 11 |  | 
| 10 | 
            -
                    @context = context || {
         | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
                      "Task"         => {}
         | 
| 18 | 
            -
                    }
         | 
| 12 | 
            +
                    @context = context || {}
         | 
| 13 | 
            +
                    self["Execution"]          ||= {}
         | 
| 14 | 
            +
                    self["Execution"]["Input"] ||= input
         | 
| 15 | 
            +
                    self["State"]              ||= {}
         | 
| 16 | 
            +
                    self["StateHistory"]       ||= []
         | 
| 17 | 
            +
                    self["StateMachine"]       ||= {}
         | 
| 18 | 
            +
                    self["Task"]               ||= {}
         | 
| 19 19 | 
             
                  end
         | 
| 20 20 |  | 
| 21 21 | 
             
                  def execution
         | 
| @@ -30,6 +30,10 @@ module Floe | |
| 30 30 | 
             
                    started? && !ended?
         | 
| 31 31 | 
             
                  end
         | 
| 32 32 |  | 
| 33 | 
            +
                  def failed?
         | 
| 34 | 
            +
                    output&.key?("Error") || false
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 33 37 | 
             
                  def ended?
         | 
| 34 38 | 
             
                    execution.key?("EndTime")
         | 
| 35 39 | 
             
                  end
         | 
| @@ -67,7 +71,7 @@ module Floe | |
| 67 71 | 
             
                      "pending"
         | 
| 68 72 | 
             
                    elsif running?
         | 
| 69 73 | 
             
                      "running"
         | 
| 70 | 
            -
                    elsif  | 
| 74 | 
            +
                    elsif failed?
         | 
| 71 75 | 
             
                      "failure"
         | 
| 72 76 | 
             
                    else
         | 
| 73 77 | 
             
                      "success"
         | 
| @@ -19,11 +19,11 @@ module Floe | |
| 19 19 | 
             
                    super
         | 
| 20 20 |  | 
| 21 21 | 
             
                    raise Floe::InvalidWorkflowError, "Invalid Reference Path" if payload.match?(/@|,|:|\?/)
         | 
| 22 | 
            +
             | 
| 22 23 | 
             
                    @path = JsonPath.new(payload)
         | 
| 23 24 | 
             
                                    .path[1..]
         | 
| 24 25 | 
             
                                    .map { |v| v.match(/\[(?<name>.+)\]/)["name"] }
         | 
| 25 | 
            -
                                    . | 
| 26 | 
            -
                                    .compact
         | 
| 26 | 
            +
                                    .filter_map { |v| v[0] == "'" ? v.delete("'") : v.to_i }
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 29 | 
             
                  def get(context)
         | 
| @@ -6,9 +6,10 @@ module Floe | |
| 6 6 | 
             
                      image.match(%r{^(?<repository>.+/)?(?<image>.+):(?<tag>.+)$})&.named_captures&.dig("image")
         | 
| 7 7 | 
             
                    end
         | 
| 8 8 |  | 
| 9 | 
            -
                     | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 9 | 
            +
                    # 63 is the max kubernetes pod name length
         | 
| 10 | 
            +
                    # -5 for the "floe-" prefix
         | 
| 11 | 
            +
                    # -9 for the random hex suffix and leading hyphen
         | 
| 12 | 
            +
                    MAX_CONTAINER_NAME_SIZE = 63 - 5 - 9
         | 
| 12 13 |  | 
| 13 14 | 
             
                    def container_name(image)
         | 
| 14 15 | 
             
                      name = image_name(image)
         | 
| @@ -164,7 +164,7 @@ module Floe | |
| 164 164 |  | 
| 165 165 | 
             
                    def failed_container_states(context)
         | 
| 166 166 | 
             
                      container_statuses = context.dig("container_state", "containerStatuses") || []
         | 
| 167 | 
            -
                      container_statuses. | 
| 167 | 
            +
                      container_statuses.filter_map { |status| status["state"]&.values&.first }
         | 
| 168 168 | 
             
                                        .select { |state| FAILURE_REASONS.include?(state["reason"]) }
         | 
| 169 169 | 
             
                    end
         | 
| 170 170 |  | 
    
        data/lib/floe/workflow/state.rb
    CHANGED
    
    | @@ -58,7 +58,7 @@ module Floe | |
| 58 58 | 
             
                    context.state["Guid"]            = SecureRandom.uuid
         | 
| 59 59 | 
             
                    context.state["EnteredTime"]     = start_time
         | 
| 60 60 |  | 
| 61 | 
            -
                    logger.info("Running state: [#{ | 
| 61 | 
            +
                    logger.info("Running state: [#{long_name}] with input [#{context.input}]...")
         | 
| 62 62 | 
             
                  end
         | 
| 63 63 |  | 
| 64 64 | 
             
                  def finish
         | 
| @@ -70,7 +70,8 @@ module Floe | |
| 70 70 | 
             
                    context.state["Duration"]       = finished_time - entered_time
         | 
| 71 71 | 
             
                    context.execution["EndTime"]    = finished_time_iso if context.next_state.nil?
         | 
| 72 72 |  | 
| 73 | 
            -
                     | 
| 73 | 
            +
                    level = context.output&.[]("Error") ? :error : :info
         | 
| 74 | 
            +
                    logger.public_send(level, "Running state: [#{long_name}] with input [#{context.input}]...Complete #{context.next_state ? "- next state [#{context.next_state}]" : "workflow -"} output: [#{context.output}]")
         | 
| 74 75 |  | 
| 75 76 | 
             
                    context.state_history << context.state
         | 
| 76 77 |  | 
| @@ -101,6 +102,10 @@ module Floe | |
| 101 102 | 
             
                    context.state["WaitUntil"] && Time.parse(context.state["WaitUntil"])
         | 
| 102 103 | 
             
                  end
         | 
| 103 104 |  | 
| 105 | 
            +
                  def long_name
         | 
| 106 | 
            +
                    "#{self.class.name.split("::").last}:#{name}"
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 104 109 | 
             
                  private
         | 
| 105 110 |  | 
| 106 111 | 
             
                  def wait_until!(seconds: nil, time: nil)
         | 
| @@ -18,14 +18,14 @@ module Floe | |
| 18 18 | 
             
                      @output_path = Path.new(payload.fetch("OutputPath", "$"))
         | 
| 19 19 | 
             
                    end
         | 
| 20 20 |  | 
| 21 | 
            -
                    def  | 
| 22 | 
            -
                       | 
| 23 | 
            -
                      input      = input_path.value(context, input)
         | 
| 21 | 
            +
                    def finish
         | 
| 22 | 
            +
                      input      = input_path.value(context, context.input)
         | 
| 24 23 | 
             
                      next_state = choices.detect { |choice| choice.true?(context, input) }&.next || default
         | 
| 25 24 | 
             
                      output     = output_path.value(context, input)
         | 
| 26 25 |  | 
| 27 26 | 
             
                      context.next_state = next_state
         | 
| 28 27 | 
             
                      context.output     = output
         | 
| 28 | 
            +
                      super
         | 
| 29 29 | 
             
                    end
         | 
| 30 30 |  | 
| 31 31 | 
             
                    def running?
         | 
| @@ -15,18 +15,16 @@ module Floe | |
| 15 15 | 
             
                      @error_path = Path.new(payload["ErrorPath"]) if payload["ErrorPath"]
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 |  | 
| 18 | 
            -
                    def  | 
| 19 | 
            -
                      super
         | 
| 18 | 
            +
                    def finish
         | 
| 20 19 | 
             
                      context.next_state = nil
         | 
| 21 20 | 
             
                      # TODO: support intrinsic functions here
         | 
| 22 21 | 
             
                      # see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-fail-state.html
         | 
| 23 22 | 
             
                      #     https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html#asl-intrsc-func-generic
         | 
| 24 23 | 
             
                      context.output     = {
         | 
| 25 | 
            -
                        "Error" => @error_path ? @error_path.value(context, input) : error,
         | 
| 26 | 
            -
                        "Cause" => @cause_path ? @cause_path.value(context, input) : cause
         | 
| 24 | 
            +
                        "Error" => @error_path ? @error_path.value(context, context.input) : error,
         | 
| 25 | 
            +
                        "Cause" => @cause_path ? @cause_path.value(context, context.input) : cause
         | 
| 27 26 | 
             
                      }.compact
         | 
| 28 | 
            -
                       | 
| 29 | 
            -
                      context.state["Cause"] = context.output["Cause"]
         | 
| 27 | 
            +
                      super
         | 
| 30 28 | 
             
                    end
         | 
| 31 29 |  | 
| 32 30 | 
             
                    def running?
         | 
| @@ -24,13 +24,11 @@ module Floe | |
| 24 24 | 
             
                      validate_state!
         | 
| 25 25 | 
             
                    end
         | 
| 26 26 |  | 
| 27 | 
            -
                    def  | 
| 28 | 
            -
                       | 
| 29 | 
            -
             | 
| 30 | 
            -
                      input = process_input(input)
         | 
| 31 | 
            -
             | 
| 27 | 
            +
                    def finish
         | 
| 28 | 
            +
                      input              = process_input(context.input)
         | 
| 32 29 | 
             
                      context.output     = process_output(input, result)
         | 
| 33 30 | 
             
                      context.next_state = end? ? nil : @next
         | 
| 31 | 
            +
                      super
         | 
| 34 32 | 
             
                    end
         | 
| 35 33 |  | 
| 36 34 | 
             
                    def running?
         | 
| @@ -46,19 +46,18 @@ module Floe | |
| 46 46 | 
             
                    end
         | 
| 47 47 |  | 
| 48 48 | 
             
                    def finish
         | 
| 49 | 
            -
                      super
         | 
| 50 | 
            -
             | 
| 51 49 | 
             
                      output = runner.output(context.state["RunnerContext"])
         | 
| 52 50 |  | 
| 53 51 | 
             
                      if success?
         | 
| 54 52 | 
             
                        output = parse_output(output)
         | 
| 55 | 
            -
                        context. | 
| 53 | 
            +
                        context.output = process_output(context.input.dup, output)
         | 
| 54 | 
            +
                        super
         | 
| 56 55 | 
             
                      else
         | 
| 57 56 | 
             
                        context.next_state = nil
         | 
| 58 | 
            -
                        error = parse_error(output)
         | 
| 57 | 
            +
                        context.output = error = parse_error(output)
         | 
| 58 | 
            +
                        super
         | 
| 59 59 | 
             
                        retry_state!(error) || catch_error!(error) || fail_workflow!(error)
         | 
| 60 60 | 
             
                      end
         | 
| 61 | 
            -
             | 
| 62 61 | 
             
                    ensure
         | 
| 63 62 | 
             
                      runner.cleanup(context.state["RunnerContext"])
         | 
| 64 63 | 
             
                    end
         | 
| @@ -110,6 +109,7 @@ module Floe | |
| 110 109 |  | 
| 111 110 | 
             
                      wait_until!(:seconds => retrier.sleep_duration(context["State"]["RetryCount"]))
         | 
| 112 111 | 
             
                      context.next_state = context.state_name
         | 
| 112 | 
            +
                      logger.info("Running state: [#{long_name}] with input [#{context.input}]...Retry - delay: #{wait_until}")
         | 
| 113 113 | 
             
                      true
         | 
| 114 114 | 
             
                    end
         | 
| 115 115 |  | 
| @@ -119,13 +119,15 @@ module Floe | |
| 119 119 |  | 
| 120 120 | 
             
                      context.next_state = catcher.next
         | 
| 121 121 | 
             
                      context.output     = catcher.result_path.set(context.input, error)
         | 
| 122 | 
            +
                      logger.info("Running state: [#{long_name}] with input [#{context.input}]...CatchError - next state: [#{context.next_state}] output: [#{context.output}]")
         | 
| 123 | 
            +
             | 
| 122 124 | 
             
                      true
         | 
| 123 125 | 
             
                    end
         | 
| 124 126 |  | 
| 125 127 | 
             
                    def fail_workflow!(error)
         | 
| 126 128 | 
             
                      context.next_state     = nil
         | 
| 127 129 | 
             
                      context.output         = {"Error" => error["Error"], "Cause" => error["Cause"]}.compact
         | 
| 128 | 
            -
                       | 
| 130 | 
            +
                      logger.error("Running state: [#{long_name}] with input [#{context.input}]...Complete workflow - output: [#{context.output}]")
         | 
| 129 131 | 
             
                    end
         | 
| 130 132 |  | 
| 131 133 | 
             
                    def parse_error(output)
         | 
| @@ -29,8 +29,7 @@ module Floe | |
| 29 29 | 
             
                    def start(input)
         | 
| 30 30 | 
             
                      super
         | 
| 31 31 |  | 
| 32 | 
            -
                      input | 
| 33 | 
            -
                      context.output = output_path.value(context, input)
         | 
| 32 | 
            +
                      input = input_path.value(context, context.input)
         | 
| 34 33 |  | 
| 35 34 | 
             
                      wait_until!(
         | 
| 36 35 | 
             
                        :seconds => seconds_path ? seconds_path.value(context, input).to_i : seconds,
         | 
| @@ -38,6 +37,12 @@ module Floe | |
| 38 37 | 
             
                      )
         | 
| 39 38 | 
             
                    end
         | 
| 40 39 |  | 
| 40 | 
            +
                    def finish
         | 
| 41 | 
            +
                      input          = input_path.value(context, context.input)
         | 
| 42 | 
            +
                      context.output = output_path.value(context, input)
         | 
| 43 | 
            +
                      super
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 41 46 | 
             
                    def running?
         | 
| 42 47 | 
             
                      waiting?
         | 
| 43 48 | 
             
                    end
         | 
    
        data/lib/floe/workflow.rb
    CHANGED
    
    | @@ -85,7 +85,7 @@ module Floe | |
| 85 85 | 
             
                  end
         | 
| 86 86 | 
             
                end
         | 
| 87 87 |  | 
| 88 | 
            -
                attr_reader :context, :credentials, :payload, :states, :states_by_name, :start_at, :name
         | 
| 88 | 
            +
                attr_reader :context, :credentials, :payload, :states, :states_by_name, :start_at, :name, :comment
         | 
| 89 89 |  | 
| 90 90 | 
             
                def initialize(payload, context = nil, credentials = {}, name = nil)
         | 
| 91 91 | 
             
                  payload     = JSON.parse(payload)     if payload.kind_of?(String)
         | 
| @@ -100,6 +100,7 @@ module Floe | |
| 100 100 | 
             
                  @payload     = payload
         | 
| 101 101 | 
             
                  @context     = context
         | 
| 102 102 | 
             
                  @credentials = credentials || {}
         | 
| 103 | 
            +
                  @comment     = payload["Comment"]
         | 
| 103 104 | 
             
                  @start_at    = payload["StartAt"]
         | 
| 104 105 |  | 
| 105 106 | 
             
                  @states         = payload["States"].to_a.map { |state_name, state| State.build!(self, state_name, state) }
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: floe
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.10.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - ManageIQ Developers
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024- | 
| 11 | 
            +
            date: 2024-04-05 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: awesome_spawn
         | 
| @@ -80,6 +80,90 @@ dependencies: | |
| 80 80 | 
             
                - - "~>"
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 82 | 
             
                    version: '3.0'
         | 
| 83 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 84 | 
            +
              name: manageiq-style
         | 
| 85 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 | 
            +
                requirements:
         | 
| 87 | 
            +
                - - ">="
         | 
| 88 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            +
                    version: '0'
         | 
| 90 | 
            +
              type: :development
         | 
| 91 | 
            +
              prerelease: false
         | 
| 92 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
                requirements:
         | 
| 94 | 
            +
                - - ">="
         | 
| 95 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                    version: '0'
         | 
| 97 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 98 | 
            +
              name: rake
         | 
| 99 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
                requirements:
         | 
| 101 | 
            +
                - - "~>"
         | 
| 102 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                    version: '13.0'
         | 
| 104 | 
            +
              type: :development
         | 
| 105 | 
            +
              prerelease: false
         | 
| 106 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - "~>"
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: '13.0'
         | 
| 111 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 112 | 
            +
              name: rspec
         | 
| 113 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 114 | 
            +
                requirements:
         | 
| 115 | 
            +
                - - ">="
         | 
| 116 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 117 | 
            +
                    version: '0'
         | 
| 118 | 
            +
              type: :development
         | 
| 119 | 
            +
              prerelease: false
         | 
| 120 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 121 | 
            +
                requirements:
         | 
| 122 | 
            +
                - - ">="
         | 
| 123 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 124 | 
            +
                    version: '0'
         | 
| 125 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 126 | 
            +
              name: rubocop
         | 
| 127 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 128 | 
            +
                requirements:
         | 
| 129 | 
            +
                - - ">="
         | 
| 130 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            +
                    version: '0'
         | 
| 132 | 
            +
              type: :development
         | 
| 133 | 
            +
              prerelease: false
         | 
| 134 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 135 | 
            +
                requirements:
         | 
| 136 | 
            +
                - - ">="
         | 
| 137 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 138 | 
            +
                    version: '0'
         | 
| 139 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 140 | 
            +
              name: simplecov
         | 
| 141 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 142 | 
            +
                requirements:
         | 
| 143 | 
            +
                - - ">="
         | 
| 144 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 145 | 
            +
                    version: 0.21.2
         | 
| 146 | 
            +
              type: :development
         | 
| 147 | 
            +
              prerelease: false
         | 
| 148 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 149 | 
            +
                requirements:
         | 
| 150 | 
            +
                - - ">="
         | 
| 151 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 152 | 
            +
                    version: 0.21.2
         | 
| 153 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 154 | 
            +
              name: timecop
         | 
| 155 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 156 | 
            +
                requirements:
         | 
| 157 | 
            +
                - - ">="
         | 
| 158 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 159 | 
            +
                    version: '0'
         | 
| 160 | 
            +
              type: :development
         | 
| 161 | 
            +
              prerelease: false
         | 
| 162 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 163 | 
            +
                requirements:
         | 
| 164 | 
            +
                - - ">="
         | 
| 165 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 166 | 
            +
                    version: '0'
         | 
| 83 167 | 
             
            description: Simple Workflow Runner.
         | 
| 84 168 | 
             
            email:
         | 
| 85 169 | 
             
            executables:
         |