#!/usr/bin/env ruby # frozen_string_literal: true require "floe" require "optimist" opts = Optimist.options do version("v#{Floe::VERSION}\n") usage("[options] workflow input [workflow2 input2]") opt :workflow, "Path to your workflow json (legacy)", :type => :string opt :input, "JSON payload to input to the workflow (legacy)", :type => :string opt :credentials, "JSON payload with credentials", :type => :string opt :credentials_file, "Path to a file with credentials", :type => :string opt :docker_runner, "Type of runner for docker images", :type => :string, :short => 'r' opt :docker_runner_options, "Options to pass to the runner", :type => :strings, :short => 'o' opt :docker, "Use docker to run images (short for --docker_runner=docker)", :type => :boolean opt :podman, "Use podman to run images (short for --docker_runner=podman)", :type => :boolean opt :kubernetes, "Use kubernetes to run images (short for --docker_runner=kubernetes)", :type => :boolean end Optimist.die(:docker_runner, "must be one of #{Floe::Workflow::Runner::TYPES.join(", ")}") unless Floe::Workflow::Runner::TYPES.include?(opts[:docker_runner]) # legacy support for --workflow args = ARGV.empty? ? [opts[:workflow], opts[:input]] : ARGV Optimist.die(:workflow, "must be specified") if args.empty? # shortcut support opts[:docker_runner] ||= "docker" if opts[:docker] opts[:docker_runner] ||= "podman" if opts[:podman] opts[:docker_runner] ||= "kubernetes" if opts[:kubernetes] require "logger" Floe.logger = Logger.new($stdout) runner_klass = case opts[:docker_runner] when "docker" Floe::Workflow::Runner::Docker when "podman" Floe::Workflow::Runner::Podman when "kubernetes" Floe::Workflow::Runner::Kubernetes end runner_options = opts[:docker_runner_options].to_h { |opt| opt.split("=", 2) } Floe::Workflow::Runner.docker_runner = runner_klass.new(runner_options) credentials = if opts[:credentials_given] opts[:credentials] == "-" ? $stdin.read : opts[:credentials] elsif opts[:credentials_file_given] File.read(opts[:credentials_file]) end workflows = args.each_slice(2).map do |workflow, input| context = Floe::Workflow::Context.new(:input => input || opts[:input] || "{}") Floe::Workflow.load(workflow, context, credentials) end # run outstanding = workflows.dup until outstanding.empty? ready = outstanding.select(&:step_nonblock_ready?) ready.map(&:run_nonblock) outstanding -= ready.select(&:end?) sleep(1) if !outstanding.empty? end # display status workflows.each do |workflow| puts "", "#{workflow.name}#{" (#{workflow.status})" unless workflow.context.success?}", "===" if workflows.size > 1 puts workflow.output.inspect end # exit status exit workflows.all? { |workflow| workflow.context.success? } ? 0 : 1