-
Notifications
You must be signed in to change notification settings - Fork 257
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
auto-args for targets? #24
Comments
May conflict with #34 |
While it's a little ugly, I think you could support both features if you kept the multi-target support to be explicitly delimited. The available bind targets then for the method arguments would be the union of the two. If both targets had an |
I see . what you mean, like if build had an mage build compile -OS=windows -output=foo.exe That's not terrible :) |
That's not ugly, it's beautiful! And elegant if targets declare a same named arg and you only have to specify it once on the command line. Or where you thinking of some other approach, @jrnt30? |
Now that was the general thought I had a well |
I don't know about coupling the variables to the positional args for a given target. Wouldn't most use cases be satisfied with something closer to: type Args map[string][]string
func Build(args Args) error {
switch {
case args.Get("GOOS") && args.Get("GOARCH"):
// build with GOOS and GOARCH
default:
// other
}
}
// Get returns the first argument
func (a Args) Get(key string) string { ... } The interface is basically ripped off from https://golang.org/pkg/net/url/#Values.Get ? This solves a huge list of problems on our end with mage and would be a very, very welcome feature. Maybe return the args as part of a |
I think the question is mainly how they're specified on the command line and how that interacts / interferes with calling multiple targets. Getting args into the target itself is easy enough. Right now, you can do
But defining the args in the target function's arguments is more elegant and lets us validate them automatically, produce docs for them, etc. The only problem is how they look when you specify them on the command line, how or if we disambiguate between two targets' args, etc |
That's true, too. I think if you have multiple targets, you have to scan from left to right and parse the args between the targets and use that as the rough function signature. Does order matter? That's problematic UX. How do you pre-register an argument so it's available as help? What if a target has 10 flags available and half of them are optional, then what? Pass them all in as arguments to the target func Foo(barRequired string, bazOptional *string) error { ? but times however many args? The problem I have with using a container like a |
Could you, for a start, just allow additional arguments after the targets? For now, |
As for the multiple targets, I would suggest to use prefixes: |
Disclaimer: I absolutely did not think this through, this is basically a quick brain dump to maybe fuel the conversation. How about using structs to define global and target specific arguments ? Something like this: // +build mage
package main
import "fmt"
type globalParams struct {
Verbose bool `default:false short:v`
}
type uploadParams struct {
Source string
Target string `default:"someURL"`
Retry *int
}
// Default is the default target when invoking mage without an explicit target
var Default = Upload
// GlobalParams maps the global options that can be passed from command line
var GlobalParams = globalParams{}
// Hello says hello
func Hello() {
if GlobalParams.Verbose {
fmt.Println("Hello World")
}
}
// Upload sends stuff to some place
func Upload(params uploadParams) {
if GlobalParams.Verbose {
fmt.Printf("Uploading %s to %s...\n", params.Source, params.Target)
}
} Using a struct would allow to:
In the snippet above for example, So that would allow:
The
So these combinations would be valid:
I kinda like the fact that this is more explicit than magic 😊 |
Sorry for necromancy Many Unix tool stop parsing command line args after encountering That way, you don't have to bother about deciding on a format to choose, it's the task of the Magefile writer. Just my 2c (I just stumbled upon a situation where I could use something like this) |
hmmm... that's a really interesting idea. I don't think it's a full solution, but it may be good enough for a start, and it gives windows users a better way to get data into a script, without having to do wacky things (since they can't do |
Also - there's no such thing as necromancy for open issues. Open is open :) |
I keep coming back to this issue whenever I start writing new tasks. This would greatly simplify a lot of things. I wanted to propose a pattern that is used in the wild in Devops world: This is how ansible does it:
And this is how terraform does it:
I like how terraform does it and I think we could adopt that for mage. I feel it's a good enough solution
|
Hmm I kind of like that. It's nice not to have to generate new flag handling based on what target you're calling. One flag to contain all variables is nice. |
depending on the format though you might add more suphisticated parsing. not that its very hard to do, but still |
I'd like to add that this is how jsonnet does this
|
for reading vars from files, i'd prefer one of the dotenv solutions |
Explicit file in addition to env substitution has its uses, for example when using mage to orchestrate infrastructure workflows or materialize templates with lots of vars from ci/cd.
Based on that preference, consider a slight variation on Terraform that might look like this
|
It is certainly simpler to implement. It's not obvious to me that it is nicer to use. |
Hmm actually it's not as big of a help as I was thinking... because to make it actually easy, it would need to be I think we can do it a nicer way where you can do
and it'll do the right thing. |
well, you could create a second flags instance (beside flags.commandline) that will read flags.args()[1:] to create a second parse using the flags coming after your flags.args()[0] entry. |
Probably a stupid proposition, but why not simply use |
Prefer |
Done! I went with "just do positional args, ya dummy" and I think it worked out awesomely. |
Slight variation when I use pwsh.
|
Super late to the party, but the reason why you might not want to do that is that you might have other parameters too as well as optional parameters. In the case os and arch, what if 99% of the time you build for the host box, but you still want to be able to build for other architectures? Unless you wanted to have to enter them in every single time despite having sane defaults, you'd have to add a new command, |
It wouldn't be too hard to auto-generate a CLI for each target so the user could pass in positional args or flags per arg.
e.g.
The text was updated successfully, but these errors were encountered: