Compare commits

...

261 Commits

Author SHA1 Message Date
Andrey Nering
3eb4c9eae8 v3.22.0 2023-03-10 15:35:56 -03:00
Pete Davison
0838d48ee3 refactor: decouple fingerprinting from executor (#1039) 2023-03-10 15:27:30 -03:00
Pete Davison
c64f8818be Merge pull request #1043 from go-task/update-install-from-source-docs
chore: remove installation docs for Go 1.15
2023-03-09 19:16:57 +00:00
Pete Davison
97ffd84d0e chore: remove installation docs for Go 1.15 2023-03-09 19:07:05 +00:00
Andrey Nering
f2114f09f7 Fix capitalization of flags descriptions on task -h
Also, adds missing periods.
2023-03-08 23:24:39 -03:00
Andrey Nering
9c844850e4 Add --global (-g) flag (#1029)
This will run a Taskfile from the home directory, i.e., `$HOME/Taskfile.yml`.
2023-03-08 23:21:23 -03:00
Andrey Nering
68aef2ef0d Add CHANGELOG entry for #1022 2023-03-08 22:37:04 -03:00
Dennis Jekubczyk
88d644a7e9 Add ability to set error_only: true on the group output mode 2023-03-08 22:34:52 -03:00
dependabot[bot]
4b97d4f7f5 build(deps): bump dns-packet from 5.3.1 to 5.4.0 in /docs (#1034)
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 5.3.1 to 5.4.0.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v5.3.1...5.4.0)

---
updated-dependencies:
- dependency-name: dns-packet
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-08 22:23:31 -03:00
Andrey Nering
bc14c633ae Taskfile: Remove task commited by mistake 2023-03-08 22:21:27 -03:00
Pete Davison
a29e5d39ca Merge pull request #1037 from go-task/fix-status-and-sources
fix: status and sources
2023-03-07 00:35:45 +00:00
Pete Davison
f1506ee500 fix: status and sources 2023-03-07 00:30:24 +00:00
Andrey Nering
6e346de9fb CHANGELOG: Add entry for #1035 2023-03-06 09:47:33 -03:00
Harel Wahnich
99ab2a4d62 for task up to date check both status and sources (#1035)
* remove redundant if statement

* add subtests to TestStatusChecksum
2023-03-05 22:16:41 -08:00
Pete Davison
d4ed7c3cfc Merge pull request #1004 from go-task/semver
feat: use semver package for taskfile schema version
2023-03-02 19:07:52 +00:00
pzloty
bc0554575a Fix output "prefixed" option in schema.json (#1031)
Fix the output option to match implementation and documentation.
2023-03-02 10:42:11 -03:00
Andrey Nering
1f4906244b Add CHANGELOG for #1025 2023-03-01 22:06:16 -03:00
Bevan Arps
52756ab83e Fix deadlock issue with run: once (#1025) 2023-03-01 21:53:38 -03:00
Pete Davison
97dcbe6932 Merge pull request #1026 from go-task/fix-schema-for-group
fix: schema for output group
2023-02-28 13:49:03 +00:00
Pete Davison
e35bf22dd3 fix: schema for output group (#1005) 2023-02-28 11:50:26 +01:00
Andrey Nering
a36b1b9cec Website: Remove Carbon 2023-02-23 19:30:10 -03:00
Andrey Nering
1920ee38c3 v3.21.0 2023-02-22 22:12:48 -03:00
João Pedro
ec2110e58f Add new TASK_VERSION special variable
Closes #1014
Closes #990
2023-02-22 22:08:38 -03:00
Andrey Nering
12a1cd6f62 Docs: Update API page 2023-02-16 21:16:43 -03:00
Aleksandr Komlev
9af056e746 Add FORCE_COLOR env support (#1003) 2023-02-16 21:12:44 -03:00
Pete Davison
c8fe450623 Merge pull request #1010 from go-task/go-1-20
chore: update to go 1.20
2023-02-13 13:33:51 +00:00
Pete Davison
ab1fe742f3 chore: update to go 1.20 2023-02-13 13:28:49 +00:00
Pete Davison
8b72c86ba5 feat: use semver package for taskfile schema version 2023-02-10 18:14:38 +00:00
Pete Davison
28c5f4a635 Merge pull request #1007 from go-task/fix-tasks-being-incorrectly-marked-as-internal
fix: tasks being incorrectly marked as internal
2023-02-10 18:14:01 +00:00
Pete Davison
74f69a21cd fix: tasks being incorrectly marked as internal 2023-02-10 17:02:11 +00:00
dependabot[bot]
e23dacd6d4 build(deps): bump github.com/joho/godotenv from 1.4.0 to 1.5.1 (#1002)
Bumps [github.com/joho/godotenv](https://github.com/joho/godotenv) from 1.4.0 to 1.5.1.
- [Release notes](https://github.com/joho/godotenv/releases)
- [Commits](https://github.com/joho/godotenv/compare/v1.4.0...v1.5.1)

---
updated-dependencies:
- dependency-name: github.com/joho/godotenv
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 09:41:37 -03:00
Andrey Nering
58d582941b Documentation: Remove mentions of Minify in favor of esbuild 2023-02-04 20:29:10 -03:00
dependabot[bot]
3bbc51949c build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 in /docs (#1000)
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-04 18:51:05 -03:00
Andrey Nering
69e0254a99 Website: Update 2023-01-29 15:42:59 -03:00
Andrey Nering
1091a914bd Documentation: version: '2' -> version: '3'
https://github.com/go-task/task/pull/929#discussion_r1082370557
2023-01-29 15:39:45 -03:00
dependabot[bot]
ecc65a218e build(deps): bump github.com/fatih/color from 1.13.0 to 1.14.1 (#995)
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.13.0 to 1.14.1.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.13.0...v1.14.1)

---
updated-dependencies:
- dependency-name: github.com/fatih/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-28 08:07:12 -03:00
dependabot[bot]
426ed7eff6 build(deps): bump ua-parser-js from 0.7.31 to 0.7.33 in /docs (#991)
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.31 to 0.7.33.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Changelog](https://github.com/faisalman/ua-parser-js/blob/master/changelog.md)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.31...0.7.33)

---
updated-dependencies:
- dependency-name: ua-parser-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-27 09:55:18 -03:00
Andrey Nering
73aba36309 v3.20.0 2023-01-14 17:34:15 -03:00
Andrey Nering
cb393ccd3a Add CHANGELOG entry + small adjustments to #977 2023-01-14 17:18:26 -03:00
Amin Yahyaabadi
347fcf9f67 fix: avoid reruns when the timestamp method is used (#977) 2023-01-14 17:17:36 -03:00
Andrey Nering
fce7575b03 Add README entry for #982 2023-01-14 16:48:04 -03:00
Pete Davison
2da7ddc399 chore: optimize task filtering (#982) 2023-01-14 16:45:52 -03:00
Pete Davison
1c1be683ab feat: set and shopt directives (#929)
Co-authored-by: Andrey Nering <andrey@nering.com.br>
2023-01-14 16:41:56 -03:00
Andrey Nering
4be1050234 Optimize the Taskfile a bit
`go list ./...` takes quite a few seconds to run. Let's restrict it to the
tasks that actually use it.
2023-01-06 21:41:18 -03:00
Andrey Nering
2efb3533ec Add CHANGELOG + improvements to #980
Closes #978
2023-01-06 21:39:57 -03:00
Lea Anthony
aa6c7e4b94 Add support for 'platforms' in both task and command (#980) 2023-01-06 21:38:35 -03:00
Andrey Nering
63c50d13ee Website/README: Add link to the Mastodon account 2023-01-01 21:24:16 -03:00
Andrey Nering
c1e127e42f Website: Update outdated URL 2022-12-31 14:28:37 -03:00
dependabot[bot]
9e38e8a4db build(deps): bump json5 from 2.2.1 to 2.2.2 in /docs (#972)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-31 14:15:20 -03:00
Andrey Nering
b4c95d6b0b v3.19.1 2022-12-31 14:03:55 -03:00
Pete Davison
c4766e2611 fix: add missing nil check (#971)
Co-authored-by: Andrey Nering <andrey@nering.com.br>
2022-12-31 13:54:26 -03:00
Pete Davison
796097e3ab fix: watch interval (#970) 2022-12-31 13:48:49 -03:00
Pete Davison
c7d9efebf9 Merge pull request #967 from go-task/gha-issue-closed
feat: add action for when an issue is closed
2022-12-23 16:34:40 -06:00
Pete Davison
8f4306d321 feat: add action for when an issue is closed 2022-12-23 22:31:02 +00:00
Pete Davison
435f086cb7 Merge pull request #965 from go-task/fix-interval-schema
fix: incorrect schema type for interval
2022-12-22 18:36:15 -06:00
Pete Davison
01c9158120 fix: incorrect schema type for interval
- Fixes #962
2022-12-23 00:34:08 +00:00
Andrey Nering
e235d77d64 Add CHANGELOG to #964 2022-12-22 21:27:19 -03:00
Henrique Corrêa
dbe8131b75 Close Taskfile after reading it (#964)
This should fix issues preventing modifications to the Taskfile while tasks are still running, like switching git branches for example.

See #963.
2022-12-22 21:23:17 -03:00
Pete Davison
0a9d76515e Merge pull request #957 from go-task/faq
FAQ doc
2022-12-19 19:58:06 +00:00
Pete Davison
0ce1af9ee0 WIP: FAQ doc 2022-12-19 19:51:22 +00:00
Andrey Nering
c4452d2698 Website > Installation: Document official Homebrew go-task package 2022-12-18 22:41:42 -03:00
Pete Davison
491888f6c0 feat: improve unmarshal error handling and use v3 yaml interface everywhere (#959) 2022-12-18 22:11:31 -03:00
Pete Davison
e4158dc5e4 feat: add local-prefixes flag to goimports linter (#958) 2022-12-18 22:06:09 -03:00
Andrey Nering
0307ca8ac6 Website: Upgrade Docusaurus (#956) 2022-12-17 11:43:43 -03:00
Andrey Nering
156a273351 go.mod: Pin released v3.6.0 version of mvdan/sh 2022-12-17 11:18:23 -03:00
Andrey Nering
d6d51a2f8b Prevent TestFileWatcherInterval from running on CI
This test can fail intermittently. It's fine to run it only locally.

We were already doing this for TestSignalSentToProcessGroup.
2022-12-17 11:08:41 -03:00
Andrey Nering
a98b41d657 Add goimports as a linter 2022-12-17 11:02:17 -03:00
Andrey Nering
87ec78fbaa Cleanup: Remove duplicated internal/sleepit/main.go file 2022-12-17 11:01:54 -03:00
Andrey Nering
957bff4b89 CHANGELOG + small improvements to #936 2022-12-17 10:35:30 -03:00
David Alpert
321f7b59d8 Add --json flag to be used by editor extensions (#936) 2022-12-17 10:31:00 -03:00
Andrey Nering
41a9316523 Website: Update "Donate" page + FUNDING.yml 2022-12-07 21:33:49 -03:00
Andrey Nering
1072ff5950 v3.19.0 2022-12-05 22:28:15 -03:00
Andrey Nering
983f6fff5d Upgrade @go-task/go-npm to support pnpm 2022-12-05 22:24:10 -03:00
Pete Davison
b3627fcb18 Run Taskfiles from sub/child directories (#920) 2022-12-05 21:58:20 -03:00
Pete Davison
99d7338c29 feat: add task-level dotenv support (#904) 2022-12-05 21:25:16 -03:00
Andrey Nering
9cf930454d Add CHANGELOG entry for #492, #493 2022-12-05 20:56:47 -03:00
Andrey Nering
4b4962e8c6 Merge pull request #943 from go-task/fix-interpolation-in-includes
fix: interpolate includes taskfile and dir
2022-12-05 20:54:04 -03:00
Andrey Nering
f2afa77114 Website: Update Community > JSON Schema section 2022-11-27 19:50:05 -03:00
Andrey Nering
3aa647c89b Website: Update Chinese translation link label 2022-11-27 19:49:07 -03:00
Andrey Nering
45ab4dc718 Website: Link to the Chinese translation
Closes #921
2022-11-26 18:24:31 -03:00
Andrey Nering
d1850e8fd2 Add Gold Sponsors section 2022-11-24 13:05:24 -03:00
Pete Davison
f1d516cf2a fix: interpolate includes taskfile and dir 2022-11-23 17:58:08 +00:00
Andrey Nering
d55282b53c Merge pull request #934 from go-task/dependabot/npm_and_yarn/docs/loader-utils-2.0.4
Bump loader-utils from 2.0.3 to 2.0.4 in /docs
2022-11-19 22:41:44 -03:00
Andrey Nering
ef9f7af0c5 Merge pull request #938 from rrrix/jetbrains-json-schema-validator-workaround
JetBrains JSON Schema Validator Error Workaround
2022-11-19 22:15:01 -03:00
Rick Bowen
8823887bb4 JetBrains JSON Schema Validator Error Workaround
`schema.json` Workaround for these two JetBrains issues:

- [IDEA-236928 json schema: False positive "Schema validation: Validates to more than one variant" with "oneOf"](https://youtrack.jetbrains.com/issue/IDEA-236928)
- [IDEA-265710 JSON schema validation fails if anyOf is nested in oneOf](https://youtrack.jetbrains.com/issue/IDEA-265710)

There is no material effect on the actual schema validation, as the `oneOf`/`allOf` evaluates only one list entry.

`allOf([1])` is `1`, and `oneOf([1])` is also `1`.

Fixes #847
2022-11-17 16:22:51 -08:00
Andrey Nering
593980e45a Upgrade @go-task/go-npm 2022-11-17 21:04:53 -03:00
dependabot[bot]
081dc16312 Bump loader-utils from 2.0.3 to 2.0.4 in /docs
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 2.0.3 to 2.0.4.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v2.0.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v2.0.3...v2.0.4)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-16 05:26:21 +00:00
Andrey Nering
35599af04b v3.18.0 2022-11-12 13:36:52 -03:00
Andrey Nering
a74b35379e Merge pull request #932 from go-task/dependabot/go_modules/github.com/mattn/go-zglob-0.0.4
Bump github.com/mattn/go-zglob from 0.0.3 to 0.0.4
2022-11-12 13:13:04 -03:00
dependabot[bot]
7d16c9f68d Bump github.com/mattn/go-zglob from 0.0.3 to 0.0.4
Bumps [github.com/mattn/go-zglob](https://github.com/mattn/go-zglob) from 0.0.3 to 0.0.4.
- [Release notes](https://github.com/mattn/go-zglob/releases)
- [Commits](https://github.com/mattn/go-zglob/compare/v0.0.3...v0.0.4)

---
updated-dependencies:
- dependency-name: github.com/mattn/go-zglob
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-12 16:09:23 +00:00
Andrey Nering
890759cc5f Add CHANGELOG entry for #919 2022-11-12 10:19:11 -03:00
Andrey Nering
e710e2cc5d Merge pull request #919 from go-task/include-alises-in-list-when-silent
feat: include aliases in --list --silent output
2022-11-12 10:16:38 -03:00
Andrey Nering
d787faece4 Improve docs/Taskfile.yml 2022-11-12 09:26:35 -03:00
Andrey Nering
9702109ea9 Merge pull request #927 from go-task/dependabot/npm_and_yarn/docs/loader-utils-2.0.3
Bump loader-utils from 2.0.2 to 2.0.3 in /docs
2022-11-09 10:07:47 -03:00
dependabot[bot]
e547829505 Bump loader-utils from 2.0.2 to 2.0.3 in /docs
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v2.0.3/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v2.0.2...v2.0.3)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-09 07:32:40 +00:00
Pete Davison
a664a26062 Merge pull request #890 from go-task/task-list-filtering
refactor: implement task list filtering
2022-11-02 14:49:06 +00:00
Pete Davison
fa105a8a93 refactor: implement task list filtering 2022-11-02 14:42:59 +00:00
Andrey Nering
3a0c7a8c36 Add CHANGELOG for #815
Closes #661
2022-11-02 11:39:05 -03:00
Andrey Nering
13f4b376e8 Merge pull request #815 from pd93/default-included-task
feat: run default task in included file when task is omitted
2022-11-02 11:34:19 -03:00
Pete Davison
5a08409a27 feat: run default task in included file when task is omitted 2022-11-02 14:27:15 +00:00
Andrey Nering
9bbdac3c2e Merge pull request #914 from go-task/update-contribution-guide
chore: add schema info to contribution guide
2022-11-02 11:22:19 -03:00
Andrey Nering
a990ffe53d Refactor: Use early return 2022-11-02 10:23:19 -03:00
Pete Davison
3a4b347d50 feat: include aliases in --list --silent output 2022-10-31 17:19:27 +00:00
Pete Davison
b80e1e4a43 chore: add schema info to contribution guide 2022-10-29 16:04:23 +00:00
Andrey Nering
fd71dfda6a Move docs/schema.json to docs/static/schema.json 2022-10-29 11:59:42 -03:00
Andrey Nering
fdbcbd395d Merge pull request #895 from Eun/add-arm-vx-builds
fix: add armv5 & armv7 builds
2022-10-29 11:57:46 -03:00
Andrey Nering
dba964b559 Merge pull request #910 from go-task/bring-schema-in-house
Bring schema in house
2022-10-29 11:54:08 -03:00
Andrey Nering
8e0816a09d Merge pull request #901 from go-task/github-actions-labels
feat: add actions to auto label issues
2022-10-29 11:52:37 -03:00
Andrey Nering
405b79f86c Merge pull request #902 from trim21/patch-1
make powershell completion works to fill task name
2022-10-29 11:46:45 -03:00
Pete Davison
620e6955e5 chore: update schema/docs to match
- Also reorder them both to match the struct definitions. This makes it easier to compare them
2022-10-29 14:45:32 +00:00
Pete Davison
a4997dd54d feat: copy schema as defined in schemastore 2022-10-29 14:43:47 +00:00
Andrey Nering
3efa9ac8c3 Documentation: Small adjustments to #906 2022-10-29 11:41:05 -03:00
Andrey Nering
fdd52d74e9 Merge pull request #906 from viconnex/add-completion-documentation
Document completion installation
2022-10-29 11:37:58 -03:00
Andrey Nering
ac81dea3ec Merge pull request #912 from go-task/dependabot/go_modules/github.com/stretchr/testify-1.8.1
Bump github.com/stretchr/testify from 1.8.0 to 1.8.1
2022-10-29 11:23:06 -03:00
dependabot[bot]
549c37ef87 Bump github.com/stretchr/testify from 1.8.0 to 1.8.1
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-29 11:03:18 +00:00
Victor Lebrun
6a369ee31c Document completion installation 2022-10-25 21:00:00 +02:00
Trim21
2e573d37ae Update task.ps1 2022-10-18 00:09:07 +08:00
Trim21
394afe2633 Update task.ps1 2022-10-17 23:52:56 +08:00
Tobias Salzmann
99ed3001f0 revert changes, add fix for arm downloads 2022-10-17 09:25:26 +02:00
Pete Davison
9e4cab2af9 feat: add actions to auto label issues 2022-10-15 17:47:39 +00:00
Andrey Nering
33b6927b79 v3.17.0 2022-10-14 21:11:48 -03:00
Andrey Nering
852a176e1f PR Template: Fix content 2022-10-14 21:08:53 -03:00
Andrey Nering
7511249514 GitHub: Attempt to fix PR template 2022-10-14 21:08:07 -03:00
Andrey Nering
3429cdd8af GitHub: Giving up on fancy templates (sigh)
GitHub is was not showing them and I have no idea why.
2022-10-14 21:05:03 -03:00
Andrey Nering
a1cd8eafd8 GitHub: Yet another attempt to fix issue templates 2022-10-14 20:58:31 -03:00
Andrey Nering
fbfb4ba9c4 GitHub: Attempt to fix issue templates 2022-10-14 20:55:46 -03:00
Andrey Nering
ba9ba63792 GitHub: Improving our issue & PR templates 2022-10-14 20:47:09 -03:00
Andrey Nering
460b89ce51 Merge branch 'feat/suggest-similar-task' 2022-10-14 20:08:00 -03:00
Andrey Nering
a4ec6e5257 Improve test #887 2022-10-14 19:50:43 -03:00
Andrey Nering
44aa2ee3b3 Add CHANGELOG and improvements to #887 2022-10-14 19:48:45 -03:00
Andrey Nering
80b417c4ab Merge pull request #887 from ronaudinho/fix/yaml-error-msg
Add file path to YAML error message
2022-10-14 19:36:58 -03:00
Andrey Nering
6d90c781c9 Merge pull request #879 from go-task/aliases
Aliases
2022-10-14 19:32:04 -03:00
Andrey Nering
c51f04eca8 Add some alises to our own Taskfiles 2022-10-14 19:28:27 -03:00
Andrey Nering
dda2004753 --list: Print aliases on its own column 2022-10-14 19:28:05 -03:00
Andrey Nering
297f9eccea For include aliases, consider the main task name as well 2022-10-14 19:27:20 -03:00
Andrey Nering
d2f2cba6d8 Merge branch 'master' into aliases 2022-10-14 18:44:56 -03:00
Andrey Nering
172d71435a Add CHANGELOG for #897 2022-10-14 18:32:12 -03:00
Andrey Nering
bb1aec8a7e Merge pull request #897 from mymmrac/improve-fish-completion
Improved fish shell completions
2022-10-14 18:31:19 -03:00
Artem Yadelskyi
476d9f5e70 Improved fish shell completions 2022-10-15 00:24:11 +03:00
Andrey Nering
99014ad38d Small adjustments + CHANGELOG for #865 2022-10-14 16:51:14 -03:00
Andrey Nering
403456d3dc Merge pull request #865 from ilewin/configurable_watch_interval_#813
Configurable watch interval #813
2022-10-14 16:26:13 -03:00
Andrey Nering
6335878317 Merge pull request #896 from go-task/ignore-fleet-settings
Ignore fleet configuration directory
2022-10-13 12:35:40 -03:00
Pete Davison
6bff658af0 chore: ignore fleet configuration directory 2022-10-13 14:37:52 +00:00
Tobias Salzmann
b111e7bd12 add armv5 & armv7 builds 2022-10-13 11:49:13 +02:00
Max Pushkarov
3e5ee2332a feat: suggest the most similar task name when a given task does not exist 2022-10-10 13:17:19 +03:00
Pete Davison
66f6998c86 docs: update changelog 2022-10-07 11:11:45 +00:00
Pete Davison
f2a8f8ad8f docs: update usage and api reference 2022-10-07 11:11:45 +00:00
Pete Davison
540f6ecfdb tests: update alias test to cover namespace aliases 2022-10-07 11:11:45 +00:00
Pete Davison
8ec89f1bbd refactor: use x/exp/slices instead of custom contains function 2022-10-07 11:11:14 +00:00
Pete Davison
d33906b6e4 fix: deep copy included tasks 2022-10-07 11:11:14 +00:00
Pete Davison
bb79fa1dc3 feat: namespace aliases 2022-10-07 11:11:14 +00:00
Pete Davison
376a6182eb feat: aliases
feat: add aliases to --list and --list-all flags

feat: add aliases to --summary

feat: enable aliases for included tasks

tests: added alias unit tests
2022-10-07 11:11:14 +00:00
ronaudinho
81de61d8db Add file path to YAML error message 2022-10-07 10:18:53 +00:00
Pete Davison
d2061ec898 Merge pull request #874 from go-task/845-colorize-output
Colorize --list, --list-all and --summary output
2022-10-07 11:05:48 +01:00
Pete Davison
077efbd2e7 Add CHANGELOG for #874 2022-10-07 10:01:54 +00:00
Pete Davison
8ce1782380 feat: add coloured output to --list, --list-all and --summary flags
feat: add coloured output to --list and --list-all

feat: add coloured output to --summary

chore: update colors

refactor: better consistency in writer calls in printTasks

feat: subtasks are printed green in --summary
2022-10-07 09:54:17 +00:00
ilewin
c2f20465ab Updated test for file watcher interval param
Updated Interval Setting Priority
2022-10-07 08:56:13 +02:00
Andrey Nering
fb0e43989d Add CHANGELOG for #877 2022-10-06 22:46:59 -03:00
Andrey Nering
754248395c Merge pull request #877 from biozz/master
Fix task names for `--list` and `--list-all`
2022-10-06 22:44:40 -03:00
Andrey Nering
6e975ca155 Merge pull request #882 from go-task/contribution-guide
Add a contributions guide
2022-10-06 22:38:44 -03:00
Pete Davison
79a2bc404e draft: add a contributions guide 2022-10-07 01:21:49 +00:00
Andrey Nering
42a26e1741 Revert "Website: Update Open Graph image"
This reverts commit b16e705a6c.
2022-10-06 22:03:55 -03:00
Andrey Nering
695711e124 Merge pull request #881 from danquah/document-sources-generate-status
Clearify that sources/generate and status can be used together
2022-10-06 21:27:16 -03:00
Mads H. Danquah
0d5811e502 docs: Add paragraphs about how to use generates/sources + status 2022-10-03 13:00:14 +00:00
Ivan Elfimov
b9d070f76b Fix test related to task lables 2022-09-30 19:17:04 +04:00
Ivan Elfimov
122c3f083e Fix task names for --list and --list-all
Task names should not be overrided by `label`.
2022-09-30 19:02:50 +04:00
Andrey Nering
5d22cf4327 v3.16.0 2022-09-29 22:01:16 -03:00
Andrey Nering
219d3ad193 Website: Fix link to file 2022-09-29 21:38:26 -03:00
Andrey Nering
e72157e26a Merge pull request #871 from go-task/release-to-npm
Add package.json to allow users to install Task using npm
2022-09-29 21:34:39 -03:00
Andrey Nering
50a377a7c4 Add package.json to allow users to install Task using npm
Closes #870
2022-09-29 21:27:30 -03:00
Andrey Nering
9d7ddff60c README: Add more links 2022-09-29 13:33:20 -03:00
Andrey Nering
081d878f86 Website > Installation: Update Arch Linux installation method
Package and maintainer changed. See #869.
2022-09-20 13:05:18 -03:00
ilewin
d8dc091267 Merge branch 'go-task:master' into configurable_watch_interval_#813 2022-09-19 20:22:26 +02:00
ilewin
1c44d8049a Issue 813. Made watch interval configurable through global setting in Taskfile and through CLI arg.
Separated Taskfile param and Arg flag
2022-09-19 20:14:35 +02:00
Andrey Nering
a95191d29e Website: Improve syntax highlighting 2022-09-17 13:51:54 -03:00
Andrey Nering
111f6e7f18 Add CHANGELOG entry and API documentation for #818 2022-09-17 13:11:16 -03:00
Andrey Nering
4a5c1e9ec4 Merge branch 'internal-tasks' of https://github.com/pd93/task into pd93-internal-tasks 2022-09-17 12:59:19 -03:00
Andrey Nering
8f0893b5f7 Website: Adjustments to Carbon 2022-09-17 11:11:02 -03:00
Andrey Nering
b16e705a6c Website: Update Open Graph image 2022-09-15 11:17:01 -03:00
Andrey Nering
3cad318b70 v3.15.2
I pushed v3.15.1 tagged in a commit in a detached branch by mistake.

Repushing as v3.15.2
2022-09-08 21:26:18 -03:00
Andrey Nering
8c6002cae6 v3.15.1 2022-09-08 21:22:19 -03:00
Andrey Nering
0355bbaf3b Merge pull request #861 from cdaguerre/feat/make-zsh-completion-configurable
Make zsh completion list configurable
2022-09-08 21:01:04 -03:00
Andrey Nering
2ba083a650 Merge pull request #863 from MarioSchwalbe/bash-completion
Fix handling of CLI_ARGS
2022-09-08 20:59:16 -03:00
Andrey Nering
c79ea5a257 Merge pull request #866 from pd93/fix-read-dotenv
fix: ignore empty dotfile file names
2022-09-08 20:58:25 -03:00
Pete Davison
44706f4957 fix: ignore empty dotfile file names 2022-09-08 18:51:39 +00:00
Mario Schwalbe
a1b3bb03ed * Fix handling of CLI_ARGS 2022-09-08 19:03:29 +02:00
Christian Daguerre
76caa16909 Make zsh completion list configurable 2022-09-07 10:33:55 +02:00
Andrey Nering
160b788198 Merge pull request #859 from jfhovinne/docs-reprobuilds
Document how to reproduce release binaries
2022-09-05 14:29:42 -03:00
jfhovinne
eada62f62c Document how to reproduce executables 2022-09-05 19:08:37 +02:00
Andrey Nering
bd9419e6db Website: Use "Roboto" as the main font
This is to add consistency between different operating systems, specially
Windows which used "Segoe UI" before this commit.
2022-09-04 17:38:29 -03:00
Andrey Nering
bdd9de3001 CHANGELOG: Add extra link 2022-09-03 18:28:24 -03:00
Andrey Nering
200ba4ed04 v3.15.0 2022-09-03 18:21:40 -03:00
Andrey Nering
1e8939dd58 Merge pull request #857 from go-task/feature/add-dir-special-variables
Add ROOT_DIR and TASKFILE_DIR special variables
2022-09-03 18:18:43 -03:00
Andrey Nering
f45dd11e53 Add ROOT_DIR and TASKFILE_DIR special variables
Closes #215
2022-09-03 18:14:54 -03:00
Andrey Nering
1a0cc1d64d Update favicon.ico 2022-08-31 13:21:43 -03:00
Wes McNamee
421cb522d9 Merge pull request #846 from rootulp/patch-1
fix: grammar in docs
2022-08-24 22:07:23 -07:00
Rootul Patel
1b18b041d6 fix: grammar in docs 2022-08-24 20:30:21 -04:00
Andrey Nering
8788703ac6 CHANGELOG for #831
Closes #826
2022-08-23 18:43:04 -03:00
Andrey Nering
b6c25e3ad9 Mention #844 on CHANGELOG 2022-08-23 18:40:34 -03:00
Andrey Nering
73eaa68cd1 Merge pull request #844 from MarioSchwalbe/bash-completion
Use --silent to get the list of tasks (bash completion)
2022-08-23 18:39:47 -03:00
Andrey Nering
beb927f7b4 Merge pull request #831 from ilewin/check_path_for_symlinks_issue_826
Attempt to fix Task not following symlinks
2022-08-23 18:38:17 -03:00
ilewin
cdc969cd4e Added test to check if symlinks are evaluated for task source files 2022-08-23 18:36:19 +02:00
ilewin
2a67499f12 Issue #826. Replaced zglob.Glob func with GlobFollowSymlinks to evaluate symlinks 2022-08-23 18:25:11 +02:00
Mario Schwalbe
6a3cc79daa * Use --silent to get list of tasks 2022-08-23 18:03:15 +02:00
Andrey Nering
97d4a947ee Merge pull request #838 from pcgeek86/patch-1
Update releasing.md
2022-08-17 20:50:18 -03:00
Wes McNamee
e0e47ad9a0 Merge pull request #841 from cristaloleg/fix-linter
Fix go-critic suggestions
2022-08-17 12:38:12 -07:00
Oleg Kovalov
b08eac58e9 Fix go-critic suggestions 2022-08-17 19:37:58 +02:00
Pete Davison
11409ccf21 fix: list + silent flags shouldn't display internal tasks 2022-08-16 17:07:05 +00:00
Pete Davison
e3b6c97c3b fix: the merged task should be internal if the task OR the taskfile are internal 2022-08-16 17:07:05 +00:00
Pete Davison
d3da086ebf docs: added usage 2022-08-16 17:07:05 +00:00
Pete Davison
3507fa40f1 feat: add internal to included files 2022-08-16 17:07:05 +00:00
Pete Davison
6f8f1f1409 feat(task): tasks can be internal (not accessible from cli) 2022-08-16 17:06:25 +00:00
Trevor Sullivan
c2148a359d Update releasing.md 2022-08-16 04:33:54 -06:00
Andrey Nering
c172185a24 Update CHANGELOG 2022-08-15 09:55:11 -03:00
Andrey Nering
1140a5c4ae Merge pull request #835 from MarioSchwalbe/bash-completion
Improved bash completion
2022-08-15 09:52:07 -03:00
Mario Schwalbe
3cc378c960 * Convert indentation to 2 spaces 2022-08-13 21:55:35 +02:00
Andrey Nering
9b3a961303 Merge pull request #832 from jfhovinne/reprobuilds
Modify goreleaser defaults for reproducible builds
2022-08-13 12:04:27 -03:00
Mario Schwalbe
d048555149 Improved bash completion for task 2022-08-11 20:48:41 +02:00
jfhovinne
7533858a52 Modify goreleaser defaults for reproducible builds 2022-08-10 15:33:17 +02:00
Andrey Nering
c4e10ef0aa Refactor: Add SmartJoin to handle IsAbs automatically 2022-08-06 18:19:07 -03:00
Andrey Nering
c20842e7cd v3.14.1: Add CHANGELOG to website 2022-08-03 22:26:39 -03:00
Andrey Nering
6cfdb21313 v3.14.1 2022-08-03 22:08:17 -03:00
Bevan Arps
e396f4d06f Resolve relative include paths relative to the including Taskfile
Closes #823
Closes #822
2022-08-03 21:59:17 -03:00
Andrey Nering
47c1bb6a5b Merge pull request #816 from go-task/dependabot/npm_and_yarn/docs/terser-5.14.2
Bump terser from 5.13.1 to 5.14.2 in /docs
2022-08-03 21:00:52 -03:00
Andrey Nering
adfb0b513e Merge pull request #827 from go-task/go-1-19
Upgrade to Go v1.19
2022-08-03 21:00:44 -03:00
Andrey Nering
98d78b9d8a Upgrade to Go v1.19 2022-08-03 20:58:06 -03:00
Wes McNamee
a1c32a56ea Merge pull request #817 from white-gecko/patch-1
Resolve contradiction.
2022-07-27 23:36:25 -07:00
Natanael Arndt
6584bcf87f Resolve contradiction. 2022-07-21 14:30:51 +02:00
dependabot[bot]
7ac75af622 Bump terser from 5.13.1 to 5.14.2 in /docs
Bumps [terser](https://github.com/terser/terser) from 5.13.1 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-21 05:16:51 +00:00
Andrey Nering
b3c283b282 Merge pull request #814 from abner-chenc/master
go.mod: update to current golang.org/x/sys revision
2022-07-18 10:30:57 -03:00
Guoqi Chen
c2615dd746 go.mod: update to current golang.org/x/sys revision
go get -d golang.org/x/sys@c0bba94af5f85fbad9f6dc2e04ed5b8fac9696cf
go mod tidy

This brings in linux/loong64 support.
2022-07-18 10:11:48 +08:00
Andrey Nering
789518f70d Merge pull request #811 from go-task/imgbot
[ImgBot] Optimize images
2022-07-16 23:28:31 -03:00
ImgBotApp
ad3008d855 [ImgBot] Optimize images
*Total -- 61.47kb -> 34.61kb (43.69%)

/docs/static/img/pix.png -- 12.63kb -> 1.25kb (90.13%)
/docs/static/img/logo.png -- 21.79kb -> 13.21kb (39.38%)
/docs/static/img/og-image.png -- 26.26kb -> 19.38kb (26.2%)
/docs/static/img/logo.svg -- 0.44kb -> 0.42kb (2.47%)
/docs/static/img/logo_mono.svg -- 0.36kb -> 0.35kb (1.37%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2022-07-17 02:23:22 +00:00
Andrey Nering
3da426603f Website: Improve "Install Script" documentation
Add note about common installation paths.

Closes #775
2022-07-16 22:55:57 -03:00
Andrey Nering
8d26e34b0a Use --list-all to PowerShell completion + Add CHANGELOG to #803 2022-07-16 22:07:24 -03:00
Andrey Nering
110d1d7245 Merge pull request #803 from carlsmedstad/zsh-completion
Fix Zsh completion for tasks without description
2022-07-16 21:38:50 -03:00
Andrey Nering
f7384623df Merge pull request #802 from nokome/patch-1
Update api_reference.md
2022-07-16 21:37:19 -03:00
Carl Smedstad
5d24e166ab Fix Zsh completion for tasks without description
Use --list-all instead of --list in order include tasks without
description in the auto-completion.
2022-07-10 01:52:38 +02:00
Andrey Nering
d9ec5bcd24 v3.14.0 2022-07-08 15:19:32 -03:00
Andrey Nering
bf9cd7625b Refactor task.Setup(): Move to its own file and split in separated functions 2022-07-08 15:16:04 -03:00
Andrey Nering
afbf98c974 Website: Add ENV section to API page 2022-07-08 14:49:52 -03:00
Andrey Nering
fedb68cde7 Allow override the .task dir location with the TASK_TEMP_DIR env 2022-07-08 14:40:10 -03:00
Nokome Bentley
f787937a30 Update api_reference.md
Using `cmd` (singular) with a single string is valid syntax also.
2022-07-08 14:01:41 +12:00
Alexander Mancevice
f54fef7e7b Allow users to override colors using environment variables
Closes #568
Closes #792
2022-07-06 11:46:59 -03:00
Andrey Nering
e36c77aaf3 Fix bug with STDOUT and STDERR in the "group" output mode
Took the oportunity to refactor a bit how we handle closing of the streams.

Fixes #779
2022-07-06 10:45:07 -03:00
Andrey Nering
de45e48c37 Release ARM binaries to Snap. Deprecate i386
Actually done here: https://github.com/go-task/snap/blob/master/snap/snapcraft.yaml

Closes #795
2022-07-04 11:50:36 -03:00
Andrey Nering
ef0ce8224e Merge pull request #797 from go-task/dependabot/go_modules/github.com/stretchr/testify-1.8.0
Bump github.com/stretchr/testify from 1.7.2 to 1.8.0
2022-07-04 11:18:25 -03:00
Andrey Nering
5b4d5387bf Website: Link to Twitter account 2022-07-04 11:14:20 -03:00
Andrey Nering
5c460b38c9 Website: Add more entries to the Community page 2022-07-04 10:50:03 -03:00
Andrey Nering
8b836ab446 CHANGELOG: Mention #769 forggoten on SIGINT entry 2022-07-04 10:44:17 -03:00
dependabot[bot]
1be1fccc76 Bump github.com/stretchr/testify from 1.7.2 to 1.8.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.7.2 to 1.8.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.7.2...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 13:41:49 +00:00
Andrey Nering
2c1fda97f0 Upgrade mvdan.cc/sh, which fixes a bug with associative arrays
Fixes #785
2022-07-04 10:40:25 -03:00
Andrey Nering
71f7b719b5 Merge pull request #791 from MPLew-is/patch-1
Correct `method: timestamp` example block in usage docs
2022-06-27 17:52:18 -03:00
Andrey Nering
e39006b511 Merge pull request #790 from Trim21/patch-2
docs: scoop extra bucket is not required anymore
2022-06-27 17:51:17 -03:00
Mike Lewis
37d07d415a Correct method: timestamp example block
The text above this block currently references a `timestamp` method for checking if a task should be run, then the example uses `checksum` instead.
2022-06-27 14:06:25 -06:00
Trim21
b80c8f78fc extra bucket is not required anymore 2022-06-28 03:22:32 +08:00
Andrey Nering
7707179b93 Merge pull request #783 from ssbarnea/fix/gha-group
Fix GHA grouping examples
2022-06-21 18:08:47 -03:00
Sorin Sbarnea
4e7d8bacdb Fix GHA grouping examples
Our example was not using the correct syntax required for grouping
command output on GHA.
2022-06-21 17:40:11 +01:00
Andrey Nering
0c46fa5a56 Website: Fix typo 2022-06-17 10:05:11 -03:00
Andrey Nering
36aca00de3 Website: Update link 2022-06-15 14:33:15 -03:00
Andrey Nering
0ec8cf1b53 Hide signals tests behind a build tag
Testing signals requires additional executables to be available in the $PATH
and can intermittently fail as well.

Add a build tag, which means these specific tests will only run when requested.

Closes #780
2022-06-15 10:06:38 -03:00
166 changed files with 8088 additions and 2511 deletions

View File

@@ -8,6 +8,6 @@ charset = utf-8
trim_trailing_whitespace = true
indent_style = tab
[*.{md,yml,yaml,json,toml,htm,html,js,css,svg,sh,bash}]
[*.{md,yml,yaml,json,toml,htm,html,js,css,svg,sh,bash,fish}]
indent_style = space
indent_size = 2

4
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,3 @@
github: andreynering
github: [andreynering, pd93]
open_collective: task
custom: 'https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=GSVDU63RKG45A&currency_code=USD&source=url'
custom: https://taskfile.dev/donate/

View File

@@ -1,13 +1,15 @@
---
name: Bug Report
about: Use the template to report bugs and issues
about: Use this to report bugs and issues
---
> Thanks for your bug report!
>
> Before submitting this issue, please make sure the same problem was
> not already reported by someone else.
>
> Please describe the bug you're facing. Consider pasting example
> Taskfiles showing how to reproduce the problem.
- Task version:
- Operating System:
### Example Taskfile showing the issue
```yaml
```

View File

@@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Help forum on Discord
url: https://discord.com/channels/974121106208354339/1025054680289660989
about: 'The Discord #help channel is the best way to get help from the community.'
- name: Questions, Ideas and General Discussions
url: https://github.com/go-task/task/discussions
about: Ask questions and discuss general ideas with the community
about: Ask questions and discuss general ideas with the community.

View File

@@ -1,11 +1,11 @@
---
name: Feature Request
about: Use the template to make feature requests
about: Use this to make feature requests
---
Describe in detail what feature do you want to see in Task.
Give examples if possible.
Please, search if this wasn't proposed before, and if this is more like an idea
than a strong feature request, consider opening a
[discussion](https://github.com/go-task/task/discussions) instead.
> Describe in detail what feature do you want to see in Task.
> Give examples if possible.
>
> Please, search if this wasn't proposed before, and if this is more like an idea
> than a strong feature request, consider opening a
> [discussion](https://github.com/go-task/task/discussions) instead.

5
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,5 @@
> Thanks for your pull request, we really appreciate contributions!
>
> Please understand that it may take some time to be reviewed.
>
> Also, make sure to follow the [Contribution Guide](https://taskfile.dev/contributing/).

View File

@@ -0,0 +1,43 @@
name: issue awaiting response
on:
issue_comment:
types: [created]
jobs:
issue-awaiting-response:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
github-token: ${{secrets.GH_PAT}}
script: |
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
})
const comments = await github.paginate(
github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
}
)
const labels = await github.paginate(
github.rest.issues.listLabelsOnIssue, {
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
}
)
if (labels.find(label => label.name === 'awaiting response')) {
if (comments[comments.length-1].user?.login === issue.data.user?.login) {
github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: 'awaiting response'
})
}
}

29
.github/workflows/issue-closed.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: issue closed
on:
issues:
types: [closed]
jobs:
issue-closed:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
github-token: ${{secrets.GH_PAT}}
script: |
const labels = await github.paginate(
github.rest.issues.listLabelsOnIssue, {
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
}
)
if (labels.find(label => label.name === 'needs triage')) {
github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: 'needs triage'
})
}

View File

@@ -0,0 +1,29 @@
name: issue needs triage
on:
issues:
types: [opened]
jobs:
issue-needs-triage:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
github-token: ${{secrets.GH_PAT}}
script: |
const labels = await github.paginate(
github.rest.issues.listLabelsOnIssue, {
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
}
)
if (labels.length === 0) {
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['needs triage']
})
}

View File

@@ -14,11 +14,11 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
go-version: 1.20.x
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.46.1
version: v1.51.1

View File

@@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18.x
go-version: 1.20.x
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2

View File

@@ -13,7 +13,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [1.17.x, 1.18.x]
go-version: [1.19.x, 1.20.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{matrix.platform}}
steps:

2
.gitignore vendored
View File

@@ -22,6 +22,7 @@ dist/
# editors
.idea/
.vscode/
.fleet/
# exuberant ctags
tags
@@ -30,3 +31,4 @@ tags
!/bin/.keep
/testdata/vars/v1
/tmp
node_modules

12
.golangci.yml Normal file
View File

@@ -0,0 +1,12 @@
# NOTE(@andreynering): The linters listed here are additions on top of
# those enabled by default:
#
# https://golangci-lint.run/usage/linters/#enabled-by-default
linters:
enable:
- goimports
linters-settings:
goimports:
local-prefixes: github.com/go-task/task

View File

@@ -6,17 +6,20 @@ build:
- darwin
- linux
goarch:
- 386
- '386'
- amd64
- arm
- arm64
goarm:
- 6
- '6'
ignore:
- goos: darwin
goarch: 386
goarch: '386'
env:
- CGO_ENABLED=0
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
- -trimpath
ldflags:
- -s -w # Don't set main.version.

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
18.12.1

View File

@@ -1,12 +1,166 @@
# Changelog
## v3.22.0 - 2023-03-10
- Add a brand new `--global` (`-g`) flag that will run a Taskfile from your
`$HOME` directory. This is useful to have automation that you can run from
anywhere in your system!
([Documentation](https://taskfile.dev/usage/#running-a-global-taskfile), [#1029](https://github.com/go-task/task/pull/1029) by @andreynering).
- Add ability to set `error_only: true` on the `group` output mode. This will
instruct Task to only print a command output if it returned with a non-zero
exit code
([#664](https://github.com/go-task/task/issues/664), [#1022](https://github.com/go-task/task/pull/1022) by @jaedle).
- Fixed bug where `.task/checksum` file was sometimes not being created when
task also declares a `status:`
([#840](https://github.com/go-task/task/issues/840), [#1035](https://github.com/go-task/task/pull/1035) by @harelwa, [#1037](https://github.com/go-task/task/pull/1037) by @pd93).
- Refactored and decoupled fingerprinting from the main Task executor ([#1039](https://github.com/go-task/task/issues/1039) by @pd93).
- Fixed deadlock issue when using `run: once`
([#715](https://github.com/go-task/task/issues/715), [#1025](https://github.com/go-task/task/pull/1025) by @theunrepentantgeek).
## v3.21.0 - 2023-02-22
- Added new `TASK_VERSION` special variable
([#990](https://github.com/go-task/task/issues/990), [#1014](https://github.com/go-task/task/pull/1014) by @ja1code).
- Fixed a bug where tasks were sometimes incorrectly marked as internal ([#1007](https://github.com/go-task/task/pull/1007) by @pd93).
- Update to Go 1.20 (bump minimum version to 1.19) ([#1010](https://github.com/go-task/task/pull/1010) by @pd93)
- Added environment variable `FORCE_COLOR` support to force color output. Usefull for environments without TTY ([#1003](https://github.com/go-task/task/pull/1003) by @automation-stack)
## v3.20.0 - 2023-01-14
- Improve behavior and performance of status checking when using the
`timestamp` mode
([#976](https://github.com/go-task/task/issues/976), [#977](https://github.com/go-task/task/pull/977) by @aminya).
- Performance optimizations were made for large Taskfiles
([#982](https://github.com/go-task/task/pull/982) by @pd93).
- Add ability to configure options for the [`set`](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html)
and [`shopt`](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html) builtins
([#908](https://github.com/go-task/task/issues/908), [#929](https://github.com/go-task/task/pull/929) by @pd93, [Documentation](http://taskfile.dev/usage/#set-and-shopt)).
- Add new `platforms:` attribute to `task` and `cmd`, so it's now possible to
choose in which platforms that given task or command will be run on. Possible
values are operating system (GOOS), architecture (GOARCH) or a combination of
the two. Example: `platforms: [linux]`, `platforms: [amd64]` or
`platforms: [linux/amd64]`. Other platforms will be skipped
([#978](https://github.com/go-task/task/issues/978), [#980](https://github.com/go-task/task/pull/980) by @leaanthony).
## v3.19.1 - 2022-12-31
- Small bug fix: closing `Taskfile.yml` once we're done reading it
([#963](https://github.com/go-task/task/issues/963), [#964](https://github.com/go-task/task/pull/964) by @HeCorr).
- Fixes a bug in v2 that caused a panic when using a `Taskfile_{{OS}}.yml` file
([#961](https://github.com/go-task/task/issues/961), [#971](https://github.com/go-task/task/pull/971) by @pd93).
- Fixed a bug where watch intervals set in the Taskfile were not being respected ([#969](https://github.com/go-task/task/pull/969), [#970](https://github.com/go-task/task/pull/970) by @pd93)
- Add `--json` flag (alias `-j`) with the intent to improve support for code
editors and add room to other possible integrations. This is basic for now,
but we plan to add more info in the near future
([#936](https://github.com/go-task/task/pull/936) by @davidalpert, [#764](https://github.com/go-task/task/issues/764)).
## v3.19.0 - 2022-12-05
- Installation via npm now supports [pnpm](https://pnpm.io/) as well
([go-task/go-npm#2](https://github.com/go-task/go-npm/issues/2), [go-task/go-npm#3](https://github.com/go-task/go-npm/pull/3)).
- It's now possible to run Taskfiles from subdirectories! A new `USER_WORKING_DIR` special
variable was added to add even more flexibility for monorepos
([#289](https://github.com/go-task/task/issues/289), [#920](https://github.com/go-task/task/pull/920)).
- Add task-level `dotenv` support
([#389](https://github.com/go-task/task/issues/389), [#904](https://github.com/go-task/task/pull/904)).
- It's now possible to use global level variables on `includes`
([#942](https://github.com/go-task/task/issues/942), [#943](https://github.com/go-task/task/pull/943)).
- The website got a brand new [translation to Chinese](https://task-zh.readthedocs.io/zh_CN/latest/)
by [@DeronW](https://github.com/DeronW). Thanks!
## v3.18.0 - 2022-11-12
- Show aliases on `task --list --silent` (`task --ls`). This means that aliases
will be completed by the completion scripts
([#919](https://github.com/go-task/task/pull/919)).
- Tasks in the root Taskfile will now be displayed first in `--list`/`--list-all`
output ([#806](https://github.com/go-task/task/pull/806), [#890](https://github.com/go-task/task/pull/890)).
- It's now possible to call a `default` task in an included Taskfile by using
just the namespace. For example: `docs:default` is now automatically
aliased to `docs`
([#661](https://github.com/go-task/task/issues/661), [#815](https://github.com/go-task/task/pull/815)).
## v3.17.0 - 2022-10-14
- Add a "Did you mean ...?" suggestion when a task does not exits another one
with a similar name is found
([#867](https://github.com/go-task/task/issues/867), [#880](https://github.com/go-task/task/pull/880)).
- Now YAML parse errors will print which Taskfile failed to parse
([#885](https://github.com/go-task/task/issues/885), [#887](https://github.com/go-task/task/pull/887)).
- Add ability to set `aliases` for tasks and namespaces ([#268](https://github.com/go-task/task/pull/268), [#340](https://github.com/go-task/task/pull/340), [#879](https://github.com/go-task/task/pull/879)).
- Improvements to Fish shell completion
([#897](https://github.com/go-task/task/pull/897)).
- Added ability to set a different watch interval by setting
`interval: '500ms'` or using the `--interval=500ms` flag
([#813](https://github.com/go-task/task/issues/813), [#865](https://github.com/go-task/task/pull/865)).
- Add colored output to `--list`, `--list-all` and `--summary` flags ([#845](https://github.com/go-task/task/pull/845), [#874](https://github.com/go-task/task/pull/874)).
- Fix unexpected behavior where `label:` was being shown instead of the task
name on `--list`
([#603](https://github.com/go-task/task/issues/603), [#877](https://github.com/go-task/task/pull/877)).
## v3.16.0 - 2022-09-29
- Add `npm` as new installation method: `npm i -g @go-task/cli`
([#870](https://github.com/go-task/task/issues/870), [#871](https://github.com/go-task/task/pull/871), [npm package](https://www.npmjs.com/package/@go-task/cli)).
- Add support to marking tasks and includes as internal, which will hide them
from `--list` and `--list-all`
([#818](https://github.com/go-task/task/pull/818)).
## v3.15.2 - 2022-09-08
- Fix error when using variable in `env:` introduced in the previous release
([#858](https://github.com/go-task/task/issues/858), [#866](https://github.com/go-task/task/pull/866)).
- Fix handling of `CLI_ARGS` (`--`) in Bash completion
([#863](https://github.com/go-task/task/pull/863)).
- On zsh completion, add ability to replace `--list-all` with `--list` as
already possible on the Bash completion
([#861](https://github.com/go-task/task/pull/861)).
## v3.15.0 - 2022-09-03
- Add new special variables `ROOT_DIR` and `TASKFILE_DIR`. This was a highly
requested feature
([#215](https://github.com/go-task/task/issues/215), [#857](https://github.com/go-task/task/pull/857), [Documentation](https://taskfile.dev/api/#special-variables)).
- Follow symlinks on `sources`
([#826](https://github.com/go-task/task/issues/826), [#831](https://github.com/go-task/task/pull/831)).
- Improvements and fixes to Bash completion
([#835](https://github.com/go-task/task/pull/835), [#844](https://github.com/go-task/task/pull/844)).
## v3.14.1 - 2022-08-03
- Always resolve relative include paths relative to the including Taskfile
([#822](https://github.com/go-task/task/issues/822), [#823](https://github.com/go-task/task/pull/823)).
- Fix ZSH and PowerShell completions to consider all tasks instead of just the
public ones (those with descriptions)
([#803](https://github.com/go-task/task/pull/803)).
## v3.14.0 - 2022-07-08
- Add ability to override the `.task` directory location with the
`TASK_TEMP_DIR` environment variable.
- Allow to override Task colors using environment variables:
`TASK_COLOR_RESET`, `TASK_COLOR_BLUE`, `TASK_COLOR_GREEN`,
`TASK_COLOR_CYAN`, `TASK_COLOR_YELLOW`, `TASK_COLOR_MAGENTA`
and `TASK_COLOR_RED`
([#568](https://github.com/go-task/task/pull/568), [#792](https://github.com/go-task/task/pull/792)).
- Fixed bug when using the `output: group` mode where STDOUT and STDERR were
being print in separated blocks instead of in the right order
([#779](https://github.com/go-task/task/issues/779)).
- Starting on this release, ARM architecture binaries are been released to Snap
as well
([#795](https://github.com/go-task/task/issues/795)).
- i386 binaries won't be available anymore on Snap because Ubuntu removed the support
for this architecture.
- Upgrade mvdan.cc/sh, which fixes a bug with associative arrays
([#785](https://github.com/go-task/task/issues/785), [mvdan/sh#884](https://github.com/mvdan/sh/issues/884), [mvdan/sh#893](https://github.com/mvdan/sh/pull/893)).
## v3.13.0 - 2022-06-13
- Added `-n` as an alias to `--dry`
([#776](https://github.com/go-task/task/issues/776), [#777](https://github.com/go-task/task/pull/777)).
- Fix behavior of interrupt (SIGINT, SIGTERM) signals. Task will now give time
for the processes running to do cleanup work
([#458](https://github.com/go-task/task/issues/458), [#479](https://github.com/go-task/task/pull/479), [#728](https://github.com/go-task/task/issues/728)).
([#458](https://github.com/go-task/task/issues/458), [#479](https://github.com/go-task/task/pull/479), [#728](https://github.com/go-task/task/issues/728), [#769](https://github.com/go-task/task/pull/769)).
- Add new `--exit-code` (`-x`) flag that will pass-through the exit form the
command being ran
([#755](https://github.com/go-task/task/pull/755)).

View File

@@ -10,6 +10,18 @@
</p>
<p>
See <a href="https://taskfile.dev">taskfile.dev</a> for the documentation.
<a href="https://taskfile.dev/installation/">Installation</a> | <a href="https://taskfile.dev/usage/">Documentation</a> | <a href="https://twitter.com/taskfiledev">Twitter</a> | <a href="https://fosstodon.org/@task">Mastodon</a> | <a href="https://discord.gg/6TY36E39UK">Discord</a>
</p>
</div>
## Gold Sponsors
<div align="center">
| [Appwrite][appwrite] |
| - |
| [![Appwrite](/docs/static/img/appwrite.svg)][appwrite] |
</div>
[appwrite]: https://appwrite.io/?utm_source=task_github&utm_medium=social&utm_campaign=task_oss_fund

View File

@@ -2,16 +2,10 @@ version: '3'
includes:
docs:
aliases: [d]
taskfile: ./docs
dir: ./docs
vars:
GIT_COMMIT:
sh: git log -n 1 --format=%h
GO_PACKAGES:
sh: go list ./...
env:
CGO_ENABLED: '0'
@@ -23,10 +17,33 @@ tasks:
install:
desc: Installs Task
aliases: [i]
sources:
- './**/*.go'
cmds:
- go install -v -ldflags="-w -s -X main.version={{.GIT_COMMIT}}" ./cmd/task
- go install -v -ldflags="-w -s -X '{{.VERSION_VAR}}={{.GIT_COMMIT}}'" ./cmd/task
vars:
VERSION_VAR: github.com/go-task/task/v3/internal/version.version
GIT_COMMIT:
sh: git log -n 1 --format=%h
generate:
desc: Runs Go generate to create mocks
aliases: [gen, g]
deps: [install:mockgen]
sources:
- "internal/fingerprint/checker.go"
generates:
- "internal/fingerprint/checker_mock.go"
cmds:
- mockgen -source=internal/fingerprint/checker.go -destination=internal/fingerprint/checker_mock.go -package=fingerprint
install:mockgen:
desc: Installs mockgen; a tool to generate mock files
status:
- command -v mockgen &>/dev/null
cmds:
- go install github.com/golang/mock/mockgen@latest
mod:
desc: Downloads and tidy Go modules
@@ -42,8 +59,10 @@ tasks:
lint:
desc: Runs golangci-lint
aliases: [l]
sources:
- './**/*.go'
- .golangci.yml
cmds:
- golangci-lint run
@@ -65,16 +84,50 @@ tasks:
test:
desc: Runs test suite
deps: [install, sleepit:build]
aliases: [t]
deps: [install]
cmds:
- go test {{catLines .GO_PACKAGES}}
vars:
GO_PACKAGES:
sh: go list ./...
test:all:
desc: Runs test suite with signals and watch tests included
deps: [install, sleepit:build]
cmds:
- go test {{catLines .GO_PACKAGES}} -tags 'signals watch'
vars:
GO_PACKAGES:
sh: go list ./...
test-release:
desc: Tests release process without publishing
cmds:
- goreleaser --snapshot --rm-dist
docs:changelog:
desc: Copy CHANGELOG.md to the documentation website
vars:
FILE: docs/docs/changelog.md
cmds:
- rm {{.FILE}}
- 'echo "---" >> {{.FILE}}'
- 'echo "slug: /changelog/" >> {{.FILE}}'
- 'echo "sidebar_position: 7" >> {{.FILE}}'
- 'echo "---" >> {{.FILE}}'
- 'echo "" >> {{.FILE}}'
- 'cat CHANGELOG.md >> {{.FILE}}'
npm:publish:
desc: Publish release to npm
cmds:
- npm publish --access=public
packages:
cmds:
- echo '{{.GO_PACKAGES}}'
vars:
GO_PACKAGES:
sh: go list ./...
silent: true

View File

@@ -130,11 +130,11 @@ func supervisor(
// The goroutine will prepend its prints with the prefix `name`.
// The goroutine will simulate some work and will terminate when one of the following
// conditions happens:
// 1. When `howlong` is elapsed. This case will be signaled on the `workerDone` channel.
// 2. When something happens on channel `canceled`. Note that this simulates real-life,
// so cancellation is not instantaneous: if the caller wants a synchronous cancel,
// it should send a message; if instead it wants an asynchronous cancel, it should
// close the channel.
// 1. When `howlong` is elapsed. This case will be signaled on the `workerDone` channel.
// 2. When something happens on channel `canceled`. Note that this simulates real-life,
// so cancellation is not instantaneous: if the caller wants a synchronous cancel,
// it should send a message; if instead it wants an asynchronous cancel, it should
// close the channel.
func worker(
canceled <-chan struct{},
howlong time.Duration,

View File

@@ -6,8 +6,8 @@ import (
"log"
"os"
"path/filepath"
"runtime/debug"
"strings"
"time"
"github.com/spf13/pflag"
"mvdan.cc/sh/v3/syntax"
@@ -15,13 +15,10 @@ import (
"github.com/go-task/task/v3"
"github.com/go-task/task/v3/args"
"github.com/go-task/task/v3/internal/logger"
ver "github.com/go-task/task/v3/internal/version"
"github.com/go-task/task/v3/taskfile"
)
var (
version = ""
)
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--taskfile] [--dry] [--summary] [task...]
Runs the specified task(s). Falls back to the "default" task if no task name
@@ -59,6 +56,7 @@ func main() {
init bool
list bool
listAll bool
listJson bool
status bool
force bool
watch bool
@@ -73,33 +71,39 @@ func main() {
entrypoint string
output taskfile.Output
color bool
interval time.Duration
global bool
)
pflag.BoolVar(&versionFlag, "version", false, "show Task version")
pflag.BoolVarP(&helpFlag, "help", "h", false, "shows Task usage")
pflag.BoolVarP(&init, "init", "i", false, "creates a new Taskfile.yaml in the current folder")
pflag.BoolVarP(&list, "list", "l", false, "lists tasks with description of current Taskfile")
pflag.BoolVarP(&listAll, "list-all", "a", false, "lists tasks with or without a description")
pflag.BoolVar(&status, "status", false, "exits with non-zero exit code if any of the given tasks is not up-to-date")
pflag.BoolVarP(&force, "force", "f", false, "forces execution even when the task is up-to-date")
pflag.BoolVarP(&watch, "watch", "w", false, "enables watch of the given task")
pflag.BoolVarP(&verbose, "verbose", "v", false, "enables verbose mode")
pflag.BoolVarP(&silent, "silent", "s", false, "disables echoing")
pflag.BoolVarP(&parallel, "parallel", "p", false, "executes tasks provided on command line in parallel")
pflag.BoolVarP(&dry, "dry", "n", false, "compiles and prints tasks in the order that they would be run, without executing them")
pflag.BoolVar(&summary, "summary", false, "show summary about a task")
pflag.BoolVarP(&exitCode, "exit-code", "x", false, "pass-through the exit code of the task command")
pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution")
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`)
pflag.StringVarP(&output.Name, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
pflag.StringVar(&output.Group.Begin, "output-group-begin", "", "message template to print before a task's grouped output")
pflag.StringVar(&output.Group.End, "output-group-end", "", "message template to print after a task's grouped output")
pflag.BoolVarP(&color, "color", "c", true, "colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable")
pflag.IntVarP(&concurrency, "concurrency", "C", 0, "limit number tasks to run concurrently")
pflag.BoolVar(&versionFlag, "version", false, "Show Task version.")
pflag.BoolVarP(&helpFlag, "help", "h", false, "Shows Task usage.")
pflag.BoolVarP(&init, "init", "i", false, "Creates a new Taskfile.yaml in the current folder.")
pflag.BoolVarP(&list, "list", "l", false, "Lists tasks with description of current Taskfile.")
pflag.BoolVarP(&listAll, "list-all", "a", false, "Lists tasks with or without a description.")
pflag.BoolVarP(&listJson, "json", "j", false, "Formats task list as JSON.")
pflag.BoolVar(&status, "status", false, "Exits with non-zero exit code if any of the given tasks is not up-to-date.")
pflag.BoolVarP(&force, "force", "f", false, "Forces execution even when the task is up-to-date.")
pflag.BoolVarP(&watch, "watch", "w", false, "Enables watch of the given task.")
pflag.BoolVarP(&verbose, "verbose", "v", false, "Enables verbose mode.")
pflag.BoolVarP(&silent, "silent", "s", false, "Disables echoing.")
pflag.BoolVarP(&parallel, "parallel", "p", false, "Executes tasks provided on command line in parallel.")
pflag.BoolVarP(&dry, "dry", "n", false, "Compiles and prints tasks in the order that they would be run, without executing them.")
pflag.BoolVar(&summary, "summary", false, "Show summary about a task.")
pflag.BoolVarP(&exitCode, "exit-code", "x", false, "Pass-through the exit code of the task command.")
pflag.StringVarP(&dir, "dir", "d", "", "Sets directory of execution.")
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `Choose which Taskfile to run. Defaults to "Taskfile.yml".`)
pflag.StringVarP(&output.Name, "output", "o", "", "Sets output style: [interleaved|group|prefixed].")
pflag.StringVar(&output.Group.Begin, "output-group-begin", "", "Message template to print before a task's grouped output.")
pflag.StringVar(&output.Group.End, "output-group-end", "", "Message template to print after a task's grouped output.")
pflag.BoolVar(&output.Group.ErrorOnly, "output-group-error-only", false, "Swallow output from successful tasks.")
pflag.BoolVarP(&color, "color", "c", true, "Colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable.")
pflag.IntVarP(&concurrency, "concurrency", "C", 0, "Limit number tasks to run concurrently.")
pflag.DurationVarP(&interval, "interval", "I", 0, "Interval to watch for changes.")
pflag.BoolVarP(&global, "global", "g", false, "Runs global Taskfile, from $HOME/Taskfile.{yml,yaml}.")
pflag.Parse()
if versionFlag {
fmt.Printf("Task version: %s\n", getVersion())
fmt.Printf("Task version: %s\n", ver.GetVersion())
return
}
@@ -119,6 +123,19 @@ func main() {
return
}
if global && dir != "" {
log.Fatal("task: You can't set both --global and --dir")
return
}
if global {
home, err := os.UserHomeDir()
if err != nil {
log.Fatal("task: Failed to get user home directory: %w", err)
return
}
dir = home
}
if dir != "" && entrypoint != "" {
log.Fatal("task: You can't set both --dir and --taskfile")
return
@@ -137,6 +154,10 @@ func main() {
log.Fatal("task: You can't set --output-group-end without --output=group")
return
}
if output.Group.ErrorOnly {
log.Fatal("task: You can't set --output-group-error-only without --output=group")
return
}
}
e := task.Executor{
@@ -151,6 +172,7 @@ func main() {
Parallel: parallel,
Color: color,
Concurrency: concurrency,
Interval: interval,
Stdin: os.Stdin,
Stdout: os.Stdout,
@@ -159,7 +181,12 @@ func main() {
OutputStyle: output,
}
if (list || listAll) && silent {
var listOptions = task.NewListOptions(list, listAll, listJson)
if err := listOptions.Validate(); err != nil {
log.Fatal(err)
}
if (listOptions.ShouldListTasks()) && silent {
e.ListTaskNames(listAll)
return
}
@@ -167,19 +194,11 @@ func main() {
if err := e.Setup(); err != nil {
log.Fatal(err)
}
v, err := e.Taskfile.ParsedVersion()
if err != nil {
log.Fatal(err)
return
}
if list {
e.ListTasksWithDesc()
return
}
if listAll {
e.ListAllTasks()
if listOptions.ShouldListTasks() {
if foundTasks, err := e.ListTasks(listOptions); !foundTasks || err != nil {
os.Exit(1)
}
return
}
@@ -193,7 +212,7 @@ func main() {
log.Fatal(err)
}
if v >= 3.0 {
if e.Taskfile.Version.Compare(taskfile.V3) >= 0 {
calls, globals = args.ParseV3(tasksAndVars...)
} else {
calls, globals = args.ParseV2(tasksAndVars...)
@@ -247,21 +266,3 @@ func getArgs() ([]string, string, error) {
}
return args[:doubleDashPos], strings.Join(quotedCliArgs, " "), nil
}
func getVersion() string {
if version != "" {
return version
}
info, ok := debug.ReadBuildInfo()
if !ok || info.Main.Version == "" {
return "unknown"
}
version = info.Main.Version
if info.Main.Sum != "" {
version += fmt.Sprintf(" (%s)", info.Main.Sum)
}
return version
}

View File

@@ -1,26 +1,55 @@
#!/bin/bash
# vim: set tabstop=2 shiftwidth=2 expandtab:
GO_TASK_PROGNAME=task
_GO_TASK_COMPLETION_LIST_OPTION='--list-all'
_go_task_completion()
function _task()
{
local cur
_get_comp_words_by_ref -n : cur
local cur prev words cword
_init_completion -n : || return
case "$cur" in
--*)
local options
options="$(_parse_help task)"
mapfile -t COMPREPLY < <(compgen -W "$options" -- "$cur")
# Check for `--` within command-line and quit or strip suffix.
local i
for i in "${!words[@]}"; do
if [ "${words[$i]}" == "--" ]; then
# Do not complete words following `--` passed to CLI_ARGS.
[ $cword -gt $i ] && return
# Remove the words following `--` to not put --list in CLI_ARGS.
words=( "${words[@]:0:$i}" )
break
fi
done
# Handle special arguments of options.
case "$prev" in
-d|--dir)
_filedir -d
return $?
;;
*)
local tasks
tasks="$($GO_TASK_PROGNAME --list-all 2> /dev/null | awk 'NR>1 { sub(/:$/,"",$2); print $2 }')"
mapfile -t COMPREPLY < <(compgen -W "$tasks" -- "$cur")
-t|--taskfile)
_filedir yaml || return $?
_filedir yml
return $?
;;
-o|--output)
COMPREPLY=( $( compgen -W "interleaved group prefixed" -- $cur ) )
return 0
;;
esac
# Handle normal options.
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "$(_parse_help $1)" -- $cur ) )
return 0
;;
esac
# Prepare task name completions.
local tasks=( $( "${words[@]}" --silent $_GO_TASK_COMPLETION_LIST_OPTION 2> /dev/null ) )
COMPREPLY=( $( compgen -W "${tasks[*]}" -- "$cur" ) )
# Post-process because task names might contain colons.
__ltrim_colon_completions "$cur"
}
complete -F _go_task_completion $GO_TASK_PROGNAME
complete -F _task task

View File

@@ -1,16 +1,24 @@
set GO_TASK_PROGNAME task
function __task_get_tasks --description "Prints all available tasks with their description"
set -l output ($GO_TASK_PROGNAME --list-all | sed '1d; s/\* \(.*\):\s*\(.*\)/\1\t\2/' | string split0)
# Read the list of tasks (and potential errors)
$GO_TASK_PROGNAME --list-all 2>&1 | read -lz rawOutput
# Return on non-zero exit code (for cases when there is no Taskfile found or etc.)
if test $status -ne 0
return
end
# Grab names and descriptions (if any) of the tasks
set -l output (echo $rawOutput | sed '1d; s/\* \(.*\):\s*\(.*\)/\1\t\2/' | string split0)
if test $output
echo $output
echo $output
end
end
complete -c $GO_TASK_PROGNAME -d 'Runs the specified task(s). Falls back to the "default" task if no task name was specified, or lists all tasks if an unknown task name was
specified.' -xa "(__task_get_tasks)"
complete -c $GO_TASK_PROGNAME -s c -l color -d 'colored output (default true)'
complete -c $GO_TASK_PROGNAME -s d -l dir -d 'sets directory of execution'
complete -c $GO_TASK_PROGNAME -l dry -d 'compiles and prints tasks in the order that they would be run, without executing them'

View File

@@ -1,10 +1,8 @@
$scriptBlock = {
param($commandName, $wordToComplete, $cursorPosition)
$curReg = "task{.exe}? (.*?)$"
$startsWith = $wordToComplete | Select-String $curReg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value }
$reg = "\* ($startsWith.+?):"
$listOutput = $(task -l)
$listOutput | Select-String $reg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value + " " }
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters )
$reg = "\* ($commandName.+?):"
$listOutput = $(task --list-all)
$listOutput | Select-String $reg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value }
}
Register-ArgumentCompleter -Native -CommandName task -ScriptBlock $scriptBlock
Register-ArgumentCompleter -CommandName task -ScriptBlock $scriptBlock

View File

@@ -3,6 +3,8 @@
local context state state_descr line
typeset -A opt_args
_GO_TASK_COMPLETION_LIST_OPTION="${GO_TASK_COMPLETION_LIST_OPTION:---list-all}"
# Listing commands from Taskfile.yml
function __task_list() {
local -a scripts cmd
@@ -27,7 +29,7 @@ function __task_list() {
(( enabled )) || return 0
scripts=()
for item in "${(@)${(f)$("${cmd[@]}" --list)}[2,-1]#\* }"; do
for item in "${(@)${(f)$("${cmd[@]}" $_GO_TASK_COMPLETION_LIST_OPTION)}[2,-1]#\* }"; do
task="${item%%:[[:space:]]*}"
desc="${item##[^[:space:]]##[[:space:]]##}"
scripts+=( "${task//:/\\:}:$desc" )

View File

@@ -1,20 +1,27 @@
version: '3'
tasks:
setup:
yarn:install:
desc: Setup Docusaurus locally
cmds:
- yarn install
sources:
- package.json
- yarn.lock
start:
default:
desc: Start website
deps: [yarn:install]
aliases: [s, start]
vars:
HOST: '{{default "localhost" .HOST}}'
PORT: '{{default "3001" .PORT}}'
cmds:
- npx docusaurus start --no-open --port={{.PORT}}
- npx docusaurus start --no-open --host={{.HOST}} --port={{.PORT}}
build:
desc: Build website
deps: [yarn:install]
cmds:
- npx docusaurus build
@@ -24,6 +31,12 @@ tasks:
- rm -rf ./build
deploy:
desc: Build and deploy Docusaurus. Requires GIT_USER and GIT_PASS envs to be previous set
desc: Build and deploy Docusaurus
summary: Requires GIT_USER and GIT_PASS envs to be previous set
cmds:
- npx docusaurus deploy
upgrade:
desc: Upgrade Docusaurus
cmds:
- yarn upgrade @docusaurus/core@latest @docusaurus/preset-classic@latest

13
docs/constants.js Normal file
View File

@@ -0,0 +1,13 @@
const GITHUB_URL = 'https://github.com/go-task/task';
const TWITTER_URL = 'https://twitter.com/taskfiledev';
const MASTODON_URL = 'https://fosstodon.org/@task';
const DISCORD_URL = 'https://discord.gg/6TY36E39UK';
const CHINESE_URL = 'https://task-zh.readthedocs.io/zh_CN/latest/';
module.exports = {
CHINESE_URL,
DISCORD_URL,
GITHUB_URL,
MASTODON_URL,
TWITTER_URL
};

View File

@@ -15,7 +15,7 @@ task [--flags] [tasks...] [-- CLI_ARGS...]
:::tip
If `--` is given, all remaning arguments to assigned to a special `CLI_ARGS`
If `--` is given, all remaning arguments will be assigned to a special `CLI_ARGS`
variable
:::
@@ -28,13 +28,16 @@ variable
| `-n` | `--dry` | `bool` | `false` | Compiles and prints tasks in the order that they would be run, without executing them. |
| `-x` | `--exit-code` | `bool` | `false` | Pass-through the exit code of the task command. |
| `-f` | `--force` | `bool` | `false` | Forces execution even when the task is up-to-date. |
| `-g` | `--global` | `bool` | `false` | Runs global Taskfile, from `$HOME/Taskfile.{yml,yaml}`. |
| `-h` | `--help` | `bool` | `false` | Shows Task usage. |
| `-i` | `--init` | `bool` | `false` | Creates a new Taskfile.yaml in the current folder. |
| `-I` | `--interval` | `string` | `5s` | Sets a different watch interval when using `--watch`, the default being 5 seconds. This string should be a valid [Go Duration](https://pkg.go.dev/time#ParseDuration). |
| `-l` | `--list` | `bool` | `false` | Lists tasks with description of current Taskfile. |
| `-a` | `--list-all` | `bool` | `false` | Lists tasks with or without a description. |
| `-o` | `--output` | `string` | Default set in the Taskfile or `intervealed` | Sets output style: [`interleaved`/`group`/`prefixed`]. |
| | `--output-group-begin` | `string` | | Message template to print before a task's grouped output. |
| | `--output-group-end ` | `string` | | Message template to print after a task's grouped output. |
| | `--output-group-end` | `string` | | Message template to print after a task's grouped output. |
| | `--output-group-error-only` | `bool` | `false` | Swallow command output on zero exit code. |
| `-p` | `--parallel` | `bool` | `false` | Executes tasks provided on command line in parallel. |
| `-s` | `--silent` | `bool` | `false` | Disables echoing. |
| | `--status` | `bool` | `false` | Exits with non-zero exit code if any of the given tasks is not up-to-date. |
@@ -44,6 +47,37 @@ variable
| | `--version` | `bool` | `false` | Show Task version. |
| `-w` | `--watch` | `bool` | `false` | Enables watch of the given task. |
## Special Variables
There are some special variables that is available on the templating system:
| Var | Description |
| - | - |
| `CLI_ARGS` | Contain all extra arguments passed after `--` when calling Task through the CLI. |
| `TASK` | The name of the current task. |
| `ROOT_DIR` | The absolute path of the root Taskfile. |
| `TASKFILE_DIR` | The absolute path of the included Taskfile. |
| `USER_WORKING_DIR` | The absolute path of the directory `task` was called from. |
| `CHECKSUM` | The checksum of the files listed in `sources`. Only available within the `status` prop and if method is set to `checksum`. |
| `TIMESTAMP` | The date object of the greatest timestamp of the files listes in `sources`. Only available within the `status` prop and if method is set to `timestamp`. |
| `TASK_VERSION` | The current version of task. |
## ENV
Some environment variables can be overriden to adjust Task behavior.
| ENV | Default | Description |
| - | - | - |
| `TASK_TEMP_DIR` | `.task` | Location of the temp dir. Can relative to the project like `tmp/task` or absolute like `/tmp/.task` or `~/.task`. |
| `TASK_COLOR_RESET` | `0` | Color used for white. |
| `TASK_COLOR_BLUE` | `34` | Color used for blue. |
| `TASK_COLOR_GREEN` | `32` | Color used for green. |
| `TASK_COLOR_CYAN` | `36` | Color used for cyan. |
| `TASK_COLOR_YELLOW` | `33` | Color used for yellow. |
| `TASK_COLOR_MAGENTA` | `35` | Color used for magenta. |
| `TASK_COLOR_RED` | `31` | Color used for red. |
| `FORCE_COLOR` | | Force color output usage. |
## Schema
### Taskfile
@@ -51,24 +85,29 @@ variable
| Attribute | Type | Default | Description |
| - | - | - | - |
| `version` | `string` | | Version of the Taskfile. The current version is `3`. |
| `includes` | [`map[string]Include`](#include) | | Additional Taskfiles to be included. |
| `output` | `string` | `interleaved` | Output mode. Available options: `interleaved`, `group` and `prefixed`. |
| `method` | `string` | `checksum` | Default method in this Taskfile. Can be overriden in a task by task basis. Available options: `checksum`, `timestamp` and `none`. |
| `silent` | `bool` | `false` | Default "silent" options for this Taskfile. If `false`, can be overidden with `true` in a task by task basis. |
| `run` | `string` | `always` | Default "run" option for this Taskfile. Available options: `always`, `once` and `when_changed`. |
| `vars` | [`map[string]Variable`](#variable) | | Global variables. |
| `env` | [`map[string]Variable`](#variable) | | Global environment. |
| `includes` | [`map[string]Include`](#include) | | Additional Taskfiles to be included. |
| `vars` | [`map[string]Variable`](#variable) | | A set of global variables. |
| `env` | [`map[string]Variable`](#variable) | | A set of global environment variables. |
| `tasks` | [`map[string]Task`](#task) | | A set of task definitions. |
| `silent` | `bool` | `false` | Default 'silent' options for this Taskfile. If `false`, can be overidden with `true` in a task by task basis. |
| `dotenv` | `[]string` | | A list of `.env` file paths to be parsed. |
| `tasks` | [`map[string]Task`](#task) | | The task definitions. |
| `run` | `string` | `always` | Default 'run' option for this Taskfile. Available options: `always`, `once` and `when_changed`. |
| `interval` | `string` | `5s` | Sets a different watch interval when using `--watch`, the default being 5 seconds. This string should be a valid [Go Duration](https://pkg.go.dev/time#ParseDuration). |
| `set` | `[]string` | | Specify options for the [`set` builtin](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html). |
| `shopt` | `[]string` | | Specify option for the [`shopt` builtin](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html). |
### Include
| Attribute | Type | Default | Description |
| - | - | - | - |
| `taskfile` | `string` | | The path for the Taskfile or directory to be included. If a directory, Task will look for files named `Taskfile.yml` or `Taskfile.yaml` inside that directory. |
| `taskfile` | `string` | | The path for the Taskfile or directory to be included. If a directory, Task will look for files named `Taskfile.yml` or `Taskfile.yaml` inside that directory. If a relative path, resolved relative to the directory containing the including Taskfile. |
| `dir` | `string` | The parent Taskfile directory | The working directory of the included tasks when run. |
| `optional` | `bool` | `false` | If `true`, no errors will be thrown if the specified file does not exist. |
| `internal` | `bool` | `false` | Stops any task in the included Taskfile from being callable on the command line. These commands will also be omitted from the output when used with `--list`. |
| `aliases` | `[]string` | | Alternative names for the namespace of the included Taskfile. |
| `vars` | `map[string]Variable` | | A set of variables to apply to the included Taskfile. |
:::info
@@ -85,22 +124,30 @@ includes:
| Attribute | Type | Default | Description |
| - | - | - | - |
| `desc` | `string` | | A short description of the task. This is listed when calling `task --list`. |
| `summary` | `string` | | A longer description of the task. This is listed when calling `task --summary [task]`. |
| `sources` | `[]string` | | List of sources to check before running this task. Relevant for `checksum` and `timestamp` methods. Can be file paths or star globs. |
| `dir` | `string` | | The current directory which this task should run. |
| `method` | `string` | `checksum` | Method used by this task. Default to the one declared globally or `checksum`. Available options: `checksum`, `timestamp` and `none` |
| `silent` | `bool` | `false` | Skips some output for this task. Note that STDOUT and STDERR of the commands will still be redirected. |
| `cmds` | [`[]Command`](#command) | | A list of shell commands to be executed. |
| `deps` | [`[]Dependency`](#dependency) | | A list of dependencies of this task. Tasks defined here will run in parallel before this task. |
| `label` | `string` | | Overrides the name of the task in the output when a task is run. Supports variables. |
| `desc` | `string` | | A short description of the task. This is displayed when calling `task --list`. |
| `summary` | `string` | | A longer description of the task. This is displayed when calling `task --summary [task]`. |
| `aliases` | `[]string` | | A list of alternative names by which the task can be called. |
| `sources` | `[]string` | | A list of sources to check before running this task. Relevant for `checksum` and `timestamp` methods. Can be file paths or star globs. |
| `generates` | `[]string` | | A list of files meant to be generated by this task. Relevant for `timestamp` method. Can be file paths or star globs. |
| `status` | `[]string` | | A list of commands to check if this task should run. The task is skipped otherwise. This overrides `method`, `sources` and `generates`. |
| `preconditions` | [`[]Precondition`](#precondition) | | A list of commands to check if this task should run. If a condition is not met, the task will error. |
| `dir` | `string` | | The directory in which this task should run. Defaults to the current working directory. |
| `vars` | [`map[string]Variable`](#variable) | | A set of variables that can be used in the task. |
| `env` | [`map[string]Variable`](#variable) | | A set of environment variables that will be made available to shell commands. |
| `dotenv` | `[]string` | | A list of `.env` file paths to be parsed. |
| `silent` | `bool` | `false` | Hides task name and command from output. The command's output will still be redirected to `STDOUT` and `STDERR`. When combined with the `--list` flag, task descriptions will be hidden. |
| `interactive` | `bool` | `false` | Tells task that the command is interactive. |
| `internal` | `bool` | `false` | Stops a task from being callable on the command line. It will also be omitted from the output when used with `--list`. |
| `method` | `string` | `checksum` | Defines which method is used to check the task is up-to-date. `timestamp` will compare the timestamp of the sources and generates files. `checksum` will check the checksum (You probably want to ignore the .task folder in your .gitignore file). `none` skips any validation and always run the task. |
| `prefix` | `string` | | Defines a string to prefix the output of tasks running in parallel. Only used when the output mode is `prefixed`. |
| `ignore_error` | `bool` | `false` | Continue execution if errors happen while executing commands. |
| `run` | `string` | The one declared globally in the Taskfile or `always` | Specifies whether the task should run again or not if called more than once. Available options: `always`, `once` and `when_changed`. |
| `prefix` | `string` | | Allows to override the prefix print before the STDOUT. Only relevant when using the `prefixed` output mode. |
| `ignore_error` | `bool` | `false` | Continue execution if errors happen while executing the commands. |
| `generates` | `[]string` | | List of files meant to be generated by this task. Relevant for `timestamp` method. Can be file paths or star globs. |
| `status` | `[]string` | | List of commands to check if this task should run. The task is skipped otherwise. This overrides `method`, `sources` and `generates`. |
| `preconditions` | [`[]Precondition`](#precondition) | | List of commands to check if this task should run. The task errors otherwise. |
| `vars` | [`map[string]Variable`](#variable) | | Task variables. |
| `env` | [`map[string]Variable`](#variable) | | Task environment. |
| `deps` | [`[]Dependency`](#dependency) | | List of dependencies of this task. |
| `cmds` | [`[]Command`](#command) | | List of commands to be executed. |
| `platforms` | `[]string` | All platforms | Specifies which platforms the task should be run on. [Valid GOOS and GOARCH values allowed](https://github.com/golang/go/blob/master/src/go/build/syslist.go). Task will be skipped otherwise. |
| `set` | `[]string` | | Specify options for the [`set` builtin](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html). |
| `shopt` | `[]string` | | Specify option for the [`shopt` builtin](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html). |
:::info
@@ -114,6 +161,9 @@ tasks:
foobar:
- echo "foo"
- echo "bar"
baz:
cmd: echo "baz"
```
:::
@@ -143,11 +193,14 @@ tasks:
| Attribute | Type | Default | Description |
| - | - | - | - |
| `cmd` | `string` | | The shell command to be executed. |
| `defer` | `string` | | Alternative to `cmd`, but schedules the command to be executed at the end of this task instead of immediately. This cannot be used together with `cmd`. |
| `silent` | `bool` | `false` | Skips some output for this command. Note that STDOUT and STDERR of the commands will still be redirected. |
| `ignore_error` | `bool` | `false` | Continue execution if errors happen while executing the command. |
| `task` | `string` | | Set this to trigger execution of another task instead of running a command. This cannot be set together with `cmd`. |
| `vars` | [`map[string]Variable`](#variable) | | Optional additional variables to be passed to the referenced task. Only relevant when setting `task` instead of `cmd`. |
| `ignore_error` | `bool` | `false` | Continue execution if errors happen while executing the command. |
| `defer` | `string` | | Alternative to `cmd`, but schedules the command to be executed at the end of this task instead of immediately. This cannot be used together with `cmd`. |
| `platforms` | `[]string` | All platforms | Specifies which platforms the command should be run on. [Valid GOOS and GOARCH values allowed](https://github.com/golang/go/blob/master/src/go/build/syslist.go). Command will be skipped otherwise. |
| `set` | `[]string` | | Specify options for the [`set` builtin](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html). |
| `shopt` | `[]string` | | Specify option for the [`shopt` builtin](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html). |
:::info

View File

@@ -1,17 +1,171 @@
---
slug: /changelog/
sidebar_position: 6
sidebar_position: 7
---
# Changelog
## v3.22.0 - 2023-03-10
- Add a brand new `--global` (`-g`) flag that will run a Taskfile from your
`$HOME` directory. This is useful to have automation that you can run from
anywhere in your system!
([Documentation](https://taskfile.dev/usage/#running-a-global-taskfile), [#1029](https://github.com/go-task/task/pull/1029) by @andreynering).
- Add ability to set `error_only: true` on the `group` output mode. This will
instruct Task to only print a command output if it returned with a non-zero
exit code
([#664](https://github.com/go-task/task/issues/664), [#1022](https://github.com/go-task/task/pull/1022) by @jaedle).
- Fixed bug where `.task/checksum` file was sometimes not being created when
task also declares a `status:`
([#840](https://github.com/go-task/task/issues/840), [#1035](https://github.com/go-task/task/pull/1035) by @harelwa, [#1037](https://github.com/go-task/task/pull/1037) by @pd93).
- Refactored and decoupled fingerprinting from the main Task executor ([#1039](https://github.com/go-task/task/issues/1039) by @pd93).
- Fixed deadlock issue when using `run: once`
([#715](https://github.com/go-task/task/issues/715), [#1025](https://github.com/go-task/task/pull/1025) by @theunrepentantgeek).
## v3.21.0 - 2023-02-22
- Added new `TASK_VERSION` special variable
([#990](https://github.com/go-task/task/issues/990), [#1014](https://github.com/go-task/task/pull/1014) by @ja1code).
- Fixed a bug where tasks were sometimes incorrectly marked as internal ([#1007](https://github.com/go-task/task/pull/1007) by @pd93).
- Update to Go 1.20 (bump minimum version to 1.19) ([#1010](https://github.com/go-task/task/pull/1010) by @pd93)
- Added environment variable `FORCE_COLOR` support to force color output. Usefull for environments without TTY ([#1003](https://github.com/go-task/task/pull/1003) by @automation-stack)
## v3.20.0 - 2023-01-14
- Improve behavior and performance of status checking when using the
`timestamp` mode
([#976](https://github.com/go-task/task/issues/976), [#977](https://github.com/go-task/task/pull/977) by @aminya).
- Performance optimizations were made for large Taskfiles
([#982](https://github.com/go-task/task/pull/982) by @pd93).
- Add ability to configure options for the [`set`](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html)
and [`shopt`](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html) builtins
([#908](https://github.com/go-task/task/issues/908), [#929](https://github.com/go-task/task/pull/929) by @pd93, [Documentation](http://taskfile.dev/usage/#set-and-shopt)).
- Add new `platforms:` attribute to `task` and `cmd`, so it's now possible to
choose in which platforms that given task or command will be run on. Possible
values are operating system (GOOS), architecture (GOARCH) or a combination of
the two. Example: `platforms: [linux]`, `platforms: [amd64]` or
`platforms: [linux/amd64]`. Other platforms will be skipped
([#978](https://github.com/go-task/task/issues/978), [#980](https://github.com/go-task/task/pull/980) by @leaanthony).
## v3.19.1 - 2022-12-31
- Small bug fix: closing `Taskfile.yml` once we're done reading it
([#963](https://github.com/go-task/task/issues/963), [#964](https://github.com/go-task/task/pull/964) by @HeCorr).
- Fixes a bug in v2 that caused a panic when using a `Taskfile_{{OS}}.yml` file
([#961](https://github.com/go-task/task/issues/961), [#971](https://github.com/go-task/task/pull/971) by @pd93).
- Fixed a bug where watch intervals set in the Taskfile were not being respected ([#969](https://github.com/go-task/task/pull/969), [#970](https://github.com/go-task/task/pull/970) by @pd93)
- Add `--json` flag (alias `-j`) with the intent to improve support for code
editors and add room to other possible integrations. This is basic for now,
but we plan to add more info in the near future
([#936](https://github.com/go-task/task/pull/936) by @davidalpert, [#764](https://github.com/go-task/task/issues/764)).
## v3.19.0 - 2022-12-05
- Installation via npm now supports [pnpm](https://pnpm.io/) as well
([go-task/go-npm#2](https://github.com/go-task/go-npm/issues/2), [go-task/go-npm#3](https://github.com/go-task/go-npm/pull/3)).
- It's now possible to run Taskfiles from subdirectories! A new `USER_WORKING_DIR` special
variable was added to add even more flexibility for monorepos
([#289](https://github.com/go-task/task/issues/289), [#920](https://github.com/go-task/task/pull/920)).
- Add task-level `dotenv` support
([#389](https://github.com/go-task/task/issues/389), [#904](https://github.com/go-task/task/pull/904)).
- It's now possible to use global level variables on `includes`
([#942](https://github.com/go-task/task/issues/942), [#943](https://github.com/go-task/task/pull/943)).
- The website got a brand new [translation to Chinese](https://task-zh.readthedocs.io/zh_CN/latest/)
by [@DeronW](https://github.com/DeronW). Thanks!
## v3.18.0 - 2022-11-12
- Show aliases on `task --list --silent` (`task --ls`). This means that aliases
will be completed by the completion scripts
([#919](https://github.com/go-task/task/pull/919)).
- Tasks in the root Taskfile will now be displayed first in `--list`/`--list-all`
output ([#806](https://github.com/go-task/task/pull/806), [#890](https://github.com/go-task/task/pull/890)).
- It's now possible to call a `default` task in an included Taskfile by using
just the namespace. For example: `docs:default` is now automatically
aliased to `docs`
([#661](https://github.com/go-task/task/issues/661), [#815](https://github.com/go-task/task/pull/815)).
## v3.17.0 - 2022-10-14
- Add a "Did you mean ...?" suggestion when a task does not exits another one
with a similar name is found
([#867](https://github.com/go-task/task/issues/867), [#880](https://github.com/go-task/task/pull/880)).
- Now YAML parse errors will print which Taskfile failed to parse
([#885](https://github.com/go-task/task/issues/885), [#887](https://github.com/go-task/task/pull/887)).
- Add ability to set `aliases` for tasks and namespaces ([#268](https://github.com/go-task/task/pull/268), [#340](https://github.com/go-task/task/pull/340), [#879](https://github.com/go-task/task/pull/879)).
- Improvements to Fish shell completion
([#897](https://github.com/go-task/task/pull/897)).
- Added ability to set a different watch interval by setting
`interval: '500ms'` or using the `--interval=500ms` flag
([#813](https://github.com/go-task/task/issues/813), [#865](https://github.com/go-task/task/pull/865)).
- Add colored output to `--list`, `--list-all` and `--summary` flags ([#845](https://github.com/go-task/task/pull/845), [#874](https://github.com/go-task/task/pull/874)).
- Fix unexpected behavior where `label:` was being shown instead of the task
name on `--list`
([#603](https://github.com/go-task/task/issues/603), [#877](https://github.com/go-task/task/pull/877)).
## v3.16.0 - 2022-09-29
- Add `npm` as new installation method: `npm i -g @go-task/cli`
([#870](https://github.com/go-task/task/issues/870), [#871](https://github.com/go-task/task/pull/871), [npm package](https://www.npmjs.com/package/@go-task/cli)).
- Add support to marking tasks and includes as internal, which will hide them
from `--list` and `--list-all`
([#818](https://github.com/go-task/task/pull/818)).
## v3.15.2 - 2022-09-08
- Fix error when using variable in `env:` introduced in the previous release
([#858](https://github.com/go-task/task/issues/858), [#866](https://github.com/go-task/task/pull/866)).
- Fix handling of `CLI_ARGS` (`--`) in Bash completion
([#863](https://github.com/go-task/task/pull/863)).
- On zsh completion, add ability to replace `--list-all` with `--list` as
already possible on the Bash completion
([#861](https://github.com/go-task/task/pull/861)).
## v3.15.0 - 2022-09-03
- Add new special variables `ROOT_DIR` and `TASKFILE_DIR`. This was a highly
requested feature
([#215](https://github.com/go-task/task/issues/215), [#857](https://github.com/go-task/task/pull/857), [Documentation](https://taskfile.dev/api/#special-variables)).
- Follow symlinks on `sources`
([#826](https://github.com/go-task/task/issues/826), [#831](https://github.com/go-task/task/pull/831)).
- Improvements and fixes to Bash completion
([#835](https://github.com/go-task/task/pull/835), [#844](https://github.com/go-task/task/pull/844)).
## v3.14.1 - 2022-08-03
- Always resolve relative include paths relative to the including Taskfile
([#822](https://github.com/go-task/task/issues/822), [#823](https://github.com/go-task/task/pull/823)).
- Fix ZSH and PowerShell completions to consider all tasks instead of just the
public ones (those with descriptions)
([#803](https://github.com/go-task/task/pull/803)).
## v3.14.0 - 2022-07-08
- Add ability to override the `.task` directory location with the
`TASK_TEMP_DIR` environment variable.
- Allow to override Task colors using environment variables:
`TASK_COLOR_RESET`, `TASK_COLOR_BLUE`, `TASK_COLOR_GREEN`,
`TASK_COLOR_CYAN`, `TASK_COLOR_YELLOW`, `TASK_COLOR_MAGENTA`
and `TASK_COLOR_RED`
([#568](https://github.com/go-task/task/pull/568), [#792](https://github.com/go-task/task/pull/792)).
- Fixed bug when using the `output: group` mode where STDOUT and STDERR were
being print in separated blocks instead of in the right order
([#779](https://github.com/go-task/task/issues/779)).
- Starting on this release, ARM architecture binaries are been released to Snap
as well
([#795](https://github.com/go-task/task/issues/795)).
- i386 binaries won't be available anymore on Snap because Ubuntu removed the support
for this architecture.
- Upgrade mvdan.cc/sh, which fixes a bug with associative arrays
([#785](https://github.com/go-task/task/issues/785), [mvdan/sh#884](https://github.com/mvdan/sh/issues/884), [mvdan/sh#893](https://github.com/mvdan/sh/pull/893)).
## v3.13.0 - 2022-06-13
- Added `-n` as an alias to `--dry`
([#776](https://github.com/go-task/task/issues/776), [#777](https://github.com/go-task/task/pull/777)).
- Fix behavior of interrupt (SIGINT, SIGTERM) signals. Task will now give time
for the processes running to do cleanup work
([#458](https://github.com/go-task/task/issues/458), [#479](https://github.com/go-task/task/pull/479), [#728](https://github.com/go-task/task/issues/728)).
([#458](https://github.com/go-task/task/issues/458), [#479](https://github.com/go-task/task/pull/479), [#728](https://github.com/go-task/task/issues/728), [#769](https://github.com/go-task/task/pull/769)).
- Add new `--exit-code` (`-x`) flag that will pass-through the exit form the
command being ran
([#755](https://github.com/go-task/task/pull/755)).

View File

@@ -1,6 +1,6 @@
---
slug: /community/
sidebar_position: 6
sidebar_position: 8
---
# Community
@@ -9,17 +9,22 @@ Some of the work to improve the Task ecosystem is done by the community, be
it installation methods or integrations with code editor. I (the author) am
thankful for everyone that helps me to improve the overall experience.
## Translations
[@DeronW](https://github.com/DeronW) maintains the
[Chinese translation](https://task-zh.readthedocs.io/zh_CN/latest/) of the
website [on this repository](https://github.com/DeronW/task).
## Editor Integrations
### JSON Schema
[@KROSF](https://github.com/KROSF) worked on a JSON Schema [into this Gist](https://gist.github.com/KROSF/c5435acf590acd632f71bb720f685895),
which later was made officially available by [@Crandel](https://github.com/Crandel)
at [https://json.schemastore.org/taskfile.json](https://json.schemastore.org/taskfile.json).
Further improvements are possible by opening pull requests changing
[this file](https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/taskfile.json).
Some code editors, like Visual Studio Code, make use of Schema Store
automatically.
Initial work on the schema was made by [@KROSF](https://github.com/KROSF)
on [this Gist](https://gist.github.com/KROSF/c5435acf590acd632f71bb720f685895).
The schema is currently available at
https://taskfile.dev/schema.json and linked at https://json.schemastore.org/taskfile.json
so it is be used automatically many code editors, like VSCode.
Contributions can be done by editing [this file](https://github.com/go-task/task/blob/master/docs/static/schema.json).
### Visual Studio Code extension
@@ -46,9 +51,11 @@ Some installation methods are maintained by third party:
- [GitHub Actions](https://github.com/arduino/setup-task)
by [@arduino](https://github.com/arduino)
- [AUR](https://aur.archlinux.org/packages/taskfile-git)
by [@kovetskiy](https://github.com/kovetskiy)
- [AUR](https://aur.archlinux.org/packages/go-task-bin)
by [@carlsmedstad](https://github.com/carlsmedstad)
- [Scoop](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json)
- [Fedora](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)
- [NixOS](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/go-task/default.nix)
## More

124
docs/docs/contributing.md Normal file
View File

@@ -0,0 +1,124 @@
---
slug: /contributing/
sidebar_position: 9
---
# Contributing
Contributions to Task are very welcome, but we ask that you read this document
before submitting a PR.
## Before you start
- **Check existing work** - Is there an existing PR? Are there issues discussing
the feature/change you want to make? Please make sure you consider/address these
discussions in your work.
- **Backwards compatibility** - Will your change break existing Taskfiles? It is
much more likely that your change will merged if it backwards compatible. Is
there an approach you can take that maintains this compatibility? If not,
consider opening an issue first so that API changes can be discussed before you
invest you time into a PR.
## 1. Setup
- **Go** - Task is written in [Go]. We always support the latest two major Go
versions, so make sure your version is recent enough.
- **Node.js** - [Node.js] is used to host Task's documentation server and is
required if you want to run this server locally.
- **Yarn** - [Yarn] is the Node.js package manager used by Task.
## 2. Making changes
- **Code style** - Try to maintain the existing code style where possible and
ensure that code is formatted by `gofmt`. We use `golangci-lint` in our CI to
enforce a consistent style and best-practise. There's a `lint` command in
the Taskfile to run this locally.
- **Documentation** - Ensure that you add/update any relevant documentation. See
the [updating documentation](#updating-documentation) section below.
- **Tests** - Ensure that you add/update any relevant tests and that all tests
are passing before submitting the PR. See the [writing tests](#writing-tests)
section below.
### Running your changes
To run Task with working changes, you can use `go run ./cmd/task`. To run a
development build of task against a test Taskfile in `testdata`, you can use `go
run ./cmd/task --dir ./testdata/<my_test_dir> <task_name>`.
### Updating documentation
Task uses [Docusaurus] to host a documentation server. This can be setup and run
locally by using `task docs:setup` and `task docs:start` respectively (requires
`nodejs` & `yarn`). All content is written in Markdown and is located in the
`docs/docs` directory. All Markdown documents should have an 80 character line
wrap limit.
When making a change, consider whether a change to the [Usage Guide](./usage.md)
is necessary. This document contains descriptions and examples of how to use
Task features. If you're adding a new feature, try to find an appropriate place
to add a new section. If you're updating an existing feature, ensure that the
documentation and any examples are up-to-date. Ensure that any examples follow
the [Taskfile Styleguide](./styleguide.md).
If you added a new field, command or flag, ensure that you add it to the [API
Reference](./api_reference.md). New fields also need to be added to the
[JSON Schema](../static/schema.json). The descriptions for fields in the API
reference and the schema should match.
### Writing tests
Most of Task's test are held in the `task_test.go` file in the project root and
this is where you'll most likely want to add new ones too. Most of these tests
also have a subdirectory in the `testdata` directory where any Taskfiles/data
required to run the tests are stored.
When making a changes, consider whether new tests are required. These tests
should ensure that the functionality you are adding will continue to work in the
future. Existing tests may also need updating if you have changed Task's
behaviour.
## 3. Committing your code
Try to write meaningful commit messages and avoid having too many commits on
the PR. Most PRs should likely have a single commit (although for bigger PRs it
may be reasonable to split it in a few). Git squash and rebase is your friend!
## 4. Submitting a PR
- **Describe your changes** - Ensure that you provide a comprehensive
description of your changes.
- **Issue/PR links** - Link any previous work such as related issues or PRs.
Please describe how your changes differ to/extend this work.
- **Examples** - Add any examples that you think are useful to demonstrate the
effect of your changes.
- **Draft PRs** - If your changes are incomplete, but you would like to discuss
them, open the PR as a draft and add a comment to start a discussion. Using
comments rather than the PR description allows the description to be updated
later while preserving any discussions.
## FAQ
> I want to contribute, where do I start?
Take a look at the list of [open issues]. We have a [good first issue] label for
simpler issues that are ideal for first time contributions.
All kinds of contributions are welcome, whether its a typo fix or a shiny new
feature. You can also contribute by upvoting/commenting on issues, helping to
answer questions or contributing to other [community projects](./community.md).
> I'm stuck, where can I get help?
If you have questions, feel free to ask them in the `#help` channel on our
[Discord server].
---
[Go]: https://go.dev
[install version 1.18+]: https://go.dev/doc/install
[Node.js]: https://nodejs.org/en/
[Yarn]: https://yarnpkg.com/
[Docusaurus]: https://docusaurus.io
[open issues]: https://github.com/go-task/task/issues
[good first issue]: https://github.com/go-task/task/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
[Discord server]: https://discord.gg/6TY36E39UK

View File

@@ -1,6 +1,6 @@
---
slug: /donate/
sidebar_position: 9
sidebar_position: 12
---
# Donate
@@ -11,10 +11,23 @@ channels listed below.
This is just a way of saying "thank you", it won't give you any benefits like
higher priority on issues or something similar.
Companies who donate at least $50/month will be featured as a "Gold Sponsor"
in the website homepage and on the GitHub repository README. Make contact with
[@andreynering] with the logo you want to be shown.
Suspect businesses (gambling, casinos, etc) won't be allowed, though.
## GitHub Sponsors
The preferred way to donate to the maintainers is via GitHub Sponsors.
Just use the following links to do your donation:
- [@andreynering](https://github.com/sponsors/andreynering)
- [@pd93](https://github.com/sponsors/pd93)
## Open Collective
Task is on [Open Collective](https://opencollective.com/task) and you have
these options to donate:
If you prefer [Open Collective](https://opencollective.com/task) you can donate
by using these links:
- [$2 per month](https://opencollective.com/task/contribute/backer-4034/checkout)
- [$5 per month](https://opencollective.com/task/contribute/supporter-8404/checkout)
@@ -22,15 +35,15 @@ these options to donate:
- [$50 per month](https://opencollective.com/task/contribute/sponsor-28775/checkout)
- [Custom value - One-time donation option supported](https://opencollective.com/task/donate)
## GitHub Sponsors
- [@andreynering](https://github.com/sponsors/andreynering)
## PayPal
You can donate to [@andreynering] via PayPal as well:
- [Any value - One-time donation](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=GSVDU63RKG45A&currency_code=USD&source=url)
## PIX (Brazil only)
If you're Brazilian, you can donate any value by
And if you're Brazilian, you can also donate to [@andreynering] via PIX by
[using this QR Code](/img/pix.png).
[@andreynering]: https://github.com/andreynering

54
docs/docs/faq.md Normal file
View File

@@ -0,0 +1,54 @@
---
slug: /faq/
sidebar_position: 5
---
# FAQ
This page contains a list of frequently asked questions about Task.
- [Why won't my task update my shell environment?](#why-wont-my-task-update-my-shell-environment)
- ['x' builtin command doesn't work on Windows](#x-builtin-command-doesnt-work-on-windows)
## Why won't my task update my shell environment?
This is a limitation of how shells work. Task runs as a subprocess of your
current shell, so it can't change the environment of the shell that started it.
This limitation is shared by other task runners and build tools too.
A common way to work around this is to create a task that will generate output
that can be parsed by your shell. For example, to set an environment variable on
your shell you can write a task like this:
```yaml
my-shell-env:
cmds:
- echo "export FOO=foo"
- echo "export BAR=bar"
```
Now run `eval $(task my-shell-env)` and the variables `$FOO` and `$BAR` will be
available in your shell.
## 'x' builtin command doesn't work on Windows
The default shell on Windows (`cmd` and `powershell`) do not have commands like
`rm` and `cp` available as builtins. This means that these commands won't work.
If you want to make your Taskfile fully cross-platform, you'll need to work
around this limitation using one of the following methods:
- Use the `{{OS}}` function to run an OS-specific script.
- Use something like `{{if eq OS "windows"}}powershell {{end}}<my_cmd>` to
detect windows and run the command in Powershell directly.
- Use a shell on Windows that supports these commands as builtins, such as [Git
Bash] or [WSL].
We want to make improvements to this part of Task and the issues below track
this work. Constructive comments and contributions are very welcome!
- [#197](https://github.com/go-task/task/issues/197)
- [mvdan/sh#93](https://github.com/mvdan/sh/issues/93)
- [mvdan/sh#97](https://github.com/mvdan/sh/issues/97)
[Git Bash]: https://gitforwindows.org/
[WSL]: https://learn.microsoft.com/en-us/windows/wsl/install

View File

@@ -18,6 +18,15 @@ Task is as simple as running:
brew install go-task/tap/go-task
```
The above Formula is [maintained by ourselves](https://github.com/go-task/homebrew-tap/blob/master/Formula/go-task.rb).
Recently, Task was also made available [on the official Homebrew repository](https://formulae.brew.sh/formula/go-task),
so you also have that option if you prefer:
```bash
brew install go-task
```
### Snap
Task is available in [Snapcraft][snapcraft], but keep in mind that your
@@ -39,14 +48,12 @@ choco install go-task
This installation method is community owned.
### Scoop
If you're on Windows and have [Scoop][scoop] installed, use `extras` bucket
to install Task like:
If you're on Windows and have [Scoop][scoop] installed, getting
Task is as simple as running:
```cmd
scoop bucket add extras
scoop install task
```
@@ -56,15 +63,23 @@ may take some time until it's available on Scoop.
### AUR
If you're on Arch Linux you can install Task from
[AUR](https://aur.archlinux.org/packages/taskfile-git) using your favorite
[AUR](https://aur.archlinux.org/packages/go-task-bin) using your favorite
package manager such as `yay`, `pacaur` or `yaourt`:
```cmd
yay -S taskfile-git
yay -S go-task-bin
```
This installation method is community owned, but since it's `-git` version of
the package, it's always latest available version based on the Git repository.
Alternatively, there's
[this package](https://aur.archlinux.org/packages/go-task) which installs from
the source code instead of downloading the binary from the
[releases page](https://github.com/go-task/task/releases):
```cmd
yay -S go-task
```
This installation method is community owned.
### Fedora
@@ -90,6 +105,15 @@ nix-env -iA nixpkgs.go-task
This installation method is community owned. After a new release of Task, it
may take some time until it's available in [nixpkgs](https://github.com/NixOS/nixpkgs).
### npm
You can also use Node and npm to install Task by installing
[this package](https://www.npmjs.com/package/@go-task/cli).
```bash
npm install -g @go-task/cli
```
## Get The Binary
### Binary
@@ -107,19 +131,25 @@ We also have an [install script][installscript] which is very useful in
scenarios like CI. Many thanks to [GoDownloader][godownloader] for enabling the
easy generation of this script.
By default, it installs on the `./bin` directory relative to the working
directory:
```bash
# For Default Installation to ./bin with debug logging
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
# For Installation To /usr/local/bin for userwide access with debug logging
# May require sudo sh
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
```
:::info
It is possible to override the installation directory with the `-b` parameter.
On Linux, common choices are `~/.local/bin` and `~/bin` to install for the
current user or `/usr/local/bin` to install for all users:
This method will download the binary on the local `./bin` directory by default.
```bash
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
```
:::caution
On macOS and Windows, `~/.local/bin` and `~/bin` are not added to `$PATH` by
default.
:::
@@ -140,9 +170,10 @@ This installation method is community owned.
### Go Modules
First, make sure you have [Go][go] properly installed and setup.
Ensure that you have a supported version of [Go][go] properly installed and setup. You can find
the minimum required version of Go in the [go.mod](https://github.com/go-task/task/blob/master/go.mod#L3) file.
You can easily install the latest release globally by running:
You can then install the latest release globally by running:
```bash
go install github.com/go-task/task/v3/cmd/task@latest
@@ -154,12 +185,6 @@ Or you can install into another directory:
env GOBIN=/bin go install github.com/go-task/task/v3/cmd/task@latest
```
If using Go 1.15 or earlier, instead use:
```bash
env GO111MODULE=on go get -u github.com/go-task/task/v3/cmd/task@latest
```
:::tip
For CI environments we recommend using the [install script](#get-the-binary)
@@ -168,6 +193,68 @@ released binary.
:::
## Setup completions
Download the autocompletion file corresponding to your shell.
[All completions are available on the Task repository](https://github.com/go-task/task/tree/master/completion).
### Bash
First, ensure that you installed bash-completion using your package manager.
Make the completion file executable:
```
chmod +x path/to/task.bash
```
After, add this to your `~/.bash_profile`:
```shell
source path/to/task.bash
```
### ZSH
Put the `_task` file somewhere in your `$FPATH`:
```shell
mv path/to/_task /usr/local/share/zsh/site-functions/_task
```
Ensure that the following is present in your `~/.zshrc`:
```shell
autoload -U compinit
compinit -i
```
ZSH version 5.7 or later is recommended.
### Fish
Move the `task.fish` completion script:
```shell
mv path/to/task.fish ~/.config/fish/completions/task.fish
```
### PowerShell
Open your profile script with:
```
mkdir -Path (Split-Path -Parent $profile) -ErrorAction SilentlyContinue
notepad $profile
```
Add the line and save the file:
```shell
Invoke-Expression -Command path/to/task.ps1
```
[go]: https://golang.org/
[snapcraft]: https://snapcraft.io/task
[homebrew]: https://brew.sh/

View File

@@ -38,20 +38,31 @@ guide to check the full schema documentation and Task features.
## Features
- [Easy installation](installation.md): just download a single binary, add to
$PATH and you're done! Or you can also install using [Homebrew][homebrew],
[Snapcraft][snapcraft], or [Scoop][scoop] if you want;
`$PATH` and you're done! Or you can also install using [Homebrew][homebrew],
[Snapcraft][snapcraft], or [Scoop][scoop] if you want.
- Available on CIs: by adding [this simple command](installation.md#install-script)
to install on your CI script and you're done to use Task as part of your CI pipeline;
to install on your CI script and you're ready 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 shell interpreter for Go][sh];
Task also supports Windows thanks to [this 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).
## Gold Sponsors
<div class="gold-sponsors">
| [Appwrite][appwrite] |
| - |
| [![Appwrite](/img/appwrite.svg)][appwrite] |
</div>
[make]: https://www.gnu.org/software/make/
[go]: https://go.dev/
[yaml]: http://yaml.org/
[homebrew]: https://brew.sh/
[snapcraft]: https://snapcraft.io/
[scoop]: https://scoop.sh/
[sh]: https://mvdan.cc/sh
[sh]: https://github.com/mvdan/sh
[appwrite]: https://appwrite.io/?utm_source=taskfile.dev&utm_medium=website&utm_campaign=task_oss_fund

View File

@@ -1,6 +1,6 @@
---
slug: /releasing/
sidebar_position: 7
sidebar_position: 10
---
# Releasing
@@ -13,27 +13,35 @@ the `test-release` task of the Taskfile.
artifacts automatically when a new Git tag is pushed to master
(raw executables and DEB and RPM packages).
Since v3.15.0, raw executables can also be reproduced and verified locally by
checking out a specific tag and calling `goreleaser build`, using the Go version
defined in the above GitHub Actions.
# Homebrew
To release a new version on the [Homebrew tap][homebrewtap] edit the
[Formula/go-task.rb][gotaskrb] file, updating with the new version, download
URL and sha256.
Goreleaser will automatically push a new commit to the
[Formula/go-task.rb][gotaskrb] file in the [Homebrew tap][homebrewtap]
repository to release the new version.
# npm
To release to npm update the version in the [`package.json`][packagejson] file
and then run `task npm:publish` to push it.
# Snapcraft
The exception is the publishing of a new version of the
[snap package][snappackage]. This current require two steps after publishing
the binaries:
The [snap package][snappackage] requires to manual steps to release a new
version:
* Updating the current version on [snapcraft.yaml][snapcraftyaml];
* Moving both `i386` and `amd64` new artifacts to the stable channel on
the [Snapcraft dashboard][snapcraftdashboard]
* Updating the current version on [snapcraft.yaml][snapcraftyaml].
* Moving both `amd64`, `armhf` and `arm64` new artifacts to the stable channel on
the [Snapcraft dashboard][snapcraftdashboard].
# Scoop
Scoop is a community owned installation method. Scoop owners usually take care
of updating versions there by editing
[this file](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json).
Scoop is a command-line package manager for the Windows operating system.
Scoop package manifests are maintained by the community.
Scoop owners usually take care of updating versions there by editing [this file](https://github.com/ScoopInstaller/Main/blob/master/bucket/task.json).
If you think its Task version is outdated, open an issue to let us know.
# Nix
@@ -46,6 +54,7 @@ If you think its Task version is outdated, open an issue to let us know.
[goreleaser]: https://goreleaser.com/
[homebrewtap]: https://github.com/go-task/homebrew-tap
[gotaskrb]: https://github.com/go-task/homebrew-tap/blob/master/Formula/go-task.rb
[packagejson]: https://github.com/go-task/task/blob/master/package.json#L3
[snappackage]: https://github.com/go-task/snap
[snapcraftyaml]: https://github.com/go-task/snap/blob/master/snap/snapcraft.yaml#L2
[snapcraftdashboard]: https://snapcraft.io/task/releases

View File

@@ -1,6 +1,6 @@
---
slug: /styleguide/
sidebar_position: 5
sidebar_position: 6
---
# Styleguide

View File

@@ -1,6 +1,6 @@
---
slug: /taskfile-versions/
sidebar_position: 8
sidebar_position: 11
---
# Taskfile Versions

View File

@@ -9,7 +9,7 @@ sidebar_position: 3
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
The example below allows compiling a Go app and uses [esbuild](https://esbuild.github.io/) to concat
and minify multiple CSS files into a single one.
```yaml
@@ -22,7 +22,7 @@ tasks:
assets:
cmds:
- minify -o public/style.css src/css
- esbuild --bundle --minify css/index.css > public/bundle.css
```
Running the tasks is as simple as running:
@@ -52,6 +52,69 @@ committed version (`.dist`) while still allowing individual users to override
the Taskfile by adding an additional `Taskfile.yml` (which would be on
`.gitignore`).
### Running a Taskfile from a subdirectory
If a Taskfile cannot be found in the current working directory, it will walk up
the file tree until it finds one (similar to how `git` works). When running Task
from a subdirectory like this, it will behave as if you ran it from the
directory containing the Taskfile.
You can use this functionality along with the special `{{.USER_WORKING_DIR}}`
variable to create some very useful reusable tasks. For example, if you have a
monorepo with directories for each microservice, you can `cd` into a
microservice directory and run a task command to bring it up without having to
create multiple tasks or Taskfiles with identical content. For example:
```yaml
version: '3'
tasks:
up:
dir: '{{.USER_WORKING_DIR}}'
preconditions:
- test -f docker-compose.yml
cmds:
- docker-compose up -d
```
In this example, we can run `cd <service>` and `task up` and as long as the
`<service>` directory contains a `docker-compose.yml`, the Docker composition will be
brought up.
### Running a global Taskfile
If you call Task with the `--global` (alias `-g`) flag, it will look for your
home directory instead of your working directory. In short, Task will look for
a Taskfile on either `$HOME/Taskfile.yml` or `$HOME/Taskfile.yaml` paths.
This is useful to have automation that you can run from anywhere in your
system!
:::info
When running your global Taskfile with `-g`, tasks will run on `$HOME` by
default, and not on your working directory!
As mentioned in the previous section, the `{{.USER_WORKING_DIR}}` special
variable can be very handy here to run stuff on the directory you're calling
`task -g` from.
```yaml
version: '3'
tasks:
from-home:
cmds:
- pwd
from-working-directory:
dir: '{{.USER_WORKING_DIR}}'
cmds:
- pwd
```
:::
## Environment variables
### Task
@@ -118,6 +181,45 @@ tasks:
- echo "Using $KEYNAME and endpoint $ENDPOINT"
```
Dotenv files can also be specified at the task level:
```yaml
version: '3'
env:
ENV: testing
tasks:
greet:
dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env']
cmds:
- echo "Using $KEYNAME and endpoint $ENDPOINT"
```
Environment variables specified explicitly at the task-level will override
variables defined in dotfiles:
```yaml
version: '3'
env:
ENV: testing
tasks:
greet:
dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env']
env:
KEYNAME: DIFFERENT_VALUE
cmds:
- echo "Using $KEYNAME and endpoint $ENDPOINT"
```
:::info
Please note that you are not currently able to use the `dotenv` key inside included Taskfiles.
:::
## Including other Taskfiles
If you want to share tasks between different projects (Taskfiles), you can use
@@ -136,6 +238,8 @@ namespace. So, you'd call `task docs:serve` to run the `serve` task from
`documentation/Taskfile.yml` or `task docker:build` to run the `build` task
from the `DockerTasks.yml` file.
Relative paths are resolved relative to the directory containing the including Taskfile.
### OS-specific Taskfiles
With `version: '2'`, task automatically includes any `Taskfile_{{OS}}.yml`
@@ -192,6 +296,22 @@ tasks:
- echo "This command can still be successfully executed if ./tests/Taskfile.yml does not exist"
```
### Internal includes
Includes marked as internal will set all the tasks of the included file to be
internal as well (see the [Internal tasks](#internal-tasks) section below).
This is useful when including utility tasks that are not intended to be used
directly by the user.
```yaml
version: '3'
includes:
tests:
taskfile: ./taskfiles/Utils.yml
internal: true
```
### Vars of included Taskfiles
You can also specify variables when including a Taskfile. This may be useful
@@ -212,15 +332,53 @@ includes:
DOCKER_IMAGE: frontend_image
```
### Namespace aliases
When including a Taskfile, you can give the namespace a list of `aliases`.
This works in the same way as [task aliases](#task-aliases) and can be used
together to create shorter and easier-to-type commands.
```yaml
version: '3'
includes:
generate:
taskfile: ./taskfiles/Generate.yml
aliases: [gen]
```
:::info
Vars declared in the included Taskfile have preference over the
included ones! If you want a variable in an included Taskfile to be overridable,
variables in the including Taskfile! If you want a variable in an included Taskfile to be overridable,
use the [default function](https://go-task.github.io/slim-sprig/defaults.html):
`MY_VAR: '{{.MY_VAR | default "my-default-value"}}'`.
:::
## Internal tasks
Internal tasks are tasks that cannot be called directly by the user. They will
not appear in the output when running `task --list|--list-all`. Other tasks may
call internal tasks in the usual way. This is useful for creating reusable,
function-like tasks that have no useful purpose on the command line.
```yaml
version: '3'
tasks:
build-image-1:
cmds:
- task: build-image
vars:
DOCKER_IMAGE: image-1
build-image:
internal: true
cmds:
- docker build -t {{.DOCKER_IMAGE}} .
```
## Task directory
By default, tasks will be executed in the directory where the Taskfile is
@@ -260,7 +418,7 @@ tasks:
assets:
cmds:
- minify -o public/style.css src/css
- esbuild --bundle --minify css/index.css > public/bundle.css
```
In the above example, `assets` will always run right before `build` if you run
@@ -277,11 +435,11 @@ tasks:
js:
cmds:
- minify -o public/script.js src/js
- esbuild --bundle --minify js/index.js > public/bundle.js
css:
cmds:
- minify -o public/style.css src/css
- esbuild --bundle --minify css/index.css > public/bundle.css
```
If there is more than one dependency, they always run in parallel for better
@@ -315,6 +473,78 @@ tasks:
- echo {{.TEXT}}
```
## Platform specific tasks and commands
If you want to restrict the running of tasks to explicit platforms, this can be achieved
using the `platforms:` key. Tasks can be restricted to a specific OS, architecture or a
combination of both.
On a mismatch, the task or command will be skipped, and no error will be thrown.
The values allowed as OS or Arch are valid `GOOS` and `GOARCH` values, as
defined by the Go language
[here](https://github.com/golang/go/blob/master/src/go/build/syslist.go).
The `build-windows` task below will run only on Windows, and on any architecture:
```yaml
version: '3'
tasks:
build-windows:
platforms: [windows]
cmds:
- echo 'Running command on Windows'
```
This can be restricted to a specific architecture as follows:
```yaml
version: '3'
tasks:
build-windows-amd64:
platforms: [windows/amd64]
cmds:
- echo 'Running command on Windows (amd64)'
```
It is also possible to restrict the task to specific architectures:
```yaml
version: '3'
tasks:
build-amd64:
platforms: [amd64]
cmds:
- echo 'Running command on amd64'
```
Multiple platforms can be specified as follows:
```yaml
version: '3'
tasks:
build:
platforms: [windows/amd64, darwin]
cmds:
- echo 'Running command on Windows (amd64) and macOS'
```
Individual commands can also be restricted to specific platforms:
```yaml
version: '3'
tasks:
build:
cmds:
- cmd: echo 'Running command on Windows (amd64) and macOS'
platforms: [windows/amd64, darwin]
- cmd: echo 'Running on all platforms'
```
## Calling another task
When a task has many dependencies, they are executed concurrently. This will
@@ -387,27 +617,25 @@ tasks:
js:
cmds:
- minify -o public/script.js src/js
- esbuild --bundle --minify js/index.js > public/bundle.js
sources:
- src/js/**/*.js
generates:
- public/script.js
- public/bundle.js
css:
cmds:
- minify -o public/style.css src/css
- esbuild --bundle --minify css/index.css > public/bundle.css
sources:
- src/css/**/*.css
generates:
- public/style.css
- public/bundle.css
```
`sources` and `generates` can be files or file patterns. When given,
Task will compare the checksum of the source 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`.
You will probably want to ignore the `.task` folder in your `.gitignore` file
(It is there that Task stores the last checksum).
If you prefer this check to be made by the modification timestamp of the files,
instead of its checksum (content), just set the `method` property to `timestamp`.
@@ -423,9 +651,34 @@ tasks:
- ./*.go
generates:
- app{{exeExt}}
method: checksum
method: timestamp
```
In situations where you need more flexibility the `status` keyword can be used.
You can even combine the two. See the documentation for
[status](#using-programmatic-checks-to-indicate-a-task-is-up-to-date) for an
example.
:::info
By default, task stores checksums on a local `.task` directory in the project's
directory. Most of the time, you'll want to have this directory on `.gitignore`
(or equivalent) so it isn't committed. (If you have a task for code generation
that is committed it may make sense to commit the checksum of that task as
well, though).
If you want these files to be stored in another directory, you can set a
`TASK_TEMP_DIR` environment variable in your machine. It can contain a relative
path like `tmp/task` that will be interpreted as relative to the project
directory, or an absolute or home path like `/tmp/.task` or `~/.task`
(subdirectories will be created for each project).
```bash
export TASK_TEMP_DIR='~/.task'
```
:::
:::info
Each task has only one checksum stored for its `sources`. If you want
@@ -448,9 +701,9 @@ The method `none` skips any validation and always run the task.
:::info
For the `checksum` (default) method to work, it is only necessary to
inform the source files, but if you want to use the `timestamp` method, you
also need to inform the generated files with `generates`.
For the `checksum` (default) or `timestamp` method to work, it is only necessary to
inform the source files.
When the `timestamp` method is used, the last time of the running the task is considered as a generate.
:::
@@ -496,6 +749,30 @@ 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.
`status` can be combined with the [fingerprinting](#by-fingerprinting-locally-generated-files-and-their-sources)
to have a task run if either the the source/generated artifacts changes, or the
programmatic check fails:
```yaml
version: '3'
tasks:
build:prod:
desc: Build for production usage.
cmds:
- composer install
# Run this task if source files changes.
sources:
- composer.json
- composer.lock
generates:
- ./vendor/composer/installed.json
- ./vendor/autoload.php
# But also run the task if the last build was not a production build.
status:
- grep -q '"dev": false' ./vendor/composer/installed.json
```
### Using programmatic checks to cancel the execution of a task and its dependencies
In addition to `status` checks, `preconditions` checks are
@@ -816,11 +1093,11 @@ tasks:
js:
cmds:
- minify -o public/script.js src/js
- esbuild --bundle --minify js/index.js > public/bundle.js
css:
cmds:
- minify -o public/style.css src/css
- esbuild --bundle --minify css/index.css > public/bundle.css
```
would print the following output:
@@ -877,6 +1154,30 @@ If the task does not have a summary or a description, a warning is printed.
Please note: *showing the summary will not execute the command*.
## Task aliases
Aliases are alternative names for tasks. They can be used to make it easier and
quicker to run tasks with long or hard-to-type names. You can use them on the
command line, when [calling sub-tasks](#calling-another-task) in your Taskfile
and when [including tasks](#including-other-taskfiles) with aliases from another
Taskfile. They can also be used together with [namespace
aliases](#namespace-aliases).
```yaml
version: '3'
tasks:
generate:
aliases: [gen]
cmds:
- task: gen-mocks
generate-mocks:
aliases: [gen-mocks]
cmds:
- echo "generating..."
```
## Overriding task name
Sometimes you may want to override the task name printed on the summary, up-to-date
@@ -1058,7 +1359,7 @@ version: '3'
output:
group:
begin: '::begin::{{.TASK}}'
begin: '::group::{{.TASK}}'
end: '::endgroup::'
tasks:
@@ -1070,11 +1371,35 @@ tasks:
```bash
$ task default
::begin::default
::group::default
Hello, World!
::endgroup::
```
When using the `group` output, you may swallow the output of the executed command
on standard output and standard error if it does not fail (zero exit code).
```yaml
version: '3'
silent: true
output:
group:
error_only: true
tasks:
passes: echo 'output-of-passes'
errors: echo 'output-of-errors' && exit 1
```
```bash
$ task passes
$ task errors
output-of-errors
task: Failed to run task "errors": exit status 1
```
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:
@@ -1153,11 +1478,39 @@ tasks:
- ./app{{exeExt}} -h localhost -p 8080
```
## `set` and `shopt`
It's possible to specify options to the
[`set`](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html)
and [`shopt`](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html)
builtins. This can be added at global, task or command level.
```yaml
version: '3'
set: [pipefail]
shopt: [globstar]
tasks:
# `globstar` required for double star globs to work
default: echo **/*.go
```
:::info
Keep in mind that not all options are available in the
[shell interpreter library](https://github.com/mvdan/sh) that Task uses.
:::
## Watch tasks
With the flags `--watch` or `-w` task will watch for file changes
and run the task again. This requires the `sources` attribute to be given,
so task knows which files to watch.
The default watch interval is 5 seconds, but it's possible to change it by
either setting `interval: '500ms'` in the root of the Taskfile passing it
as an argument like `--interval=500ms`.
[gotemplate]: https://golang.org/pkg/text/template/
[minify]: https://github.com/tdewolff/minify/tree/master/cmd/minify

View File

@@ -1,11 +1,15 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require('prism-react-renderer/themes/github');
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
const GITHUB_URL = 'https://github.com/go-task/task';
const DISCORD_URL = 'https://discord.gg/6TY36E39UK';
const {
CHINESE_URL,
DISCORD_URL,
GITHUB_URL,
MASTODON_URL,
TWITTER_URL
} = require('./constants');
const lightCodeTheme = require('./src/themes/prismLight');
const darkCodeTheme = require('./src/themes/prismDark');
/** @type {import('@docusaurus/types').Config} */
const config = {
@@ -37,10 +41,7 @@ const config = {
},
blog: false,
theme: {
customCss: [
require.resolve('./src/css/custom.css'),
require.resolve('./src/css/carbon.css')
]
customCss: [require.resolve('./src/css/custom.css')]
},
gtag: {
trackingID: 'G-4RT25NXQ7N',
@@ -100,6 +101,16 @@ const config = {
label: 'GitHub',
position: 'right'
},
{
href: TWITTER_URL,
label: 'Twitter',
position: 'right'
},
{
href: MASTODON_URL,
label: 'Mastodon',
position: 'right'
},
{
href: DISCORD_URL,
label: 'Discord',
@@ -134,6 +145,14 @@ const config = {
label: 'GitHub',
href: GITHUB_URL
},
{
label: 'Twitter',
href: TWITTER_URL
},
{
label: 'Mastodon',
href: MASTODON_URL
},
{
label: 'Discord',
href: DISCORD_URL
@@ -143,6 +162,15 @@ const config = {
href: 'https://opencollective.com/task'
}
]
},
{
title: 'Translations',
items: [
{
label: 'Chinese | 中国人',
href: CHINESE_URL
}
]
}
]
},
@@ -156,14 +184,7 @@ const config = {
apiKey: '34b64ae4fc8d9da43d9a13d9710aaddc',
indexName: 'taskfile'
}
}),
scripts: [
{
src: '/js/carbon.js',
async: true
}
]
})
};
module.exports = config;

View File

@@ -14,8 +14,8 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.20",
"@docusaurus/preset-classic": "2.0.0-beta.20",
"@docusaurus/core": "^2.2.0",
"@docusaurus/preset-classic": "^2.2.0",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.1.1",
"prism-react-renderer": "^1.3.1",

View File

@@ -1,12 +1,18 @@
// @ts-check
const { CHINESE_URL } = require('./constants');
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
tutorialSidebar: [
{ type: 'autogenerated', dirName: '.' },
{
type: 'html',
value: '<div id="sidebar-ads"></div>'
type: 'autogenerated',
dirName: '.'
},
{
type: 'link',
label: 'Chinese | 中国人',
href: CHINESE_URL
}
]
};

View File

@@ -1,65 +0,0 @@
#carbonads * {
margin: initial;
padding: initial;
}
#carbonads {
display: flex;
max-width: 330px;
background-color: hsl(0, 0%, 98%);
box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, 0.1);
z-index: 100;
}
#carbonads a {
color: inherit;
text-decoration: none;
}
#carbonads a:hover {
color: inherit;
}
#carbonads span {
position: relative;
display: block;
overflow: hidden;
}
#carbonads .carbon-wrap {
display: flex;
}
#carbonads .carbon-img {
display: block;
margin: 0;
line-height: 1;
}
#carbonads .carbon-img img {
display: block;
}
#carbonads .carbon-text {
font-size: 13px;
padding: 10px;
margin-bottom: 16px;
line-height: 1.5;
text-align: left;
}
#carbonads .carbon-poweredby {
display: block;
padding: 6px 8px;
background: #f1f1f2;
text-align: center;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 600;
font-size: 8px;
line-height: 1;
border-top-left-radius: 3px;
position: absolute;
bottom: 0;
right: 0;
}
[data-theme='dark'] #carbonads {
background-color: hsl(0, 0%, 35%);
box-shadow: 0 1px 4px 1px hsl(0, 0%, 55%);
}
[data-theme='dark'] #carbonads .carbon-poweredby {
background-color: hsl(0, 0%, 55%);
}

View File

@@ -1,4 +1,9 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap');
:root {
--ifm-font-family-base: Roboto, system-ui, -apple-system, Segoe UI, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
--ifm-font-family-monospace: 'Roboto Mono', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
--ifm-color-primary: #43ABA2 ;
--ifm-color-primary-dark: #3AB2A6;
--ifm-color-primary-darker: #32B8AB;
@@ -11,13 +16,6 @@
}
[data-theme='dark'] {
--ifm-color-primary: #43ABA2 ;
--ifm-color-primary-dark: #3AB2A6;
--ifm-color-primary-darker: #32B8AB;
--ifm-color-primary-darkest: #29BEB0;
--ifm-color-primary-light: #4CA59D;
--ifm-color-primary-lighter: #559F98;
--ifm-color-primary-lightest: #5D9993;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}
@@ -25,7 +23,11 @@
width: 100%;
}
#carbonads {
margin-top: 30px;
margin-right: 10px;
.gold-sponsors {
display: flex;
justify-content: center;
}
.gold-sponsors table img {
width: 200px;
}

View File

@@ -0,0 +1,79 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const darkTheme = require('prism-react-renderer/themes/vsDark/index.cjs.js');
module.exports = {
plain: {
color: '#D4D4D4',
backgroundColor: '#212121'
},
styles: [
...darkTheme.styles,
{
types: ['title'],
style: {
color: '#569CD6',
fontWeight: 'bold'
}
},
{
types: ['property', 'parameter'],
style: {
color: '#9CDCFE'
}
},
{
types: ['script'],
style: {
color: '#D4D4D4'
}
},
{
types: ['boolean', 'arrow', 'atrule', 'tag'],
style: {
color: '#569CD6'
}
},
{
types: ['number', 'color', 'unit'],
style: {
color: '#B5CEA8'
}
},
{
types: ['font-matter'],
style: {
color: '#CE9178'
}
},
{
types: ['keyword', 'rule'],
style: {
color: '#C586C0'
}
},
{
types: ['regex'],
style: {
color: '#D16969'
}
},
{
types: ['maybe-class-name'],
style: {
color: '#4EC9B0'
}
},
{
types: ['constant'],
style: {
color: '#4FC1FF'
}
}
]
};

View File

@@ -0,0 +1,100 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const lightTheme = require('prism-react-renderer/themes/github/index.cjs.js');
module.exports = {
...lightTheme,
styles: [
...lightTheme.styles,
{
types: ['title'],
style: {
color: '#0550AE',
fontWeight: 'bold'
}
},
{
types: ['parameter'],
style: {
color: '#953800'
}
},
{
types: ['boolean', 'rule', 'color', 'number', 'constant', 'property'],
style: {
color: '#005CC5'
}
},
{
types: ['atrule', 'tag'],
style: {
color: '#22863A'
}
},
{
types: ['script'],
style: {
color: '#24292E'
}
},
{
types: ['operator', 'unit', 'rule'],
style: {
color: '#D73A49'
}
},
{
types: ['font-matter', 'string', 'attr-value'],
style: {
color: '#C6105F'
}
},
{
types: ['class-name'],
style: {
color: '#116329'
}
},
{
types: ['attr-name'],
style: {
color: '#0550AE'
}
},
{
types: ['keyword'],
style: {
color: '#CF222E'
}
},
{
types: ['function'],
style: {
color: '#8250DF'
}
},
{
types: ['selector'],
style: {
color: '#6F42C1'
}
},
{
types: ['variable'],
style: {
color: '#E36209'
}
},
{
types: ['comment'],
style: {
color: '#6B6B6B'
}
}
]
};

7
docs/static/img/appwrite.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,5 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 375 375" width="500" height="500">
<path fill="#29beb0" d="M 187.570312 190.933594 L 187.570312 375 L 30.070312 279.535156 L 30.070312 95.464844 Z"/>
<path fill="#69d2c8" d="M 187.570312 190.933594 L 187.570312 375 L 345.070312 279.535156 L 345.070312 95.464844 Z"/>
<path fill="#94dfd8" d="M 187.570312 190.933594 L 30.070312 95.464844 L 187.570312 0 L 345.070312 95.464844 Z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 375 375"><path fill="#29beb0" d="M 187.570312 190.933594 L 187.570312 375 L 30.070312 279.535156 L 30.070312 95.464844 Z"/><path fill="#69d2c8" d="M 187.570312 190.933594 L 187.570312 375 L 345.070312 279.535156 L 345.070312 95.464844 Z"/><path fill="#94dfd8" d="M 187.570312 190.933594 L 30.070312 95.464844 L 187.570312 0 L 345.070312 95.464844 Z"/></svg>

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 435 B

View File

@@ -1,3 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 375 375" width="500" height="500">
<path d="M 29.021972 281.445466 L 183.370289 375 L 183.370289 194.622441 L 29.021972 101.064089 Z M 345.978037 281.445466 L 345.978037 101.064079 L 191.629731 194.622431 L 191.629731 375 Z M 342.140723 93.731759 L 187.5 0 L 32.859297 93.731759 L 187.5 187.467349 Z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 375 375"><path d="M 29.021972 281.445466 L 183.370289 375 L 183.370289 194.622441 L 29.021972 101.064089 Z M 345.978037 281.445466 L 345.978037 101.064079 L 191.629731 194.622431 L 191.629731 375 Z M 342.140723 93.731759 L 187.5 0 L 32.859297 93.731759 L 187.5 187.467349 Z"/></svg>

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -64,15 +64,21 @@ get_binaries() {
case "$PLATFORM" in
darwin/amd64) BINARIES="task" ;;
darwin/arm64) BINARIES="task" ;;
darwin/armv5) BINARIES="task" ;;
darwin/armv6) BINARIES="task" ;;
darwin/armv7) BINARIES="task" ;;
linux/386) BINARIES="task" ;;
linux/amd64) BINARIES="task" ;;
linux/arm64) BINARIES="task" ;;
linux/armv5) BINARIES="task" ;;
linux/armv6) BINARIES="task" ;;
linux/armv7) BINARIES="task" ;;
windows/386) BINARIES="task" ;;
windows/amd64) BINARIES="task" ;;
windows/arm64) BINARIES="task" ;;
windows/armv5) BINARIES="task" ;;
windows/armv6) BINARIES="task" ;;
windows/armv7) BINARIES="task" ;;
*)
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
@@ -184,9 +190,9 @@ uname_arch() {
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
armv5*) arch="arm" ;;
armv6*) arch="arm" ;;
armv7*) arch="arm" ;;
esac
echo ${arch}
}
@@ -214,9 +220,7 @@ uname_arch_check() {
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
arm) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;

0
docs/static/js/.keep vendored Normal file
View File

View File

@@ -1,24 +0,0 @@
(function () {
function attachAd() {
const el = document.createElement('script');
el.setAttribute('type', 'text/javascript');
el.setAttribute('id', '_carbonads_js');
el.setAttribute(
'src',
'//cdn.carbonads.com/carbon.js?serve=CESI65QJ&placement=taskfiledev'
);
el.setAttribute('async', 'async');
const wrapper = document.getElementById('sidebar-ads');
wrapper.innerHTML = '';
wrapper.appendChild(el);
}
setTimeout(function () {
attachAd();
window.addEventListener('popstate', function () {
attachAd();
});
}, 1000);
})();

483
docs/static/schema.json vendored Normal file
View File

@@ -0,0 +1,483 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Taskfile YAML Schema",
"description": "Schema for Taskfile files.",
"definitions": {
"3": {
"env": {
"$ref": "#/definitions/3/vars"
},
"tasks": {
"type": "object",
"patternProperties": {
"^.*$": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/3/task_call"
}
]
}
},
{
"$ref": "#/definitions/3/task"
}
]
}
}
},
"task": {
"type": "object",
"additionalProperties": false,
"properties": {
"cmds": {
"description": "A list of commands to be executed.",
"$ref": "#/definitions/3/cmds"
},
"deps": {
"description": "A list of dependencies of this task. Tasks defined here will run in parallel before this task.",
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/3/task_call"
}
]
}
},
"label": {
"description": "Overrides the name of the task in the output when a task is run. Supports variables.",
"type": "string"
},
"desc": {
"description": "A short description of the task. This is displayed when calling `task --list`.",
"type": "string"
},
"summary": {
"description": "A longer description of the task. This is displayed when calling `task --summary [task]`.",
"type": "string"
},
"aliases": {
"description": "A list of alternative names by which the task can be called.",
"type": "array",
"items": {
"type": "string"
}
},
"sources": {
"description": "A list of sources to check before running this task. Relevant for `checksum` and `timestamp` methods. Can be file paths or star globs.",
"type": "array",
"items": {
"type": "string"
}
},
"generates": {
"description": "A list of files meant to be generated by this task. Relevant for `timestamp` method. Can be file paths or star globs.",
"type": "array",
"items": {
"type": "string"
}
},
"status": {
"description": "A list of commands to check if this task should run. The task is skipped otherwise. This overrides `method`, `sources` and `generates`.",
"type": "array",
"items": {
"type": "string"
}
},
"preconditions": {
"description": "A list of commands to check if this task should run. If a condition is not met, the task will error.",
"type": "array",
"items": {
"$ref": "#/definitions/3/precondition"
}
},
"dir": {
"description": "The directory in which this task should run. Defaults to the current working directory.",
"type": "string"
},
"set": {
"description": "Enables POSIX shell options for all of a task's commands. See https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html",
"type": "array",
"items": {
"$ref": "#/definitions/3/set"
}
},
"shopt": {
"description": "Enables Bash shell options for all of a task's commands. See https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html",
"type": "array",
"items": {
"$ref": "#/definitions/3/shopt"
}
},
"vars": {
"description": "A set of variables that can be used in the task.",
"$ref": "#/definitions/3/vars"
},
"env": {
"description": "A set of environment variables that will be made available to shell commands.",
"$ref": "#/definitions/3/env"
},
"dotenv": {
"description": "A list of `.env` file paths to be parsed.",
"type": "array",
"items": {
"type": "string"
}
},
"silent": {
"description": "Hides task name and command from output. The command's output will still be redirected to `STDOUT` and `STDERR`. When combined with the `--list` flag, task descriptions will be hidden.",
"type": "boolean",
"default": false
},
"interactive": {
"description": "Tells task that the command is interactive.",
"type": "boolean",
"default": false
},
"internal": {
"description": "Stops a task from being callable on the command line. It will also be omitted from the output when used with `--list`.",
"type": "boolean",
"default": false
},
"method": {
"description": "Defines which method is used to check the task is up-to-date. `timestamp` will compare the timestamp of the sources and generates files. `checksum` will check the checksum (You probably want to ignore the .task folder in your .gitignore file). `none` skips any validation and always run the task.",
"type": "string",
"enum": ["none", "checksum", "timestamp"],
"default": "none"
},
"prefix": {
"description": "Defines a string to prefix the output of tasks running in parallel. Only used when the output mode is `prefixed`.",
"type": "string"
},
"ignore_error": {
"description": "Continue execution if errors happen while executing commands.",
"type": "boolean"
},
"run": {
"description": "Specifies whether the task should run again or not if called more than once. Available options: `always`, `once` and `when_changed`.",
"$ref": "#/definitions/3/run"
},
"platforms": {
"description": "Specifies which platforms the task should be run on.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"cmds": {
"type": "array",
"items": {
"$ref": "#/definitions/3/cmd"
}
},
"cmd": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/3/cmd_call"
},
{
"$ref": "#/definitions/3/task_call"
}
]
},
"set": {
"type": "string",
"enum": ["allexport", "a", "errexit", "e", "noexec", "n", "noglob", "f", "nounset", "u", "xtrace", "x", "pipefail"]
},
"shopt": {
"type": "string",
"enum": ["expand_aliases", "globstar", "nullglob"]
},
"vars": {
"type": "object",
"patternProperties": {
"^.*$": {
"anyOf": [
{
"type": ["boolean", "integer", "null", "number", "string"]
},
{
"$ref": "#/definitions/3/dynamic_var"
}
]
}
}
},
"dynamic_var": {
"type": "object",
"properties": {
"sh": {
"type": "string",
"description": "The value will be treated as a command and the output assigned"
},
"additionalProperties": false
}
},
"task_call": {
"type": "object",
"properties": {
"task": {
"description": "Name of the task to run",
"type": "string"
},
"vars": {
"description": "Values passed to the task called",
"$ref": "#/definitions/3/vars"
}
}
},
"cmd_call": {
"type": "object",
"properties": {
"cmd": {
"description": "Command to run",
"type": "string"
},
"silent": {
"description": "Silent mode disables echoing of command before Task runs it",
"type": "boolean"
},
"set": {
"description": "Enables POSIX shell options for this command. See https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html",
"type": "array",
"items": {
"$ref": "#/definitions/3/set"
}
},
"shopt": {
"description": "Enables Bash shell options for this command. See https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html",
"type": "array",
"items": {
"$ref": "#/definitions/3/shopt"
}
},
"ignore_error": {
"description": "Prevent command from aborting the execution of task even after receiving a status code of 1",
"type": "boolean"
},
"defer": {
"description": "",
"type": "boolean"
},
"platforms": {
"description": "Specifies which platforms the command should be run on.",
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
"required": ["cmd"]
},
"precondition": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/3/precondition_obj"
}
]
},
"precondition_obj": {
"type": "object",
"properties": {
"sh": {
"description": "Command to run. If that command returns 1, the condition will fail",
"type": "string"
},
"msg": {
"description": "Failure message to display when the condition fails",
"type": "string"
}
}
},
"run": {
"type": "string",
"enum": ["always", "once", "when_changed"]
},
"outputString": {
"type": "string",
"enum": ["interleaved", "prefixed", "group"],
"default": "interleaved"
},
"outputObject": {
"type": "object",
"properties": {
"group": {
"type": "object",
"properties": {
"begin": {
"type": "string"
},
"end": {
"type": "string"
},
"error_only": {
"description": "Swallows command output on zero exit code",
"type": "boolean",
"default": false
}
}
}
}
}
}
},
"allOf": [
{
"type": "object",
"properties": {
"version": {
"description": "Specify the Taskfile format that this file conforms to.",
"anyOf": [
{
"type": "number",
"enum": [3]
},
{
"type": "string",
"enum": ["3"]
}
]
},
"output": {
"description": "Defines how the STDOUT and STDERR are printed when running tasks in parallel. The interleaved output prints lines in real time (default). 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.",
"anyOf": [
{"$ref": "#/definitions/3/outputString"},
{"$ref": "#/definitions/3/outputObject"}
]
},
"method": {
"description": "Defines which method is used to check the task is up-to-date. (default: checksum)",
"type": "string",
"enum": ["none", "checksum", "timestamp"],
"default": "checksum"
},
"includes": {
"description": "Imports tasks from the specified taskfiles. The tasks described in the given Taskfiles will be available with the informed namespace.",
"type": "object",
"patternProperties": {
"^.*$": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"taskfile": {
"description": "The path for the Taskfile or directory to be included. If a directory, Task will look for files named `Taskfile.yml` or `Taskfile.yaml` inside that directory. If a relative path, resolved relative to the directory containing the including Taskfile.",
"type": "string"
},
"dir": {
"description": "The working directory of the included tasks when run.",
"type": "string"
},
"optional": {
"description": "If `true`, no errors will be thrown if the specified file does not exist.",
"type": "boolean"
},
"internal": {
"description": "Stops any task in the included Taskfile from being callable on the command line. These commands will also be omitted from the output when used with `--list`.",
"type": "boolean"
},
"aliases": {
"description": "Alternative names for the namespace of the included Taskfile.",
"type": "array",
"items": {
"type": "string"
}
},
"vars": {
"description": "A set of variables to apply to the included Taskfile.",
"$ref": "#/definitions/3/vars"
}
}
}
]
}
}
},
"vars": {
"description": "A set of global variables.",
"$ref": "#/definitions/3/vars"
},
"env": {
"description": "A set of global environment variables.",
"$ref": "#/definitions/3/env"
},
"tasks": {
"description": "A set of task definitions.",
"$ref": "#/definitions/3/tasks"
},
"silent": {
"description": "Default 'silent' options for this Taskfile. If `false`, can be overidden with `true` in a task by task basis.",
"type": "boolean"
},
"set": {
"description": "Enables POSIX shell options for all commands in the Taskfile. See https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html",
"type": "array",
"items": {
"$ref": "#/definitions/3/set"
}
},
"shopt": {
"description": "Enables Bash shell options for all commands in the Taskfile. See https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html",
"type": "array",
"items": {
"$ref": "#/definitions/3/shopt"
}
},
"dotenv": {
"type": "array",
"description": "A list of `.env` file paths to be parsed.",
"items": {
"type": "string"
}
},
"run": {
"description": "Default 'run' option for this Taskfile. Available options: `always`, `once` and `when_changed`.",
"$ref": "#/definitions/3/run"
},
"interval": {
"description": "Sets a different watch interval when using `--watch`, the default being 5 seconds. This string should be a valid Go duration: https://pkg.go.dev/time#ParseDuration.",
"type": "string",
"pattern": "^[0-9]+(?:m|s|ms)$"
}
},
"additionalProperties": false,
"required": ["version"],
"anyOf": [
{
"required": ["includes"]
},
{
"required": ["tasks"]
},
{
"required": ["includes", "tasks"]
}
]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ package task
import (
"errors"
"fmt"
"strings"
"mvdan.cc/sh/v3/interp"
)
@@ -13,11 +14,37 @@ var (
)
type taskNotFoundError struct {
taskName string
taskName string
didYouMean string
}
func (err *taskNotFoundError) Error() string {
return fmt.Sprintf(`task: Task "%s" not found`, err.taskName)
if err.didYouMean != "" {
return fmt.Sprintf(
`task: Task %q does not exist. Did you mean %q?`,
err.taskName,
err.didYouMean,
)
}
return fmt.Sprintf(`task: Task %q does not exist`, err.taskName)
}
type multipleTasksWithAliasError struct {
aliasName string
taskNames []string
}
func (err *multipleTasksWithAliasError) Error() string {
return fmt.Sprintf(`task: Multiple tasks (%s) with alias %q found`, strings.Join(err.taskNames, ", "), err.aliasName)
}
type taskInternalError struct {
taskName string
}
func (err *taskInternalError) Error() string {
return fmt.Sprintf(`task: Task "%s" is internal`, err.taskName)
}
type TaskRunError struct {
@@ -26,7 +53,7 @@ type TaskRunError struct {
}
func (err *TaskRunError) Error() string {
return fmt.Sprintf(`task: Failed to run task "%s": %v`, err.taskName, err.err)
return fmt.Sprintf(`task: Failed to run task %q: %v`, err.taskName, err.err)
}
func (err *TaskRunError) ExitCode() int {
@@ -46,7 +73,7 @@ type MaximumTaskCallExceededError struct {
func (e *MaximumTaskCallExceededError) Error() string {
return fmt.Sprintf(
`task: maximum task call exceeded (%d) for task "%s": probably an cyclic dep or infinite loop`,
`task: maximum task call exceeded (%d) for task %q: probably an cyclic dep or infinite loop`,
MaximumTaskCall,
e.task,
)

29
go.mod
View File

@@ -1,26 +1,31 @@
module github.com/go-task/task/v3
go 1.19
require (
github.com/fatih/color v1.13.0
github.com/Masterminds/semver/v3 v3.2.0
github.com/fatih/color v1.14.1
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
github.com/joho/godotenv v1.4.0
github.com/mattn/go-zglob v0.0.3
github.com/golang/mock v1.6.0
github.com/joho/godotenv v1.5.1
github.com/mattn/go-zglob v0.0.4
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/radovskyb/watcher v1.0.7
github.com/sajari/fuzzy v1.0.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.2
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
github.com/stretchr/testify v1.8.1
golang.org/x/exp v0.0.0-20230212135524-a684f29349b6
golang.org/x/sync v0.1.0
gopkg.in/yaml.v3 v3.0.1
mvdan.cc/sh/v3 v3.5.1
mvdan.cc/sh/v3 v3.6.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/term v0.3.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
)
go 1.17

111
go.sum
View File

@@ -1,74 +1,85 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-zglob v0.0.3 h1:6Ry4EYsScDyt5di4OI6xw1bYhOqfE5S33Z1OPy+d+To=
github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM=
github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY=
github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20230212135524-a684f29349b6 h1:Ic9KukPQ7PegFzHckNiMTQXGgEszA7mY2Fn4ZMtnMbw=
golang.org/x/exp v0.0.0-20230212135524-a684f29349b6/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
mvdan.cc/sh/v3 v3.5.1 h1:hmP3UOw4f+EYexsJjFxvU38+kn+V/s2CclXHanIBkmQ=
mvdan.cc/sh/v3 v3.5.1/go.mod h1:1JcoyAKm1lZw/2bZje/iYKWicU/KMd0rsyJeKHnsK4E=
mvdan.cc/sh/v3 v3.6.0 h1:gtva4EXJ0dFNvl5bHjcUEvws+KRcDslT8VKheTYkbGU=
mvdan.cc/sh/v3 v3.6.0/go.mod h1:U4mhtBLZ32iWhif5/lD+ygy1zrgaQhUu+XFy7C8+TTA=

162
help.go
View File

@@ -1,6 +1,8 @@
package task
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
@@ -9,71 +11,107 @@ import (
"strings"
"text/tabwriter"
"github.com/go-task/task/v3/internal/editors"
"github.com/go-task/task/v3/internal/fingerprint"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/taskfile"
)
// ListTasksWithDesc reports tasks that have a description spec.
func (e *Executor) ListTasksWithDesc() {
e.printTasks(false)
// ListOptions collects list-related options
type ListOptions struct {
ListOnlyTasksWithDescriptions bool
ListAllTasks bool
FormatTaskListAsJSON bool
}
// ListAllTasks reports all tasks, with or without a description spec.
func (e *Executor) ListAllTasks() {
e.printTasks(true)
// NewListOptions creates a new ListOptions instance
func NewListOptions(list, listAll, listAsJson bool) ListOptions {
return ListOptions{
ListOnlyTasksWithDescriptions: list,
ListAllTasks: listAll,
FormatTaskListAsJSON: listAsJson,
}
}
func (e *Executor) printTasks(listAll bool) {
var tasks []*taskfile.Task
if listAll {
tasks = e.allTaskNames()
} else {
tasks = e.tasksWithDesc()
// ShouldListTasks returns true if one of the options to list tasks has been set to true
func (o ListOptions) ShouldListTasks() bool {
return o.ListOnlyTasksWithDescriptions || o.ListAllTasks
}
// Validate validates that the collection of list-related options are in a valid configuration
func (o ListOptions) Validate() error {
if o.ListOnlyTasksWithDescriptions && o.ListAllTasks {
return fmt.Errorf("task: cannot use --list and --list-all at the same time")
}
if o.FormatTaskListAsJSON && !o.ShouldListTasks() {
return fmt.Errorf("task: --json only applies to --list or --list-all")
}
return nil
}
// Filters returns the slice of FilterFunc which filters a list
// of taskfile.Task according to the given ListOptions
func (o ListOptions) Filters() []FilterFunc {
filters := []FilterFunc{FilterOutInternal}
if o.ListOnlyTasksWithDescriptions {
filters = append(filters, FilterOutNoDesc)
}
if len(tasks) == 0 {
if listAll {
e.Logger.Outf(logger.Yellow, "task: No tasks available")
} else {
e.Logger.Outf(logger.Yellow, "task: No tasks with description available. Try --list-all to list all tasks")
return filters
}
// ListTasks prints a list of tasks.
// Tasks that match the given filters will be excluded from the list.
// The function returns a boolean indicating whether tasks were found
// and an error if one was encountered while preparing the output.
func (e *Executor) ListTasks(o ListOptions) (bool, error) {
tasks, err := e.GetTaskList(o.Filters()...)
if err != nil {
return false, err
}
if o.FormatTaskListAsJSON {
output, err := e.ToEditorOutput(tasks)
if err != nil {
return false, err
}
return
encoder := json.NewEncoder(e.Stdout)
encoder.SetIndent("", " ")
if err := encoder.Encode(output); err != nil {
return false, err
}
return len(tasks) > 0, nil
}
if len(tasks) == 0 {
if o.ListOnlyTasksWithDescriptions {
e.Logger.Outf(logger.Yellow, "task: No tasks with description available. Try --list-all to list all tasks")
} else if o.ListAllTasks {
e.Logger.Outf(logger.Yellow, "task: No tasks available")
}
return false, nil
}
e.Logger.Outf(logger.Default, "task: Available tasks for this project:")
// Format in tab-separated columns with a tab stop of 8.
w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0)
w := tabwriter.NewWriter(e.Stdout, 0, 8, 6, ' ', 0)
for _, task := range tasks {
fmt.Fprintf(w, "* %s: \t%s\n", task.Name(), task.Desc)
}
w.Flush()
}
func (e *Executor) allTaskNames() (tasks []*taskfile.Task) {
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
for _, task := range e.Taskfile.Tasks {
tasks = append(tasks, task)
}
sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task })
return
}
func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) {
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
for _, task := range e.Taskfile.Tasks {
if task.Desc != "" {
compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task})
if err == nil {
task = compiledTask
}
tasks = append(tasks, task)
e.Logger.FOutf(w, logger.Yellow, "* ")
e.Logger.FOutf(w, logger.Green, task.Task)
e.Logger.FOutf(w, logger.Default, ": \t%s", task.Desc)
if len(task.Aliases) > 0 {
e.Logger.FOutf(w, logger.Cyan, "\t(aliases: %s)", strings.Join(task.Aliases, ", "))
}
_, _ = fmt.Fprint(w, "\n")
}
sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task })
return
if err := w.Flush(); err != nil {
return false, err
}
return true, nil
}
// PrintTaskNames prints only the task names in a Taskfile.
// ListTaskNames prints only the task names in a Taskfile.
// Only tasks with a non-empty description are printed if allTasks is false.
// Otherwise, all task names are printed.
func (e *Executor) ListTaskNames(allTasks bool) {
@@ -92,8 +130,11 @@ func (e *Executor) ListTaskNames(allTasks bool) {
// create a string slice from all map values (*taskfile.Task)
s := make([]string, 0, len(e.Taskfile.Tasks))
for _, t := range e.Taskfile.Tasks {
if allTasks || t.Desc != "" {
if (allTasks || t.Desc != "") && !t.Internal {
s = append(s, strings.TrimRight(t.Task, ":"))
for _, alias := range t.Aliases {
s = append(s, strings.TrimRight(alias, ":"))
}
}
}
// sort and print all task names
@@ -102,3 +143,32 @@ func (e *Executor) ListTaskNames(allTasks bool) {
fmt.Fprintln(w, t)
}
}
func (e *Executor) ToEditorOutput(tasks []*taskfile.Task) (*editors.Output, error) {
o := &editors.Output{
Tasks: make([]editors.Task, len(tasks)),
}
for i, t := range tasks {
// Get the fingerprinting method to use
method := e.Taskfile.Method
if t.Method != "" {
method = t.Method
}
upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), t,
fingerprint.WithMethod(method),
fingerprint.WithTempDir(e.TempDir),
fingerprint.WithDry(e.Dry),
fingerprint.WithLogger(e.Logger),
)
if err != nil {
return nil, err
}
o.Tasks[i] = editors.Task{
Name: t.Name(),
Desc: t.Desc,
Summary: t.Summary,
UpToDate: upToDate,
}
}
return o, nil
}

View File

@@ -4,7 +4,8 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/go-task/task/v3/internal/filepathext"
)
const defaultTaskfile = `# https://taskfile.dev
@@ -23,13 +24,13 @@ tasks:
// InitTaskfile Taskfile creates a new Taskfile
func InitTaskfile(w io.Writer, dir string) error {
f := filepath.Join(dir, "Taskfile.yaml")
f := filepathext.SmartJoin(dir, "Taskfile.yaml")
if _, err := os.Stat(f); err == nil {
return ErrTaskfileAlreadyExists
}
if err := os.WriteFile(f, []byte(defaultTaskfile), 0644); err != nil {
if err := os.WriteFile(f, []byte(defaultTaskfile), 0o644); err != nil {
return err
}
fmt.Fprintf(w, "Taskfile.yaml created in the current directory\n")

View File

@@ -64,15 +64,21 @@ get_binaries() {
case "$PLATFORM" in
darwin/amd64) BINARIES="task" ;;
darwin/arm64) BINARIES="task" ;;
darwin/armv5) BINARIES="task" ;;
darwin/armv6) BINARIES="task" ;;
darwin/armv7) BINARIES="task" ;;
linux/386) BINARIES="task" ;;
linux/amd64) BINARIES="task" ;;
linux/arm64) BINARIES="task" ;;
linux/armv5) BINARIES="task" ;;
linux/armv6) BINARIES="task" ;;
linux/armv7) BINARIES="task" ;;
windows/386) BINARIES="task" ;;
windows/amd64) BINARIES="task" ;;
windows/arm64) BINARIES="task" ;;
windows/armv5) BINARIES="task" ;;
windows/armv6) BINARIES="task" ;;
windows/armv7) BINARIES="task" ;;
*)
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
@@ -184,9 +190,9 @@ uname_arch() {
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
armv5*) arch="arm" ;;
armv6*) arch="arm" ;;
armv7*) arch="arm" ;;
esac
echo ${arch}
}
@@ -214,9 +220,7 @@ uname_arch_check() {
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
arm) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;

View File

@@ -4,21 +4,23 @@ import (
"bytes"
"context"
"fmt"
"path/filepath"
"strings"
"sync"
"github.com/go-task/task/v3/internal/compiler"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/internal/version"
"github.com/go-task/task/v3/taskfile"
)
var _ compiler.Compiler = &CompilerV3{}
type CompilerV3 struct {
Dir string
Dir string
UserWorkingDir string
TaskfileEnv *taskfile.Vars
TaskfileVars *taskfile.Vars
@@ -44,7 +46,13 @@ func (c *CompilerV3) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*ta
func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluateShVars bool) (*taskfile.Vars, error) {
result := compiler.GetEnviron()
if t != nil {
result.Set("TASK", taskfile.Var{Static: t.Task})
specialVars, err := c.getSpecialVars(t)
if err != nil {
return nil, err
}
for k, v := range specialVars {
result.Set(k, taskfile.Var{Static: v})
}
}
getRangeFunc := func(dir string) func(k string, v taskfile.Var) error {
@@ -83,9 +91,7 @@ func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluat
if err := tr.Err(); err != nil {
return nil, err
}
if !filepath.IsAbs(dir) {
dir = filepath.Join(c.Dir, dir)
}
dir = filepathext.SmartJoin(c.Dir, dir)
taskRangeFunc = getRangeFunc(dir)
}
@@ -167,3 +173,25 @@ func (c *CompilerV3) ResetCache() {
c.dynamicCache = nil
}
func (c *CompilerV3) getSpecialVars(t *taskfile.Task) (map[string]string, error) {
taskfileDir, err := c.getTaskfileDir(t)
if err != nil {
return nil, err
}
return map[string]string{
"TASK": t.Task,
"ROOT_DIR": c.Dir,
"TASKFILE_DIR": taskfileDir,
"USER_WORKING_DIR": c.UserWorkingDir,
"TASK_VERSION": version.GetVersion(),
}, nil
}
func (c *CompilerV3) getTaskfileDir(t *taskfile.Task) (string, error) {
if t.IncludedTaskfile != nil {
return t.IncludedTaskfile.FullDirPath()
}
return c.Dir, nil
}

View File

@@ -0,0 +1,14 @@
package editors
// Output wraps task list output for use in editor integrations (e.g. VSCode, etc)
type Output struct {
Tasks []Task `json:"tasks"`
}
// Task describes a single task
type Task struct {
Name string `json:"name"`
Desc string `json:"desc"`
Summary string `json:"summary"`
UpToDate bool `json:"up_to_date"`
}

31
internal/env/env.go vendored Normal file
View File

@@ -0,0 +1,31 @@
package env
import (
"fmt"
"os"
"github.com/go-task/task/v3/taskfile"
)
func Get(t *taskfile.Task) []string {
if t.Env == nil {
return nil
}
environ := os.Environ()
for k, v := range t.Env.ToCacheMap() {
str, isString := v.(string)
if !isString {
continue
}
if _, alreadySet := os.LookupEnv(k); alreadySet {
continue
}
environ = append(environ, fmt.Sprintf("%s=%s", k, str))
}
return environ
}

View File

@@ -3,6 +3,7 @@ package execext
import (
"context"
"errors"
"fmt"
"io"
"os"
"path/filepath"
@@ -17,12 +18,14 @@ import (
// RunCommandOptions is the options for the RunCommand func
type RunCommandOptions struct {
Command string
Dir string
Env []string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Command string
Dir string
Env []string
PosixOpts []string
BashOpts []string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
var (
@@ -36,9 +39,18 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
return ErrNilOptions
}
p, err := syntax.NewParser().Parse(strings.NewReader(opts.Command), "")
if err != nil {
return err
// Set "-e" or "errexit" by default
opts.PosixOpts = append(opts.PosixOpts, "e")
// Format POSIX options into a slice that mvdan/sh understands
var params []string
for _, opt := range opts.PosixOpts {
if len(opt) == 1 {
params = append(params, fmt.Sprintf("-%s", opt))
} else {
params = append(params, "-o")
params = append(params, opt)
}
}
environ := opts.Env
@@ -47,7 +59,7 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
}
r, err := interp.New(
interp.Params("-e"),
interp.Params(params...),
interp.Env(expand.ListEnviron(environ...)),
interp.ExecHandler(interp.DefaultExecHandler(15*time.Second)),
interp.OpenHandler(openHandler),
@@ -58,6 +70,25 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
return err
}
parser := syntax.NewParser()
// Run any shopt commands
if len(opts.BashOpts) > 0 {
shoptCmdStr := fmt.Sprintf("shopt -s %s", strings.Join(opts.BashOpts, " "))
shoptCmd, err := parser.Parse(strings.NewReader(shoptCmdStr), "")
if err != nil {
return err
}
if err := r.Run(ctx, shoptCmd); err != nil {
return err
}
}
// Run the user-defined command
p, err := parser.Parse(strings.NewReader(opts.Command), "")
if err != nil {
return err
}
return r.Run(ctx, p)
}
@@ -73,7 +104,7 @@ func IsExitError(err error) bool {
// if available.
func Expand(s string) (string, error) {
s = filepath.ToSlash(s)
s = strings.Replace(s, " ", `\ `, -1)
s = strings.ReplaceAll(s, " ", `\ `)
fields, err := shell.Fields(s, nil)
if err != nil {
return "", err

View File

@@ -0,0 +1,31 @@
package filepathext
import (
"os"
"path/filepath"
)
// SmartJoin joins two paths, but only if the second is not already an
// absolute path.
func SmartJoin(a, b string) string {
if filepath.IsAbs(b) {
return b
}
return filepath.Join(a, b)
}
// TryAbsToRel tries to convert an absolute path to relative based on the
// process working directory. If it can't, it returns the absolute path.
func TryAbsToRel(abs string) string {
wd, err := os.Getwd()
if err != nil {
return abs
}
rel, err := filepath.Rel(wd, abs)
if err != nil {
return abs
}
return rel
}

View File

@@ -0,0 +1,20 @@
package fingerprint
import (
"context"
"github.com/go-task/task/v3/taskfile"
)
// StatusCheckable defines any type that can check if the status of a task is up-to-date.
type StatusCheckable interface {
IsUpToDate(ctx context.Context, t *taskfile.Task) (bool, error)
}
// SourcesCheckable defines any type that can check if the sources of a task are up-to-date.
type SourcesCheckable interface {
IsUpToDate(t *taskfile.Task) (bool, error)
Value(t *taskfile.Task) (interface{}, error)
OnError(t *taskfile.Task) error
Kind() string
}

View File

@@ -0,0 +1,132 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: checker.go
// Package fingerprint is a generated GoMock package.
package fingerprint
import (
context "context"
reflect "reflect"
taskfile "github.com/go-task/task/v3/taskfile"
gomock "github.com/golang/mock/gomock"
)
// MockStatusCheckable is a mock of StatusCheckable interface.
type MockStatusCheckable struct {
ctrl *gomock.Controller
recorder *MockStatusCheckableMockRecorder
}
// MockStatusCheckableMockRecorder is the mock recorder for MockStatusCheckable.
type MockStatusCheckableMockRecorder struct {
mock *MockStatusCheckable
}
// NewMockStatusCheckable creates a new mock instance.
func NewMockStatusCheckable(ctrl *gomock.Controller) *MockStatusCheckable {
mock := &MockStatusCheckable{ctrl: ctrl}
mock.recorder = &MockStatusCheckableMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockStatusCheckable) EXPECT() *MockStatusCheckableMockRecorder {
return m.recorder
}
// IsUpToDate mocks base method.
func (m *MockStatusCheckable) IsUpToDate(ctx context.Context, t *taskfile.Task) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsUpToDate", ctx, t)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IsUpToDate indicates an expected call of IsUpToDate.
func (mr *MockStatusCheckableMockRecorder) IsUpToDate(ctx, t interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUpToDate", reflect.TypeOf((*MockStatusCheckable)(nil).IsUpToDate), ctx, t)
}
// MockSourcesCheckable is a mock of SourcesCheckable interface.
type MockSourcesCheckable struct {
ctrl *gomock.Controller
recorder *MockSourcesCheckableMockRecorder
}
// MockSourcesCheckableMockRecorder is the mock recorder for MockSourcesCheckable.
type MockSourcesCheckableMockRecorder struct {
mock *MockSourcesCheckable
}
// NewMockSourcesCheckable creates a new mock instance.
func NewMockSourcesCheckable(ctrl *gomock.Controller) *MockSourcesCheckable {
mock := &MockSourcesCheckable{ctrl: ctrl}
mock.recorder = &MockSourcesCheckableMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockSourcesCheckable) EXPECT() *MockSourcesCheckableMockRecorder {
return m.recorder
}
// IsUpToDate mocks base method.
func (m *MockSourcesCheckable) IsUpToDate(t *taskfile.Task) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsUpToDate", t)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IsUpToDate indicates an expected call of IsUpToDate.
func (mr *MockSourcesCheckableMockRecorder) IsUpToDate(t interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUpToDate", reflect.TypeOf((*MockSourcesCheckable)(nil).IsUpToDate), t)
}
// Kind mocks base method.
func (m *MockSourcesCheckable) Kind() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Kind")
ret0, _ := ret[0].(string)
return ret0
}
// Kind indicates an expected call of Kind.
func (mr *MockSourcesCheckableMockRecorder) Kind() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Kind", reflect.TypeOf((*MockSourcesCheckable)(nil).Kind))
}
// OnError mocks base method.
func (m *MockSourcesCheckable) OnError(t *taskfile.Task) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "OnError", t)
ret0, _ := ret[0].(error)
return ret0
}
// OnError indicates an expected call of OnError.
func (mr *MockSourcesCheckableMockRecorder) OnError(t interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnError", reflect.TypeOf((*MockSourcesCheckable)(nil).OnError), t)
}
// Value mocks base method.
func (m *MockSourcesCheckable) Value(t *taskfile.Task) (interface{}, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Value", t)
ret0, _ := ret[0].(interface{})
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Value indicates an expected call of Value.
func (mr *MockSourcesCheckableMockRecorder) Value(t interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Value", reflect.TypeOf((*MockSourcesCheckable)(nil).Value), t)
}

View File

@@ -1,13 +1,13 @@
package status
package fingerprint
import (
"os"
"path/filepath"
"sort"
"github.com/mattn/go-zglob"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
)
func globs(dir string, globs []string) ([]string, error) {
@@ -25,17 +25,18 @@ func globs(dir string, globs []string) ([]string, error) {
func Glob(dir string, g string) ([]string, error) {
files := make([]string, 0)
if !filepath.IsAbs(g) {
g = filepath.Join(dir, g)
}
g = filepathext.SmartJoin(dir, g)
g, err := execext.Expand(g)
if err != nil {
return nil, err
}
fs, err := zglob.Glob(g)
fs, err := zglob.GlobFollowSymlinks(g)
if err != nil {
return nil, err
}
for _, f := range fs {
info, err := os.Stat(f)
if err != nil {

View File

@@ -0,0 +1,16 @@
package fingerprint
import "fmt"
func NewSourcesChecker(method, tempDir string, dry bool) (SourcesCheckable, error) {
switch method {
case "timestamp":
return NewTimestampChecker(tempDir, dry), nil
case "checksum":
return NewChecksumChecker(tempDir, dry), nil
case "none":
return NoneChecker{}, nil
default:
return nil, fmt.Errorf(`task: invalid method "%s"`, method)
}
}

View File

@@ -0,0 +1,121 @@
package fingerprint
import (
"crypto/md5"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/taskfile"
)
// ChecksumChecker validates if a task is up to date by calculating its source
// files checksum
type ChecksumChecker struct {
tempDir string
dry bool
}
func NewChecksumChecker(tempDir string, dry bool) *ChecksumChecker {
return &ChecksumChecker{
tempDir: tempDir,
dry: dry,
}
}
func (checker *ChecksumChecker) IsUpToDate(t *taskfile.Task) (bool, error) {
if len(t.Sources) == 0 {
return false, nil
}
checksumFile := checker.checksumFilePath(t)
data, _ := os.ReadFile(checksumFile)
oldMd5 := strings.TrimSpace(string(data))
sources, err := globs(t.Dir, t.Sources)
if err != nil {
return false, err
}
newMd5, err := checker.checksum(sources...)
if err != nil {
return false, nil
}
if !checker.dry {
_ = os.MkdirAll(filepathext.SmartJoin(checker.tempDir, "checksum"), 0o755)
if err = os.WriteFile(checksumFile, []byte(newMd5+"\n"), 0o644); err != nil {
return false, err
}
}
if len(t.Generates) > 0 {
// For each specified 'generates' field, check whether the files actually exist
for _, g := range t.Generates {
generates, err := Glob(t.Dir, g)
if os.IsNotExist(err) {
return false, nil
}
if err != nil {
return false, err
}
if len(generates) == 0 {
return false, nil
}
}
}
return oldMd5 == newMd5, nil
}
func (checker *ChecksumChecker) Value(t *taskfile.Task) (interface{}, error) {
return checker.checksum()
}
func (checker *ChecksumChecker) OnError(t *taskfile.Task) error {
if len(t.Sources) == 0 {
return nil
}
return os.Remove(checker.checksumFilePath(t))
}
func (*ChecksumChecker) Kind() string {
return "checksum"
}
func (c *ChecksumChecker) checksum(files ...string) (string, error) {
h := md5.New()
for _, f := range files {
// also sum the filename, so checksum changes for renaming a file
if _, err := io.Copy(h, strings.NewReader(filepath.Base(f))); err != nil {
return "", err
}
f, err := os.Open(f)
if err != nil {
return "", err
}
if _, err = io.Copy(h, f); err != nil {
return "", err
}
f.Close()
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
}
func (checker *ChecksumChecker) checksumFilePath(t *taskfile.Task) string {
return filepath.Join(checker.tempDir, "checksum", normalizeFilename(t.Name()))
}
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
// replaces invalid characters on filenames with "-"
func normalizeFilename(f string) string {
return checksumFilenameRegexp.ReplaceAllString(f, "-")
}

View File

@@ -1,4 +1,4 @@
package status
package fingerprint
import (
"testing"
@@ -16,6 +16,6 @@ func TestNormalizeFilename(t *testing.T) {
{"foo1bar2baz3", "foo1bar2baz3"},
}
for _, test := range tests {
assert.Equal(t, test.Out, (&Checksum{}).normalizeFilename(test.In))
assert.Equal(t, test.Out, normalizeFilename(test.In))
}
}

View File

@@ -0,0 +1,23 @@
package fingerprint
import "github.com/go-task/task/v3/taskfile"
// NoneChecker is a no-op Checker.
// It will always report that the task is not up-to-date.
type NoneChecker struct{}
func (NoneChecker) IsUpToDate(t *taskfile.Task) (bool, error) {
return false, nil
}
func (NoneChecker) Value(t *taskfile.Task) (interface{}, error) {
return "", nil
}
func (NoneChecker) OnError(t *taskfile.Task) error {
return nil
}
func (NoneChecker) Kind() string {
return "none"
}

View File

@@ -0,0 +1,151 @@
package fingerprint
import (
"os"
"path/filepath"
"time"
"github.com/go-task/task/v3/taskfile"
)
// TimestampChecker checks if any source change compared with the generated files,
// using file modifications timestamps.
type TimestampChecker struct {
tempDir string
dry bool
}
func NewTimestampChecker(tempDir string, dry bool) *TimestampChecker {
return &TimestampChecker{
tempDir: tempDir,
dry: dry,
}
}
// IsUpToDate implements the Checker interface
func (checker *TimestampChecker) IsUpToDate(t *taskfile.Task) (bool, error) {
if len(t.Sources) == 0 {
return false, nil
}
sources, err := globs(t.Dir, t.Sources)
if err != nil {
return false, nil
}
generates, err := globs(t.Dir, t.Generates)
if err != nil {
return false, nil
}
timestampFile := checker.timestampFilePath(t)
// If the file exists, add the file path to the generates.
// If the generate file is old, the task will be executed.
_, err = os.Stat(timestampFile)
if err == nil {
generates = append(generates, timestampFile)
} else {
// Create the timestamp file for the next execution when the file does not exist.
if !checker.dry {
if err := os.MkdirAll(filepath.Dir(timestampFile), 0o755); err != nil {
return false, err
}
f, err := os.Create(timestampFile)
if err != nil {
return false, err
}
f.Close()
}
}
taskTime := time.Now()
// Compare the time of the generates and sources. If the generates are old, the task will be executed.
// Get the max time of the generates.
generateMaxTime, err := getMaxTime(generates...)
if err != nil || generateMaxTime.IsZero() {
return false, nil
}
// Check if any of the source files is newer than the max time of the generates.
shouldUpdate, err := anyFileNewerThan(sources, generateMaxTime)
if err != nil {
return false, nil
}
// Modify the metadata of the file to the the current time.
if !checker.dry {
if err := os.Chtimes(timestampFile, taskTime, taskTime); err != nil {
return false, err
}
}
return !shouldUpdate, nil
}
func (checker *TimestampChecker) Kind() string {
return "timestamp"
}
// Value implements the Checker Interface
func (checker *TimestampChecker) Value(t *taskfile.Task) (interface{}, error) {
sources, err := globs(t.Dir, t.Sources)
if err != nil {
return time.Now(), err
}
sourcesMaxTime, err := getMaxTime(sources...)
if err != nil {
return time.Now(), err
}
if sourcesMaxTime.IsZero() {
return time.Unix(0, 0), nil
}
return sourcesMaxTime, nil
}
func getMaxTime(files ...string) (time.Time, error) {
var t time.Time
for _, f := range files {
info, err := os.Stat(f)
if err != nil {
return time.Time{}, err
}
t = maxTime(t, info.ModTime())
}
return t, nil
}
func maxTime(a, b time.Time) time.Time {
if a.After(b) {
return a
}
return b
}
// If the modification time of any of the files is newer than the the given time, returns true.
// This function is lazy, as it stops when it finds a file newer than the given time.
func anyFileNewerThan(files []string, givenTime time.Time) (bool, error) {
for _, f := range files {
info, err := os.Stat(f)
if err != nil {
return false, err
}
if info.ModTime().After(givenTime) {
return true, nil
}
}
return false, nil
}
// OnError implements the Checker interface
func (*TimestampChecker) OnError(t *taskfile.Task) error {
return nil
}
func (checker *TimestampChecker) timestampFilePath(t *taskfile.Task) string {
return filepath.Join(checker.tempDir, "timestamp", normalizeFilename(t.Task))
}

View File

@@ -0,0 +1,36 @@
package fingerprint
import (
"context"
"github.com/go-task/task/v3/internal/env"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/taskfile"
)
type StatusChecker struct {
logger *logger.Logger
}
func NewStatusChecker(logger *logger.Logger) StatusCheckable {
return &StatusChecker{
logger: logger,
}
}
func (checker *StatusChecker) IsUpToDate(ctx context.Context, t *taskfile.Task) (bool, error) {
for _, s := range t.Status {
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
Command: s,
Dir: t.Dir,
Env: env.Get(t),
})
if err != nil {
checker.logger.VerboseOutf(logger.Yellow, "task: status command %s exited non-zero: %s", s, err)
return false, nil
}
checker.logger.VerboseOutf(logger.Yellow, "task: status command %s exited zero", s)
}
return true, nil
}

View File

@@ -0,0 +1,132 @@
package fingerprint
import (
"context"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/taskfile"
)
type (
CheckerOption func(*CheckerConfig)
CheckerConfig struct {
method string
dry bool
tempDir string
logger *logger.Logger
statusChecker StatusCheckable
sourcesChecker SourcesCheckable
}
)
func WithMethod(method string) CheckerOption {
return func(config *CheckerConfig) {
config.method = method
}
}
func WithDry(dry bool) CheckerOption {
return func(config *CheckerConfig) {
config.dry = dry
}
}
func WithTempDir(tempDir string) CheckerOption {
return func(config *CheckerConfig) {
config.tempDir = tempDir
}
}
func WithLogger(logger *logger.Logger) CheckerOption {
return func(config *CheckerConfig) {
config.logger = logger
}
}
func WithStatusChecker(checker StatusCheckable) CheckerOption {
return func(config *CheckerConfig) {
config.statusChecker = checker
}
}
func WithSourcesChecker(checker SourcesCheckable) CheckerOption {
return func(config *CheckerConfig) {
config.sourcesChecker = checker
}
}
func IsTaskUpToDate(
ctx context.Context,
t *taskfile.Task,
opts ...CheckerOption,
) (bool, error) {
var statusUpToDate bool
var sourcesUpToDate bool
var err error
// Default config
config := &CheckerConfig{
method: "none",
tempDir: "",
dry: false,
logger: nil,
statusChecker: nil,
sourcesChecker: nil,
}
// Apply functional options
for _, opt := range opts {
opt(config)
}
// If no status checker was given, set up the default one
if config.statusChecker == nil {
config.statusChecker = NewStatusChecker(config.logger)
}
// If no sources checker was given, set up the default one
if config.sourcesChecker == nil {
config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry)
if err != nil {
return false, err
}
}
statusIsSet := len(t.Status) != 0
sourcesIsSet := len(t.Sources) != 0
// If status is set, check if it is up-to-date
if statusIsSet {
statusUpToDate, err = config.statusChecker.IsUpToDate(ctx, t)
if err != nil {
return false, err
}
}
// If sources is set, check if they are up-to-date
if sourcesIsSet {
sourcesUpToDate, err = config.sourcesChecker.IsUpToDate(t)
if err != nil {
return false, err
}
}
// If both status and sources are set, the task is up-to-date if both are up-to-date
if statusIsSet && sourcesIsSet {
return statusUpToDate && sourcesUpToDate, nil
}
// If only status is set, the task is up-to-date if the status is up-to-date
if statusIsSet {
return statusUpToDate, nil
}
// If only sources is set, the task is up-to-date if the sources are up-to-date
if sourcesIsSet {
return sourcesUpToDate, nil
}
// If no status or sources are set, the task should always run
// i.e. it is never considered "up-to-date"
return false, nil
}

View File

@@ -0,0 +1,174 @@
package fingerprint
import (
"context"
"testing"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/go-task/task/v3/taskfile"
)
// TruthTable
//
// | Status up-to-date | Sources up-to-date | Task is up-to-date |
// | ----------------- | ------------------ | ------------------ |
// | not set | not set | false |
// | not set | true | true |
// | not set | false | false |
// | true | not set | true |
// | true | true | true |
// | true | false | false |
// | false | not set | false |
// | false | true | false |
// | false | false | false |
func TestIsTaskUpToDate(t *testing.T) {
tests := []struct {
name string
task *taskfile.Task
setupMockStatusChecker func(m *MockStatusCheckable)
setupMockSourcesChecker func(m *MockSourcesCheckable)
expected bool
}{
{
name: "expect FALSE when no status or sources are defined",
task: &taskfile.Task{
Status: nil,
Sources: nil,
},
setupMockStatusChecker: nil,
setupMockSourcesChecker: nil,
expected: false,
},
{
name: "expect TRUE when no status is defined and sources are up-to-date",
task: &taskfile.Task{
Status: nil,
Sources: []string{"sources"},
},
setupMockStatusChecker: nil,
setupMockSourcesChecker: func(m *MockSourcesCheckable) {
m.EXPECT().IsUpToDate(gomock.Any()).Return(true, nil)
},
expected: true,
},
{
name: "expect FALSE when no status is defined and sources are NOT up-to-date",
task: &taskfile.Task{
Status: nil,
Sources: []string{"sources"},
},
setupMockStatusChecker: nil,
setupMockSourcesChecker: func(m *MockSourcesCheckable) {
m.EXPECT().IsUpToDate(gomock.Any()).Return(false, nil)
},
expected: false,
},
{
name: "expect TRUE when status is up-to-date and sources are not defined",
task: &taskfile.Task{
Status: []string{"status"},
Sources: nil,
},
setupMockStatusChecker: func(m *MockStatusCheckable) {
m.EXPECT().IsUpToDate(gomock.Any(), gomock.Any()).Return(true, nil)
},
setupMockSourcesChecker: nil,
expected: true,
},
{
name: "expect TRUE when status and sources are up-to-date",
task: &taskfile.Task{
Status: []string{"status"},
Sources: []string{"sources"},
},
setupMockStatusChecker: func(m *MockStatusCheckable) {
m.EXPECT().IsUpToDate(gomock.Any(), gomock.Any()).Return(true, nil)
},
setupMockSourcesChecker: func(m *MockSourcesCheckable) {
m.EXPECT().IsUpToDate(gomock.Any()).Return(true, nil)
},
expected: true,
},
{
name: "expect FALSE when status is up-to-date, but sources are NOT up-to-date",
task: &taskfile.Task{
Status: []string{"status"},
Sources: []string{"sources"},
},
setupMockStatusChecker: func(m *MockStatusCheckable) {
m.EXPECT().IsUpToDate(gomock.Any(), gomock.Any()).Return(true, nil)
},
setupMockSourcesChecker: func(m *MockSourcesCheckable) {
m.EXPECT().IsUpToDate(gomock.Any()).Return(false, nil)
},
expected: false,
},
{
name: "expect FALSE when status is NOT up-to-date and sources are not defined",
task: &taskfile.Task{
Status: []string{"status"},
Sources: nil,
},
setupMockStatusChecker: func(m *MockStatusCheckable) {
m.EXPECT().IsUpToDate(gomock.Any(), gomock.Any()).Return(false, nil)
},
setupMockSourcesChecker: nil,
expected: false,
},
{
name: "expect FALSE when status is NOT up-to-date, but sources are up-to-date",
task: &taskfile.Task{
Status: []string{"status"},
Sources: []string{"sources"},
},
setupMockStatusChecker: func(m *MockStatusCheckable) {
m.EXPECT().IsUpToDate(gomock.Any(), gomock.Any()).Return(false, nil)
},
setupMockSourcesChecker: func(m *MockSourcesCheckable) {
m.EXPECT().IsUpToDate(gomock.Any()).Return(true, nil)
},
expected: false,
},
{
name: "expect FALSE when status and sources are NOT up-to-date",
task: &taskfile.Task{
Status: []string{"status"},
Sources: []string{"sources"},
},
setupMockStatusChecker: func(m *MockStatusCheckable) {
m.EXPECT().IsUpToDate(gomock.Any(), gomock.Any()).Return(false, nil)
},
setupMockSourcesChecker: func(m *MockSourcesCheckable) {
m.EXPECT().IsUpToDate(gomock.Any()).Return(false, nil)
},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
mockStatusChecker := NewMockStatusCheckable(ctrl)
if tt.setupMockStatusChecker != nil {
tt.setupMockStatusChecker(mockStatusChecker)
}
mockSourcesChecker := NewMockSourcesCheckable(ctrl)
if tt.setupMockSourcesChecker != nil {
tt.setupMockSourcesChecker(mockSourcesChecker)
}
result, err := IsTaskUpToDate(
context.Background(),
tt.task,
WithStatusChecker(mockStatusChecker),
WithSourcesChecker(mockSourcesChecker),
)
require.NoError(t, err)
assert.Equal(t, tt.expected, result)
})
}
}

62
internal/goext/meta.go Normal file
View File

@@ -0,0 +1,62 @@
package goext
// NOTE(@andreynering): The lists in this file were copied from:
//
// https://github.com/golang/go/blob/master/src/go/build/syslist.go
func IsKnownOS(str string) bool {
_, known := knownOS[str]
return known
}
func IsKnownArch(str string) bool {
_, known := knownArch[str]
return known
}
var knownOS = map[string]struct{}{
"aix": {},
"android": {},
"darwin": {},
"dragonfly": {},
"freebsd": {},
"hurd": {},
"illumos": {},
"ios": {},
"js": {},
"linux": {},
"nacl": {},
"netbsd": {},
"openbsd": {},
"plan9": {},
"solaris": {},
"windows": {},
"zos": {},
}
var knownArch = map[string]struct{}{
"386": {},
"amd64": {},
"amd64p32": {},
"arm": {},
"armbe": {},
"arm64": {},
"arm64be": {},
"loong64": {},
"mips": {},
"mipsle": {},
"mips64": {},
"mips64le": {},
"mips64p32": {},
"mips64p32le": {},
"ppc": {},
"ppc64": {},
"ppc64le": {},
"riscv": {},
"riscv64": {},
"s390": {},
"s390x": {},
"sparc": {},
"sparc64": {},
"wasm": {},
}

View File

@@ -2,6 +2,8 @@ package logger
import (
"io"
"os"
"strconv"
"github.com/fatih/color"
)
@@ -9,13 +11,40 @@ import (
type Color func() PrintFunc
type PrintFunc func(io.Writer, string, ...interface{})
func Default() PrintFunc { return color.New(color.Reset).FprintfFunc() }
func Blue() PrintFunc { return color.New(color.FgBlue).FprintfFunc() }
func Green() PrintFunc { return color.New(color.FgGreen).FprintfFunc() }
func Cyan() PrintFunc { return color.New(color.FgCyan).FprintfFunc() }
func Yellow() PrintFunc { return color.New(color.FgYellow).FprintfFunc() }
func Magenta() PrintFunc { return color.New(color.FgMagenta).FprintfFunc() }
func Red() PrintFunc { return color.New(color.FgRed).FprintfFunc() }
func Default() PrintFunc {
return color.New(envColor("TASK_COLOR_RESET", color.Reset)).FprintfFunc()
}
func Blue() PrintFunc {
return color.New(envColor("TASK_COLOR_BLUE", color.FgBlue)).FprintfFunc()
}
func Green() PrintFunc {
return color.New(envColor("TASK_COLOR_GREEN", color.FgGreen)).FprintfFunc()
}
func Cyan() PrintFunc {
return color.New(envColor("TASK_COLOR_CYAN", color.FgCyan)).FprintfFunc()
}
func Yellow() PrintFunc {
return color.New(envColor("TASK_COLOR_YELLOW", color.FgYellow)).FprintfFunc()
}
func Magenta() PrintFunc {
return color.New(envColor("TASK_COLOR_MAGENTA", color.FgMagenta)).FprintfFunc()
}
func Red() PrintFunc {
return color.New(envColor("TASK_COLOR_RED", color.FgRed)).FprintfFunc()
}
func envColor(env string, defaultColor color.Attribute) color.Attribute {
if os.Getenv("FORCE_COLOR") != "" {
color.NoColor = false
}
override, err := strconv.Atoi(os.Getenv(env))
if err == nil {
return color.Attribute(override)
}
return defaultColor
}
// Logger is just a wrapper that prints stuff to STDOUT or STDERR,
// with optional color.
@@ -28,6 +57,11 @@ type Logger struct {
// Outf prints stuff to STDOUT.
func (l *Logger) Outf(color Color, s string, args ...interface{}) {
l.FOutf(l.Stdout, color, s+"\n", args...)
}
// FOutf prints stuff to the given writer.
func (l *Logger) FOutf(w io.Writer, color Color, s string, args ...interface{}) {
if len(args) == 0 {
s, args = "%s", []interface{}{s}
}
@@ -35,7 +69,7 @@ func (l *Logger) Outf(color Color, s string, args ...interface{}) {
color = Default
}
print := color()
print(l.Stdout, s+"\n", args...)
print(w, s, args...)
}
// VerboseOutf prints stuff to STDOUT if verbose mode is enabled.

View File

@@ -5,24 +5,31 @@ import (
"io"
)
type Group struct{
type Group struct {
Begin, End string
ErrorOnly bool
}
func (g Group) WrapWriter(w io.Writer, _ string, tmpl Templater) io.Writer {
gw := &groupWriter{writer: w}
func (g Group) WrapWriter(stdOut, _ io.Writer, _ string, tmpl Templater) (io.Writer, io.Writer, CloseFunc) {
gw := &groupWriter{writer: stdOut}
if g.Begin != "" {
gw.begin = tmpl.Replace(g.Begin) + "\n"
}
if g.End != "" {
gw.end = tmpl.Replace(g.End) + "\n"
}
return gw
return gw, gw, func(err error) error {
if g.ErrorOnly && err == nil {
return nil
}
return gw.close()
}
}
type groupWriter struct {
writer io.Writer
buff bytes.Buffer
writer io.Writer
buff bytes.Buffer
begin, end string
}
@@ -30,7 +37,7 @@ func (gw *groupWriter) Write(p []byte) (int, error) {
return gw.buff.Write(p)
}
func (gw *groupWriter) Close() error {
func (gw *groupWriter) close() error {
if gw.buff.Len() == 0 {
// don't print begin/end messages if there's no buffered entries
return nil

View File

@@ -6,6 +6,6 @@ import (
type Interleaved struct{}
func (Interleaved) WrapWriter(w io.Writer, _ string, _ Templater) io.Writer {
return w
func (Interleaved) WrapWriter(stdOut, stdErr io.Writer, _ string, _ Templater) (io.Writer, io.Writer, CloseFunc) {
return stdOut, stdErr, func(error) error { return nil }
}

View File

@@ -15,9 +15,11 @@ type Templater interface {
}
type Output interface {
WrapWriter(w io.Writer, prefix string, tmpl Templater) io.Writer
WrapWriter(stdOut, stdErr io.Writer, prefix string, tmpl Templater) (io.Writer, io.Writer, CloseFunc)
}
type CloseFunc func(err error) error
// Build the Output for the requested taskfile.Output.
func BuildFor(o *taskfile.Output) (Output, error) {
switch o.Name {
@@ -28,8 +30,9 @@ func BuildFor(o *taskfile.Output) (Output, error) {
return Interleaved{}, nil
case "group":
return Group{
Begin: o.Group.Begin,
End: o.Group.End,
Begin: o.Group.Begin,
End: o.Group.End,
ErrorOnly: o.Group.ErrorOnly,
}, nil
case "prefixed":
if err := checkOutputGroupUnset(o); err != nil {

View File

@@ -2,21 +2,22 @@ package output_test
import (
"bytes"
"errors"
"fmt"
"io"
"testing"
"github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile"
"github.com/stretchr/testify/assert"
"github.com/go-task/task/v3/internal/output"
"github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile"
)
func TestInterleaved(t *testing.T) {
var b bytes.Buffer
var o output.Output = output.Interleaved{}
var w = o.WrapWriter(&b, "", nil)
var w, _, _ = o.WrapWriter(&b, io.Discard, "", nil)
fmt.Fprintln(w, "foo\nbar")
assert.Equal(t, "foo\nbar\n", b.String())
@@ -27,14 +28,19 @@ func TestInterleaved(t *testing.T) {
func TestGroup(t *testing.T) {
var b bytes.Buffer
var o output.Output = output.Group{}
var w = o.WrapWriter(&b, "", nil).(io.WriteCloser)
var stdOut, stdErr, cleanup = o.WrapWriter(&b, io.Discard, "", nil)
fmt.Fprintln(w, "foo\nbar")
fmt.Fprintln(stdOut, "out\nout")
assert.Equal(t, "", b.String())
fmt.Fprintln(w, "baz")
fmt.Fprintln(stdErr, "err\nerr")
assert.Equal(t, "", b.String())
assert.NoError(t, w.Close())
assert.Equal(t, "foo\nbar\nbaz\n", b.String())
fmt.Fprintln(stdOut, "out")
assert.Equal(t, "", b.String())
fmt.Fprintln(stdErr, "err")
assert.Equal(t, "", b.String())
assert.NoError(t, cleanup(nil))
assert.Equal(t, "out\nout\nerr\nerr\nout\nerr\n", b.String())
}
func TestGroupWithBeginEnd(t *testing.T) {
@@ -53,27 +59,54 @@ func TestGroupWithBeginEnd(t *testing.T) {
}
t.Run("simple", func(t *testing.T) {
var b bytes.Buffer
var w = o.WrapWriter(&b, "", &tmpl).(io.WriteCloser)
var w, _, cleanup = o.WrapWriter(&b, io.Discard, "", &tmpl)
fmt.Fprintln(w, "foo\nbar")
assert.Equal(t, "", b.String())
fmt.Fprintln(w, "baz")
assert.Equal(t, "", b.String())
assert.NoError(t, w.Close())
assert.NoError(t, cleanup(nil))
assert.Equal(t, "::group::example-value\nfoo\nbar\nbaz\n::endgroup::\n", b.String())
})
t.Run("no output", func(t *testing.T) {
var b bytes.Buffer
var w = o.WrapWriter(&b, "", &tmpl).(io.WriteCloser)
assert.NoError(t, w.Close())
var _, _, cleanup = o.WrapWriter(&b, io.Discard, "", &tmpl)
assert.NoError(t, cleanup(nil))
assert.Equal(t, "", b.String())
})
}
func TestGroupErrorOnlySwallowsOutputOnNoError(t *testing.T) {
var b bytes.Buffer
var o output.Output = output.Group{
ErrorOnly: true,
}
var stdOut, stdErr, cleanup = o.WrapWriter(&b, io.Discard, "", nil)
_, _ = fmt.Fprintln(stdOut, "std-out")
_, _ = fmt.Fprintln(stdErr, "std-err")
assert.NoError(t, cleanup(nil))
assert.Empty(t, b.String())
}
func TestGroupErrorOnlyShowsOutputOnError(t *testing.T) {
var b bytes.Buffer
var o output.Output = output.Group{
ErrorOnly: true,
}
var stdOut, stdErr, cleanup = o.WrapWriter(&b, io.Discard, "", nil)
_, _ = fmt.Fprintln(stdOut, "std-out")
_, _ = fmt.Fprintln(stdErr, "std-err")
assert.NoError(t, cleanup(errors.New("any-error")))
assert.Equal(t, "std-out\nstd-err\n", b.String())
}
func TestPrefixed(t *testing.T) {
var b bytes.Buffer
var o output.Output = output.Prefixed{}
var w = o.WrapWriter(&b, "prefix", nil).(io.WriteCloser)
var w, _, cleanup = o.WrapWriter(&b, io.Discard, "prefix", nil)
t.Run("simple use cases", func(t *testing.T) {
b.Reset()
@@ -82,6 +115,7 @@ func TestPrefixed(t *testing.T) {
assert.Equal(t, "[prefix] foo\n[prefix] bar\n", b.String())
fmt.Fprintln(w, "baz")
assert.Equal(t, "[prefix] foo\n[prefix] bar\n[prefix] baz\n", b.String())
assert.NoError(t, cleanup(nil))
})
t.Run("multiple writes for a single line", func(t *testing.T) {
@@ -92,7 +126,7 @@ func TestPrefixed(t *testing.T) {
assert.Equal(t, "", b.String())
}
assert.NoError(t, w.Close())
assert.NoError(t, cleanup(nil))
assert.Equal(t, "[prefix] Test!\n", b.String())
})
}

View File

@@ -9,8 +9,9 @@ import (
type Prefixed struct{}
func (Prefixed) WrapWriter(w io.Writer, prefix string, _ Templater) io.Writer {
return &prefixWriter{writer: w, prefix: prefix}
func (Prefixed) WrapWriter(stdOut, _ io.Writer, prefix string, _ Templater) (io.Writer, io.Writer, CloseFunc) {
pw := &prefixWriter{writer: stdOut, prefix: prefix}
return pw, pw, func(error) error { return pw.close() }
}
type prefixWriter struct {
@@ -28,7 +29,7 @@ func (pw *prefixWriter) Write(p []byte) (int, error) {
return n, pw.writeOutputLines(false)
}
func (pw *prefixWriter) Close() error {
func (pw *prefixWriter) close() error {
return pw.writeOutputLines(true)
}

View File

@@ -1,176 +0,0 @@
// This code is released under the MIT License
// Copyright (c) 2020 Marco Molteni and the timeit contributors.
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"time"
)
const usage = `sleepit: sleep for the specified duration, optionally handling signals
When the line "sleepit: ready" is printed, it means that it is safe to send signals to it
Usage: sleepit <command> [<args>]
Commands
default Use default action: on reception of SIGINT terminate abruptly
handle Handle signals: on reception of SIGINT perform cleanup before exiting
version Show the sleepit version`
var (
// Filled by the linker.
fullVersion = "unknown" // example: v0.0.9-8-g941583d027-dirty
)
func main() {
os.Exit(run(os.Args[1:]))
}
func run(args []string) int {
if len(args) < 1 {
fmt.Fprintln(os.Stderr, usage)
return 2
}
defaultCmd := flag.NewFlagSet("default", flag.ExitOnError)
defaultSleep := defaultCmd.Duration("sleep", 5*time.Second, "Sleep duration")
handleCmd := flag.NewFlagSet("handle", flag.ExitOnError)
handleSleep := handleCmd.Duration("sleep", 5*time.Second, "Sleep duration")
handleCleanup := handleCmd.Duration("cleanup", 5*time.Second, "Cleanup duration")
handleTermAfter := handleCmd.Int("term-after", 0,
"Terminate immediately after `N` signals.\n"+
"Default is to terminate only when the cleanup phase has completed.")
versionCmd := flag.NewFlagSet("version", flag.ExitOnError)
switch args[0] {
case "default":
_ = defaultCmd.Parse(args[1:])
if len(defaultCmd.Args()) > 0 {
fmt.Fprintf(os.Stderr, "default: unexpected arguments: %v\n", defaultCmd.Args())
return 2
}
return supervisor(*defaultSleep, 0, 0, nil)
case "handle":
_ = handleCmd.Parse(args[1:])
if *handleTermAfter == 1 {
fmt.Fprintf(os.Stderr, "handle: term-after cannot be 1\n")
return 2
}
if len(handleCmd.Args()) > 0 {
fmt.Fprintf(os.Stderr, "handle: unexpected arguments: %v\n", handleCmd.Args())
return 2
}
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt) // Ctrl-C -> SIGINT
return supervisor(*handleSleep, *handleCleanup, *handleTermAfter, sigCh)
case "version":
_ = versionCmd.Parse(args[1:])
if len(versionCmd.Args()) > 0 {
fmt.Fprintf(os.Stderr, "version: unexpected arguments: %v\n", versionCmd.Args())
return 2
}
fmt.Printf("sleepit version %s\n", fullVersion)
return 0
default:
fmt.Fprintln(os.Stderr, usage)
return 2
}
}
func supervisor(
sleep time.Duration,
cleanup time.Duration,
termAfter int,
sigCh <-chan os.Signal,
) int {
fmt.Printf("sleepit: ready\n")
fmt.Printf("sleepit: PID=%d sleep=%v cleanup=%v\n",
os.Getpid(), sleep, cleanup)
cancelWork := make(chan struct{})
workerDone := worker(cancelWork, sleep, "work")
cancelCleaner := make(chan struct{})
var cleanerDone <-chan struct{}
sigCount := 0
for {
select {
case sig := <-sigCh:
sigCount++
fmt.Printf("sleepit: got signal=%s count=%d\n", sig, sigCount)
if sigCount == 1 {
// since `cancelWork` is unbuffered, sending will be synchronous:
// we are ensured that the worker has terminated before starting cleanup.
// This is important in some real-life situations.
cancelWork <- struct{}{}
cleanerDone = worker(cancelCleaner, cleanup, "cleanup")
}
if sigCount == termAfter {
cancelCleaner <- struct{}{}
return 4
}
case <-workerDone:
return 0
case <-cleanerDone:
return 3
}
}
}
// Start a worker goroutine and return immediately a `workerDone` channel.
// The goroutine will prepend its prints with the prefix `name`.
// The goroutine will simulate some work and will terminate when one of the following
// conditions happens:
// 1. When `howlong` is elapsed. This case will be signaled on the `workerDone` channel.
// 2. When something happens on channel `canceled`. Note that this simulates real-life,
// so cancellation is not instantaneous: if the caller wants a synchronous cancel,
// it should send a message; if instead it wants an asynchronous cancel, it should
// close the channel.
func worker(
canceled <-chan struct{},
howlong time.Duration,
name string,
) <-chan struct{} {
workerDone := make(chan struct{})
deadline := time.Now().Add(howlong)
go func() {
fmt.Printf("sleepit: %s started\n", name)
for {
select {
case <-canceled:
fmt.Printf("sleepit: %s canceled\n", name)
return
default:
if doSomeWork(deadline) {
fmt.Printf("sleepit: %s done\n", name) // <== NOTE THIS LINE
workerDone <- struct{}{}
return
}
}
}
}()
return workerDone
}
// Do some work and then return, so that the caller can decide wether to continue or not.
// Return true when all work is done.
func doSomeWork(deadline time.Time) bool {
if time.Now().After(deadline) {
return true
}
timeout := 100 * time.Millisecond
time.Sleep(timeout)
return false
}

View File

@@ -0,0 +1,20 @@
package slicesext
import (
"golang.org/x/exp/constraints"
"golang.org/x/exp/slices"
)
func UniqueJoin[T constraints.Ordered](ss ...[]T) []T {
var length int
for _, s := range ss {
length += len(s)
}
r := make([]T, length)
var i int
for _, s := range ss {
i += copy(r[i:], s)
}
slices.Sort(r)
return slices.Compact(r)
}

View File

@@ -1,118 +0,0 @@
package status
import (
"crypto/md5"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strings"
)
// Checksum validades if a task is up to date by calculating its source
// files checksum
type Checksum struct {
BaseDir string
TaskDir string
Task string
Sources []string
Generates []string
Dry bool
}
// IsUpToDate implements the Checker interface
func (c *Checksum) IsUpToDate() (bool, error) {
if len(c.Sources) == 0 {
return false, nil
}
checksumFile := c.checksumFilePath()
data, _ := os.ReadFile(checksumFile)
oldMd5 := strings.TrimSpace(string(data))
sources, err := globs(c.TaskDir, c.Sources)
if err != nil {
return false, err
}
newMd5, err := c.checksum(sources...)
if err != nil {
return false, nil
}
if !c.Dry {
_ = os.MkdirAll(filepath.Join(c.BaseDir, ".task", "checksum"), 0755)
if err = os.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
return false, err
}
}
if len(c.Generates) > 0 {
// For each specified 'generates' field, check whether the files actually exist
for _, g := range c.Generates {
generates, err := Glob(c.TaskDir, g)
if os.IsNotExist(err) {
return false, nil
}
if err != nil {
return false, err
}
if len(generates) == 0 {
return false, nil
}
}
}
return oldMd5 == newMd5, nil
}
func (c *Checksum) checksum(files ...string) (string, error) {
h := md5.New()
for _, f := range files {
// also sum the filename, so checksum changes for renaming a file
if _, err := io.Copy(h, strings.NewReader(filepath.Base(f))); err != nil {
return "", err
}
f, err := os.Open(f)
if err != nil {
return "", err
}
if _, err = io.Copy(h, f); err != nil {
return "", err
}
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
}
// Value implements the Checker Interface
func (c *Checksum) Value() (interface{}, error) {
return c.checksum()
}
// OnError implements the Checker interface
func (c *Checksum) OnError() error {
if len(c.Sources) == 0 {
return nil
}
return os.Remove(c.checksumFilePath())
}
// Kind implements the Checker Interface
func (*Checksum) Kind() string {
return "checksum"
}
func (c *Checksum) checksumFilePath() string {
return filepath.Join(c.BaseDir, ".task", "checksum", c.normalizeFilename(c.Task))
}
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
// replaces invalid caracters on filenames with "-"
func (*Checksum) normalizeFilename(f string) string {
return checksumFilenameRegexp.ReplaceAllString(f, "-")
}

View File

@@ -1,23 +0,0 @@
package status
// None is a no-op Checker
type None struct{}
// IsUpToDate implements the Checker interface
func (None) IsUpToDate() (bool, error) {
return false, nil
}
// Value implements the Checker interface
func (None) Value() (interface{}, error) {
return "", nil
}
func (None) Kind() string {
return "none"
}
// OnError implements the Checker interface
func (None) OnError() error {
return nil
}

View File

@@ -1,15 +0,0 @@
package status
var (
_ Checker = &Timestamp{}
_ Checker = &Checksum{}
_ Checker = None{}
)
// Checker is an interface that checks if the status is up-to-date
type Checker interface {
IsUpToDate() (bool, error)
Value() (interface{}, error)
OnError() error
Kind() string
}

View File

@@ -1,108 +0,0 @@
package status
import (
"os"
"time"
)
// Timestamp checks if any source change compared with the generated files,
// using file modifications timestamps.
type Timestamp struct {
Dir string
Sources []string
Generates []string
}
// IsUpToDate implements the Checker interface
func (t *Timestamp) IsUpToDate() (bool, error) {
if len(t.Sources) == 0 || len(t.Generates) == 0 {
return false, nil
}
sources, err := globs(t.Dir, t.Sources)
if err != nil {
return false, nil
}
generates, err := globs(t.Dir, t.Generates)
if err != nil {
return false, nil
}
sourcesMaxTime, err := getMaxTime(sources...)
if err != nil || sourcesMaxTime.IsZero() {
return false, nil
}
generatesMinTime, err := getMinTime(generates...)
if err != nil || generatesMinTime.IsZero() {
return false, nil
}
return !generatesMinTime.Before(sourcesMaxTime), nil
}
func (t *Timestamp) Kind() string {
return "timestamp"
}
// Value implements the Checker Interface
func (t *Timestamp) Value() (interface{}, error) {
sources, err := globs(t.Dir, t.Sources)
if err != nil {
return time.Now(), err
}
sourcesMaxTime, err := getMaxTime(sources...)
if err != nil {
return time.Now(), err
}
if sourcesMaxTime.IsZero() {
return time.Unix(0, 0), nil
}
return sourcesMaxTime, nil
}
func getMinTime(files ...string) (time.Time, error) {
var t time.Time
for _, f := range files {
info, err := os.Stat(f)
if err != nil {
return time.Time{}, err
}
t = minTime(t, info.ModTime())
}
return t, nil
}
func getMaxTime(files ...string) (time.Time, error) {
var t time.Time
for _, f := range files {
info, err := os.Stat(f)
if err != nil {
return time.Time{}, err
}
t = maxTime(t, info.ModTime())
}
return t, nil
}
func minTime(a, b time.Time) time.Time {
if !a.IsZero() && a.Before(b) {
return a
}
return b
}
func maxTime(a, b time.Time) time.Time {
if a.After(b) {
return a
}
return b
}
// OnError implements the Checker interface
func (*Timestamp) OnError() error {
return nil
}

View File

@@ -28,6 +28,7 @@ func PrintTask(l *logger.Logger, t *taskfile.Task) {
printTaskName(l, t)
printTaskDescribingText(t, l)
printTaskDependencies(l, t)
printTaskAliases(l, t)
printTaskCommands(l, t)
}
@@ -56,10 +57,23 @@ func printTaskSummary(l *logger.Logger, t *taskfile.Task) {
}
func printTaskName(l *logger.Logger, t *taskfile.Task) {
l.Outf(logger.Default, "task: %s", t.Name())
l.FOutf(l.Stdout, logger.Default, "task: ")
l.FOutf(l.Stdout, logger.Green, "%s\n", t.Name())
l.Outf(logger.Default, "")
}
func printTaskAliases(l *logger.Logger, t *taskfile.Task) {
if len(t.Aliases) == 0 {
return
}
l.Outf(logger.Default, "")
l.Outf(logger.Default, "aliases:")
for _, alias := range t.Aliases {
l.FOutf(l.Stdout, logger.Default, " - ")
l.Outf(logger.Cyan, alias)
}
}
func hasDescription(t *taskfile.Task) bool {
return t.Desc != ""
}
@@ -94,10 +108,11 @@ func printTaskCommands(l *logger.Logger, t *taskfile.Task) {
l.Outf(logger.Default, "commands:")
for _, c := range t.Cmds {
isCommand := c.Cmd != ""
l.FOutf(l.Stdout, logger.Default, " - ")
if isCommand {
l.Outf(logger.Default, " - %s", c.Cmd)
l.FOutf(l.Stdout, logger.Yellow, "%s\n", c.Cmd)
} else {
l.Outf(logger.Default, " - Task: %s", c.Task)
l.FOutf(l.Stdout, logger.Green, "Task: %s\n", c.Task)
}
}
}

22
internal/sysinfo/uid.go Normal file
View File

@@ -0,0 +1,22 @@
//go:build !windows
package sysinfo
import (
"os"
"syscall"
)
func Owner(path string) (int, error) {
info, err := os.Stat(path)
if err != nil {
return 0, err
}
var uid int
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
uid = int(stat.Uid)
} else {
uid = os.Getuid()
}
return uid, nil
}

View File

@@ -0,0 +1,9 @@
//go:build windows
package sysinfo
// NOTE: This always returns -1 since there is currently no easy way to get
// file owner information on Windows.
func Owner(path string) (int, error) {
return -1, nil
}

View File

@@ -19,11 +19,11 @@ func init() {
"OS": func() string { return runtime.GOOS },
"ARCH": func() string { return runtime.GOARCH },
"catLines": func(s string) string {
s = strings.Replace(s, "\r\n", " ", -1)
return strings.Replace(s, "\n", " ", -1)
s = strings.ReplaceAll(s, "\r\n", " ")
return strings.ReplaceAll(s, "\n", " ")
},
"splitLines": func(s string) []string {
s = strings.Replace(s, "\r\n", "\n", -1)
s = strings.ReplaceAll(s, "\r\n", "\n")
return strings.Split(s, "\n")
},
"fromSlash": func(path string) string {

View File

@@ -0,0 +1,25 @@
package version
import (
"fmt"
"runtime/debug"
)
var version = ""
func GetVersion() string {
if version != "" {
return version
}
info, ok := debug.ReadBuildInfo()
if !ok || info.Main.Version == "" {
return "unknown"
}
ver := info.Main.Version
if info.Main.Sum != "" {
ver += fmt.Sprintf(" (%s)", info.Main.Sum)
}
return ver
}

32
package-lock.json generated Normal file
View File

@@ -0,0 +1,32 @@
{
"name": "@go-task/cli",
"version": "3.22.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@go-task/cli",
"version": "3.22.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@go-task/go-npm": "^0.1.17"
}
},
"node_modules/@go-task/go-npm": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/@go-task/go-npm/-/go-npm-0.1.17.tgz",
"integrity": "sha512-j+xydQWrAxsqLYjweok1fWzDmBAA1g/gmFbPyG8kRI/d/+rzXGGLlro8zdS6mJ3Is+8BrIy2ZBmQkoONhowh7A==",
"bin": {
"go-npm": "bin/index.js"
}
}
},
"dependencies": {
"@go-task/go-npm": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/@go-task/go-npm/-/go-npm-0.1.17.tgz",
"integrity": "sha512-j+xydQWrAxsqLYjweok1fWzDmBAA1g/gmFbPyG8kRI/d/+rzXGGLlro8zdS6mJ3Is+8BrIy2ZBmQkoONhowh7A=="
}
}
}

34
package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "@go-task/cli",
"version": "3.22.0",
"description": "A task runner / simpler Make alternative written in Go",
"scripts": {
"postinstall": "go-npm install",
"preuninstall": "go-npm uninstall"
},
"goBinary": {
"name": "task",
"path": "./bin",
"url": "https://github.com/go-task/task/releases/download/v{{version}}/task_{{platform}}_{{arch}}{{archive_ext}}"
},
"files": [],
"repository": {
"type": "git",
"url": "https://github.com/go-task/task.git"
},
"keywords": [
"task",
"taskfile",
"build-tool",
"task-runner"
],
"author": "Andrey Nering",
"license": "MIT",
"bugs": {
"url": "https://github.com/go-task/task/issues"
},
"homepage": "https://taskfile.dev",
"dependencies": {
"@go-task/go-npm": "^0.1.17"
}
}

Some files were not shown because too many files have changed in this diff Show More