mirror of
				https://github.com/go-task/task.git
				synced 2025-10-30 23:58:01 +02:00 
			
		
		
		
	Merge branch 'master' into feature/include
This commit is contained in:
		| @@ -9,6 +9,6 @@ trim_trailing_whitespace = true | |||||||
| indent_style = tab | indent_style = tab | ||||||
| indent_size = 8 | indent_size = 8 | ||||||
|  |  | ||||||
| [*.{md,yml,yaml,json,toml}] | [*.{md,yml,yaml,json,toml,htm,html}] | ||||||
| indent_style = space | indent_style = space | ||||||
| indent_size = 2 | indent_size = 2 | ||||||
|   | |||||||
							
								
								
									
										787
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										787
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,789 +1,12 @@ | |||||||
| [](https://travis-ci.org/go-task/task) | [](https://travis-ci.org/go-task/task) | ||||||
|  |  | ||||||
| # Task - A task runner / simpler Make alternative written in Go | # Task | ||||||
|  |  | ||||||
| > We recently released version 2.0.0 of Task. The Taskfile changed a bit. | Task is a task runner / build tool that aims to be simpler and easier to use | ||||||
| Please, check the [Taskfile versions](TASKFILE_VERSIONS.md) document to see | than, for example, [GNU Make][make]. | ||||||
| what changed and how to upgrade. |  | ||||||
|  |  | ||||||
| Task is a simple tool that allows you to easily run development and build | --- | ||||||
| tasks. Task is written in Golang, but can be used to develop any language. |  | ||||||
| It aims to be simpler and easier to use then [GNU Make][make]. |  | ||||||
|  |  | ||||||
| - [Installation](#installation) | See [taskfile.org](https://taskfile.org) for documentation. | ||||||
|   - [Go](#go) |  | ||||||
|   - [Homebrew](#homebrew) |  | ||||||
|   - [Snap](#snap) |  | ||||||
|   - [Binary](#binary) |  | ||||||
| - [Usage](#usage) |  | ||||||
|   - [Environment](#environment) |  | ||||||
|   - [OS specific task](#os-specific-task) |  | ||||||
|   - [Task directory](#task-directory) |  | ||||||
|   - [Task dependencies](#task-dependencies) |  | ||||||
|   - [Calling another task](#calling-another-task) |  | ||||||
|   - [Prevent unnecessary work](#prevent-unnecessary-work) |  | ||||||
|   - [Variables](#variables) |  | ||||||
|     - [Dynamic variables](#dynamic-variables) |  | ||||||
|   - [Go's template engine](#gos-template-engine) |  | ||||||
|   - [Help](#help) |  | ||||||
|   - [Silent mode](#silent-mode) |  | ||||||
|   - [Dry run mode](#dry-run-mode) |  | ||||||
|   - [Ignore errors](#ignore-errors) |  | ||||||
|   - [Output syntax](#output-syntax) |  | ||||||
|   - [Watch tasks](#watch-tasks-experimental) |  | ||||||
| - [Examples](#examples) |  | ||||||
| - [Alternative task runners](#alternative-task-runners) |  | ||||||
|  |  | ||||||
| ## Installation |  | ||||||
|  |  | ||||||
| ### Go |  | ||||||
|  |  | ||||||
| If you have a [Golang][golang] environment setup, you can simply run: |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| go get -u -v github.com/go-task/task/cmd/task |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Homebrew |  | ||||||
|  |  | ||||||
| If you're on macOS and have [Homebrew][homebrew] installed, getting Task is |  | ||||||
| as simple as running: |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| brew install go-task/tap/go-task |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Snap |  | ||||||
|  |  | ||||||
| Task is available for [Snapcraft][snapcraft], but keep in mind that your |  | ||||||
| Linux distribution should allow classic confinement for Snaps to Task work |  | ||||||
| right: |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| sudo snap install task |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Install script |  | ||||||
|  |  | ||||||
| We also have a [install script][installscript], which is very useful on |  | ||||||
| scanarios like CIs. Many thanks to [godownloader][godownloader] for easily |  | ||||||
| generating this script. |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| curl -s https://raw.githubusercontent.com/go-task/task/master/install-task.sh | sh |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Binary |  | ||||||
|  |  | ||||||
| Or you can download the binary from the [releases][releases] page and add to |  | ||||||
| your `PATH`. DEB and RPM packages are also available. |  | ||||||
| The `task_checksums.txt` file contains the sha256 checksum for each file. |  | ||||||
|  |  | ||||||
| ## Usage |  | ||||||
|  |  | ||||||
| Create a file called `Taskfile.yml` in the root of your project. |  | ||||||
| The `cmds` attribute should contain the commands of a task. |  | ||||||
| The example below allows compiling a Go app and uses [Minify][minify] to concat |  | ||||||
| and minify multiple CSS files into a single one. |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     cmds: |  | ||||||
|       - go build -v -i main.go |  | ||||||
|  |  | ||||||
|   assets: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/style.css src/css |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Running the tasks is as simple as running: |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| task assets build |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Task uses [github.com/mvdan/sh](https://github.com/mvdan/sh), a native Go sh |  | ||||||
| interpreter. So you can write sh/bash commands and it will work even on |  | ||||||
| Windows, where `sh` or `bash` are usually not available. Just remember any |  | ||||||
| executable called must be available by the OS or in PATH. |  | ||||||
|  |  | ||||||
| If you ommit a task name, "default" will be assumed. |  | ||||||
|  |  | ||||||
| ### Environment |  | ||||||
|  |  | ||||||
| You can specify environment variables that are added when running a command: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     cmds: |  | ||||||
|       - echo $hallo |  | ||||||
|     env: |  | ||||||
|       hallo: welt |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### OS specific task |  | ||||||
|  |  | ||||||
| If you add a `Taskfile_{{GOOS}}.yml` you can override or amend your Taskfile |  | ||||||
| based on the operating system. |  | ||||||
|  |  | ||||||
| Example: |  | ||||||
|  |  | ||||||
| Taskfile.yml: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     cmds: |  | ||||||
|       - echo "default" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Taskfile_linux.yml: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     cmds: |  | ||||||
|       - echo "linux" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Will print out `linux` and not `default`. |  | ||||||
|  |  | ||||||
| Keep in mind that the version of the files should match. Also, when redefining |  | ||||||
| a task the whole task is replaced, properties of the task are not merged. |  | ||||||
|  |  | ||||||
| It's also possible to have an OS specific `Taskvars.yml` file, like |  | ||||||
| `Taskvars_windows.yml`, `Taskfile_linux.yml`, or `Taskvars_darwin.yml`. See the |  | ||||||
| [variables section](#variables) below. |  | ||||||
|  |  | ||||||
| ### Task directory |  | ||||||
|  |  | ||||||
| By default, tasks will be executed in the directory where the Taskfile is |  | ||||||
| located. But you can easily make the task run in another folder informing |  | ||||||
| `dir`: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   serve: |  | ||||||
|     dir: public/www |  | ||||||
|     cmds: |  | ||||||
|       # run http server |  | ||||||
|       - caddy |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Task dependencies |  | ||||||
|  |  | ||||||
| You may have tasks that depend on others. Just pointing them on `deps` will |  | ||||||
| make them run automatically before running the parent task: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     deps: [assets] |  | ||||||
|     cmds: |  | ||||||
|       - go build -v -i main.go |  | ||||||
|  |  | ||||||
|   assets: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/style.css src/css |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| In the above example, `assets` will always run right before `build` if you run |  | ||||||
| `task build`. |  | ||||||
|  |  | ||||||
| A task can have only dependencies and no commands to group tasks together: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   assets: |  | ||||||
|     deps: [js, css] |  | ||||||
|  |  | ||||||
|   js: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/script.js src/js |  | ||||||
|  |  | ||||||
|   css: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/style.css src/css |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| If there is more than one dependency, they always run in parallel for better |  | ||||||
| performance. |  | ||||||
|  |  | ||||||
| If you want to pass information to dependencies, you can do that the same |  | ||||||
| manner as you would to [call another task](#calling-another-task): |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   default: |  | ||||||
|     deps: |  | ||||||
|       - task: echo_sth |  | ||||||
|         vars: {TEXT: "before 1"} |  | ||||||
|       - task: echo_sth |  | ||||||
|         vars: {TEXT: "before 2"} |  | ||||||
|     cmds: |  | ||||||
|       - echo "after" |  | ||||||
|  |  | ||||||
|   echo_sth: |  | ||||||
|     cmds: |  | ||||||
|       - echo {{.TEXT}} |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Calling another task |  | ||||||
|  |  | ||||||
| When a task has many dependencies, they are executed concurrently. This will |  | ||||||
| often result in a faster build pipeline. But in some situations you may need |  | ||||||
| to call other tasks serially. In this case, just use the following syntax: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   main-task: |  | ||||||
|     cmds: |  | ||||||
|       - task: task-to-be-called |  | ||||||
|       - task: another-task |  | ||||||
|       - echo "Both done" |  | ||||||
|  |  | ||||||
|   task-to-be-called: |  | ||||||
|     cmds: |  | ||||||
|       - echo "Task to be called" |  | ||||||
|  |  | ||||||
|   another-task: |  | ||||||
|     cmds: |  | ||||||
|       - echo "Another task" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Overriding variables in the called task is as simple as informing `vars` |  | ||||||
| attribute: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   main-task: |  | ||||||
|     cmds: |  | ||||||
|       - task: write-file |  | ||||||
|         vars: {FILE: "hello.txt", CONTENT: "Hello!"} |  | ||||||
|       - task: write-file |  | ||||||
|         vars: {FILE: "world.txt", CONTENT: "World!"} |  | ||||||
|  |  | ||||||
|   write-file: |  | ||||||
|     cmds: |  | ||||||
|       - echo "{{.CONTENT}}" > {{.FILE}} |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| The above syntax is also supported in `deps`. |  | ||||||
|  |  | ||||||
| ### Prevent unnecessary work |  | ||||||
|  |  | ||||||
| If a task generates something, you can inform Task the source and generated |  | ||||||
| files, so Task will prevent to run them if not necessary. |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     deps: [js, css] |  | ||||||
|     cmds: |  | ||||||
|       - go build -v -i main.go |  | ||||||
|  |  | ||||||
|   js: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/script.js src/js |  | ||||||
|     sources: |  | ||||||
|       - src/js/**/*.js |  | ||||||
|     generates: |  | ||||||
|       - public/script.js |  | ||||||
|  |  | ||||||
|   css: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/style.css src/css |  | ||||||
|     sources: |  | ||||||
|       - src/css/**/*.css |  | ||||||
|     generates: |  | ||||||
|       - public/style.css |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| `sources` and `generates` can be files or file patterns. When both are given, |  | ||||||
| Task will compare the modification date/time of the files to determine if it's |  | ||||||
| necessary to run the task. If not, it will just print a message like |  | ||||||
| `Task "js" is up to date`. |  | ||||||
|  |  | ||||||
| If you prefer this check to be made by the content of the files, instead of |  | ||||||
| its timestamp, just set the `method` property to `checksum`. |  | ||||||
| You will probably want to ignore the `.task` folder in your `.gitignore` file |  | ||||||
| (It's there that Task stores the last checksum). |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     cmds: |  | ||||||
|       - go build . |  | ||||||
|     sources: |  | ||||||
|       - ./*.go |  | ||||||
|     generates: |  | ||||||
|       - app{{exeExt}} |  | ||||||
|     method: checksum |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| > TIP: method `none` skips any validation and always run the task. |  | ||||||
|  |  | ||||||
| Alternatively, you can inform a sequence of tests as `status`. If no error |  | ||||||
| is returned (exit status 0), the task is considered up-to-date: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   generate-files: |  | ||||||
|     cmds: |  | ||||||
|       - mkdir directory |  | ||||||
|       - touch directory/file1.txt |  | ||||||
|       - touch directory/file2.txt |  | ||||||
|     # test existence of files |  | ||||||
|     status: |  | ||||||
|       - test -d directory |  | ||||||
|       - test -f directory/file1.txt |  | ||||||
|       - test -f directory/file2.txt |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| You can use `--force` or `-f` if you want to force a task to run even when |  | ||||||
| up-to-date. |  | ||||||
|  |  | ||||||
| Also, `task --status [tasks]...` will exit with a non-zero exit code if any of |  | ||||||
| the tasks are not up-to-date. |  | ||||||
|  |  | ||||||
| ### Variables |  | ||||||
|  |  | ||||||
| When doing interpolation of variables, Task will look for the below. |  | ||||||
| They are listed below in order of importance (e.g. most important first): |  | ||||||
|  |  | ||||||
| - Variables declared locally in the task |  | ||||||
| - Variables given while calling a task from another. |  | ||||||
|   (See [Calling another task](#calling-another-task) above) |  | ||||||
| - Variables declared in the `vars:` option in the `Taskfile` |  | ||||||
| - Variables available in the `Taskvars.yml` file |  | ||||||
| - Environment variables |  | ||||||
|  |  | ||||||
| Example of sending parameters with environment variables: |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| $ TASK_VARIABLE=a-value task do-something |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Since some shells don't support above syntax to set environment variables |  | ||||||
| (Windows) tasks also accepts a similar style when not in the beginning of |  | ||||||
| the command. Variables given in this form are only visible to the task called |  | ||||||
| right before. |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| $ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done!" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Example of locally declared vars: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   print-var: |  | ||||||
|     cmds: |  | ||||||
|       echo "{{.VAR}}" |  | ||||||
|     vars: |  | ||||||
|       VAR: Hello! |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Example of global vars in a `Taskfile.yml`: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| vars: |  | ||||||
|   GREETING: Hello from Taskfile! |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   greet: |  | ||||||
|     cmds: |  | ||||||
|       - echo "{{.GREETING}}" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Example of `Taskvars.yml` file: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| PROJECT_NAME: My Project |  | ||||||
| DEV_MODE: production |  | ||||||
| GIT_COMMIT: {sh: git log -n 1 --format=%h} |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| #### Variables expansion |  | ||||||
|  |  | ||||||
| Variables are expanded 2 times by default. You can change that by setting the |  | ||||||
| `expansions:` option. Change that will be necessary if you compose many |  | ||||||
| variables together: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| expansions: 3 |  | ||||||
|  |  | ||||||
| vars: |  | ||||||
|   FOO: foo |  | ||||||
|   BAR: bar |  | ||||||
|   BAZ: baz |  | ||||||
|   FOOBAR: "{{.FOO}}{{.BAR}}" |  | ||||||
|   FOOBARBAZ: "{{.FOOBAR}}{{.BAZ}}" |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   default: |  | ||||||
|     cmds: |  | ||||||
|       - echo "{{.FOOBARBAZ}}" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| #### Dynamic variables |  | ||||||
|  |  | ||||||
| The below syntax (`sh:` prop in a variable) is considered a dynamic variable. |  | ||||||
| The value will be treated as a command and the output assigned. If there is one |  | ||||||
| or more trailing newlines, the last newline will be trimmed. |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     cmds: |  | ||||||
|       - go build -ldflags="-X main.Version={{.GIT_COMMIT}}" main.go |  | ||||||
|     vars: |  | ||||||
|       GIT_COMMIT: |  | ||||||
|         sh: git log -n 1 --format=%h |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| This works for all types of variables. |  | ||||||
|  |  | ||||||
| ### Go's template engine |  | ||||||
|  |  | ||||||
| Task parse commands as [Go's template engine][gotemplate] before executing |  | ||||||
| them. Variables are accessible through dot syntax (`.VARNAME`). |  | ||||||
|  |  | ||||||
| All functions by the Go's [sprig lib](http://masterminds.github.io/sprig/) |  | ||||||
| are available. The following example gets the current date in a given format: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   print-date: |  | ||||||
|     cmds: |  | ||||||
|       - echo {{now | date "2006-01-02"}} |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Task also adds the following functions: |  | ||||||
|  |  | ||||||
| - `OS`: Returns operating system. Possible values are "windows", "linux", |  | ||||||
|   "darwin" (macOS) and "freebsd". |  | ||||||
| - `ARCH`: return the architecture Task was compiled to: "386", "amd64", "arm" |  | ||||||
|   or "s390x". |  | ||||||
| - `splitLines`: Splits Unix (\n) and Windows (\r\n) styled newlines. |  | ||||||
| - `catLines`: Replaces Unix (\n) and Windows (\r\n) styled newlines with a space. |  | ||||||
| - `toSlash`: Does nothing on Unix, but on Windows converts a string from `\` |  | ||||||
|   path format to `/`. |  | ||||||
| - `fromSlash`: Oposite of `toSlash`. Does nothing on Unix, but on Windows |  | ||||||
|   converts a string from `\` path format to `/`. |  | ||||||
| - `exeExt`: Returns the right executable extension for the current OS |  | ||||||
|   (`".exe"` for Windows, `""` for others). |  | ||||||
|  |  | ||||||
| Example: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   print-os: |  | ||||||
|     cmds: |  | ||||||
|       - echo '{{OS}} {{ARCH}}' |  | ||||||
|       - echo '{{if eq OS "windows"}}windows-command{{else}}unix-command{{end}}' |  | ||||||
|       # This will be path/to/file on Unix but path\to\file on Windows |  | ||||||
|       - echo '{{fromSlash "path/to/file"}}' |  | ||||||
|   enumerated-file: |  | ||||||
|     vars: |  | ||||||
|       CONTENT: | |  | ||||||
|         foo |  | ||||||
|         bar |  | ||||||
|     cmds: |  | ||||||
|       - | |  | ||||||
|         cat << EOF > output.txt |  | ||||||
|         {{range $i, $line := .CONTENT | splitLines -}} |  | ||||||
|         {{printf "%3d" $i}}: {{$line}} |  | ||||||
|         {{end}}EOF |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Help |  | ||||||
|  |  | ||||||
| Running `task --list` (or `task -l`) lists all tasks with a description. |  | ||||||
| The following taskfile: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   build: |  | ||||||
|     desc: Build the go binary. |  | ||||||
|     cmds: |  | ||||||
|       - go build -v -i main.go |  | ||||||
|  |  | ||||||
|   test: |  | ||||||
|     desc: Run all the go tests. |  | ||||||
|     cmds: |  | ||||||
|       - go test -race ./... |  | ||||||
|  |  | ||||||
|   js: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/script.js src/js |  | ||||||
|  |  | ||||||
|   css: |  | ||||||
|     cmds: |  | ||||||
|       - minify -o public/style.css src/css |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| would print the following output: |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| * build:   Build the go binary. |  | ||||||
| * test:    Run all the go tests. |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ## Silent mode |  | ||||||
|  |  | ||||||
| Silent mode disables echoing of commands before Task runs it. |  | ||||||
| For the following Taskfile: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   echo: |  | ||||||
|     cmds: |  | ||||||
|       - echo "Print something" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Normally this will be print: |  | ||||||
|  |  | ||||||
| ```sh |  | ||||||
| echo "Print something" |  | ||||||
| Print something |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| With silent mode on, the below will be print instead: |  | ||||||
|  |  | ||||||
| ```sh |  | ||||||
| Print something |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| There's three ways to enable silent mode: |  | ||||||
|  |  | ||||||
| * At command level: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   echo: |  | ||||||
|     cmds: |  | ||||||
|       - cmd: echo "Print something" |  | ||||||
|         silent: true |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| * At task level: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   echo: |  | ||||||
|     cmds: |  | ||||||
|       - echo "Print something" |  | ||||||
|     silent: true |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| * Or globally with `--silent` or `-s` flag |  | ||||||
|  |  | ||||||
| If you want to suppress stdout instead, just redirect a command to `/dev/null`: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   echo: |  | ||||||
|     cmds: |  | ||||||
|       - echo "This will print nothing" > /dev/null |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ## Dry run mode |  | ||||||
|  |  | ||||||
| Dry run mode (`--dry`) compiles and steps through each task, printing the commands |  | ||||||
| that would be run without executing them. This is useful for debugging your Taskfiles. |  | ||||||
|  |  | ||||||
| ## Ignore errors |  | ||||||
|  |  | ||||||
| You have the option to ignore errors during command execution. |  | ||||||
| Given the following Taskfile: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   echo: |  | ||||||
|     cmds: |  | ||||||
|       - exit 1 |  | ||||||
|       - echo "Hello World" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Task will abort the execution after running `exit 1` because the status code `1` stands for `EXIT_FAILURE`. |  | ||||||
| However it is possible to continue with execution using `ignore_error`: |  | ||||||
|  |  | ||||||
| ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   echo: |  | ||||||
|     cmds: |  | ||||||
|       - cmd: exit 1 |  | ||||||
|         ignore_error: true |  | ||||||
|       - echo "Hello World" |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| `ignore_error` can also be set for a task, which mean errors will be supressed |  | ||||||
| for all commands. But keep in mind this option won't propagate to other tasks |  | ||||||
| called either by `deps` or `cmds`! |  | ||||||
|  |  | ||||||
| ## Output syntax |  | ||||||
|  |  | ||||||
| By default, Task just redirect the STDOUT and STDERR of the running commands |  | ||||||
| to the shell in real time. This is good for having live feedback for log |  | ||||||
| printed by commands, but the output can become messy if you have multiple |  | ||||||
| commands running at the same time and printing lots of stuff. |  | ||||||
|  |  | ||||||
| To make this more customizable, there are currently three different output |  | ||||||
| options you can choose: |  | ||||||
|  |  | ||||||
| - `interleaved` (default) |  | ||||||
| - `group` |  | ||||||
| - `prefixed` |  | ||||||
|  |  | ||||||
|  To choose another one, just set it to root in the Taskfile: |  | ||||||
|  |  | ||||||
|  ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| output: 'group' |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   # ... |  | ||||||
|  ``` |  | ||||||
|  |  | ||||||
|  The `group` output will print the entire output of a command once, after it |  | ||||||
|  finishes, so you won't have live feedback for commands that take a long time |  | ||||||
|  to run. |  | ||||||
|  |  | ||||||
|  The `prefix` output will prefix every line printed by a command with |  | ||||||
|  `[task-name] ` as the prefix, but you can customize the prefix for a command |  | ||||||
|  with the `prefix:` attribute: |  | ||||||
|  |  | ||||||
|  ```yml |  | ||||||
| version: '2' |  | ||||||
|  |  | ||||||
| output: prefixed |  | ||||||
|  |  | ||||||
| tasks: |  | ||||||
|   default: |  | ||||||
|     deps: |  | ||||||
|       - task: print |  | ||||||
|         vars: {TEXT: foo} |  | ||||||
|       - task: print |  | ||||||
|         vars: {TEXT: bar} |  | ||||||
|       - task: print |  | ||||||
|         vars: {TEXT: baz} |  | ||||||
|  |  | ||||||
|   print: |  | ||||||
|     cmds: |  | ||||||
|       - echo "{{.TEXT}}" |  | ||||||
|     prefix: "print-{{.TEXT}}" |  | ||||||
|     silent: true |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ```bash |  | ||||||
| $ task default |  | ||||||
| [print-foo] foo |  | ||||||
| [print-bar] bar |  | ||||||
| [print-baz] baz |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ## Watch tasks |  | ||||||
|  |  | ||||||
| If you give a `--watch` or `-w` argument, task will watch for file changes |  | ||||||
| and run the task again. This requires the `sources` attribute to be given, |  | ||||||
| so task know which files to watch. |  | ||||||
|  |  | ||||||
| ## Examples |  | ||||||
|  |  | ||||||
| The [go-task/examples][examples] intends to be a collection of Taskfiles for |  | ||||||
| various use cases. |  | ||||||
| (It still lacks many examples, though. Contributions are welcome). |  | ||||||
|  |  | ||||||
| ## Alternative task runners |  | ||||||
|  |  | ||||||
| - YAML based: |  | ||||||
|   - [rliebz/tusk][tusk] |  | ||||||
| - Go based: |  | ||||||
|   - [magefile/mage][mage] |  | ||||||
| - Make based or similar: |  | ||||||
|   - [casey/just][just] |  | ||||||
|  |  | ||||||
| ### Sponsors |  | ||||||
|  |  | ||||||
| [][opencollective] |  | ||||||
|  |  | ||||||
| ### Backers |  | ||||||
|  |  | ||||||
| [][opencollective] |  | ||||||
|  |  | ||||||
| ### Contributors |  | ||||||
|  |  | ||||||
| [][contributors] |  | ||||||
|  |  | ||||||
| [make]: https://www.gnu.org/software/make/ | [make]: https://www.gnu.org/software/make/ | ||||||
| [releases]: https://github.com/go-task/task/releases |  | ||||||
| [golang]: https://golang.org/ |  | ||||||
| [gotemplate]: https://golang.org/pkg/text/template/ |  | ||||||
| [tusk]: https://github.com/rliebz/tusk |  | ||||||
| [mage]: https://github.com/magefile/mage |  | ||||||
| [just]: https://github.com/casey/just |  | ||||||
| [sh]: https://github.com/mvdan/sh |  | ||||||
| [minify]: https://github.com/tdewolff/minify/tree/master/cmd/minify |  | ||||||
| [examples]: https://github.com/go-task/examples |  | ||||||
| [snapcraft]: https://snapcraft.io/ |  | ||||||
| [homebrew]: https://brew.sh/ |  | ||||||
| [installscript]: https://github.com/go-task/task/blob/master/install-task.sh |  | ||||||
| [godownloader]: https://github.com/goreleaser/godownloader |  | ||||||
| [opencollective]: https://opencollective.com/task |  | ||||||
| [contributors]: https://github.com/go-task/task/graphs/contributors |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								Taskfile.yml
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Taskfile.yml
									
									
									
									
									
								
							| @@ -60,9 +60,10 @@ tasks: | |||||||
|       - goreleaser --snapshot --rm-dist |       - goreleaser --snapshot --rm-dist | ||||||
|  |  | ||||||
|   generate-install-script: |   generate-install-script: | ||||||
|     desc: Generate install script using https://githbub.com/goreleaser/godownloader |     desc: Generate install script using https://github.com/goreleaser/godownloader | ||||||
|     cmds: |     cmds: | ||||||
|       - godownloader --repo go-task/task -o install-task.sh |       - godownloader --repo go-task/task -o install-task.sh | ||||||
|  |       - cp ./install-task.sh ./docs/install.sh | ||||||
|  |  | ||||||
|   ci: |   ci: | ||||||
|     cmds: |     cmds: | ||||||
| @@ -79,3 +80,13 @@ tasks: | |||||||
|     cmds: |     cmds: | ||||||
|       - echo '{{.GO_PACKAGES}}' |       - echo '{{.GO_PACKAGES}}' | ||||||
|     silent: true |     silent: true | ||||||
|  |  | ||||||
|  |   docs:install: | ||||||
|  |     desc: Installs docsify to work the on the documentation site | ||||||
|  |     cmds: | ||||||
|  |       - npm install docsify-cli -g | ||||||
|  |  | ||||||
|  |   docs:serve: | ||||||
|  |     desc: Serves the documentation site locally | ||||||
|  |     cmds: | ||||||
|  |       - docsify serve docs | ||||||
|   | |||||||
| @@ -87,6 +87,11 @@ func main() { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	if !watch { | ||||||
|  | 		ctx = getSignalContext() | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	e := task.Executor{ | 	e := task.Executor{ | ||||||
| 		Force:   force, | 		Force:   force, | ||||||
| 		Watch:   watch, | 		Watch:   watch, | ||||||
| @@ -95,7 +100,7 @@ func main() { | |||||||
| 		Dir:     dir, | 		Dir:     dir, | ||||||
| 		Dry:     dry, | 		Dry:     dry, | ||||||
|  |  | ||||||
| 		Context: getSignalContext(), | 		Context: ctx, | ||||||
|  |  | ||||||
| 		Stdin:  os.Stdin, | 		Stdin:  os.Stdin, | ||||||
| 		Stdout: os.Stdout, | 		Stdout: os.Stdout, | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								docs/.nojekyll
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								docs/.nojekyll
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								docs/CNAME
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/CNAME
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | taskfile.org | ||||||
							
								
								
									
										46
									
								
								docs/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								docs/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | # Task | ||||||
|  |  | ||||||
|  | Task is a task runner / build tool that aims to be simpler and easier to use | ||||||
|  | than, for example, [GNU Make][make]. | ||||||
|  |  | ||||||
|  | Since it's written in [Go][go], Task is just a single binary and has no other | ||||||
|  | dependencies, which means you don't need to mess with any complicated install | ||||||
|  | setups just to use a build tool. | ||||||
|  |  | ||||||
|  | Once [installed](installation), you just need to describe your build tasks | ||||||
|  | using a simple [YAML][yaml] schema in a file called `Taskfile.yml`: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   hello: | ||||||
|  |     cmds: | ||||||
|  |       - echo 'Hello World from Task!' | ||||||
|  |     silent: true | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | And call it by running `task hello` from you terminal. | ||||||
|  |  | ||||||
|  | The above example is just the start, you can take a look at the [usage](usage) | ||||||
|  | guide to check the full schema documentation and Task features. | ||||||
|  |  | ||||||
|  | ## Features | ||||||
|  |  | ||||||
|  | - [Easy installation](installation): just download a single binary, add to | ||||||
|  |   $PATH and you're done! Or you can also install using [Homebrew][homebrew] or | ||||||
|  |   [Snapcraft][snapcraft] if you want; | ||||||
|  | - Available on CIs: by adding [this simple command](installation#install-script) | ||||||
|  |   to install on your CI script and you're done to use Task as part of your CI pipeline; | ||||||
|  | - Truly cross-platform: while most build tools only work well on Linux or macOS, | ||||||
|  |   Task also supports Windows thanks to [this awesome shell interpreter for Go][sh]; | ||||||
|  | - Great for code generation: you can easily [prevent a task from running](usage#prevent-unnecessary-work) | ||||||
|  |   if a given set of files haven't changed since last run (based either on its | ||||||
|  |   timestamp or content). | ||||||
|  |  | ||||||
|  | [make]: https://www.gnu.org/software/make/ | ||||||
|  | [go]: https://golang.org/ | ||||||
|  | [yaml]: http://yaml.org/ | ||||||
|  | [homebrew]: https://brew.sh/ | ||||||
|  | [snapcraft]: https://snapcraft.io/ | ||||||
|  | [sh]: https://mvdan.cc/sh | ||||||
							
								
								
									
										8
									
								
								docs/_sidebar.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/_sidebar.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | - [Installation](installation) | ||||||
|  | - [Usage](usage) | ||||||
|  | - [Taskfile Versions](taskfile_versions) | ||||||
|  | - [Examples](examples) | ||||||
|  | - [Releasing Task](releasing_task) | ||||||
|  | - [Alternative Task Runners](alternative_task_runners) | ||||||
|  | - [Sponsors and Backers](sponsors_and_backers) | ||||||
|  | - [Github](https://github.com/go-task/task) | ||||||
							
								
								
									
										17
									
								
								docs/alternative_task_runners.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								docs/alternative_task_runners.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | # Alternative task runners | ||||||
|  |  | ||||||
|  | ## YAML based | ||||||
|  |  | ||||||
|  | - [rliebz/tusk][tusk] | ||||||
|  |  | ||||||
|  | ## Go based | ||||||
|  |  | ||||||
|  | - [magefile/mage][mage] | ||||||
|  |  | ||||||
|  | ## Make similar | ||||||
|  |  | ||||||
|  | - [casey/just][just] | ||||||
|  |  | ||||||
|  | [tusk]: https://github.com/rliebz/tusk | ||||||
|  | [mage]: https://github.com/magefile/mage | ||||||
|  | [just]: https://github.com/casey/just | ||||||
							
								
								
									
										7
									
								
								docs/examples.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								docs/examples.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | # Examples | ||||||
|  |  | ||||||
|  | The [go-task/examples][examples] intends to be a collection of Taskfiles for | ||||||
|  | various use cases. | ||||||
|  | (It still lacks many examples, though. Contributions are welcome). | ||||||
|  |  | ||||||
|  | [examples]: https://github.com/go-task/examples | ||||||
							
								
								
									
										
											BIN
										
									
								
								docs/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 136 KiB | 
							
								
								
									
										31
									
								
								docs/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								docs/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="en"> | ||||||
|  |   <head> | ||||||
|  |     <meta charset="UTF-8"> | ||||||
|  |     <title>Task</title> | ||||||
|  |     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> | ||||||
|  |     <meta name="description" content="A task runner / simpler Make alternative written in Go"> | ||||||
|  |     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | ||||||
|  |     <link rel="stylesheet" href="//unpkg.com/docsify-themeable/dist/css/theme-simple.css"> | ||||||
|  |   </head> | ||||||
|  |   <body> | ||||||
|  |     <div id="app"></div> | ||||||
|  |     <script> | ||||||
|  |       window.$docsify = { | ||||||
|  |         name: 'Task', | ||||||
|  |         repo: 'go-task/task', | ||||||
|  |         ga: 'UA-126286662-1', | ||||||
|  |         themeColor: '#83d0f2', | ||||||
|  |         loadSidebar: true, | ||||||
|  |         auto2top: true, | ||||||
|  |         maxLevel: 3, | ||||||
|  |         subMaxLevel: 3 | ||||||
|  |       } | ||||||
|  |     </script> | ||||||
|  |     <script src="//unpkg.com/docsify/lib/docsify.min.js"></script> | ||||||
|  |     <script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script> | ||||||
|  |     <script src="//unpkg.com/docsify-themeable"></script> | ||||||
|  |     <script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script> | ||||||
|  |     <script src="//unpkg.com/prismjs/components/prism-yaml.min.js"></script> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										390
									
								
								docs/install.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										390
									
								
								docs/install.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,390 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | set -e | ||||||
|  | # Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | usage() { | ||||||
|  |   this=$1 | ||||||
|  |   cat <<EOF | ||||||
|  | $this: download go binaries for go-task/task | ||||||
|  |  | ||||||
|  | Usage: $this [-b] bindir [-d] [tag] | ||||||
|  |   -b sets bindir or installation directory, Defaults to ./bin | ||||||
|  |   -d turns on debug logging | ||||||
|  |    [tag] is a tag from | ||||||
|  |    https://github.com/go-task/task/releases | ||||||
|  |    If tag is missing, then the latest will be used. | ||||||
|  |  | ||||||
|  |  Generated by godownloader | ||||||
|  |   https://github.com/goreleaser/godownloader | ||||||
|  |  | ||||||
|  | EOF | ||||||
|  |   exit 2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | parse_args() { | ||||||
|  |   #BINDIR is ./bin unless set be ENV | ||||||
|  |   # over-ridden by flag below | ||||||
|  |  | ||||||
|  |   BINDIR=${BINDIR:-./bin} | ||||||
|  |   while getopts "b:dh?" arg; do | ||||||
|  |     case "$arg" in | ||||||
|  |       b) BINDIR="$OPTARG" ;; | ||||||
|  |       d) log_set_priority 10 ;; | ||||||
|  |       h | \?) usage "$0" ;; | ||||||
|  |     esac | ||||||
|  |   done | ||||||
|  |   shift $((OPTIND - 1)) | ||||||
|  |   TAG=$1 | ||||||
|  | } | ||||||
|  | # this function wraps all the destructive operations | ||||||
|  | # if a curl|bash cuts off the end of the script due to | ||||||
|  | # network, either nothing will happen or will syntax error | ||||||
|  | # out preventing half-done work | ||||||
|  | execute() { | ||||||
|  |   tmpdir=$(mktmpdir) | ||||||
|  |   log_debug "downloading files into ${tmpdir}" | ||||||
|  |   http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}" | ||||||
|  |   http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}" | ||||||
|  |   hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}" | ||||||
|  |   srcdir="${tmpdir}" | ||||||
|  |   (cd "${tmpdir}" && untar "${TARBALL}") | ||||||
|  |   install -d "${BINDIR}" | ||||||
|  |   for binexe in "task" ; do | ||||||
|  |     if [ "$OS" = "windows" ]; then | ||||||
|  |       binexe="${binexe}.exe" | ||||||
|  |     fi | ||||||
|  |     install "${srcdir}/${binexe}" "${BINDIR}/" | ||||||
|  |     log_info "installed ${BINDIR}/${binexe}" | ||||||
|  |   done | ||||||
|  | } | ||||||
|  | is_supported_platform() { | ||||||
|  |   platform=$1 | ||||||
|  |   found=1 | ||||||
|  |   case "$platform" in | ||||||
|  |     windows/386) found=0 ;; | ||||||
|  |     windows/amd64) found=0 ;; | ||||||
|  |     darwin/386) found=0 ;; | ||||||
|  |     darwin/amd64) found=0 ;; | ||||||
|  |     linux/386) found=0 ;; | ||||||
|  |     linux/amd64) found=0 ;; | ||||||
|  |   esac | ||||||
|  |   case "$platform" in | ||||||
|  |     darwin/386) found=1 ;; | ||||||
|  |   esac | ||||||
|  |   return $found | ||||||
|  | } | ||||||
|  | check_platform() { | ||||||
|  |   if is_supported_platform "$PLATFORM"; then | ||||||
|  |     # optional logging goes here | ||||||
|  |     true | ||||||
|  |   else | ||||||
|  |     log_crit "platform $PLATFORM is not supported.  Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new" | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | tag_to_version() { | ||||||
|  |   if [ -z "${TAG}" ]; then | ||||||
|  |     log_info "checking GitHub for latest tag" | ||||||
|  |   else | ||||||
|  |     log_info "checking GitHub for tag '${TAG}'" | ||||||
|  |   fi | ||||||
|  |   REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true | ||||||
|  |   if test -z "$REALTAG"; then | ||||||
|  |     log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details" | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  |   # if version starts with 'v', remove it | ||||||
|  |   TAG="$REALTAG" | ||||||
|  |   VERSION=${TAG#v} | ||||||
|  | } | ||||||
|  | adjust_format() { | ||||||
|  |   # change format (tar.gz or zip) based on ARCH | ||||||
|  |   case ${ARCH} in | ||||||
|  |     windows) FORMAT=zip ;; | ||||||
|  |   esac | ||||||
|  |   true | ||||||
|  | } | ||||||
|  | adjust_os() { | ||||||
|  |   # adjust archive name based on OS | ||||||
|  |   true | ||||||
|  | } | ||||||
|  | adjust_arch() { | ||||||
|  |   # adjust archive name based on ARCH | ||||||
|  |   true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | cat /dev/null <<EOF | ||||||
|  | ------------------------------------------------------------------------ | ||||||
|  | https://github.com/client9/shlib - portable posix shell functions | ||||||
|  | Public domain - http://unlicense.org | ||||||
|  | https://github.com/client9/shlib/blob/master/LICENSE.md | ||||||
|  | but credit (and pull requests) appreciated. | ||||||
|  | ------------------------------------------------------------------------ | ||||||
|  | EOF | ||||||
|  | is_command() { | ||||||
|  |   command -v "$1" >/dev/null | ||||||
|  | } | ||||||
|  | echoerr() { | ||||||
|  |   echo "$@" 1>&2 | ||||||
|  | } | ||||||
|  | log_prefix() { | ||||||
|  |   echo "$0" | ||||||
|  | } | ||||||
|  | _logp=6 | ||||||
|  | log_set_priority() { | ||||||
|  |   _logp="$1" | ||||||
|  | } | ||||||
|  | log_priority() { | ||||||
|  |   if test -z "$1"; then | ||||||
|  |     echo "$_logp" | ||||||
|  |     return | ||||||
|  |   fi | ||||||
|  |   [ "$1" -le "$_logp" ] | ||||||
|  | } | ||||||
|  | log_tag() { | ||||||
|  |   case $1 in | ||||||
|  |     0) echo "emerg" ;; | ||||||
|  |     1) echo "alert" ;; | ||||||
|  |     2) echo "crit" ;; | ||||||
|  |     3) echo "err" ;; | ||||||
|  |     4) echo "warning" ;; | ||||||
|  |     5) echo "notice" ;; | ||||||
|  |     6) echo "info" ;; | ||||||
|  |     7) echo "debug" ;; | ||||||
|  |     *) echo "$1" ;; | ||||||
|  |   esac | ||||||
|  | } | ||||||
|  | log_debug() { | ||||||
|  |   log_priority 7 || return 0 | ||||||
|  |   echoerr "$(log_prefix)" "$(log_tag 7)" "$@" | ||||||
|  | } | ||||||
|  | log_info() { | ||||||
|  |   log_priority 6 || return 0 | ||||||
|  |   echoerr "$(log_prefix)" "$(log_tag 6)" "$@" | ||||||
|  | } | ||||||
|  | log_err() { | ||||||
|  |   log_priority 3 || return 0 | ||||||
|  |   echoerr "$(log_prefix)" "$(log_tag 3)" "$@" | ||||||
|  | } | ||||||
|  | log_crit() { | ||||||
|  |   log_priority 2 || return 0 | ||||||
|  |   echoerr "$(log_prefix)" "$(log_tag 2)" "$@" | ||||||
|  | } | ||||||
|  | uname_os() { | ||||||
|  |   os=$(uname -s | tr '[:upper:]' '[:lower:]') | ||||||
|  |   case "$os" in | ||||||
|  |     msys_nt) os="windows" ;; | ||||||
|  |   esac | ||||||
|  |   echo "$os" | ||||||
|  | } | ||||||
|  | uname_arch() { | ||||||
|  |   arch=$(uname -m) | ||||||
|  |   case $arch in | ||||||
|  |     x86_64) arch="amd64" ;; | ||||||
|  |     x86) arch="386" ;; | ||||||
|  |     i686) arch="386" ;; | ||||||
|  |     i386) arch="386" ;; | ||||||
|  |     aarch64) arch="arm64" ;; | ||||||
|  |     armv5*) arch="arm5" ;; | ||||||
|  |     armv6*) arch="arm6" ;; | ||||||
|  |     armv7*) arch="arm7" ;; | ||||||
|  |   esac | ||||||
|  |   echo ${arch} | ||||||
|  | } | ||||||
|  | uname_os_check() { | ||||||
|  |   os=$(uname_os) | ||||||
|  |   case "$os" in | ||||||
|  |     darwin) return 0 ;; | ||||||
|  |     dragonfly) return 0 ;; | ||||||
|  |     freebsd) return 0 ;; | ||||||
|  |     linux) return 0 ;; | ||||||
|  |     android) return 0 ;; | ||||||
|  |     nacl) return 0 ;; | ||||||
|  |     netbsd) return 0 ;; | ||||||
|  |     openbsd) return 0 ;; | ||||||
|  |     plan9) return 0 ;; | ||||||
|  |     solaris) return 0 ;; | ||||||
|  |     windows) return 0 ;; | ||||||
|  |   esac | ||||||
|  |   log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib" | ||||||
|  |   return 1 | ||||||
|  | } | ||||||
|  | uname_arch_check() { | ||||||
|  |   arch=$(uname_arch) | ||||||
|  |   case "$arch" in | ||||||
|  |     386) return 0 ;; | ||||||
|  |     amd64) return 0 ;; | ||||||
|  |     arm64) return 0 ;; | ||||||
|  |     armv5) return 0 ;; | ||||||
|  |     armv6) return 0 ;; | ||||||
|  |     armv7) return 0 ;; | ||||||
|  |     ppc64) return 0 ;; | ||||||
|  |     ppc64le) return 0 ;; | ||||||
|  |     mips) return 0 ;; | ||||||
|  |     mipsle) return 0 ;; | ||||||
|  |     mips64) return 0 ;; | ||||||
|  |     mips64le) return 0 ;; | ||||||
|  |     s390x) return 0 ;; | ||||||
|  |     amd64p32) return 0 ;; | ||||||
|  |   esac | ||||||
|  |   log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value.  Please file bug report at https://github.com/client9/shlib" | ||||||
|  |   return 1 | ||||||
|  | } | ||||||
|  | untar() { | ||||||
|  |   tarball=$1 | ||||||
|  |   case "${tarball}" in | ||||||
|  |     *.tar.gz | *.tgz) tar -xzf "${tarball}" ;; | ||||||
|  |     *.tar) tar -xf "${tarball}" ;; | ||||||
|  |     *.zip) unzip "${tarball}" ;; | ||||||
|  |     *) | ||||||
|  |       log_err "untar unknown archive format for ${tarball}" | ||||||
|  |       return 1 | ||||||
|  |       ;; | ||||||
|  |   esac | ||||||
|  | } | ||||||
|  | mktmpdir() { | ||||||
|  |   test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" | ||||||
|  |   mkdir -p "${TMPDIR}" | ||||||
|  |   echo "${TMPDIR}" | ||||||
|  | } | ||||||
|  | http_download_curl() { | ||||||
|  |   local_file=$1 | ||||||
|  |   source_url=$2 | ||||||
|  |   header=$3 | ||||||
|  |   if [ -z "$header" ]; then | ||||||
|  |     code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url") | ||||||
|  |   else | ||||||
|  |     code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url") | ||||||
|  |   fi | ||||||
|  |   if [ "$code" != "200" ]; then | ||||||
|  |     log_debug "http_download_curl received HTTP status $code" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  |   return 0 | ||||||
|  | } | ||||||
|  | http_download_wget() { | ||||||
|  |   local_file=$1 | ||||||
|  |   source_url=$2 | ||||||
|  |   header=$3 | ||||||
|  |   if [ -z "$header" ]; then | ||||||
|  |     wget -q -O "$local_file" "$source_url" | ||||||
|  |   else | ||||||
|  |     wget -q --header "$header" -O "$local_file" "$source_url" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | http_download() { | ||||||
|  |   log_debug "http_download $2" | ||||||
|  |   if is_command curl; then | ||||||
|  |     http_download_curl "$@" | ||||||
|  |     return | ||||||
|  |   elif is_command wget; then | ||||||
|  |     http_download_wget "$@" | ||||||
|  |     return | ||||||
|  |   fi | ||||||
|  |   log_crit "http_download unable to find wget or curl" | ||||||
|  |   return 1 | ||||||
|  | } | ||||||
|  | http_copy() { | ||||||
|  |   tmp=$(mktemp) | ||||||
|  |   http_download "${tmp}" "$1" "$2" || return 1 | ||||||
|  |   body=$(cat "$tmp") | ||||||
|  |   rm -f "${tmp}" | ||||||
|  |   echo "$body" | ||||||
|  | } | ||||||
|  | github_release() { | ||||||
|  |   owner_repo=$1 | ||||||
|  |   version=$2 | ||||||
|  |   test -z "$version" && version="latest" | ||||||
|  |   giturl="https://github.com/${owner_repo}/releases/${version}" | ||||||
|  |   json=$(http_copy "$giturl" "Accept:application/json") | ||||||
|  |   test -z "$json" && return 1 | ||||||
|  |   version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') | ||||||
|  |   test -z "$version" && return 1 | ||||||
|  |   echo "$version" | ||||||
|  | } | ||||||
|  | hash_sha256() { | ||||||
|  |   TARGET=${1:-/dev/stdin} | ||||||
|  |   if is_command gsha256sum; then | ||||||
|  |     hash=$(gsha256sum "$TARGET") || return 1 | ||||||
|  |     echo "$hash" | cut -d ' ' -f 1 | ||||||
|  |   elif is_command sha256sum; then | ||||||
|  |     hash=$(sha256sum "$TARGET") || return 1 | ||||||
|  |     echo "$hash" | cut -d ' ' -f 1 | ||||||
|  |   elif is_command shasum; then | ||||||
|  |     hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 | ||||||
|  |     echo "$hash" | cut -d ' ' -f 1 | ||||||
|  |   elif is_command openssl; then | ||||||
|  |     hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 | ||||||
|  |     echo "$hash" | cut -d ' ' -f a | ||||||
|  |   else | ||||||
|  |     log_crit "hash_sha256 unable to find command to compute sha-256 hash" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | hash_sha256_verify() { | ||||||
|  |   TARGET=$1 | ||||||
|  |   checksums=$2 | ||||||
|  |   if [ -z "$checksums" ]; then | ||||||
|  |     log_err "hash_sha256_verify checksum file not specified in arg2" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  |   BASENAME=${TARGET##*/} | ||||||
|  |   want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) | ||||||
|  |   if [ -z "$want" ]; then | ||||||
|  |     log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  |   got=$(hash_sha256 "$TARGET") | ||||||
|  |   if [ "$want" != "$got" ]; then | ||||||
|  |     log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | cat /dev/null <<EOF | ||||||
|  | ------------------------------------------------------------------------ | ||||||
|  | End of functions from https://github.com/client9/shlib | ||||||
|  | ------------------------------------------------------------------------ | ||||||
|  | EOF | ||||||
|  |  | ||||||
|  | PROJECT_NAME="task" | ||||||
|  | OWNER=go-task | ||||||
|  | REPO="task" | ||||||
|  | BINARY=task | ||||||
|  | FORMAT=tar.gz | ||||||
|  | OS=$(uname_os) | ||||||
|  | ARCH=$(uname_arch) | ||||||
|  | PREFIX="$OWNER/$REPO" | ||||||
|  |  | ||||||
|  | # use in logging routines | ||||||
|  | log_prefix() { | ||||||
|  | 	echo "$PREFIX" | ||||||
|  | } | ||||||
|  | PLATFORM="${OS}/${ARCH}" | ||||||
|  | GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download | ||||||
|  |  | ||||||
|  | uname_os_check "$OS" | ||||||
|  | uname_arch_check "$ARCH" | ||||||
|  |  | ||||||
|  | parse_args "$@" | ||||||
|  |  | ||||||
|  | check_platform | ||||||
|  |  | ||||||
|  | tag_to_version | ||||||
|  |  | ||||||
|  | adjust_format | ||||||
|  |  | ||||||
|  | adjust_os | ||||||
|  |  | ||||||
|  | adjust_arch | ||||||
|  |  | ||||||
|  | log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}" | ||||||
|  |  | ||||||
|  | NAME=${BINARY}_${OS}_${ARCH} | ||||||
|  | TARBALL=${NAME}.${FORMAT} | ||||||
|  | TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL} | ||||||
|  | CHECKSUM=task_checksums.txt | ||||||
|  | CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | execute | ||||||
							
								
								
									
										53
									
								
								docs/installation.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								docs/installation.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | # Installation | ||||||
|  |  | ||||||
|  | ## Binary | ||||||
|  |  | ||||||
|  | Or you can download the binary from the [releases][releases] page and add to | ||||||
|  | your $PATH. DEB and RPM packages are also available. | ||||||
|  | The `task_checksums.txt` file contains the sha256 checksum for each file. | ||||||
|  |  | ||||||
|  | ## Homebrew | ||||||
|  |  | ||||||
|  | If you're on macOS and have [Homebrew][homebrew] installed, getting Task is | ||||||
|  | as simple as running: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | brew install go-task/tap/go-task | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Snap | ||||||
|  |  | ||||||
|  | Task is available for [Snapcraft][snapcraft], but keep in mind that your | ||||||
|  | Linux distribution should allow classic confinement for Snaps to Task work | ||||||
|  | right: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | sudo snap install task | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Go | ||||||
|  |  | ||||||
|  | If you have a [Go][go] environment setup, you can simply run: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | go get -u -v github.com/go-task/task/cmd/task | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Install script | ||||||
|  |  | ||||||
|  | We also have a [install script][installscript], which is very useful on | ||||||
|  | scanarios like CIs. Many thanks to [godownloader][godownloader] for allowing | ||||||
|  | easily generating this script. | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | curl -s https://taskfile.org/install.sh | sh | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | > This method will download the binary on the local `./bin` directory by default. | ||||||
|  |  | ||||||
|  | [go]: https://golang.org/ | ||||||
|  | [snapcraft]: https://snapcraft.io/ | ||||||
|  | [homebrew]: https://brew.sh/ | ||||||
|  | [installscript]: https://github.com/go-task/task/blob/master/install-task.sh | ||||||
|  | [releases]: https://github.com/go-task/task/releases | ||||||
|  | [godownloader]: https://github.com/goreleaser/godownloader | ||||||
							
								
								
									
										16
									
								
								docs/sponsors_and_backers.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								docs/sponsors_and_backers.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | # Sponsors and Backers | ||||||
|  |  | ||||||
|  | ## Sponsors | ||||||
|  |  | ||||||
|  | [][opencollective] | ||||||
|  |  | ||||||
|  | ## Backers | ||||||
|  |  | ||||||
|  | [][opencollective] | ||||||
|  |  | ||||||
|  | ## Contributors | ||||||
|  |  | ||||||
|  | [][contributors] | ||||||
|  |  | ||||||
|  | [opencollective]: https://opencollective.com/task | ||||||
|  | [contributors]: https://github.com/go-task/task/graphs/contributors | ||||||
| @@ -1,9 +1,9 @@ | |||||||
| # Taskfile version | # Taskfile Versions | ||||||
| 
 | 
 | ||||||
| The Taskfile syntax and features changed with time. This document explains what | The Taskfile syntax and features changed with time. This document explains what | ||||||
| changed on each version and how to upgrade your Taskfile. | changed on each version and how to upgrade your Taskfile. | ||||||
| 
 | 
 | ||||||
| # What the Taskfile version mean | ## What the Taskfile version mean | ||||||
| 
 | 
 | ||||||
| The Taskfile version follows the Task version. E.g. the change to Taskfile | The Taskfile version follows the Task version. E.g. the change to Taskfile | ||||||
| version `2` means that Task `v2.0.0` should be release to support it. | version `2` means that Task `v2.0.0` should be release to support it. | ||||||
| @@ -18,7 +18,7 @@ available, but not `3.0.0+`. | |||||||
| In the first version of the `Taskfile`, the `version:` key was not available, | In the first version of the `Taskfile`, the `version:` key was not available, | ||||||
| because the tasks was in the root of the YAML document. Like this: | because the tasks was in the root of the YAML document. Like this: | ||||||
| 
 | 
 | ||||||
| ```yml | ```yaml | ||||||
| echo: | echo: | ||||||
|   cmds: |   cmds: | ||||||
|     - echo "Hello, World!" |     - echo "Hello, World!" | ||||||
| @@ -37,7 +37,7 @@ At version 2, we introduced the `version:` key, to allow us to envolve Task | |||||||
| with new features without breaking existing Taskfiles. The new syntax is as | with new features without breaking existing Taskfiles. The new syntax is as | ||||||
| follows: | follows: | ||||||
| 
 | 
 | ||||||
| ```yml | ```yaml | ||||||
| version: '2' | version: '2' | ||||||
| 
 | 
 | ||||||
| tasks: | tasks: | ||||||
| @@ -49,7 +49,7 @@ tasks: | |||||||
| Version 2 allows you to write global variables directly in the Taskfile, | Version 2 allows you to write global variables directly in the Taskfile, | ||||||
| if you don't want to create a `Taskvars.yml`: | if you don't want to create a `Taskvars.yml`: | ||||||
| 
 | 
 | ||||||
| ```yml | ```yaml | ||||||
| version: '2' | version: '2' | ||||||
| 
 | 
 | ||||||
| vars: | vars: | ||||||
| @@ -72,7 +72,7 @@ The variable priority order changed to the following: | |||||||
| A new global option was added to configure the number of variables expansions | A new global option was added to configure the number of variables expansions | ||||||
| (which default to 2): | (which default to 2): | ||||||
| 
 | 
 | ||||||
| ```yml | ```yaml | ||||||
| version: '2' | version: '2' | ||||||
| 
 | 
 | ||||||
| expansions: 3 | expansions: 3 | ||||||
| @@ -96,7 +96,7 @@ Version 2.1 includes a global `output` option, to allow having more control | |||||||
| over how commands output are printed to the console | over how commands output are printed to the console | ||||||
| (see [documentation][output] for more info): | (see [documentation][output] for more info): | ||||||
| 
 | 
 | ||||||
| ```yml | ```yaml | ||||||
| version: '2' | version: '2' | ||||||
| 
 | 
 | ||||||
| output: prefixed | output: prefixed | ||||||
| @@ -109,9 +109,9 @@ tasks: | |||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| From this version it's not also possible to ignore errors of a command or task | From this version it's not also possible to ignore errors of a command or task | ||||||
| (check documentatio [here][ignore_errors]): | (check documentation [here][ignore_errors]): | ||||||
| 
 | 
 | ||||||
| ```yml | ```yaml | ||||||
| version: '2' | version: '2' | ||||||
| 
 | 
 | ||||||
| tasks: | tasks: | ||||||
							
								
								
									
										669
									
								
								docs/usage.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										669
									
								
								docs/usage.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,669 @@ | |||||||
|  | # Usage | ||||||
|  |  | ||||||
|  | ## Getting started | ||||||
|  |  | ||||||
|  | Create a file called `Taskfile.yml` in the root of your project. | ||||||
|  | The `cmds` attribute should contain the commands of a task. | ||||||
|  | The example below allows compiling a Go app and uses [Minify][minify] to concat | ||||||
|  | and minify multiple CSS files into a single one. | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     cmds: | ||||||
|  |       - go build -v -i main.go | ||||||
|  |  | ||||||
|  |   assets: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/style.css src/css | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Running the tasks is as simple as running: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | task assets build | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Task uses [github.com/mvdan/sh](https://github.com/mvdan/sh), a native Go sh | ||||||
|  | interpreter. So you can write sh/bash commands and it will work even on | ||||||
|  | Windows, where `sh` or `bash` are usually not available. Just remember any | ||||||
|  | executable called must be available by the OS or in PATH. | ||||||
|  |  | ||||||
|  | If you ommit a task name, "default" will be assumed. | ||||||
|  |  | ||||||
|  | ## Environment | ||||||
|  |  | ||||||
|  | You can specify environment variables that are added when running a command: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     cmds: | ||||||
|  |       - echo $hallo | ||||||
|  |     env: | ||||||
|  |       hallo: welt | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## OS specific task | ||||||
|  |  | ||||||
|  | If you add a `Taskfile_{{GOOS}}.yml` you can override or amend your Taskfile | ||||||
|  | based on the operating system. | ||||||
|  |  | ||||||
|  | Example: | ||||||
|  |  | ||||||
|  | Taskfile.yml: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     cmds: | ||||||
|  |       - echo "default" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Taskfile_linux.yml: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     cmds: | ||||||
|  |       - echo "linux" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Will print out `linux` and not `default`. | ||||||
|  |  | ||||||
|  | Keep in mind that the version of the files should match. Also, when redefining | ||||||
|  | a task the whole task is replaced, properties of the task are not merged. | ||||||
|  |  | ||||||
|  | It's also possible to have an OS specific `Taskvars.yml` file, like | ||||||
|  | `Taskvars_windows.yml`, `Taskfile_linux.yml`, or `Taskvars_darwin.yml`. See the | ||||||
|  | [variables section](#variables) below. | ||||||
|  |  | ||||||
|  | ## Task directory | ||||||
|  |  | ||||||
|  | By default, tasks will be executed in the directory where the Taskfile is | ||||||
|  | located. But you can easily make the task run in another folder informing | ||||||
|  | `dir`: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   serve: | ||||||
|  |     dir: public/www | ||||||
|  |     cmds: | ||||||
|  |       # run http server | ||||||
|  |       - caddy | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Task dependencies | ||||||
|  |  | ||||||
|  | You may have tasks that depend on others. Just pointing them on `deps` will | ||||||
|  | make them run automatically before running the parent task: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     deps: [assets] | ||||||
|  |     cmds: | ||||||
|  |       - go build -v -i main.go | ||||||
|  |  | ||||||
|  |   assets: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/style.css src/css | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | In the above example, `assets` will always run right before `build` if you run | ||||||
|  | `task build`. | ||||||
|  |  | ||||||
|  | A task can have only dependencies and no commands to group tasks together: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   assets: | ||||||
|  |     deps: [js, css] | ||||||
|  |  | ||||||
|  |   js: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/script.js src/js | ||||||
|  |  | ||||||
|  |   css: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/style.css src/css | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | If there is more than one dependency, they always run in parallel for better | ||||||
|  | performance. | ||||||
|  |  | ||||||
|  | If you want to pass information to dependencies, you can do that the same | ||||||
|  | manner as you would to [call another task](#calling-another-task): | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   default: | ||||||
|  |     deps: | ||||||
|  |       - task: echo_sth | ||||||
|  |         vars: {TEXT: "before 1"} | ||||||
|  |       - task: echo_sth | ||||||
|  |         vars: {TEXT: "before 2"} | ||||||
|  |     cmds: | ||||||
|  |       - echo "after" | ||||||
|  |  | ||||||
|  |   echo_sth: | ||||||
|  |     cmds: | ||||||
|  |       - echo {{.TEXT}} | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Calling another task | ||||||
|  |  | ||||||
|  | When a task has many dependencies, they are executed concurrently. This will | ||||||
|  | often result in a faster build pipeline. But in some situations you may need | ||||||
|  | to call other tasks serially. In this case, just use the following syntax: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   main-task: | ||||||
|  |     cmds: | ||||||
|  |       - task: task-to-be-called | ||||||
|  |       - task: another-task | ||||||
|  |       - echo "Both done" | ||||||
|  |  | ||||||
|  |   task-to-be-called: | ||||||
|  |     cmds: | ||||||
|  |       - echo "Task to be called" | ||||||
|  |  | ||||||
|  |   another-task: | ||||||
|  |     cmds: | ||||||
|  |       - echo "Another task" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Overriding variables in the called task is as simple as informing `vars` | ||||||
|  | attribute: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   main-task: | ||||||
|  |     cmds: | ||||||
|  |       - task: write-file | ||||||
|  |         vars: {FILE: "hello.txt", CONTENT: "Hello!"} | ||||||
|  |       - task: write-file | ||||||
|  |         vars: {FILE: "world.txt", CONTENT: "World!"} | ||||||
|  |  | ||||||
|  |   write-file: | ||||||
|  |     cmds: | ||||||
|  |       - echo "{{.CONTENT}}" > {{.FILE}} | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | The above syntax is also supported in `deps`. | ||||||
|  |  | ||||||
|  | ## Prevent unnecessary work | ||||||
|  |  | ||||||
|  | If a task generates something, you can inform Task the source and generated | ||||||
|  | files, so Task will prevent to run them if not necessary. | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     deps: [js, css] | ||||||
|  |     cmds: | ||||||
|  |       - go build -v -i main.go | ||||||
|  |  | ||||||
|  |   js: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/script.js src/js | ||||||
|  |     sources: | ||||||
|  |       - src/js/**/*.js | ||||||
|  |     generates: | ||||||
|  |       - public/script.js | ||||||
|  |  | ||||||
|  |   css: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/style.css src/css | ||||||
|  |     sources: | ||||||
|  |       - src/css/**/*.css | ||||||
|  |     generates: | ||||||
|  |       - public/style.css | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | `sources` and `generates` can be files or file patterns. When both are given, | ||||||
|  | Task will compare the modification date/time of the files to determine if it's | ||||||
|  | necessary to run the task. If not, it will just print a message like | ||||||
|  | `Task "js" is up to date`. | ||||||
|  |  | ||||||
|  | If you prefer this check to be made by the content of the files, instead of | ||||||
|  | its timestamp, just set the `method` property to `checksum`. | ||||||
|  | You will probably want to ignore the `.task` folder in your `.gitignore` file | ||||||
|  | (It's there that Task stores the last checksum). | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     cmds: | ||||||
|  |       - go build . | ||||||
|  |     sources: | ||||||
|  |       - ./*.go | ||||||
|  |     generates: | ||||||
|  |       - app{{exeExt}} | ||||||
|  |     method: checksum | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | > TIP: method `none` skips any validation and always run the task. | ||||||
|  |  | ||||||
|  | Alternatively, you can inform a sequence of tests as `status`. If no error | ||||||
|  | is returned (exit status 0), the task is considered up-to-date: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   generate-files: | ||||||
|  |     cmds: | ||||||
|  |       - mkdir directory | ||||||
|  |       - touch directory/file1.txt | ||||||
|  |       - touch directory/file2.txt | ||||||
|  |     # test existence of files | ||||||
|  |     status: | ||||||
|  |       - test -d directory | ||||||
|  |       - test -f directory/file1.txt | ||||||
|  |       - test -f directory/file2.txt | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | You can use `--force` or `-f` if you want to force a task to run even when | ||||||
|  | up-to-date. | ||||||
|  |  | ||||||
|  | Also, `task --status [tasks]...` will exit with a non-zero exit code if any of | ||||||
|  | the tasks are not up-to-date. | ||||||
|  |  | ||||||
|  | ## Variables | ||||||
|  |  | ||||||
|  | When doing interpolation of variables, Task will look for the below. | ||||||
|  | They are listed below in order of importance (e.g. most important first): | ||||||
|  |  | ||||||
|  | - Variables declared locally in the task | ||||||
|  | - Variables given while calling a task from another. | ||||||
|  |   (See [Calling another task](#calling-another-task) above) | ||||||
|  | - Variables declared in the `vars:` option in the `Taskfile` | ||||||
|  | - Variables available in the `Taskvars.yml` file | ||||||
|  | - Environment variables | ||||||
|  |  | ||||||
|  | Example of sending parameters with environment variables: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | $ TASK_VARIABLE=a-value task do-something | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Since some shells don't support above syntax to set environment variables | ||||||
|  | (Windows) tasks also accepts a similar style when not in the beginning of | ||||||
|  | the command. Variables given in this form are only visible to the task called | ||||||
|  | right before. | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | $ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done!" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Example of locally declared vars: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   print-var: | ||||||
|  |     cmds: | ||||||
|  |       echo "{{.VAR}}" | ||||||
|  |     vars: | ||||||
|  |       VAR: Hello! | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Example of global vars in a `Taskfile.yml`: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | vars: | ||||||
|  |   GREETING: Hello from Taskfile! | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   greet: | ||||||
|  |     cmds: | ||||||
|  |       - echo "{{.GREETING}}" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Example of `Taskvars.yml` file: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | PROJECT_NAME: My Project | ||||||
|  | DEV_MODE: production | ||||||
|  | GIT_COMMIT: {sh: git log -n 1 --format=%h} | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Variables expansion | ||||||
|  |  | ||||||
|  | Variables are expanded 2 times by default. You can change that by setting the | ||||||
|  | `expansions:` option. Change that will be necessary if you compose many | ||||||
|  | variables together: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | expansions: 3 | ||||||
|  |  | ||||||
|  | vars: | ||||||
|  |   FOO: foo | ||||||
|  |   BAR: bar | ||||||
|  |   BAZ: baz | ||||||
|  |   FOOBAR: "{{.FOO}}{{.BAR}}" | ||||||
|  |   FOOBARBAZ: "{{.FOOBAR}}{{.BAZ}}" | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   default: | ||||||
|  |     cmds: | ||||||
|  |       - echo "{{.FOOBARBAZ}}" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Dynamic variables | ||||||
|  |  | ||||||
|  | The below syntax (`sh:` prop in a variable) is considered a dynamic variable. | ||||||
|  | The value will be treated as a command and the output assigned. If there is one | ||||||
|  | or more trailing newlines, the last newline will be trimmed. | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     cmds: | ||||||
|  |       - go build -ldflags="-X main.Version={{.GIT_COMMIT}}" main.go | ||||||
|  |     vars: | ||||||
|  |       GIT_COMMIT: | ||||||
|  |         sh: git log -n 1 --format=%h | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | This works for all types of variables. | ||||||
|  |  | ||||||
|  | ## Go's template engine | ||||||
|  |  | ||||||
|  | Task parse commands as [Go's template engine][gotemplate] before executing | ||||||
|  | them. Variables are accessible through dot syntax (`.VARNAME`). | ||||||
|  |  | ||||||
|  | All functions by the Go's [sprig lib](http://masterminds.github.io/sprig/) | ||||||
|  | are available. The following example gets the current date in a given format: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   print-date: | ||||||
|  |     cmds: | ||||||
|  |       - echo {{now | date "2006-01-02"}} | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Task also adds the following functions: | ||||||
|  |  | ||||||
|  | - `OS`: Returns operating system. Possible values are "windows", "linux", | ||||||
|  |   "darwin" (macOS) and "freebsd". | ||||||
|  | - `ARCH`: return the architecture Task was compiled to: "386", "amd64", "arm" | ||||||
|  |   or "s390x". | ||||||
|  | - `splitLines`: Splits Unix (\n) and Windows (\r\n) styled newlines. | ||||||
|  | - `catLines`: Replaces Unix (\n) and Windows (\r\n) styled newlines with a space. | ||||||
|  | - `toSlash`: Does nothing on Unix, but on Windows converts a string from `\` | ||||||
|  |   path format to `/`. | ||||||
|  | - `fromSlash`: Oposite of `toSlash`. Does nothing on Unix, but on Windows | ||||||
|  |   converts a string from `\` path format to `/`. | ||||||
|  | - `exeExt`: Returns the right executable extension for the current OS | ||||||
|  |   (`".exe"` for Windows, `""` for others). | ||||||
|  |  | ||||||
|  | Example: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   print-os: | ||||||
|  |     cmds: | ||||||
|  |       - echo '{{OS}} {{ARCH}}' | ||||||
|  |       - echo '{{if eq OS "windows"}}windows-command{{else}}unix-command{{end}}' | ||||||
|  |       # This will be path/to/file on Unix but path\to\file on Windows | ||||||
|  |       - echo '{{fromSlash "path/to/file"}}' | ||||||
|  |   enumerated-file: | ||||||
|  |     vars: | ||||||
|  |       CONTENT: | | ||||||
|  |         foo | ||||||
|  |         bar | ||||||
|  |     cmds: | ||||||
|  |       - | | ||||||
|  |         cat << EOF > output.txt | ||||||
|  |         {{range $i, $line := .CONTENT | splitLines -}} | ||||||
|  |         {{printf "%3d" $i}}: {{$line}} | ||||||
|  |         {{end}}EOF | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Help | ||||||
|  |  | ||||||
|  | Running `task --list` (or `task -l`) lists all tasks with a description. | ||||||
|  | The following taskfile: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   build: | ||||||
|  |     desc: Build the go binary. | ||||||
|  |     cmds: | ||||||
|  |       - go build -v -i main.go | ||||||
|  |  | ||||||
|  |   test: | ||||||
|  |     desc: Run all the go tests. | ||||||
|  |     cmds: | ||||||
|  |       - go test -race ./... | ||||||
|  |  | ||||||
|  |   js: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/script.js src/js | ||||||
|  |  | ||||||
|  |   css: | ||||||
|  |     cmds: | ||||||
|  |       - minify -o public/style.css src/css | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | would print the following output: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | * build:   Build the go binary. | ||||||
|  | * test:    Run all the go tests. | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Silent mode | ||||||
|  |  | ||||||
|  | Silent mode disables echoing of commands before Task runs it. | ||||||
|  | For the following Taskfile: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   echo: | ||||||
|  |     cmds: | ||||||
|  |       - echo "Print something" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Normally this will be print: | ||||||
|  |  | ||||||
|  | ```sh | ||||||
|  | echo "Print something" | ||||||
|  | Print something | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | With silent mode on, the below will be print instead: | ||||||
|  |  | ||||||
|  | ```sh | ||||||
|  | Print something | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | There's three ways to enable silent mode: | ||||||
|  |  | ||||||
|  | * At command level: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   echo: | ||||||
|  |     cmds: | ||||||
|  |       - cmd: echo "Print something" | ||||||
|  |         silent: true | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | * At task level: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   echo: | ||||||
|  |     cmds: | ||||||
|  |       - echo "Print something" | ||||||
|  |     silent: true | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | * Or globally with `--silent` or `-s` flag | ||||||
|  |  | ||||||
|  | If you want to suppress stdout instead, just redirect a command to `/dev/null`: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   echo: | ||||||
|  |     cmds: | ||||||
|  |       - echo "This will print nothing" > /dev/null | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Dry run mode | ||||||
|  |  | ||||||
|  | Dry run mode (`--dry`) compiles and steps through each task, printing the commands | ||||||
|  | that would be run without executing them. This is useful for debugging your Taskfiles. | ||||||
|  |  | ||||||
|  | ## Ignore errors | ||||||
|  |  | ||||||
|  | You have the option to ignore errors during command execution. | ||||||
|  | Given the following Taskfile: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   echo: | ||||||
|  |     cmds: | ||||||
|  |       - exit 1 | ||||||
|  |       - echo "Hello World" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Task will abort the execution after running `exit 1` because the status code `1` stands for `EXIT_FAILURE`. | ||||||
|  | However it is possible to continue with execution using `ignore_error`: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   echo: | ||||||
|  |     cmds: | ||||||
|  |       - cmd: exit 1 | ||||||
|  |         ignore_error: true | ||||||
|  |       - echo "Hello World" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | `ignore_error` can also be set for a task, which mean errors will be supressed | ||||||
|  | for all commands. But keep in mind this option won't propagate to other tasks | ||||||
|  | called either by `deps` or `cmds`! | ||||||
|  |  | ||||||
|  | ## Output syntax | ||||||
|  |  | ||||||
|  | By default, Task just redirect the STDOUT and STDERR of the running commands | ||||||
|  | to the shell in real time. This is good for having live feedback for log | ||||||
|  | printed by commands, but the output can become messy if you have multiple | ||||||
|  | commands running at the same time and printing lots of stuff. | ||||||
|  |  | ||||||
|  | To make this more customizable, there are currently three different output | ||||||
|  | options you can choose: | ||||||
|  |  | ||||||
|  | - `interleaved` (default) | ||||||
|  | - `group` | ||||||
|  | - `prefixed` | ||||||
|  |  | ||||||
|  | To choose another one, just set it to root in the Taskfile: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | output: 'group' | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   # ... | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  The `group` output will print the entire output of a command once, after it | ||||||
|  |  finishes, so you won't have live feedback for commands that take a long time | ||||||
|  |  to run. | ||||||
|  |  | ||||||
|  |  The `prefix` output will prefix every line printed by a command with | ||||||
|  |  `[task-name] ` as the prefix, but you can customize the prefix for a command | ||||||
|  |  with the `prefix:` attribute: | ||||||
|  |  | ||||||
|  |  ```yaml | ||||||
|  | version: '2' | ||||||
|  |  | ||||||
|  | output: prefixed | ||||||
|  |  | ||||||
|  | tasks: | ||||||
|  |   default: | ||||||
|  |     deps: | ||||||
|  |       - task: print | ||||||
|  |         vars: {TEXT: foo} | ||||||
|  |       - task: print | ||||||
|  |         vars: {TEXT: bar} | ||||||
|  |       - task: print | ||||||
|  |         vars: {TEXT: baz} | ||||||
|  |  | ||||||
|  |   print: | ||||||
|  |     cmds: | ||||||
|  |       - echo "{{.TEXT}}" | ||||||
|  |     prefix: "print-{{.TEXT}}" | ||||||
|  |     silent: true | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | $ task default | ||||||
|  | [print-foo] foo | ||||||
|  | [print-bar] bar | ||||||
|  | [print-baz] baz | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Watch tasks | ||||||
|  |  | ||||||
|  | If you give a `--watch` or `-w` argument, task will watch for file changes | ||||||
|  | and run the task again. This requires the `sources` attribute to be given, | ||||||
|  | so task know which files to watch. | ||||||
|  |  | ||||||
|  | [gotemplate]: https://golang.org/pkg/text/template/ | ||||||
|  | [minify]: https://github.com/tdewolff/minify/tree/master/cmd/minify | ||||||
| @@ -14,9 +14,12 @@ import ( | |||||||
| // Taskfile reads a Taskfile for a given directory | // Taskfile reads a Taskfile for a given directory | ||||||
| func Taskfile(dir string) (*taskfile.Taskfile, error) { | func Taskfile(dir string) (*taskfile.Taskfile, error) { | ||||||
| 	path := filepath.Join(dir, "Taskfile.yml") | 	path := filepath.Join(dir, "Taskfile.yml") | ||||||
|  | 	if _, err := os.Stat(path); err != nil { | ||||||
|  | 		return nil, fmt.Errorf(`No Taskfile.yml found. Use "task --init" to create a new one`) | ||||||
|  | 	} | ||||||
| 	t, err := readTaskfile(path) | 	t, err := readTaskfile(path) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf(`No Taskfile.yml found. Use "task --init" to create a new one`) | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for namespace, path := range t.Includes { | 	for namespace, path := range t.Includes { | ||||||
|   | |||||||
| @@ -12,9 +12,9 @@ import ( | |||||||
| // Status returns an error if any the of given tasks is not up-to-date | // Status returns an error if any the of given tasks is not up-to-date | ||||||
| func (e *Executor) Status(calls ...taskfile.Call) error { | func (e *Executor) Status(calls ...taskfile.Call) error { | ||||||
| 	for _, call := range calls { | 	for _, call := range calls { | ||||||
| 		t, ok := e.Taskfile.Tasks[call.Task] | 		t, err := e.CompiledTask(call) | ||||||
| 		if !ok { | 		if err != nil { | ||||||
| 			return &taskNotFoundError{taskName: call.Task} | 			return err | ||||||
| 		} | 		} | ||||||
| 		isUpToDate, err := isTaskUpToDate(e.Context, t) | 		isUpToDate, err := isTaskUpToDate(e.Context, t) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								watch.go
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								watch.go
									
									
									
									
									
								
							| @@ -2,7 +2,10 @@ package task | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"os" | ||||||
|  | 	"os/signal" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"syscall" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/go-task/task/internal/taskfile" | 	"github.com/go-task/task/internal/taskfile" | ||||||
| @@ -40,6 +43,8 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	closeOnInterrupt(w) | ||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		for { | 		for { | ||||||
| 			select { | 			select { | ||||||
| @@ -66,6 +71,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error { | |||||||
| 					e.Logger.Errf("%v", err) | 					e.Logger.Errf("%v", err) | ||||||
| 				} | 				} | ||||||
| 			case <-w.Closed: | 			case <-w.Closed: | ||||||
|  | 				cancel() | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -84,6 +90,19 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error { | |||||||
| 	return w.Start(time.Second) | 	return w.Start(time.Second) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func isContextError(err error) bool { | ||||||
|  | 	return err == context.Canceled || err == context.DeadlineExceeded | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func closeOnInterrupt(w *watcher.Watcher) { | ||||||
|  | 	ch := make(chan os.Signal, 1) | ||||||
|  | 	signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGTERM) | ||||||
|  | 	go func() { | ||||||
|  | 		<-ch | ||||||
|  | 		w.Close() | ||||||
|  | 	}() | ||||||
|  | } | ||||||
|  |  | ||||||
| func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Call) error { | func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Call) error { | ||||||
| 	oldWatchedFiles := make(map[string]struct{}) | 	oldWatchedFiles := make(map[string]struct{}) | ||||||
| 	for f := range w.WatchedFiles() { | 	for f := range w.WatchedFiles() { | ||||||
| @@ -140,12 +159,3 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca | |||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func isContextError(err error) bool { |  | ||||||
| 	switch err { |  | ||||||
| 	case context.Canceled, context.DeadlineExceeded: |  | ||||||
| 		return true |  | ||||||
| 	default: |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user