feat: add gitignore option to exclude ignored files from sources/generates

When `gitignore: true` is set at the Taskfile or task level, files
matching .gitignore rules are automatically excluded from sources and
generates glob resolution. This prevents rebuilds triggered by changes
to files that are in .gitignore (build artifacts, generated files, etc.).

Uses go-git to load .gitignore patterns including nested .gitignore
files, .git/info/exclude, and global gitignore configuration.
This commit is contained in:
Valentin Maerten
2026-04-03 22:35:04 +02:00
parent 81d621d8aa
commit fe542d5418
16 changed files with 395 additions and 20 deletions

View File

@@ -38,6 +38,7 @@ type Task struct {
Method string
Prefix string `hash:"ignore"`
IgnoreError bool
Gitignore *bool
Run string
Platforms []*Platform
If string
@@ -75,6 +76,12 @@ func (t *Task) IsSilent() bool {
return t.Silent != nil && *t.Silent
}
// IsGitignore returns true if the task has gitignore filtering explicitly enabled.
// Returns false if Gitignore is nil (not set) or explicitly set to false.
func (t *Task) IsGitignore() bool {
return t.Gitignore != nil && *t.Gitignore
}
// WildcardMatch will check if the given string matches the name of the Task and returns any wildcard values.
func (t *Task) WildcardMatch(name string) (bool, []string) {
names := append([]string{t.Task}, t.Aliases...)
@@ -150,6 +157,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error {
Method string
Prefix string
IgnoreError bool `yaml:"ignore_error"`
Gitignore *bool `yaml:"gitignore,omitempty"`
Run string
Platforms []*Platform
If string
@@ -190,6 +198,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error {
t.Method = task.Method
t.Prefix = task.Prefix
t.IgnoreError = task.IgnoreError
t.Gitignore = deepcopy.Scalar(task.Gitignore)
t.Run = task.Run
t.Platforms = task.Platforms
t.If = task.If
@@ -233,6 +242,7 @@ func (t *Task) DeepCopy() *Task {
Method: t.Method,
Prefix: t.Prefix,
IgnoreError: t.IgnoreError,
Gitignore: deepcopy.Scalar(t.Gitignore),
Run: t.Run,
IncludeVars: t.IncludeVars.DeepCopy(),
IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(),

View File

@@ -30,10 +30,11 @@ type Taskfile struct {
Vars *Vars
Env *Vars
Tasks *Tasks
Silent bool
Dotenv []string
Run string
Interval time.Duration
Silent bool
Dotenv []string
Run string
Interval time.Duration
Gitignore bool
}
// Merge merges the second Taskfile into the first
@@ -88,7 +89,8 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error {
Silent bool
Dotenv []string
Run string
Interval time.Duration
Interval time.Duration
Gitignore bool
}
if err := node.Decode(&taskfile); err != nil {
return errors.NewTaskfileDecodeError(err, node)
@@ -106,6 +108,7 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error {
tf.Dotenv = taskfile.Dotenv
tf.Run = taskfile.Run
tf.Interval = taskfile.Interval
tf.Gitignore = taskfile.Gitignore
if tf.Includes == nil {
tf.Includes = NewIncludes()
}