Skip to content

Commit

Permalink
Chore: Replace Husky/Lint-staged with Lefthook (grafana#66608)
Browse files Browse the repository at this point in the history
* Switch from husky+precommit to lefthook

Migrate from husky/precommit to lefthook

h

old husky precommit

lefthook so far

remove husky folder

switch to new lefthook package

Add postinstall script to clean up after husky

preinstall to remove husky config

package.json

package.json

package.json

script

v

Reduce lefthook output

Cleanup

testing

reduce output

testing betterer

testing betterer

testing betterer

testing betterer

testing betterer

testing betterer

testing betterer

skip skipping execution info

small cleanup

remove comment from testing

clean up old husky hooks in .git/hooks path

run scripts in parallel

update codeowners

don't auto-install lefthook

install lefthook with make command

fix yarn checksum

* update codeowners

* don't use source because it isn't available in ubuntu/debian's /bin/sh

* Ensure lefthook commits files fixed by precommit hooks

* add comment to lefthook.rc explaining what it does

* add i18n:pseudo precommit

* Don't create .husky/safe-to-delete file anymore

* cleanup old lint-staged config

* contribute docs

* update lefthook to 1.4.8

* Move frontend encouragement docs

* rewrite husky cleanup script in bash so we can run it with make

* Make old husky precommit script reject commits until husky is removed

* log precommit warning for everyone

* fix package.json

* run lefthook hooks from old husky hook

* run lefthook hooks from old husky hook

* comments

* codeowners

* codeowners
  • Loading branch information
joshhunt authored Aug 17, 2023
1 parent 3463dc8 commit 654d99f
Show file tree
Hide file tree
Showing 14 changed files with 731 additions and 239 deletions.
6 changes: 6 additions & 0 deletions .bingo/Variables.mk
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ $(JB): $(BINGO_DIR)/jb.mod
@echo "(re)installing $(GOBIN)/jb-v0.5.1"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=jb.mod -o=$(GOBIN)/jb-v0.5.1 "github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb"

LEFTHOOK := $(GOBIN)/lefthook-v1.4.8
$(LEFTHOOK): $(BINGO_DIR)/lefthook.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
@echo "(re)installing $(GOBIN)/lefthook-v1.4.8"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=lefthook.mod -o=$(GOBIN)/lefthook-v1.4.8 "github.com/evilmartians/lefthook"

SWAGGER := $(GOBIN)/swagger-v0.30.2
$(SWAGGER): $(BINGO_DIR)/swagger.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
Expand Down
5 changes: 5 additions & 0 deletions .bingo/lefthook.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT

go 1.20

require github.com/evilmartians/lefthook v1.4.8
523 changes: 523 additions & 0 deletions .bingo/lefthook.sum

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions .bingo/variables.env
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.53.3"

JB="${GOBIN}/jb-v0.5.1"

LEFTHOOK="${GOBIN}/lefthook-v1.4.8"

SWAGGER="${GOBIN}/swagger-v0.30.2"

WIRE="${GOBIN}/wire-v0.5.0"
Expand Down
5 changes: 4 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ tsconfig.json @grafana/frontend-ops
/.eslintignore @grafana/frontend-ops
/.gitattributes @grafana/frontend-ops
/.gitignore @grafana/frontend-ops
/.husky/pre-commit @grafana/frontend-ops
/.nvmrc @grafana/frontend-ops
/.prettierignore @grafana/frontend-ops
/.yarn @grafana/frontend-ops
Expand All @@ -352,6 +351,9 @@ lerna.json @grafana/frontend-ops
/metadata.md @grafana/plugins-platform
/stylelint.config.js @grafana/frontend-ops
/tools/ @grafana/frontend-ops
/lefthook.yml @grafana/frontend-ops
/lefthook.rc @grafana/frontend-ops
.husky/pre-commit @grafana/frontend-ops


# public folder
Expand Down Expand Up @@ -493,6 +495,7 @@ lerna.json @grafana/frontend-ops
/scripts/trigger_docker_build.sh @grafana/grafana-delivery
/scripts/trigger_grafana_packer.sh @grafana/grafana-delivery
/scripts/trigger_windows_build.sh @grafana/grafana-delivery
/scripts/cleanup-husky.sh @grafana/frontend-ops
/scripts/verify-repo-update/ @grafana/grafana-delivery

/scripts/webpack/ @grafana/frontend-ops
Expand Down
30 changes: 26 additions & 4 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
#!/bin/sh

# Ignore husky hooks if no frontend code has been changed
git diff --cached --name-only | grep -v --quiet "^pkg/" || exit 0
# Catch devs who have installed lefthook, went back into the past and reinstalled husky,
# then came back into lefthook-land.
if [ -f ".git/hooks/pre-commit" ]; then
if grep -q lefthook ".git/hooks/pre-commit"; then
# Remove husky from their git config
env SILENT=1 ./scripts/cleanup-husky.sh

. "$(dirname "$0")/_/husky.sh"
# And run the lefthook precommit hook instead of this
./.git/hooks/pre-commit "$@"
exit $?
fi
fi

yarn run precommit
# This precommit hook exists only for people who still have hooksPath=.husky in their git config
# from when we used husky. This is intended to run only on first commit after pulling the lefthook changes.
#
# Either setting up lefthook, or running the clean command will unset the hooksPath git config so this
# hook is no longer ran when committing.

echo "\n⚠️⚠️⚠️ \e[1mImportant: Pre-commit hooks are now opt-in.\e[0m ⚠️⚠️⚠️"
echo "To install the new pre-commit hooks:"
echo " $ \e[96mmake lefthook-install\e[0m"
echo "Or, silence this message by cleaning up the old hooks"
echo " $ \e[96mmake cleanup-old-git-hooks\e[0m"
echo "\nPre-commit hooks will not run on this commit and it will be committed even if it contains lint errors."
echo "See https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md#configure-precommit-hooks for more info\n"

exit 0
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ validate-api-spec: $(MERGED_SPEC_TARGET) $(SWAGGER) ## Validate API spec
clean-api-spec:
rm -f $(SPEC_TARGET) $(MERGED_SPEC_TARGET) $(OAPI_SPEC_TARGET)

.PHONY: cleanup-old-git-hooks
cleanup-old-git-hooks:
./scripts/cleanup-husky.sh

.PHONY: lefthook-install
lefthook-install: cleanup-old-git-hooks $(LEFTHOOK) # install lefthook for pre-commit hooks
$(LEFTHOOK) install -f

.PHONY: lefthook-uninstall
lefthook-uninstall: $(LEFTHOOK)
$(LEFTHOOK) uninstall

##@ OpenAPI 3
OAPI_SPEC_TARGET = public/openapi3.json

Expand Down
1 change: 1 addition & 0 deletions contribute/create-pull-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ We know you're excited to create your first pull request. Before we get started,

- Learn how to start [Contributing to Grafana](/CONTRIBUTING.md).
- Make sure your code follows the relevant [style guides](/contribute/style-guides).
- It's recommened you [set up precommit hooks](/contribute/developer-guide.md) to auto-format when you commit

## Your first pull request

Expand Down
19 changes: 19 additions & 0 deletions contribute/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ it's as easy as running `yarn dlx @yarnpkg/sdks vscode` or `yarn dlx @yarnpkg/sd

More information can be found [here](https://yarnpkg.com/getting-started/editor-sdks).

### Configure precommit hooks

We use pre-commit hooks (via [lefthook](https://github.com/evilmartians/lefthook)) to lint, fix, and format code as you commit your changes. Previously the Grafana repository automatically installed these hook when you did `yarn install`, but they are now opt in for all contributors

Install the lefthook precommit hooks with:

```sh
make lefthook-install
```

To remove precommit hooks, run

```sh
make lefthook-uninstall
```

> [!NOTE]
> Contributors working on the frontend are highly encouraged to install the precommit hooks, even if your IDE formats on save, so the `.betterer.results` file is kept up to sync.
## Build Grafana

Grafana consists of two components; the _frontend_, and the _backend_.
Expand Down
8 changes: 8 additions & 0 deletions lefthook.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file is used by lefthook to 'expose' the bingo-installed lefthook under
# the name `lefthook`, as expected by the lefthook pre-commit scripts

. .bingo/variables.env

lefthook () {
${LEFTHOOK} "$@"
}
48 changes: 48 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
skip_output:
- meta
- execution_out
- skips

min_version: 1.4.3

rc: ./lefthook.rc

pre-commit:
parallel: true
commands:
frontend-betterer:
glob: '*.{ts,tsx}'
run: yarn betterer precommit {staged_files}
stage_fixed: true

frontend-lint:
glob: '*.{js,ts,tsx}'
run: |
yarn eslint --ext .js,.tsx,.ts --cache --fix {staged_files}
yarn prettier --write {staged_files}
stage_fixed: true

internationalization:
glob: 'public/locales/en-US/grafana.json'
run: yarn i18n:pseudo
stage_fixed: true

other-format:
glob: '*.{json,scss,md,mdx}'
run: yarn prettier --write {staged_files}
stage_fixed: true

backend-format:
glob: '*pkg/**/*.go'
run: gofmt -w -s {staged_files}
stage_fixed: true

cue-fix-kinds:
glob: '*kinds/**/*.cue'
run: make fix-cue
stage_fixed: true

cue-fix-public:
glob: '*public/app/plugins/**/**/*.cue'
run: make fix-cue
stage_fixed: true
28 changes: 0 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"packages:prepare": "lerna version --no-push --no-git-tag-version --force-publish --exact",
"packages:pack": "mkdir -p ./npm-artifacts && lerna exec --no-private -- yarn pack --out \"../../npm-artifacts/%s-%v.tgz\"",
"packages:typecheck": "lerna run typecheck",
"precommit": "yarn run lint-staged",
"prettier:check": "prettier --check --list-different=false --log-level=warn \"**/*.{ts,tsx,scss,md,mdx}\"",
"prettier:checkDocs": "prettier --check --list-different=false --log-level=warn \"docs/**/*.md\" \"*.md\" \"packages/**/*.{ts,tsx,scss,md,mdx}\"",
"prettier:write": "prettier --list-different \"**/*.{js,ts,tsx,scss,md,mdx}\" --write",
Expand All @@ -46,7 +45,6 @@
"plugins:build-bundled": "find plugins-bundled -name package.json -not -path '*/node_modules/*' -execdir yarn build \\;",
"watch": "yarn start -d watch,start core:start --watchTheme",
"ci:test-frontend": "yarn run test:ci",
"postinstall": "husky install",
"i18n:clean": "rimraf public/locales/en-US/grafana.json",
"i18n:extract": "yarn run i18next -c public/locales/i18next-parser.config.js 'public/**/*.{tsx,ts}' 'packages/grafana-ui/**/*.{tsx,ts}'",
"i18n:compile": "echo 'no i18n compile yet, all good'",
Expand All @@ -60,30 +58,6 @@
"whatsNewUrl": "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v10-0/",
"releaseNotesUrl": "https://grafana.com/docs/grafana/next/release-notes/"
},
"lint-staged": {
"*.{ts,tsx}": [
"betterer precommit"
],
"*.{js,ts,tsx}": [
"eslint --ext .js,.tsx,.ts --cache --fix",
"prettier --write"
],
"*.{json,scss,md,mdx}": [
"prettier --write"
],
"*pkg/**/*.go": [
"gofmt -w -s"
],
"*kinds/**/*.cue": [
"make fix-cue"
],
"*public/app/plugins/**/**/*.cue": [
"make fix-cue"
],
"./public/locales/en-US/grafana.json": [
"yarn i18n:pseudo"
]
},
"devDependencies": {
"@babel/core": "7.22.9",
"@babel/plugin-proposal-class-properties": "7.18.6",
Expand Down Expand Up @@ -206,7 +180,6 @@
"html-loader": "4.2.0",
"html-webpack-plugin": "5.5.3",
"http-server": "14.1.1",
"husky": "8.0.3",
"i18next-parser": "6.6.0",
"jest": "29.3.1",
"jest-canvas-mock": "2.5.2",
Expand All @@ -216,7 +189,6 @@
"jest-junit": "16.0.0",
"jest-matcher-utils": "29.3.1",
"lerna": "5.5.4",
"lint-staged": "13.2.3",
"mini-css-extract-plugin": "2.7.6",
"msw": "1.2.2",
"mutationobserver-shim": "0.3.7",
Expand Down
55 changes: 55 additions & 0 deletions scripts/cleanup-husky.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -e



# Husky modified your git config to store git hooks in the repo, so do that change
currentHooksPath=$(git config core.hooksPath || true)
if [[ $currentHooksPath == ".husky" ]]; then
if [ -z "$SILENT" ]; then
echo "Unsetting git hooks path because it was previously set to .husky."
echo "If you had custom git hooks in .husky you may want to move them to .git/hooks"
fi

git config --unset core.hooksPath
fi

oldHuskyHookNames=(
"applypatch-msg"
"commit-msg"
"post-applypatch"
"post-checkout"
"post-commit"
"post-merge"
"post-receive"
"post-rewrite"
"post-update"
"pre-applypatch"
"pre-auto-gc"
"pre-merge-commit"
"pre-push"
"pre-rebase"
"pre-receive"
"push-to-checkout"
"sendemail-validate"
"update"
)

#
# Also extra-old husky dumped a bunch of hooks into .git/hooks, so check for them
# and rename them so they don't run
for hookName in "${oldHuskyHookNames[@]}"; do
hookPath=".git/hooks/$hookName"

if [[ -f $hookPath ]]; then
if grep -q husky "$hookPath"; then
newHookPath="$hookPath.old"

if [ -z "$SILENT" ]; then
echo "Renaming old husky hook $hookPath to $newHookPath"
fi

mv "$hookPath" "$newHookPath" --suffix=old --backup=numbered
fi
fi
done
Loading

0 comments on commit 654d99f

Please sign in to comment.