Skip to content

Commit bdda8b3

Browse files
authored
Set up husky.net (#2175)
1 parent 0bceb0c commit bdda8b3

File tree

9 files changed

+206
-14
lines changed

9 files changed

+206
-14
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ max_line_length = 160
1515
indent_style = space
1616
indent_size = 4
1717

18-
[*.{md,markdown,json,js,yml,csproj,fsproj,targets,targets,props}]
18+
[*.{md,markdown,json,js,yml,yaml,csproj,fsproj,targets,targets,props}]
1919
indent_style = space
2020
indent_size = 2
2121

.github/actions/bootstrap/action.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ runs:
1616
# Ensure we fetch all tags
1717
- shell: bash
1818
run: |
19-
git fetch --prune --unshallow --tags
19+
if [ -f .git/shallow ]; then
20+
git fetch --prune --unshallow --tags
21+
else
22+
git fetch --prune --tags
23+
fi
2024
git tag --list
2125
2226
- name: Git config

.husky/pre-commit

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
4+
dotnet husky run --group pre-commit

.husky/pre-push

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
4+
dotnet husky run --group pre-push

.husky/task-runner.json

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"$schema": "https://alirezanet.github.io/Husky.Net/schema.json",
3+
"variables": [
4+
{
5+
"name": "push-files",
6+
"command": "bash",
7+
"args": [
8+
"-c",
9+
"git diff --name-only --diff-filter=d @{upstream}..HEAD 2>/dev/null || git diff --name-only --diff-filter=d origin/main..HEAD 2>/dev/null || git diff --name-only --diff-filter=d HEAD~1..HEAD"
10+
]
11+
}
12+
],
13+
"tasks": [
14+
{
15+
"name": "dotnet-lint",
16+
"group": "pre-push",
17+
"command": "bash",
18+
"args": ["./build.sh", "lint", "${push-files}"],
19+
"include": ["**/*.cs", "**/*.fs"]
20+
},
21+
{
22+
"name": "prettier",
23+
"group": "pre-commit",
24+
"pathMode": "absolute",
25+
"cwd": "src/Elastic.Documentation.Site",
26+
"command": "npx",
27+
"args": ["prettier", "--write", "${staged}"],
28+
"include": [
29+
"src/Elastic.Documentation.Site/**/*.ts",
30+
"src/Elastic.Documentation.Site/**/*.tsx",
31+
"src/Elastic.Documentation.Site/**/*.js",
32+
"src/Elastic.Documentation.Site/**/*.jsx",
33+
"src/Elastic.Documentation.Site/**/*.css",
34+
"src/Elastic.Documentation.Site/**/*.json"
35+
]
36+
},
37+
{
38+
"name": "typescript-check",
39+
"group": "pre-commit",
40+
"cwd": "src/Elastic.Documentation.Site",
41+
"command": "npx",
42+
"args": ["tsc", "--noEmit"],
43+
"include": [
44+
"src/Elastic.Documentation.Site/**/*.ts",
45+
"src/Elastic.Documentation.Site/**/*.tsx"
46+
],
47+
"filteringRule": "staged"
48+
},
49+
{
50+
"name": "eslint",
51+
"group": "pre-commit",
52+
"pathMode": "absolute",
53+
"cwd": "src/Elastic.Documentation.Site",
54+
"command": "npx",
55+
"args": ["eslint", "--fix", "${staged}"],
56+
"include": [
57+
"src/Elastic.Documentation.Site/**/*.ts",
58+
"src/Elastic.Documentation.Site/**/*.tsx",
59+
"src/Elastic.Documentation.Site/**/*.js",
60+
"src/Elastic.Documentation.Site/**/*.jsx",
61+
"src/Elastic.Documentation.Site/**/*.mjs"
62+
]
63+
}
64+
]
65+
}

CONTRIBUTING.MD renamed to CONTRIBUTING.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,77 @@ based on the labels of the pull requests merged into the `main` branch.
5656

5757
See the [release-drafter configuration](./.github/release-drafter.yml) for more details.
5858

59+
## Git Hooks with Husky.Net
60+
61+
This repository uses [Husky.Net](https://alirezanet.github.io/Husky.Net/) to automatically format and validate code before commits and pushes.
62+
63+
### What Gets Checked
64+
65+
**Pre-commit hooks** (run on staged files):
66+
- **prettier** - Formats TypeScript, JavaScript, CSS, and JSON files in `src/Elastic.Documentation.Site/`
67+
- **typescript-check** - Type checks TypeScript files with `tsc --noEmit` (only if TS files are staged)
68+
- **eslint** - Lints and fixes JavaScript/TypeScript files
69+
70+
**Pre-push hooks** (run on files being pushed):
71+
- **dotnet-lint** - Lints C# and F# files using `./build.sh lint` (runs `dotnet format --verify-no-changes`)
72+
73+
### Installation
74+
75+
Husky.Net is included as a dotnet tool. After cloning the repository, restore the tools:
76+
77+
```bash
78+
dotnet tool restore
79+
```
80+
81+
Then install the git hooks:
82+
83+
```bash
84+
dotnet husky install
85+
```
86+
87+
That's it! The hooks will now run automatically on every commit and push.
88+
89+
### Usage
90+
91+
Once installed, hooks run automatically when you commit or push:
92+
93+
```bash
94+
git add .
95+
git commit -m "your message" # Pre-commit hooks run here
96+
git push # Pre-push hooks run here
97+
```
98+
99+
**Note:** If hooks modify files (prettier, eslint), the commit will fail so you can review the changes. Simply stage the changes and commit again:
100+
101+
```bash
102+
git add -u
103+
git commit -m "your message"
104+
```
105+
106+
If the **dotnet-lint** hook fails during push, you need to fix the linting errors and commit the fixes before pushing again.
107+
108+
### Manual Execution
109+
110+
You can test hooks without committing or pushing:
111+
112+
```bash
113+
# Run all pre-commit tasks
114+
dotnet husky run --group pre-commit
115+
116+
# Run all pre-push tasks
117+
dotnet husky run --group pre-push
118+
119+
# Test individual tasks
120+
dotnet husky run --name prettier
121+
dotnet husky run --name typescript-check
122+
dotnet husky run --name eslint
123+
dotnet husky run --name dotnet-lint
124+
```
125+
126+
### Configuration
127+
128+
Hook configuration is defined in `.husky/task-runner.json`. See the [Husky.Net documentation](https://alirezanet.github.io/Husky.Net/guide/task-runner.html) for more details.
129+
59130
## Creating a New Release
60131

61132
To create a new release trigger the [release](https://github.com/elastic/docs-builder/actions/workflows/release.yml) workflow on the `main` branch.

build/CommandLine.fs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ type TestSuite = All | Unit | Integration
1515
match FSharpValue.GetUnionFields(this, typeof<TestSuite>) with
1616
| case, _ -> case.Name.ToLowerInvariant()
1717

18+
type FormatArgs =
19+
| [<MainCommand>] Include of string list
20+
with
21+
interface IArgParserTemplate with
22+
member this.Usage =
23+
match this with
24+
| Include _ -> "Specify files to include in format, passed to dotnet format --include"
25+
26+
type LintArgs =
27+
| [<MainCommand>] Include of string list
28+
with
29+
interface IArgParserTemplate with
30+
member this.Usage =
31+
match this with
32+
| Include _ -> "Specify files to include in lint check, passed to dotnet format --include"
33+
1834
type Build =
1935
| [<CliPrefix(CliPrefix.None);SubCommand>] Clean
2036
| [<CliPrefix(CliPrefix.None);SubCommand>] Version
@@ -25,10 +41,10 @@ type Build =
2541
| [<CliPrefix(CliPrefix.None);SubCommand>] Unit_Test
2642
| [<CliPrefix(CliPrefix.None);SubCommand>] Integrate
2743

28-
| [<CliPrefix(CliPrefix.None);SubCommand>] Format
44+
| [<CliPrefix(CliPrefix.None);SubCommand>] Format of ParseResults<FormatArgs>
2945
| [<CliPrefix(CliPrefix.None);SubCommand>] Watch
3046

31-
| [<CliPrefix(CliPrefix.None);Hidden;SubCommand>] Lint
47+
| [<CliPrefix(CliPrefix.None);Hidden;SubCommand>] Lint of ParseResults<LintArgs>
3248
| [<CliPrefix(CliPrefix.None);Hidden;SubCommand>] PristineCheck
3349
| [<CliPrefix(CliPrefix.None);Hidden;SubCommand>] ValidateLicenses
3450

@@ -59,12 +75,12 @@ with
5975

6076
| Release -> "runs build, tests, and create and validates the packages shy of publishing them"
6177
| Publish -> "Publishes artifacts"
62-
| Format -> "runs dotnet format"
78+
| Format _ -> "runs dotnet format"
6379

6480
| Watch -> "runs dotnet watch to continuous build code/templates and web assets on the fly"
6581

6682
// steps
67-
| Lint
83+
| Lint _ -> "runs dotnet format --verify-no-changes"
6884
| PristineCheck
6985
| PublishBinaries
7086
| PublishContainers
@@ -87,10 +103,20 @@ with
87103
let cases = FSharpType.GetUnionCases(typeof<Build>)
88104
seq {
89105
for c in cases do
90-
if c.GetFields().Length = 0 then
106+
match c.GetFields().Length with
107+
| 0 ->
91108
match FSharpValue.MakeUnion(c, [| |]) with
92109
| NonNull u -> u :?> Build
93110
| _ -> failwithf $"%s{c.Name} can not be cast to Build enum"
111+
| _ when c.Name = "Format" ->
112+
// Format has sub-arguments, create empty instance
113+
let emptyFormatArgs = ArgumentParser.Create<FormatArgs>().Parse([||])
114+
Format emptyFormatArgs
115+
| _ when c.Name = "Lint" ->
116+
// Lint has sub-arguments, create empty instance
117+
let emptyLintArgs = ArgumentParser.Create<LintArgs>().Parse([||])
118+
Lint emptyLintArgs
119+
| _ -> ()
94120
}
95121

96122
static member Ignore (_: Build) _ = ()

build/Targets.fs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,22 @@ let private version _ =
3131
printfn $"Informational version: %s{version.AsString}"
3232
printfn $"Semantic version: %s{version.Normalize()}"
3333

34-
let private format _ = exec { run "dotnet" "format" "--verbosity" "quiet" }
34+
let private format (formatArgs: ParseResults<FormatArgs>) =
35+
let includeFiles = formatArgs.TryGetResult FormatArgs.Include |> Option.defaultValue []
36+
let includeArgs =
37+
if includeFiles.IsEmpty then []
38+
else ["--include"] @ includeFiles
39+
exec { run "dotnet" (["format"; "--verbosity"; "quiet"] @ includeArgs) }
3540

3641
let private watch _ = exec { run "dotnet" "watch" "--project" "src/tooling/docs-builder" "--configuration" "debug" "--" "serve" }
3742

38-
let private lint _ =
43+
let private lint (lintArgs: ParseResults<LintArgs>) =
44+
let includeFiles = lintArgs.TryGetResult LintArgs.Include |> Option.defaultValue []
45+
let includeArgs =
46+
if includeFiles.IsEmpty then []
47+
else ["--include"] @ includeFiles
3948
match exec {
40-
exit_code_of "dotnet" "format" "--verify-no-changes"
49+
exit_code_of "dotnet" (["format"; "--verify-no-changes"] @ includeArgs)
4150
} with
4251
| 0 -> printfn "There are no dotnet formatting violations, continuing the build."
4352
| _ -> failwithf "There are dotnet formatting violations. Call `dotnet format` to fix or specify -c to ./build.sh to skip this check"
@@ -148,6 +157,8 @@ let private validateLicenses _ =
148157
exec { run "dotnet" (["dotnet-project-licenses"] @ args) }
149158

150159
let Setup (parsed:ParseResults<Build>) =
160+
let emptyLintArgs = ArgumentParser.Create<LintArgs>().Parse([||])
161+
151162
let wireCommandLine (t: Build) =
152163
match t with
153164
// commands
@@ -156,7 +167,7 @@ let Setup (parsed:ParseResults<Build>) =
156167
| Compile -> Build.Step compile
157168
| Build ->
158169
Build.Cmd
159-
[Clean; Lint; Compile] [] build
170+
[Clean; Lint emptyLintArgs; Compile] [] build
160171

161172
| Test -> Build.Cmd [Compile] [] <| runTests TestSuite.All
162173
| Unit_Test -> Build.Cmd [Compile] [] <| runTests TestSuite.Unit
@@ -174,11 +185,11 @@ let Setup (parsed:ParseResults<Build>) =
174185
[PublishBinaries; PublishContainers]
175186
release
176187

177-
| Format -> Build.Step format
188+
| Format formatArgs -> Build.Step (fun _ -> format formatArgs)
178189
| Watch -> Build.Step watch
179190

180191
// steps
181-
| Lint -> Build.Step lint
192+
| Lint lintArgs -> Build.Step (fun _ -> lint lintArgs)
182193
| PristineCheck -> Build.Step pristineCheck
183194
| PublishBinaries -> Build.Step publishBinaries
184195
| PublishContainers -> Build.Step publishContainers

dotnet-tools.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
"version": 1,
33
"isRoot": true,
44
"tools": {
5+
"husky": {
6+
"version": "0.7.1",
7+
"commands": [
8+
"husky"
9+
],
10+
"rollForward": true
11+
},
512
"minver-cli": {
613
"version": "5.0.0",
714
"commands": [
@@ -31,4 +38,4 @@
3138
"rollForward": false
3239
}
3340
}
34-
}
41+
}

0 commit comments

Comments
 (0)