Skip to content

Commit

Permalink
feat: enable any variables without maps (#1547)
Browse files Browse the repository at this point in the history
* feat: enable any variable experiment (without maps)

* chore: rename any_variables experiment to map_variables

* docs: create map variables experiment docs and update usage

* blog: any variables

* fix: links

* fix: warn about broken links instead of failing
  • Loading branch information
pd93 authored Apr 9, 2024
1 parent eb2783f commit 1ff618c
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 131 deletions.
6 changes: 3 additions & 3 deletions internal/experiments/experiments.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ type Experiment struct {
var (
GentleForce Experiment
RemoteTaskfiles Experiment
AnyVariables Experiment
MapVariables Experiment
)

func init() {
readDotEnv()
GentleForce = New("GENTLE_FORCE")
RemoteTaskfiles = New("REMOTE_TASKFILES")
AnyVariables = New("ANY_VARIABLES", "1", "2")
MapVariables = New("MAP_VARIABLES", "1", "2")
}

func New(xName string, enabledValues ...string) Experiment {
Expand Down Expand Up @@ -101,6 +101,6 @@ func List(l *logger.Logger) error {
w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, ' ', 0)
printExperiment(w, l, GentleForce)
printExperiment(w, l, RemoteTaskfiles)
printExperiment(w, l, AnyVariables)
printExperiment(w, l, MapVariables)
return w.Flush()
}
27 changes: 14 additions & 13 deletions taskfile/ast/var.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ type Var struct {
}

func (v *Var) UnmarshalYAML(node *yaml.Node) error {
if experiments.AnyVariables.Enabled {
if experiments.MapVariables.Enabled {

// This implementation is not backwards-compatible and replaces the 'sh' key with map variables
if experiments.AnyVariables.Value == "1" {
if experiments.MapVariables.Value == "1" {
var value any
if err := node.Decode(&value); err != nil {
return err
Expand All @@ -103,7 +103,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error {
}

// This implementation IS backwards-compatible and keeps the 'sh' key and allows map variables to be added under the `map` key
if experiments.AnyVariables.Value == "2" {
if experiments.MapVariables.Value == "2" {
switch node.Kind {
case yaml.MappingNode:
key := node.Content[0].Value
Expand Down Expand Up @@ -141,15 +141,10 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error {

switch node.Kind {

case yaml.ScalarNode:
var str string
if err := node.Decode(&str); err != nil {
return err
}
v.Value = str
return nil

case yaml.MappingNode:
if len(node.Content) > 2 || node.Content[0].Value != "sh" {
return fmt.Errorf(`task: line %d: maps cannot be assigned to variables`, node.Line)
}
var sh struct {
Sh string
}
Expand All @@ -158,7 +153,13 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error {
}
v.Sh = sh.Sh
return nil
}

return fmt.Errorf("yaml: line %d: cannot unmarshal %s into variable", node.Line, node.ShortTag())
default:
var value any
if err := node.Decode(&value); err != nil {
return err
}
v.Value = value
return nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ communicate these kinds of thoughts to the community. So, with that in mind,
this is the first (hopefully of many) blog posts talking about Task and what
we're up to.

<!--truncate-->
{/* truncate */}

## :calendar: So, what have we been up to?

Expand Down Expand Up @@ -122,7 +122,7 @@ I plan to write more of these blog posts in the future on a variety of
Task-related topics, so make sure to check in occasionally and see what we're up
to!

<!-- prettier-ignore-start -->
{/* prettier-ignore-start */}
[vscode-task]: https://github.com/go-task/vscode-task
[crowdin]: https://crowdin.com
[contributors]: https://github.com/go-task/task/graphs/contributors
Expand All @@ -139,4 +139,4 @@ to!
[experiments-project]: https://github.com/orgs/go-task/projects/1
[gentle-force-experiment]: https://github.com/go-task/task/issues/1200
[remote-taskfiles-experiment]: https://github.com/go-task/task/issues/1317
<!-- prettier-ignore-end -->
{/* prettier-ignore-end */}
182 changes: 182 additions & 0 deletions website/blog/2024-04-09-variables.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
---
title: Any Variables
description: Task variables are no longer limited to strings!
slug: any-variables
authors: [pd93]
tags: [experiments, variables]
image: https://i.imgur.com/mErPwqL.png
hide_table_of_contents: false
draft: true
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Task has always had variables, but even though you were able to define them
using different YAML types, they would always be converted to strings by Task.
This limited users to string manipulation and encouraged messy workarounds for
simple problems. Starting from [v3.36.0][v3.36.0], this is no longer the case!
Task now supports most variable types, including **booleans**, **integers**,
**floats** and **arrays**!

{/* truncate */}

## What's the big deal?

These changes allow you to use variables in a much more natural way and opens up
a wide variety of sprig functions that were previously useless. Take a look at
some of the examples below for some inspiration.

### Evaluating booleans

No more comparing strings to "true" or "false". Now you can use actual boolean
values in your templates:

<Tabs defaultValue="2"
values={[
{label: 'Before', value: '1'},
{label: 'After', value: '2'}
]}>

<TabItem value="1">

```yaml
version: 3

tasks:
foo:
vars:
BOOL: true # <-- Parsed as a string even though its a YAML boolean
cmds:
- '{{if eq .BOOL "true"}}echo foo{{end}}'
```
</TabItem>
<TabItem value="2">
```yaml
version: 3

tasks:
foo:
vars:
BOOL: true # <-- Parsed as a boolean
cmds:
- '{{if .BOOL}}echo foo{{end}}' # <-- No need to compare to "true"
```
</TabItem></Tabs>
### Arithmetic
You can now perform basic arithmetic operations on integer and float variables:
```yaml
version: 3

tasks:
foo:
vars:
INT: 10
FLOAT: 3.14159
cmds:
- 'echo {{add .INT .FLOAT}}'
```
You can use any of the following arithmetic functions: `add`, `sub`, `mul`,
`div`, `mod`, `max`, `min`, `floor`, `ceil`, `round` and `randInt`. Check out
the [slim-sprig math documentation][slim-sprig-math] for more information.

### Arrays

You can now range over arrays inside templates and use list-based functions:

```yaml
version: 3
tasks:
foo:
vars:
ARRAY: [1, 2, 3]
cmds:
- 'echo {{range .ARRAY}}{{.}}{{end}}'
```

You can use any of the following list-based functions: `first`, `rest`, `last`,
`initial`, `append`, `prepend`, `concat`, `reverse`, `uniq`, `without`, `has`,
`compact`, `slice` and `chunk`. Check out the [slim-sprg lists
documentation][slim-sprig-list] for more information.

### Looping over variables using `for`

Previously, you would have to use a delimiter separated string to loop over an
arbitrary list of items in a variable and split them by using the `split` subkey
to specify the delimiter. However, we have now added support for looping over
"collection-type" variables using the `for` keyword, so now you are able to loop
over list variables directly:

<Tabs defaultValue="2"
values={[
{label: 'Before', value: '1'},
{label: 'After', value: '2'}
]}>

<TabItem value="1">

```yaml
version: 3
tasks:
foo:
vars:
LIST: 'foo,bar,baz'
cmds:
- for:
var: LIST
split: ','
cmd: echo {{.ITEM}}
```

</TabItem>
<TabItem value="2">

```yaml
version: 3
tasks:
foo:
vars:
LIST: ['foo', 'bar', 'baz']
cmds:
- for:
var: LIST
cmd: echo {{.ITEM}}
```

</TabItem></Tabs>

## What about maps?

Maps were originally included in the Any Variables experiment. However, they
weren't quite ready yet. Instead of making you wait for everything to be ready
at once, we have released support for all other variable types and we will
continue working on map support in the new "[Map Variables][map-variables]"
experiment.

:::note

If you were previously using maps with the Any Variables experiment and wish to
continue using them, you will need to enable the new [Map Variables
experiment][map-variables] instead.

:::

We're looking for feedback on a couple of different proposals, so please give
them a go and let us know what you think. :pray:

{/* prettier-ignore-start */}
[v3.36.0]: https://github.com/go-task/task/releases/tag/v3.36.0
[slim-sprig-math]: https://go-task.github.io/slim-sprig/math.html
[slim-sprig-list]: https://go-task.github.io/slim-sprig/lists.html
[map-variables]: /experiments/map-variables
{/* prettier-ignore-end */}
2 changes: 1 addition & 1 deletion website/docs/experiments/gentle_force.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ if you want to adopt the new behavior, you can continue to use the `--force`
flag as you do now!

{/* prettier-ignore-start */}
[enabling-experiments]: /experiments/#enabling-experiments
[enabling-experiments]: ./experiments.mdx#enabling-experiments
{/* prettier-ignore-end */}
Loading

0 comments on commit 1ff618c

Please sign in to comment.