-
-
Notifications
You must be signed in to change notification settings - Fork 104
Add run command #546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add run command #546
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
require "./spec_helper" | ||
|
||
private def bin_path(name) | ||
File.join(application_path, "bin", Shards::Helpers.exe(name)) | ||
end | ||
|
||
describe "run" do | ||
before_each do | ||
Dir.mkdir(File.join(application_path, "src")) | ||
File.write(File.join(application_path, "src", "cli.cr"), "puts __FILE__") | ||
end | ||
|
||
after_each do | ||
File.delete File.join(application_path, "shard.yml") | ||
end | ||
|
||
it "fails when no targets defined" do | ||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
ex = expect_raises(FailedCommand) do | ||
run "shards run --no-color" | ||
end | ||
ex.stdout.should contain("Targets not defined in shard.yml") | ||
end | ||
end | ||
|
||
it "fails when passing multiple targets" do | ||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
targets: | ||
app: | ||
main: src/cli.cr | ||
alt: | ||
main: src/cli.cr | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
ex = expect_raises(FailedCommand) do | ||
run "shards run --no-color app alt" | ||
end | ||
ex.stdout.should contain("Error please specify only one target. If you meant to pass arguments you may use 'shards run target -- args'") | ||
end | ||
end | ||
|
||
it "fails when multiple targets, no arg" do | ||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
targets: | ||
app: | ||
main: src/cli.cr | ||
alt: | ||
main: src/cli.cr | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
ex = expect_raises(FailedCommand) do | ||
run "shards run --no-color" | ||
end | ||
ex.stdout.should contain("Error please specify the target with 'shards run target'") | ||
end | ||
end | ||
|
||
it "runs when only one target" do | ||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
targets: | ||
app: | ||
main: src/cli.cr | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
output = run("shards run --no-color") | ||
|
||
File.exists?(bin_path("app")).should be_true | ||
|
||
output.should contain("Executing: app") | ||
output.chomp.should contain(File.join(application_path, "src", "cli.cr")) | ||
end | ||
end | ||
|
||
it "runs specified target" do | ||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
targets: | ||
< 10000 /td> | app: | |
main: src/cli.cr | ||
alt: | ||
main: src/cli.cr | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
output = run("shards run --no-color app") | ||
|
||
File.exists?(bin_path("app")).should be_true | ||
File.exists?(bin_path("alt")).should be_false | ||
|
||
output.should contain("Executing: app") | ||
output.chomp.should contain(File.join(application_path, "src", "cli.cr")) | ||
end | ||
end | ||
|
||
it "passes back execution failure from child process" do | ||
File.write File.join(application_path, "src", "fail.cr"), <<-CR | ||
puts "This command fails" | ||
exit 5 | ||
CR | ||
|
||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
targets: | ||
fail: | ||
main: src/fail.cr | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
ex = expect_raises(FailedCommand) do | ||
run "shards run --no-color" | ||
end | ||
ex.stdout.should contain("This command fails") | ||
end | ||
end | ||
|
||
it "forwards additional ARGV to child process" do | ||
File.write File.join(application_path, "src", "args.cr"), <<-CR | ||
print "args: ", ARGV.join(',') | ||
CR | ||
|
||
File.write File.join(application_path, "shard.yml"), <<-YAML | ||
name: build | ||
version: 0.1.0 | ||
targets: | ||
app: | ||
main: src/args.cr | ||
YAML | ||
|
||
Dir.cd(application_path) do | ||
output = run("shards run --no-color -- foo bar baz") | ||
output.should contain("Executing: app foo bar baz") | ||
output.should contain("args: foo,bar,baz") | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,41 @@ | ||||||
require "./command" | ||||||
|
||||||
module Shards | ||||||
module Commands | ||||||
class Run < Command | ||||||
def run(targets, options, run_options) | ||||||
if spec.targets.empty? | ||||||
raise Error.new("Targets not defined in #{SPEC_FILENAME}") | ||||||
end | ||||||
|
||||||
# when more than one target was specified | ||||||
if targets.size > 1 | ||||||
raise Error.new("Error please specify only one target. If you meant to pass arguments you may use 'shards run target -- args'") | ||||||
end | ||||||
|
||||||
# when no target was specified | ||||||
if targets.empty? | ||||||
if spec.targets.size > 1 | ||||||
raise Error.new("Error please specify the target with 'shards run target'") | ||||||
else | ||||||
name = spec.targets.first.name | ||||||
end | ||||||
else | ||||||
name = targets.first | ||||||
end | ||||||
|
||||||
if target = spec.targets.find { |t| t.name == name } | ||||||
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO the original reads better. |
||||||
Commands::Build.run(path, [target.name], options) | ||||||
|
||||||
Log.info { "Executing: #{target.name} #{run_options.join(' ')}" } | ||||||
status = Process.run(File.join(Shards.bin_path, target.name), args: run_options, output: Process::Redirect::Inherit, error: Process::Redirect::Inherit) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought about this, however decided to follow the same pattern/style used in build command: https://github.com/crystal-lang/shards/blob/master/src/commands/build.cr#L46-L48 Could change if really needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either way is good |
||||||
unless status.success? | ||||||
exit status.exit_code | ||||||
end | ||||||
else | ||||||
raise Error.new("Error target #{name} was not found in #{SPEC_FILENAME}") | ||||||
end | ||||||
end | ||||||
end | ||||||
end | ||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm too rusty to came with a non-convoluted version of these nested conditions 😬
Better versions are welcome! 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation looks fine.
But I'm not sure the resulting behaviour is what we should have. At least the discussion in #157 seemed pretty indecisive on that. It might not be that important what we pick, but this alternative is at least not my favourite 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you rephrase or explain this? Not sure I follow. The scenarios I made were:
Looking at the comments in #157 is confusing me:
(skipping the shards isn't a build tool dilema)
I'm ok with making the target mandatory, that will definitely simply the above logic, but I thought of
shards run
similar tocargo run
and the default target selectionEither way, again, we can change it, that is why I sent this PR 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we just need to come to a decision in #157. There are contradicting views on that.
Having a PR ready certainly helps to push this forward ;)