Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(experiments): use getters to prevent toc/tou limitations #2015

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func run() error {
if err != nil {
return err
}
if experiments.AnyVariables.Enabled {
if experiments.AnyVariables().Enabled {
logger.Warnf("The 'Any Variables' experiment flag is no longer required to use non-map variable types. If you wish to use map variables, please use 'TASK_X_MAP_VARIABLES' instead. See https://github.com/go-task/task/issues/1585\n")
}

Expand Down
2 changes: 1 addition & 1 deletion internal/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func GetFromVars(env *ast.Vars) []string {
if !isTypeAllowed(v) {
continue
}
if !experiments.EnvPrecedence.Enabled {
if !experiments.EnvPrecedence().Enabled {
if _, alreadySet := os.LookupEnv(k); alreadySet {
continue
}
Expand Down
36 changes: 22 additions & 14 deletions internal/experiments/experiments.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,30 @@ type Experiment struct {
Value string
}

type ExperimentGetter func() Experiment

// A list of experiments.
var (
GentleForce Experiment
RemoteTaskfiles Experiment
AnyVariables Experiment
MapVariables Experiment
EnvPrecedence Experiment
GentleForce ExperimentGetter
RemoteTaskfiles ExperimentGetter
AnyVariables ExperimentGetter
MapVariables ExperimentGetter
EnvPrecedence ExperimentGetter
)

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

func NewGetter(xName string, enabledValues ...string) ExperimentGetter {
return func() Experiment {
return New(xName, enabledValues...)
}
}

func New(xName string, enabledValues ...string) Experiment {
Expand Down Expand Up @@ -104,9 +112,9 @@ func printExperiment(w io.Writer, l *logger.Logger, x Experiment) {

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, MapVariables)
printExperiment(w, l, EnvPrecedence)
printExperiment(w, l, GentleForce())
printExperiment(w, l, RemoteTaskfiles())
printExperiment(w, l, MapVariables())
printExperiment(w, l, EnvPrecedence())
return w.Flush()
}
4 changes: 2 additions & 2 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ func init() {
pflag.BoolVar(&Experiments, "experiments", false, "Lists all the available experiments and whether or not they are enabled.")

// Gentle force experiment will override the force flag and add a new force-all flag
if experiments.GentleForce.Enabled {
if experiments.GentleForce().Enabled {
pflag.BoolVarP(&Force, "force", "f", false, "Forces execution of the directly called task.")
pflag.BoolVar(&ForceAll, "force-all", false, "Forces execution of the called task and all its dependant tasks.")
} else {
pflag.BoolVarP(&ForceAll, "force", "f", false, "Forces execution even when the task is up-to-date.")
}

// Remote Taskfiles experiment will adds the "download" and "offline" flags
if experiments.RemoteTaskfiles.Enabled {
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.")
Expand Down
8 changes: 5 additions & 3 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func TestEnv(t *testing.T) {
}
tt.Run(t)
t.Setenv("TASK_X_ENV_PRECEDENCE", "1")
experiments.EnvPrecedence = experiments.New("ENV_PRECEDENCE")
experiments.EnvPrecedence = experiments.NewGetter("ENV_PRECEDENCE")
ttt := fileContentTest{
Dir: "testdata/env",
Target: "overridden",
Expand Down Expand Up @@ -1220,7 +1220,8 @@ func TestIncludesMultiLevel(t *testing.T) {
}

func TestIncludesRemote(t *testing.T) {
enableExperimentForTest(t, &experiments.RemoteTaskfiles, "1")
exp := experiments.RemoteTaskfiles()
enableExperimentForTest(t, &exp, "1")

dir := "testdata/includes_remote"

Expand Down Expand Up @@ -1374,7 +1375,8 @@ func TestIncludesEmptyMain(t *testing.T) {
}

func TestIncludesHttp(t *testing.T) {
enableExperimentForTest(t, &experiments.RemoteTaskfiles, "1")
exp := experiments.RemoteTaskfiles()
enableExperimentForTest(t, &exp, "1")

dir, err := filepath.Abs("testdata/includes_http")
require.NoError(t, err)
Expand Down
7 changes: 4 additions & 3 deletions taskfile/ast/var.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,11 @@ type Var struct {
}

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

// This implementation is not backwards-compatible and replaces the 'sh' key with map variables
if experiments.MapVariables.Value == "1" {
if mv.Value == "1" {
var value any
if err := node.Decode(&value); err != nil {
return errors.NewTaskfileDecodeError(err, node)
Expand All @@ -199,7 +200,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.MapVariables.Value == "2" {
if mv.Value == "2" {
switch node.Kind {
case yaml.MappingNode:
key := node.Content[0].Value
Expand Down
2 changes: 1 addition & 1 deletion taskfile/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func NewNode(

}

if node.Remote() && !experiments.RemoteTaskfiles.Enabled {
if node.Remote() && !experiments.RemoteTaskfiles().Enabled {
return nil, errors.New("task: Remote taskfiles are not enabled. You can read more about this experiment and how to enable it at https://taskfile.dev/experiments/remote-taskfiles")
}
return node, err
Expand Down