From 8e4619460483d31bbf62e6c85ad39631569ac56f Mon Sep 17 00:00:00 2001 From: Justin Flannery Date: Thu, 12 Mar 2026 23:12:22 -0600 Subject: [PATCH 1/3] feat: add official pre-commit hook support --- .pre-commit-hooks.yaml | 10 +++ precommit_test.go | 48 ++++++++++++ website/src/docs/changelog.md | 7 +- website/src/docs/integrations.md | 122 ++++++++++++++++++++++++++++++- 4 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 .pre-commit-hooks.yaml create mode 100644 precommit_test.go diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml new file mode 100644 index 0000000000..68678e7e03 --- /dev/null +++ b/.pre-commit-hooks.yaml @@ -0,0 +1,10 @@ +# yaml-language-server: $schema=https://json.schemastore.org/pre-commit-hooks.json + +- id: task + name: task + description: Run a Taskfile task as a pre-commit hook + language: golang + entry: task + pass_filenames: false + require_serial: true + minimum_pre_commit_version: "3.0.0" diff --git a/precommit_test.go b/precommit_test.go new file mode 100644 index 0000000000..65638b81ec --- /dev/null +++ b/precommit_test.go @@ -0,0 +1,48 @@ +package task_test + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.yaml.in/yaml/v3" +) + +type preCommitHook struct { + ID string `yaml:"id"` + Name string `yaml:"name"` + Description string `yaml:"description"` + Language string `yaml:"language"` + Entry string `yaml:"entry"` + PassFilenames *bool `yaml:"pass_filenames"` + RequireSerial *bool `yaml:"require_serial"` + MinimumPreCommitVersion string `yaml:"minimum_pre_commit_version"` + Types []string `yaml:"types"` + Args []string `yaml:"args"` +} + +func TestPreCommitHooksFile(t *testing.T) { + t.Parallel() + + data, err := os.ReadFile(".pre-commit-hooks.yaml") + require.NoError(t, err, ".pre-commit-hooks.yaml should exist") + + var hooks []preCommitHook + err = yaml.Unmarshal(data, &hooks) + require.NoError(t, err, ".pre-commit-hooks.yaml should be valid YAML") + + require.Len(t, hooks, 1, "should define exactly one hook") + + hook := hooks[0] + assert.Equal(t, "task", hook.ID, "hook id should be 'task'") + assert.NotEmpty(t, hook.Name, "hook name should not be empty") + assert.NotEmpty(t, hook.Description, "hook description should not be empty") + assert.Equal(t, "golang", hook.Language, "hook language should be 'golang'") + assert.Equal(t, "task", hook.Entry, "hook entry should be 'task'") + require.NotNil(t, hook.PassFilenames, "pass_filenames should be set") + assert.False(t, *hook.PassFilenames, "pass_filenames should be false") + require.NotNil(t, hook.RequireSerial, "require_serial should be set") + assert.True(t, *hook.RequireSerial, "require_serial should be true") + assert.Equal(t, "3.0.0", hook.MinimumPreCommitVersion, "minimum_pre_commit_version should be '3.0.0'") +} diff --git a/website/src/docs/changelog.md b/website/src/docs/changelog.md index 570e8dff32..5673a5d8da 100644 --- a/website/src/docs/changelog.md +++ b/website/src/docs/changelog.md @@ -8,9 +8,14 @@ editLink: false ::: v-pre +## next + +- Added official [pre-commit](https://pre-commit.com/) support via a + `.pre-commit-hooks.yaml` at the repository root (#2562). + ## v3.49.1 - 2026-03-08 -* Reverted #2632 for now, which caused some regressions. That change will be +- Reverted #2632 for now, which caused some regressions. That change will be reworked (#2720, #2722, #2723). ## v3.49.0 - 2026-03-07 diff --git a/website/src/docs/integrations.md b/website/src/docs/integrations.md index de9f99521b..0f519dc1d1 100644 --- a/website/src/docs/integrations.md +++ b/website/src/docs/integrations.md @@ -2,7 +2,7 @@ title: Integrations description: Official and community integrations for Task, including VS Code, JSON schemas, - and other tools + pre-commit, and other tools outline: deep --- @@ -99,13 +99,129 @@ This integration provides: AI assistants can access Task documentation through: -- **[llms.txt](https://taskfile.dev/llms.txt)**: Lightweight overview of Task documentation -- **[llms-full.txt](https://taskfile.dev/llms-full.txt)**: Complete documentation with all content +- **[llms.txt](https://taskfile.dev/llms.txt)**: Lightweight overview of Task + documentation +- **[llms-full.txt](https://taskfile.dev/llms-full.txt)**: Complete + documentation with all content These files are automatically generated and kept in sync with the documentation, ensuring AI assistants always have access to the latest Task features and usage patterns. +## pre-commit + +Task has official support for [pre-commit](https://pre-commit.com/), a framework +for managing and maintaining multi-language pre-commit hooks. This allows you to +automatically run Task tasks as part of your Git workflow. + +### Setup + +Add the following to your `.pre-commit-config.yaml`: + +```yaml +repos: + - repo: https://github.com/go-task/task + rev: v3.x.x # Replace with the desired Task version + hooks: + - id: task + args: ['my-task'] +``` + +The hook will install Task via `go install` and run the specified task. You can +use any `task` CLI arguments in the `args` field. + +### Configuration + +The `task` hook supports the following pre-commit options: + +| Option | Default | Description | +| ---------------- | ------- | ----------------------------------------------------------- | +| `args` | `[]` | Arguments passed to `task` (e.g. task name, `--dir`, flags) | +| `files` | `''` | Only run the hook when these files change | +| `pass_filenames` | `false` | Task manages its own file resolution | + +### Examples + +Run a task unconditionally on every commit: + +```yaml +repos: + - repo: https://github.com/go-task/task + rev: v3.x.x + hooks: + - id: task + args: ['lint'] +``` + +
+Run a task only when certain files change + +```yaml +repos: + - repo: https://github.com/go-task/task + rev: v3.x.x + hooks: + - id: task + files: ^docs/ + args: ['generate-docs'] +``` + +
+ +
+Run a task in a subdirectory + +```yaml +repos: + - repo: https://github.com/go-task/task + rev: v3.x.x + hooks: + - id: task + args: ['--dir', 'frontend', 'build'] +``` + +
+ +
+Run multiple tasks with different file triggers + +```yaml +repos: + - repo: https://github.com/go-task/task + rev: v3.x.x + hooks: + - id: task + name: lint + files: \.go$ + args: ['lint'] + - id: task + name: generate + files: \.proto$ + args: ['generate'] +``` + +
+ +
+Run a lightweight task on commit and a heavier task on push + +```yaml +repos: + - repo: https://github.com/go-task/task + rev: v3.x.x + hooks: + - id: task + name: lint + args: ['lint'] + stages: [pre-commit] + - id: task + name: test + args: ['test'] + stages: [pre-push] +``` + +
+ ## Community Integrations In addition to our official integrations, there is an amazing community of From cfe2689c81fa6885506d732c6b0049fc1ca4b694 Mon Sep 17 00:00:00 2001 From: Justin Flannery Date: Thu, 12 Mar 2026 23:24:32 -0600 Subject: [PATCH 2/3] fix: remove unrelated formatting changes, collapse all examples, document pass_filenames --- website/src/docs/changelog.md | 2 +- website/src/docs/integrations.md | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/website/src/docs/changelog.md b/website/src/docs/changelog.md index 5673a5d8da..853ff7f5e1 100644 --- a/website/src/docs/changelog.md +++ b/website/src/docs/changelog.md @@ -15,7 +15,7 @@ editLink: false ## v3.49.1 - 2026-03-08 -- Reverted #2632 for now, which caused some regressions. That change will be +* Reverted #2632 for now, which caused some regressions. That change will be reworked (#2720, #2722, #2723). ## v3.49.0 - 2026-03-07 diff --git a/website/src/docs/integrations.md b/website/src/docs/integrations.md index 0f519dc1d1..54b18dbd1a 100644 --- a/website/src/docs/integrations.md +++ b/website/src/docs/integrations.md @@ -99,10 +99,8 @@ This integration provides: AI assistants can access Task documentation through: -- **[llms.txt](https://taskfile.dev/llms.txt)**: Lightweight overview of Task - documentation -- **[llms-full.txt](https://taskfile.dev/llms-full.txt)**: Complete - documentation with all content +- **[llms.txt](https://taskfile.dev/llms.txt)**: Lightweight overview of Task documentation +- **[llms-full.txt](https://taskfile.dev/llms-full.txt)**: Complete documentation with all content These files are automatically generated and kept in sync with the documentation, ensuring AI assistants always have access to the latest Task features and usage @@ -138,11 +136,12 @@ The `task` hook supports the following pre-commit options: | ---------------- | ------- | ----------------------------------------------------------- | | `args` | `[]` | Arguments passed to `task` (e.g. task name, `--dir`, flags) | | `files` | `''` | Only run the hook when these files change | -| `pass_filenames` | `false` | Task manages its own file resolution | +| `pass_filenames` | `false` | Cannot be overridden — task does not accept filenames as arguments | ### Examples -Run a task unconditionally on every commit: +
+Run a task unconditionally on every commit ```yaml repos: @@ -153,6 +152,8 @@ repos: args: ['lint'] ``` +
+
Run a task only when certain files change From 4c87b849c4ea91d1c875579566c1fd7a69ab49a4 Mon Sep 17 00:00:00 2001 From: Justin Flannery Date: Thu, 12 Mar 2026 23:27:29 -0600 Subject: [PATCH 3/3] docs: remove pass_filenames from user-facing configuration table --- website/src/docs/integrations.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/website/src/docs/integrations.md b/website/src/docs/integrations.md index 54b18dbd1a..dd434ea7d2 100644 --- a/website/src/docs/integrations.md +++ b/website/src/docs/integrations.md @@ -134,9 +134,8 @@ The `task` hook supports the following pre-commit options: | Option | Default | Description | | ---------------- | ------- | ----------------------------------------------------------- | -| `args` | `[]` | Arguments passed to `task` (e.g. task name, `--dir`, flags) | -| `files` | `''` | Only run the hook when these files change | -| `pass_filenames` | `false` | Cannot be overridden — task does not accept filenames as arguments | +| `args` | `[]` | Arguments passed to `task` (e.g. task name, `--dir`, flags) | +| `files` | `''` | Only run the hook when these files change | ### Examples