Skip to content
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
10 changes: 10 additions & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -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"
48 changes: 48 additions & 0 deletions precommit_test.go
Original file line number Diff line number Diff line change
@@ -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'")
}
5 changes: 5 additions & 0 deletions website/src/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ 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
Expand Down
118 changes: 117 additions & 1 deletion website/src/docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---

Expand Down Expand Up @@ -106,6 +106,122 @@ 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 |

### Examples

<details>
<summary>Run a task unconditionally on every commit</summary>

```yaml
repos:
- repo: https://github.com/go-task/task
rev: v3.x.x
hooks:
- id: task
args: ['lint']
```

</details>

<details>
<summary>Run a task only when certain files change</summary>

```yaml
repos:
- repo: https://github.com/go-task/task
rev: v3.x.x
hooks:
- id: task
files: ^docs/
args: ['generate-docs']
```

</details>

<details>
<summary>Run a task in a subdirectory</summary>

```yaml
repos:
- repo: https://github.com/go-task/task
rev: v3.x.x
hooks:
- id: task
args: ['--dir', 'frontend', 'build']
```

</details>

<details>
<summary>Run multiple tasks with different file triggers</summary>

```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']
```

</details>

<details>
<summary>Run a lightweight task on commit and a heavier task on push</summary>

```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]
```

</details>

## Community Integrations

In addition to our official integrations, there is an amazing community of
Expand Down