Skip to content

Commit

Permalink
Add support for CSV content from stdin in CLI (#637)
Browse files Browse the repository at this point in the history
Co-Authored-By: Étienne Barrié <[email protected]>
  • Loading branch information
promulo and etiennebarrie authored May 25, 2022
1 parent fd1e650 commit 415bb0e
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,13 +508,19 @@ Alternatively, you can run your Task in the command line:
bundle exec maintenance_tasks perform Maintenance::UpdatePostsTask
```

To run a Task that processes CSVs from the command line, use the --csv option:
To run a Task that processes CSVs from the command line, use the `--csv` option:

```sh-session
bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv "path/to/my_csv.csv"
```

To run a Task that takes arguments from the command line, use the --arguments
The `--csv` option also works with CSV content coming from the standard input:

```sh-session
curl "some/remote/csv" | bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv
```

To run a Task that takes arguments from the command line, use the `--arguments`
option, passing arguments as a set of \<key>:\<value> pairs:

```sh-session
Expand Down
12 changes: 10 additions & 2 deletions lib/maintenance_tasks/cli.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require "stringio"
require "thor"

module MaintenanceTasks
Expand Down Expand Up @@ -27,7 +28,7 @@ def exit_on_failure?
# Specify the CSV file to process for CSV Tasks
desc = "Supply a CSV file to be processed by a CSV Task, "\
"--csv path/to/csv/file.csv"
option :csv, desc: desc
option :csv, lazy_default: :stdin, desc: desc
# Specify arguments to supply to a Task supporting parameters
desc = "Supply arguments for a Task that accepts parameters as a set of "\
"<key>:<value> pairs."
Expand All @@ -52,10 +53,17 @@ def perform(name)
private

def csv_file
return unless options.key?(:csv)

csv_option = options[:csv]
if csv_option

if csv_option == :stdin
{ io: StringIO.new($stdin.read), filename: "stdin.csv" }
else
{ io: File.open(csv_option), filename: File.basename(csv_option) }
end
rescue Errno::ENOENT
raise ArgumentError, "CSV file not found: #{csv_option}"
end
end
end
44 changes: 35 additions & 9 deletions test/lib/maintenance_tasks/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,47 @@ class CLITest < ActiveSupport::TestCase
@cli.perform("Wrong")
end

test "#perform runs a CSV Task with the supplied CSV when --csv option used" do
test "#perform runs CSV task with supplied CSV when --csv option used" do
task = mock(name: "MyCsvTask")
csv_file_path = file_fixture("sample.csv")
opened_csv_file = File.open(csv_file_path)
expected_attachable = { io: opened_csv_file, filename: "sample.csv" }

@cli.expects(:options).at_least_once.returns(csv: csv_file_path)
File.expects(:open).with(csv_file_path).returns(opened_csv_file)
Runner.expects(:run)
.with(name: "MyCsvTask", csv_file: expected_attachable, arguments: {})
.with do |kwargs|
assert_equal("MyCsvTask", kwargs[:name])
assert_equal(csv_file_path.to_s, kwargs[:csv_file][:io].path)
assert_equal({}, kwargs[:arguments])
end
.returns(task)
@cli.expects(:say_status)
.with(:success, "MyCsvTask was enqueued.", :green)

@cli.perform("MyCsvTask")
assert_output(/success\s+MyCsvTask was enqueued\./) do
CLI.start(["perform", "MyCsvTask", "--csv", csv_file_path])
end
end

test "#perform runs CSV task with content from stdin" do
task = mock(name: "MyCsvTask")
csv_string = "foo,bar\n1,2\n"
$stdin = StringIO.new(csv_string)

Runner.expects(:run)
.with do |kwargs|
assert_equal("MyCsvTask", kwargs[:name])
assert_equal(csv_string, kwargs[:csv_file][:io].read)
assert_equal({}, kwargs[:arguments])
end
.returns(task)

assert_output(/success\s+MyCsvTask was enqueued\./) do
CLI.start(["perform", "MyCsvTask", "--csv"])
end

$stdin = STDIN
end

test "#perform prints error message when CSV file does not exist" do
assert_output(/error\s+CSV file not found: foo\.csv/) do
CLI.start(["perform", "MyCsvTask", "--csv", "foo.csv"])
end
end

test "#perform runs a Task with the supplied arguments when --arguments option used" do
Expand Down

0 comments on commit 415bb0e

Please sign in to comment.