go-task / task Goto Github PK
View Code? Open in Web Editor NEWA task runner / simpler Make alternative written in Go
Home Page: https://taskfile.dev
License: MIT License
A task runner / simpler Make alternative written in Go
Home Page: https://taskfile.dev
License: MIT License
In a Makefile I an declare variables for everything from compiler opts to the compile command itself, does task support variables?
I think the following would be really nice:
GIT_USER: git config user.name
GIT_EMAIL: git config user.email
STATIC_VAR: echo static
Also if #7 will be implemented, OS specific Taskvar would be nice.
What do you think?
This might be a v2.0.0 improvement as it could impose some breaking changes.
Right now, when evaluating template variables (and env) in the task package, we explicitly pass:
There is a lot of boilerplate on how to set the input parameters for this method, and challenging to keep consistent behavior, as proven by #42 and #40. It should also be noted that the Executor
has become sort of a God object with a lot of methods put directly on that, as most methods need to access something within the executor struct. It would be nice to think of a way where variables flow more naturally through the program, and allows us to drop the boiler-plate. It would also be nice if we could move methods from the executor to e.g. the Task or Call types.
I don't have a concrete proposal yet, but here are some ideas to develop further:
set
property is dropped from the yaml.When I think of breaking changes for task
, I mostly consider that as breaking changes to the yaml, however task also exposes a public API in the task package that could potentially be used programatically. Something to keep in mind, is weather the public API for the task
package could be reduced, so that it's also possible to retain compatibility there. Generally, keep as much as possible as private types / functions, and only expose what's explicitly needed for the main package to work, and what's the minimal requirement for programmatic access by end-users.
example:
dep-shfmt:
generates:
- {{GOPATH}}/bin/shfmt
cmds:
- go get github.com/mvdan/sh/cmd/shfmt
Hi - I recently discovered go-task. Overall this is pretty impressive! I am utilizing go-task as a makefile replacement on a repository that builds packer (another great go project) images. In the process I have discovered that go-task does not proxy unix signals to child processes. This presents an issue when the task that go-task is running needs to do clean up. For example, when the packer process receives SIGINT (ctrl+c) it will stop what is it doing and execute its cleanup actions so as not to leave random artifacts of half build VMs. Having go-task handle signals in the following way would help to address this issue:
As a bonus, if go-task receives SIGINT or SIGTERM more than once, it should exit immediately.
Simple task like hugo should generate site. It clearly takes bit longer in my case and 2nd following task cannot sync, as directory ~/myblog/site is not yet created.
Is there a way for 2nd task to wait for 1st task to finish?
But maybe there is issue with longer running tasks, as alone task gen
doesn't seen to work properly, it never finishes.
Taskfile.yml
gen:
desc: hugo generate site
dir: ~/myblog
cmds:
- hugo
upload:
desc: rsync to server
cmds:
- rsync -avz --delete ~/myblog/site/* blog.xxx.net:/srv/blog.xxx.net/
default:
cmds:
- task: gen
- task: upload
default:
deps: [gen, upload]
This works
cmds:
- true && {{.really}} docker build -t {{.IMAGE_NAME}}:latest .
This gives yaml: line N: did not find expected '-' indicator
cmds:
- {{.really}} docker build -t {{.IMAGE_NAME}}:latest .
really
is either empty or the path to https://manpages.debian.org/stretch/chiark-really/really.8.en.html, depending on what OS evaluates to
A task should be considered up-to-date if the newest timestamp for sources
is exactly equal to the oldest timestamp from generates
.
On Mac, the default filesystem, HFS, only supports second precession for file modification timestamps. Windows NTFS (in theory) supports 100-nanosecond interval precession, while ext4 on Linux rely on cached timestamps from the kernel which in most cases would at least be about 100 ms apart.
Especially on HFS, this can create some hard-to-debug issues where tasks some times are considered up-to-date, and sometimes not.
While writing the tests for #47, it took me a while to figure out why my test worked (sometimes) when I run task
manually in "testdata/generates", but never when I run it from task_test.go. For real-life use-cases, this would help with getting a more consistent behavior when we have task-output from one task used as input in the next (short-running) task.
So that it can be installed in a "regular" way, instead of dropping a binary on the $PATH.
Hi,
I'm trying to do a moderately fiddly env: VAR construct. At a minimum, I'd need the directory containing the taskfile as a variable. The following doesn't seem to work (and isn't ideal anyway)
mytask:
env:
CGO_LDFLAGS: '-I$(pwd)some/path'
The contents of the string are not shell evaluated as far as I can tell (that is probably a good thing!)
I think {{.TASKFILEDIR}} would be ideal.
An alternative I looked into was calling {{ .os.Getwd }}
but that doesn't seem to work (I think it would have to be added by task to the global functions before evaluating the task file) and in any case, just like pwd, would make my task definition dependent on the current working directory.
Can you suggest a good way to achieve the result I'm after ?
I'm thinking of the following use-case:
1+n repositories, each of them using a few specialized tasks, while sharing a lot of "common" code. It should be possible for me to include other Taskfile.yml
and even Taskvars.yml
files. This makes it easier to share code between runners while staying as flexible as possible.
References could either be files directly, directories or, ideally, HTTP endpoints or even (git) repositories.
When you run task example -w
for processes that complete everything is as expected: task will re-run example
on file changes.
When example
is starting a server (for example), something that never exits or 'completes', task will not re-run example
on file changes. In other words the long running process blocks task from watching files and re-running the task.
Personally I want task to re-compile and run my server on file changes, without needed to Ctrl-C it first.
I'm not sure if the current behaviour is intentional. If I have missed something obvious please let me know.
Thoughts?
Edit: Looking through the source, it seems you could use the context (which is passed all the way to the sh interpreter) to cancel the currently executing command when a file change event comes in.
One of the nice things about Makefiles is that it doesn't do unnecessary work. The way that you specify this is with target dependencies:
public/index.html: sources/index.md
markdown sources/index.md > public/index.html
If the mtime for index.md is newer than the mtime for index.html, Make runs the command. This is covered in the README for this project as far as I can tell.
A more useful property is, the files in directory X all depend on their equivalent in directory Y. For example, you have index.md, blog.md, about.md which all compile to their equivalents. If you were to do this:
public/*.html: sources/*.md
...
That would work but it would recompile every Markdown file any time any file in sources/*.md updated. Instead what we want is to establish that 1:1 mapping, done this way:
public/%.html: sources/%.md
markdown $< > $@
Maintaining different formats is getting complicated after #32, specially with TOML, that is a very inflexible format.
This was asked long ago, but I don't think anyone are actually using it.
I'm asking here if anyone have a problem with it first.
It may seem like that the files listed in "generates" (and maybe the ones in "sources"; haven't checked) are prefixed with the task dir, even when an absolute path is given.
Below is a principal example for reproducing the problem:
Taskvars.yml:
ROOT: $pwd
Taskfile.yml:
default:
dir: sub
cmds:
- cat file.txt > '{{.ROOT}}/file2.txt'
sources:
- file.txt
generates:
- "{{.ROOT}}/file2.txt"
sub/file.txt
hello world
If i run this task twice, it would not be found up to date:
$ go get -u github.com/go-task/task/cmd/task # Ensure task is up-to-date
$ task -v
task: No argument given, trying default task
task: dynamic variable: "$pwd", result: "/Users/smyrman/.local/src/github.com/searis/play"
cat file.txt > '/Users/smyrman/.local/src/github.com/searis/play/file2.txt'
$ task -v
task: No argument given, trying default task
task: dynamic variable: "$pwd", result: "/Users/smyrman/.local/src/github.com/searis/play"
cat file.txt > '/Users/smyrman/.local/src/github.com/searis/play/file2.txt'
If I change the generates section in the Taskfile.yml to be a relative path, it works:
generates:
- "../file2.txt"
Relaunch task:
$ task -v
task: No argument given, trying default task
task: dynamic variable: "$pwd", result: "/Users/smyrman/.local/src/github.com/searis/play"
task: Task "default" is up to date
As for the use-case of absolute paths in generates, it matters when you want to use the same (configurable) output directory for several build targets that are built from various sub-directories.
Taskvars.yml:
CONTEXT: /
Taskfile.yml:
view:
cmds:
- echo 'context: {{.CONTEXT}}'
Produces:
$ task view
yaml: line 3: found unexpected end of stream
Taskfile.yml:
view:
cmds:
- echo 'context: test'
Produces:
$ task view
yaml: unmarshal errors:
line 3: cannot unmarshal !!map into string
With this project, maybe it's possible to get rid of cmd
to run commands on Windows.
As of the discussion in #29, I believe we could solve part of the problem by allowing for task parameters to be implemented with the following semantics:
Example syntax:
markdown:
vars:
FILENAME:
cmds:
- markdown {{.FILENAME}}.md -o {{FILENAME}}.html
sources:
- {{.FILENAME}}.md
generates:
- {{.FILENAME}}.html
single-usage:
cmds:
- ^markdown FILENAME=index
two-deps:
deps: # Allows for parallel execution
- markdown FILENAME=index
- markdown FILENAME=docs
Ideally, there would also be a way to set multiple deps and/or call the task multiple times sequentially using using a glob pattern. An example glob task might look like:
markdown:
vars:
IN:
OUT: {{.IN | trimSufix ".md"}}.html # this might be tricky to evaluate in the right order...
cmds:
- markdown {{.IN}} -o {{.OUT}}
sources:
- {{.IN}}
generates:
- {{.OUT}}
cmd-usage:
cmds:
- ^markdown IN=src/*
two-deps:
deps:
- markdown IN=src/*
For the "vars" section in this example, it might be necessary that vars are handled in the order they are listed, which, depending on implementation here, might be hard if Go maps are used. It could also be that YAML don't like that the IN variable is empty.
If this proves to be a problem, and we also want to enforce that all task parameters are set, we could consider to add an additional keyword "args", where the semantics are to allow args to be set before vars:
markdown:
args:
- IN
vars:
OUT: {{.IN | trimSufix ".md"}}.html
cmds:
- markdown {{.IN}} -o {{.OUT}}
sources:
- {{.IN}}
generates:
- {{.OUT}}
Given the following example
task1: # Download some files from the internet that are always the same!
cmds:
- ./download_from_internet.bash
generates:
- files/v1.0.0/*
task2: # Task 2 need task1 to run only if files/v1.0.0/* does not exist.
deps:
- task1
sources:
- files/v1.0.0/file1.xml
cmds:
- ./use_files.bash
Given we try ro run task task2
, could we somehow tell task1 not to run if "files/v1.0.0/*" have been generated?
It would be cool to have global variables defined inside the Taskfile, so we dont need to necesary tamper with two files
It could be an special section just for variables, like:
global_vars:
hello: 'world'
foo: 'bar'
hola:
cmds:
- echo Hello {{.hello}}
/enhancement
I have noticed a few times that when the Taskfile.yml contains a reference to a non-existent task somewhere, I get a panic in the cyclic dependency checks. It would be nice if we could catch this condition and return a nice error instead, indicating which task reference is invalid.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x1247181]
goroutine 1 [running]:
github.com/go-task/task.(*Executor).HasCyclicDep.func1(0xc42010e000, 0x14, 0x0, 0x0)
/Users/smyrman/.local/src/github.com/go-task/task/cyclic.go:15 +0x141
github.com/go-task/task.(*Executor).HasCyclicDep.func1(0xc420013d20, 0xc, 0xc4200d6900, 0x0)
/Users/smyrman/.local/src/github.com/go-task/task/cyclic.go:16 +0x1d5
github.com/go-task/task.(*Executor).HasCyclicDep.func1(0xc420013cc0, 0x7, 0xc4200d6300, 0xc4200cfc00)
/Users/smyrman/.local/src/github.com/go-task/task/cyclic.go:16 +0x1d5
github.com/go-task/task.(*Executor).HasCyclicDep(0xc4200ee150, 0x12efb51)
/Users/smyrman/.local/src/github.com/go-task/task/cyclic.go:24 +0x171
github.com/go-task/task.(*Executor).Run(0xc4200ee150, 0xc420013c60, 0x1, 0x1, 0x1, 0x0)
/Users/smyrman/.local/src/github.com/go-task/task/task.go:64 +0x2f
main.main()
/Users/smyrman/.local/src/github.com/go-task/task/cmd/task/task.go:93 +0x52f
It would be cool being able to reference variables from other variables.
Example, in Taskvars.yml:
name: supercool
version: 0.19
repo: docker.local:5000
container: {.repo}/{.name}-{.version}
I can do this setting the "container" variable in each task, but it would be quite simpler this way
/enhancement
UPDATE: This is a general feature request to not run equal dependencies more than once. E.g. if task A
and task B
both depend on taskC
, running both task A
and task B
in parallel (witin one instance of task), should be able to resolve the dependencies so that taskC
is only run once, and this is the interesting port, if it's equal, which we will get to next.
Since you can pass variables to tasks, it's not enough to just look at the name. The best option is probably to rely on a hash of the name + sorted and resolved input variables. A close second could be to rely on unresolved but still sorted input variables, which is not perfect, but could be an acceptable trade-off if it's somehow easier in code.
I have multiple tasks in my Taskfile
that depend on a single task called go-dep
that runs the command glide install
. When I run task
to build multiple targets, I would expect go-dep to be called at most 1 time (zero if it's found to be up-to-date). Instead, I see it's called once for each task that depend on it:
$ task
task: No argument given, trying default task
glide install
glide install
glide install
glide install
PS! go-deps
in this case is called with no vars, but the rule should really apply to run a dep at most 1 time when the vars are exactly the same.
Hi
I have automated the rpm creation process of go-task. Changing package name on each release makes this process difficult.
Would be great to keep that consistent.
I don't assume this is high priority atm., rather something to discuss. I want to propose changing the evaluation order for variables, and introduce default/override semantics when declaring variables. This still relates to changes made through #56.
I see some potential issues with the current priority order for tasks:
Variables given while calling a task from another. (See Calling another task above)
Environment variables
Variables declared locally in the task
Variables available in the Taskvars.yml file
Especially the position of Environment variables
could be very scary and error-prone to collision with values set in .bashrc
and similar. Especially if you tend to use short variable names. I propose we deal with this by replacing the documented priority order with a documented evaluation order, placing the environment first, accompanied by default/override semantics for variables so that variables are either set if not already set, or overwritten for each level.
One of the common things in bash/make is to define a default value for a variable through special syntax.
Makefile:
VAR ?= default
Bash:
VAR=${VAR:-default}
One of the things I like with task
is that yaml allows a more explicit syntax over special syntax. Now that variables are a map (with "sh:" and "static:" keywords), maybe we could change the evaluation order slightly, and provide a new boolean keyword "ifAbsent". (I was also thinking about replacing "static" with "default" and "override", but then it would not be clear what do do with "sh" values.)
Example Taskfile.yml:
VAL1:
static: hey
ifAbsent: true
VAL2:
sh: echo "hey"
ifAbsent: true
Proposed new documented evaluation order:
The order of 3/4 is a bit weird, but it's done to allow access to Call
variables when compiling task templates. It also means that the task needs to explicitly
allow variables to be overwritten via Call, environment variables or Taskvars, which I think makes sense. It's like local variables v.s. function parmeters in programming; you want to allow function parmeters to be specified by the caller, but not local vars.
The semantics will be very simple. For each level, set the variable iff:
When running a task with -s
, I would expect it to be silent about non-command output. Instead, I see the output:
task: Task "bin/my-binary" is up to date
This is for a simple task with one dependency with status checks.
What is worse, is that this output is printed to stdout, not stderr which makes it it hard to pipe stdout output from the executed cmds
only into a variable:
$ MY_VAR=$(task -s my-task)
I would suggest the following:
(btw, it's more common to use -q / --quiet than -s / --silent).
I'm using gox to do parallel multiplatform builds, and it takes a parameter which is a text/template value describing the output location and name of the compiled binaries. I'm running into a problem because go-task wants to evaluate the template, and it just needs to be passed through.
buildall task:
buildall: desc: Build 64bit versions for darwin, linux, and windows cmds: - gox -arch="amd64" -os="darwin linux windows" -output="./build/{{.Dir}}_{{.OS}}_{{.Arch}}" ./cmd/hello-world/
output:
$ task buildall gox -arch="amd64" -os="darwin linux windows" -output="./build/<no value>_<no value>_<no value>" ./cmd/hello-world/
how can I escape the template in the task above so the template isn't evaluated by task?
Somehow I would expect one of these to work:
echo:
cmds:
- "echo {{.MYVAR}}"
default:
vars:
PLEASE: "awesome"
cmds:
- task: echo
vars: {MYVAR: "{{.PLEASE}}"}
- task: echo
vars: {MYVAR: "$echo {{.PLEASE}}"}
- task: echo
vars: {MYVAR: "$echo $PLEASE"}
Especially with the new parameterised tasks, this would be an important aspect of composing chains of reusable tasks.
hi :) may tell me how i get the filePath for each changed file?
BTW this is not really working. {{FILENAME}} prints
// task assets build -w
build:
cmds:
- go build -v -i main.go
assets:
cmds:
- echo "{{FILENAME}}"
sources:
- src/css/**/*.css
In suggesting #31, I realised that if we allowed vars
(and optionally a new args
list) to be specified on the command-line, go-task would basically allow people to script their own arbitrary CLIs with built-in dependency management, without doing much programming to achieve it, and that's actually pretty cool...
As of use-cases, there is a lot of computer fields where CLIs are written for internal usage, such as large-scale testing infrastructure and HPC. These CLIs are in my experience thrown-together in some language such as Python, or sometimes even bash, in order to glue together various scripts.
In these cases, creating a CLI is never a goal, but a necessity in order to fit the pieces together. Having an easy way not only to create a CLI, but also to manage dependencies, would be really useful in these fields, although these fields might be slow at changing their tooling.
I am not working in any of those fields now, but I have done so previously.
I am quite happy with this idea being shot down, as I don't think go-tasks original goal at least, was to allow for users to write full-blown CLIs to manage their tasks. I.e. I am sure there are some trade-offs to consider.
Tasfile:
create:
cmds:
- touch the-new-rpm.rpm
clean-rpm:
deps:
- create
cmds:
- rm *.rpm
Produces:
task clean-rpm
touch the-new-rpm.rpm
rm *.rpm
rm: cannot remove '*.rpm': No such file or directory
task: Failed to run task "clean-rpm": exit status 1
Does this not work anymore with the go native sh interpreter?
If so, it should probably documented somewhere.
For consistency with ^
being deprecated in favor of task: task-name
syntax.
Before:
# Taskvars.yml
GIT_COMMIT: $git log -n 1 --format=%h
After:
# Taskvars.yml
GIT_COMMIT:
sh: git log -n 1 --format=%h
Feedback welcome
Hi
The following could be a nice feature:
Let's say we have 3 Task files in our repository:
build:
cmds:
- go build -v -i main.go
assets:
cmds:
- ls
assets:
cmds:
- dir
build:
cmds:
- go build -v -i main.go
only_darwin:
cmds:
- do darwin stuff here
This should result to following tasks:
build:
cmds:
- go build -v -i main.go
assets:
cmds:
- ls
build:
cmds:
- go build -v -i main.go
assets:
cmds:
- dir
build:
cmds:
- go build -v -i main.go
assets:
cmds:
- ls
only_darwin:
cmds:
- do darwin stuff here
What do you think?
With #2 and this I could ditch our cmake file :-)
Minimal Taskfile.yml:
default:
env:
GOOS: linux
GOARCH: amd64
CGO_ENABLED: "0"
cmds:
- echo "GOOS='$GOOS' GOARCH='$GOARCH' CGO_ENABLED='$CGO_ENABLED'"
First, ensuring that task is up-to-date:
% go get -u -v github.com/go-task/task/cmd/task
github.com/go-task/task (download)
When running task, I get extra curly braces and a space around the env value ({
, }
):
% task
task: No argument given, trying default task
echo "GOOS='$GOOS' GOARCH='$GOARCH' CGO_ENABLED='$CGO_ENABLED'"
GOOS='{linux }' GOARCH='{amd64 }' CGO_ENABLED='{0 }'
I would have expected the following instead:
% task
task: No argument given, trying default task
echo "GOOS='$GOOS' GOARCH='$GOARCH' CGO_ENABLED='$CGO_ENABLED'"
GOOS='linux' GOARCH='amd64' CGO_ENABLED='0'
I have pushed a new feature proposal to discuss: feature/producer
The idea is to have multiple producer that translate the Taskfile to different target formats. So they produce either a series of executed commands or for example a bash script.
Another useful target for a producer would be a dockerfile generator.
@andreynering sorry to directly assign you to this issue, but I wanted to start the discussion about that idea
On macOS Sierra when I try task help
I get:
$ task help
Available tasks for this project:
- default: Test for Echo
- play: Run an Ansible Playbook
- wipe: Terminal screen/buffer wipe
task: Task "help" not found
instead of the expected
$ task help
Available tasks for this project:
default: Test for Echo
play: Run an Ansible Playbook
wipe: Terminal screen/buffer wipe
@andreynering The issue to discuss dependency handling
Maybe a switch to enforce running dependencies or two classes of dependencies ( run always
and run if required
) could be a valid choice.
If I could have this re run a task whenever a file changes in the source directory that would be a huge boon, I'd be willing to help contribute to this feature.
I would like to have a small web server that would allow me to execute the tasks remotely.
For example, sending a request to http: //host:8888/taskname would execute the task "taskname"
Like this basic example of dog: https://github.com/dogtools/dog/blob/master/examples/http-api/http-api.go
It would be interesting if the access was limited by a token / user
Taskvars.yml:
CONTEXT: /
Taskfile.yaml:
set-vars-notworking:
cmds:
- echo git.pnet.ch/mule/mule/pkg/http/api.context={{.CONTEXT}}
set: NOT_WORKING
set-vars-working:
cmds:
- echo git.pnet.ch/mule/mule/pkg/http/api.context{{.CONTEXT}}
set: WORKING
view:
deps:
- set-vars-notworking
- set-vars-working
cmds:
- echo 'notworking {{.NOT_WORKING}}'
- echo 'working {{.WORKING}}'
- echo 'context {{.CONTEXT}}'
Produces the following output:
$ task view
notworking git.pnet.ch/mule/mule/pkg/http/api.context
working git.pnet.ch/mule/mule/pkg/http/api.context/
context /
The notworking value should be:
notworking git.pnet.ch/mule/mule/pkg/http/api.context=/
not
notworking git.pnet.ch/mule/mule/pkg/http/api.context
Given the following Taskfile:
taskA:
vars:
A: null
B: "42"
cmds:
- echo "{{.A}} {{.B}} {{.C}}"
taskB:
vars:
A: "taskB"
B: "ignored"
aha: "weee"
deps:
- task: taskA
vars:
A: "dep:{{.A}}"
C: "{{.aha}}"
cmds:
- task: taskA
vars:
A: "cmd:{{.A}}"
C: "{{.aha}}"
default:
deps:
- task: taskB
vars: {A: "default"}
I would expect task
to output:
task: No argument given, trying default task
echo "dep:default 42 weee"
dep:default 42 weee
echo "cmd:default 42 weee"
cmd:default 42 weee
Instead, we get:
task: No argument given, trying default task
echo "dep:{{.A}} 42 {{.aha}}"
dep:{{.A}} 42 {{.aha}}
echo "cmd:default 42 weee"
cmd:default 42 weee
With the new 1.4 release and #32, is something like this supported?
some-task:
cmds:
- task: my-task
vars: {var1: {{.VAR}}, var2: {{.OTHER_VAR}}}
vars:
VAR: $echo "hello"
OTHER_VAR: $echo "hi"
my-task:
cmds:
- cmd using var1 and var2
vars:
var1: val
var2: val
The reasoning behind this is I'm obviously looking to do more intense commands than echoing a string as my values of VAR and OTHER_VAR. So I can compute my value once and pass it to all of the other tasks I'm running.
Thanks for your tool, it's really awesome!
There is only one way of setting a multiline variable in task from shell output that I am aware of, and that is using the deprecated set
.
Using the sh: program
syntax will (deliberately) give an error. I don't know what the reasoning for that is, but there are many good use cases for allowing multiline variables to be set from a shell command, such as fetching private keys from a keychain. In this case you would also prefer if you didn't need to store the private key in a temp file on disk.
I have no idea what version of Task I have installed. Just that it was probably from the master branch. An example of running task --version
on my macOS Sierra system.
$ task --version
Task version: master
It would be nice if it was noted somewhere that the values in task_checksums.txt are SHA-256. Maybe inside the text file or in the README.md where it links to the releases page? Could relieve confusion and promote usage. ๐ผ
Issue #38 is about allowing a variable to be passed onto a sub-task or dependency. The chosen way to handle it, at least initially, was to allow for template variables to be evaluated when passing on the vars. See #39.
However, it might make sense to allow global variables and task parameters to be evaluated in a task's local vars and env section as well. The example below is maybe not the best use-case, but it should illustrate what I mean:
# Taskvars.yml
GOOS: $go env GOOS
GOARCH: $go env GOARCH
# Taskfile.yml
default:
vars:
TARGET_DIR: "build/{{.GOOS}}_{{.GOARCH}}"
env:
GOOS: "{{.GOOS}}"
GOARCH: "{{.GOARCH}}"
cmds:
- mkdir -p "{{.TARGET_DIR}}"
- go build -o '{{.TARGET_DIR}}/myapp' .
cross-compile:
deps:
- task: default
vars: {GOOS: linux}
- task: default
vars: {GOOS: windows, GOARCH: 386}
- task: default
vars: {GOOS: windows, GOARCH: amd64}
- task: default
vars: {GOOS: darwin}
Another reason for adding this feature is to make the behaviour more consistent, and to allow for easier documentation of the detailed behaviour. E.g.:
I have a Taskfile that's failing to run, despite that it most likely should. It looks like this:
build: cmds: - time go build -i
Which causes it to throw this error:
task: Failed to run task "build": 1:1: unhandled command node: *syntax.TimeClause
It looks like mvdan/sh is intercepting "time", assuming it's the shell keyword, and expecting something to happen with that.
A short workaround if anyone else needs it is to change time go build -i
to $(which time) go build -i
. It will change you from using the shell keyword time to the system's time binary, which is much uglier, but it gets the job done.
I think at this point it would be nice to add some tests.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.