mirror of
https://github.com/go-task/task.git
synced 2025-10-08 23:02:02 +02:00
feat: add some config to taskrc.yml (#2389)
Co-authored-by: Pete Davison <pd93.uk@outlook.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/go-task/task/v3/taskrc"
|
||||
"github.com/go-task/task/v3/taskrc/ast"
|
||||
)
|
||||
|
||||
const envPrefix = "TASK_X_"
|
||||
@@ -31,11 +32,15 @@ var (
|
||||
var xList []Experiment
|
||||
|
||||
func Parse(dir string) {
|
||||
config, _ := taskrc.GetConfig(dir)
|
||||
|
||||
ParseWithConfig(dir, config)
|
||||
}
|
||||
|
||||
func ParseWithConfig(dir string, config *ast.TaskRC) {
|
||||
// Read any .env files
|
||||
readDotEnv(dir)
|
||||
|
||||
config, _ := taskrc.GetConfig(dir)
|
||||
|
||||
// Initialize the experiments
|
||||
GentleForce = New("GENTLE_FORCE", config, 1)
|
||||
RemoteTaskfiles = New("REMOTE_TASKFILES", config, 1)
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
@@ -13,9 +12,10 @@ import (
|
||||
"github.com/go-task/task/v3"
|
||||
"github.com/go-task/task/v3/errors"
|
||||
"github.com/go-task/task/v3/experiments"
|
||||
"github.com/go-task/task/v3/internal/env"
|
||||
"github.com/go-task/task/v3/internal/sort"
|
||||
"github.com/go-task/task/v3/taskfile/ast"
|
||||
"github.com/go-task/task/v3/taskrc"
|
||||
taskrcast "github.com/go-task/task/v3/taskrc/ast"
|
||||
)
|
||||
|
||||
const usage = `Usage: task [flags...] [task...]
|
||||
@@ -95,7 +95,9 @@ func init() {
|
||||
|
||||
// Parse the experiments
|
||||
dir = cmp.Or(dir, filepath.Dir(entrypoint))
|
||||
experiments.Parse(dir)
|
||||
|
||||
config, _ := taskrc.GetConfig(dir)
|
||||
experiments.ParseWithConfig(dir, config)
|
||||
|
||||
// Parse the rest of the flags
|
||||
log.SetFlags(0)
|
||||
@@ -104,10 +106,7 @@ func init() {
|
||||
log.Print(usage)
|
||||
pflag.PrintDefaults()
|
||||
}
|
||||
offline, err := strconv.ParseBool(cmp.Or(env.GetTaskEnv("OFFLINE"), "false"))
|
||||
if err != nil {
|
||||
offline = false
|
||||
}
|
||||
|
||||
pflag.BoolVar(&Version, "version", false, "Show Task version.")
|
||||
pflag.BoolVarP(&Help, "help", "h", false, "Shows Task usage.")
|
||||
pflag.BoolVarP(&Init, "init", "i", false, "Creates a new Taskfile.yml in the current folder.")
|
||||
@@ -118,9 +117,9 @@ func init() {
|
||||
pflag.StringVar(&TaskSort, "sort", "", "Changes the order of the tasks when listed. [default|alphanumeric|none].")
|
||||
pflag.BoolVar(&Status, "status", false, "Exits with non-zero exit code if any of the given tasks is not up-to-date.")
|
||||
pflag.BoolVar(&NoStatus, "no-status", false, "Ignore status when listing tasks as JSON")
|
||||
pflag.BoolVar(&Insecure, "insecure", false, "Forces Task to download Taskfiles over insecure connections.")
|
||||
pflag.BoolVar(&Insecure, "insecure", getConfig(config, config.Remote.Insecure, false), "Forces Task to download Taskfiles over insecure connections.")
|
||||
pflag.BoolVarP(&Watch, "watch", "w", false, "Enables watch of the given task.")
|
||||
pflag.BoolVarP(&Verbose, "verbose", "v", false, "Enables verbose mode.")
|
||||
pflag.BoolVarP(&Verbose, "verbose", "v", getConfig(config, config.Verbose, false), "Enables verbose mode.")
|
||||
pflag.BoolVarP(&Silent, "silent", "s", false, "Disables echoing.")
|
||||
pflag.BoolVarP(&AssumeYes, "yes", "y", false, "Assume \"yes\" as answer to all prompts.")
|
||||
pflag.BoolVarP(&Parallel, "parallel", "p", false, "Executes tasks provided on command line in parallel.")
|
||||
@@ -134,7 +133,7 @@ func init() {
|
||||
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 of tasks to run concurrently.")
|
||||
pflag.IntVarP(&Concurrency, "concurrency", "C", getConfig(config, config.Concurrency, 0), "Limit number of 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/{T,t}askfile.{yml,yaml}.")
|
||||
pflag.BoolVar(&Experiments, "experiments", false, "Lists all the available experiments and whether or not they are enabled.")
|
||||
@@ -150,12 +149,11 @@ func init() {
|
||||
// Remote Taskfiles experiment will adds the "download" and "offline" flags
|
||||
if experiments.RemoteTaskfiles.Enabled() {
|
||||
pflag.BoolVar(&Download, "download", false, "Downloads a cached version of a remote Taskfile.")
|
||||
pflag.BoolVar(&Offline, "offline", offline, "Forces Task to only use local or cached Taskfiles.")
|
||||
pflag.DurationVar(&Timeout, "timeout", time.Second*10, "Timeout for downloading remote Taskfiles.")
|
||||
pflag.BoolVar(&Offline, "offline", getConfig(config, config.Remote.Offline, false), "Forces Task to only use local or cached Taskfiles.")
|
||||
pflag.DurationVar(&Timeout, "timeout", getConfig(config, config.Remote.Timeout, time.Second*10), "Timeout for downloading remote Taskfiles.")
|
||||
pflag.BoolVar(&ClearCache, "clear-cache", false, "Clear the remote cache.")
|
||||
pflag.DurationVar(&CacheExpiryDuration, "expiry", 0, "Expiry duration for cached remote Taskfiles.")
|
||||
pflag.DurationVar(&CacheExpiryDuration, "expiry", getConfig(config, config.Remote.Timeout, 0), "Expiry duration for cached remote Taskfiles.")
|
||||
}
|
||||
|
||||
pflag.Parse()
|
||||
}
|
||||
|
||||
@@ -251,3 +249,15 @@ func (o *flagsOption) ApplyToExecutor(e *task.Executor) {
|
||||
task.WithVersionCheck(true),
|
||||
)
|
||||
}
|
||||
|
||||
// getConfig extracts a config value directly from a pointer field with a fallback default
|
||||
func getConfig[T any](config *taskrcast.TaskRC, field *T, fallback T) T {
|
||||
if config == nil {
|
||||
return fallback
|
||||
}
|
||||
|
||||
if field != nil {
|
||||
return *field
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
@@ -1,27 +1,48 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
)
|
||||
|
||||
type TaskRC struct {
|
||||
Version *semver.Version `yaml:"version"`
|
||||
Verbose *bool `yaml:"verbose"`
|
||||
Concurrency *int `yaml:"concurrency"`
|
||||
Remote Remote `yaml:"remote"`
|
||||
Experiments map[string]int `yaml:"experiments"`
|
||||
}
|
||||
|
||||
type Remote struct {
|
||||
Insecure *bool `yaml:"insecure"`
|
||||
Offline *bool `yaml:"offline"`
|
||||
Timeout *time.Duration `yaml:"timeout"`
|
||||
CacheExpiry *time.Duration `yaml:"cache-expiry"`
|
||||
}
|
||||
|
||||
// Merge combines the current TaskRC with another TaskRC, prioritizing non-nil fields from the other TaskRC.
|
||||
func (t *TaskRC) Merge(other *TaskRC) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
if t.Version == nil && other.Version != nil {
|
||||
t.Version = other.Version
|
||||
}
|
||||
|
||||
t.Version = cmp.Or(other.Version, t.Version)
|
||||
|
||||
if t.Experiments == nil && other.Experiments != nil {
|
||||
t.Experiments = other.Experiments
|
||||
} else if t.Experiments != nil && other.Experiments != nil {
|
||||
maps.Copy(t.Experiments, other.Experiments)
|
||||
}
|
||||
|
||||
// Merge Remote fields
|
||||
t.Remote.Insecure = cmp.Or(other.Remote.Insecure, t.Remote.Insecure)
|
||||
t.Remote.Offline = cmp.Or(other.Remote.Offline, t.Remote.Offline)
|
||||
t.Remote.Timeout = cmp.Or(other.Remote.Timeout, t.Remote.Timeout)
|
||||
t.Remote.CacheExpiry = cmp.Or(other.Remote.CacheExpiry, t.Remote.CacheExpiry)
|
||||
|
||||
t.Verbose = cmp.Or(other.Verbose, t.Verbose)
|
||||
t.Concurrency = cmp.Or(other.Concurrency, t.Concurrency)
|
||||
}
|
||||
|
@@ -5,7 +5,8 @@ import { resolve } from 'path';
|
||||
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs';
|
||||
import {
|
||||
groupIconMdPlugin,
|
||||
groupIconVitePlugin
|
||||
groupIconVitePlugin,
|
||||
localIconLoader
|
||||
} from 'vitepress-plugin-group-icons';
|
||||
import { team } from './team.ts';
|
||||
import { taskDescription, taskName } from './meta.ts';
|
||||
@@ -99,7 +100,20 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
vite: {
|
||||
plugins: [groupIconVitePlugin()],
|
||||
plugins: [
|
||||
groupIconVitePlugin({
|
||||
customIcon: {
|
||||
'.taskrc.yml': localIconLoader(
|
||||
import.meta.url,
|
||||
'./theme/icons/task.svg'
|
||||
),
|
||||
'Taskfile.yml': localIconLoader(
|
||||
import.meta.url,
|
||||
'./theme/icons/task.svg'
|
||||
)
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
{
|
||||
|
1
website/.vitepress/theme/icons/task.svg
Normal file
1
website/.vitepress/theme/icons/task.svg
Normal file
@@ -0,0 +1 @@
|
||||
<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>
|
After Width: | Height: | Size: 435 B |
@@ -290,3 +290,64 @@ You can force Task to ignore the cache and download the latest version by using
|
||||
the `--download` flag.
|
||||
|
||||
You can use the `--clear-cache` flag to clear all cached remote files.
|
||||
|
||||
## Configuration
|
||||
This experiment adds a new `remote` section to the [configuration file](../reference/config.md).
|
||||
|
||||
- **Type**: `object`
|
||||
- **Description**: Remote configuration settings for handling remote Taskfiles
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
insecure: false
|
||||
offline: false
|
||||
timeout: "30s"
|
||||
cache-expiry: "24h"
|
||||
```
|
||||
|
||||
#### `insecure`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Allow insecure connections when fetching remote Taskfiles
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
insecure: true
|
||||
```
|
||||
|
||||
#### `offline`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Work in offline mode, preventing remote Taskfile fetching
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
offline: true
|
||||
```
|
||||
|
||||
#### `timeout`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: Not specified
|
||||
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
|
||||
- **Description**: Timeout duration for remote operations (e.g., '30s', '5m')
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
timeout: "1m"
|
||||
```
|
||||
|
||||
#### `cache-expiry`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: Not specified
|
||||
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
|
||||
- **Description**: Cache expiry duration for remote Taskfiles (e.g., '1h', '24h')
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cache-expiry: "6h"
|
||||
```
|
||||
|
||||
|
@@ -73,3 +73,44 @@ option_3: foo # Taken from $XDG_CONFIG_HOME/task/.taskrc.yml
|
||||
The experiments section allows you to enable Task's experimental features. These
|
||||
options are not enumerated here. Instead, please refer to our
|
||||
[experiments documentation](../experiments/index.md) for more information.
|
||||
|
||||
```yaml
|
||||
experiments:
|
||||
feature_name: 1
|
||||
another_feature: 2
|
||||
```
|
||||
|
||||
### `verbose`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Enable verbose output for all tasks
|
||||
- **CLI equivalent**: [`-v, --verbose`](./cli.md#-v---verbose)
|
||||
|
||||
```yaml
|
||||
verbose: true
|
||||
```
|
||||
|
||||
### `concurrency`
|
||||
|
||||
- **Type**: `integer`
|
||||
- **Minimum**: `1`
|
||||
- **Description**: Number of concurrent tasks to run
|
||||
- **CLI equivalent**: [`-C, --concurrency`](./cli.md#-c---concurrency-number)
|
||||
|
||||
```yaml
|
||||
concurrency: 4
|
||||
```
|
||||
|
||||
## Example Configuration
|
||||
|
||||
Here's a complete example of a `.taskrc.yml` file with all available options:
|
||||
|
||||
```yaml
|
||||
# Global settings
|
||||
verbose: true
|
||||
concurrency: 2
|
||||
|
||||
# Enable experimental features
|
||||
experiments:
|
||||
REMOTE_TASKFILES: 1
|
||||
|
@@ -20,6 +20,40 @@
|
||||
"enum": [0, 1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"remote": {
|
||||
"type": "object",
|
||||
"description": "Remote configuration settings",
|
||||
"properties": {
|
||||
"insecure": {
|
||||
"type": "boolean",
|
||||
"description": "Forces Task to download Taskfiles over insecure connections."
|
||||
},
|
||||
"offline": {
|
||||
"type": "boolean",
|
||||
"description": "Forces Task to only use local or cached Taskfiles."
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"description": "Timeout for downloading remote Taskfiles (e.g., '30s', '5m')",
|
||||
"pattern": "^[0-9]+(ns|us|µs|ms|s|m|h)$"
|
||||
},
|
||||
"cache-expiry": {
|
||||
"type": "string",
|
||||
"description": "Expiry duration for cached remote Taskfiles (e.g., '1h', '24h')",
|
||||
"pattern": "^[0-9]+(ns|us|µs|ms|s|m|h)$"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"verbose": {
|
||||
"type": "boolean",
|
||||
"description": "Enable verbose output"
|
||||
},
|
||||
"concurrency": {
|
||||
"type": "integer",
|
||||
"description": "Number of concurrent tasks to run",
|
||||
"minimum": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
Reference in New Issue
Block a user