@ministryofjustice/hmpps-precommit-hooks 1.0.2 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -18
- package/bin/init.sh +7 -16
- package/bin/prepare.sh +44 -4
- package/bin/test.sh +5 -5
- package/default-hooks.yaml +48 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
# @ministryofjustice/hmpps-precommit-hooks
|
|
2
2
|
|
|
3
|
-
This package aims to automatically install and configure
|
|
3
|
+
This package aims to automatically install and configure pre-commit hooks using [prek](https://github.com/pre-commit/pre-commit) to help catch potential secrets and code quality issues before committing them to github.
|
|
4
4
|
|
|
5
5
|
## Status
|
|
6
6
|
|
|
7
7
|
**This library is currently: ready to adopt.**
|
|
8
8
|
Teams are welcome to use this library. Please provide feedback via slack to the `#typescript` channel.
|
|
9
9
|
|
|
10
|
+
## Migration from Husky
|
|
11
|
+
|
|
12
|
+
This package has migrated from using Husky to using [prek](https://github.com/pre-commit/pre-commit) (pre-commit) for managing git hooks. The migration will happen automatically during `npm install`:
|
|
13
|
+
|
|
14
|
+
- Husky will be uninstalled if present
|
|
15
|
+
- Existing husky hooks will be removed
|
|
16
|
+
- prek will be installed via Homebrew (if not already installed)
|
|
17
|
+
- A `.pre-commit-config.yaml` file will be created with the default hooks configuration
|
|
18
|
+
|
|
10
19
|
## Migrating existing projects
|
|
11
20
|
|
|
12
21
|
#### Automatically installing the library
|
|
@@ -19,35 +28,68 @@ Once the project has been initialised, other developers should be able to develo
|
|
|
19
28
|
|
|
20
29
|
### How this works
|
|
21
30
|
|
|
22
|
-
Initialising will add
|
|
31
|
+
Initialising will add a new prepare script in `package.json`:
|
|
23
32
|
|
|
24
33
|
```json
|
|
25
34
|
"scripts": {
|
|
26
35
|
//...
|
|
27
|
-
"prepare": "hmpps-precommit-hooks"
|
|
28
|
-
"precommit:secrets": "gitleaks git --pre-commit --redact --staged --verbose",
|
|
29
|
-
"precommit:lint": "node_modules/.bin/lint-staged",
|
|
30
|
-
"precommit:verify": "npm run typecheck && npm test"
|
|
36
|
+
"prepare": "hmpps-precommit-hooks"
|
|
31
37
|
}
|
|
32
38
|
```
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
The package will create a `.pre-commit-config.yaml` file in your project root that configures the hooks to run:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
HMPPS_HOOKS_VERSION: 1
|
|
44
|
+
|
|
45
|
+
repos:
|
|
46
|
+
- repo: local
|
|
47
|
+
hooks:
|
|
48
|
+
- id: gitleaks
|
|
49
|
+
name: Scan commit for secrets
|
|
50
|
+
language: system
|
|
51
|
+
entry: gitleaks git --pre-commit --redact --staged --verbose --config .gitleaks/config.toml --gitleaks-ignore-path .gitleaks/.gitleaksignore
|
|
52
|
+
- id: lint
|
|
53
|
+
name: linting code
|
|
54
|
+
language: system
|
|
55
|
+
entry: npm run lint
|
|
56
|
+
- id: typecheck
|
|
57
|
+
name: verify types
|
|
58
|
+
language: system
|
|
59
|
+
entry: npm run typecheck
|
|
60
|
+
- id: test
|
|
61
|
+
name: running tests
|
|
62
|
+
language: system
|
|
63
|
+
entry: npm run test
|
|
64
|
+
- repo: builtin
|
|
65
|
+
hooks:
|
|
66
|
+
- id: end-of-file-fixer
|
|
67
|
+
- id: trailing-whitespace
|
|
68
|
+
- id: check-json
|
|
69
|
+
- id: check-yaml
|
|
70
|
+
- id: check-merge-conflict
|
|
42
71
|
```
|
|
43
72
|
|
|
44
|
-
The prepare script will trigger on any install and ensure that `
|
|
73
|
+
The prepare script will trigger on any install and ensure that `prek` (pre-commit) is installed via Homebrew.
|
|
74
|
+
|
|
75
|
+
Note: `prek` is installed by `brew`. If `brew` is not available, `prepare` will display a message indicating you need to install prek manually.
|
|
45
76
|
|
|
46
|
-
|
|
77
|
+
**Important:** The `.pre-commit-config.yaml` file will only be created if it doesn't exist. Once created, it will not be overwritten, allowing you to customize hooks for your project's needs. Legacy precommit scripts (`precommit:secrets`, `precommit:lint`, `precommit:verify`) will be automatically removed from `package.json` when the config file is created.
|
|
47
78
|
|
|
48
79
|
### Prevent precommit script initialising on prepare
|
|
49
80
|
|
|
50
|
-
To disable the tool running on `npm install` and initialising
|
|
81
|
+
To disable the tool running on `npm install` and initialising prek, you can pass the `SKIP_PRECOMMIT_INIT=true` env var.
|
|
82
|
+
|
|
83
|
+
### Customizing hooks
|
|
84
|
+
|
|
85
|
+
You can modify the `.pre-commit-config.yaml` file in your project to:
|
|
86
|
+
|
|
87
|
+
- Add additional hooks
|
|
88
|
+
- Remove hooks that don't apply to your project
|
|
89
|
+
- Modify hook configurations
|
|
90
|
+
- Add hooks from external repositories
|
|
91
|
+
|
|
92
|
+
See the [pre-commit documentation](https://pre-commit.com/) for more details on hook configuration.
|
|
51
93
|
|
|
52
94
|
### Dealing with false positives
|
|
53
95
|
|
|
@@ -67,6 +109,21 @@ Repo specific rules can be added by teams in `.gitleaks/config.toml` in their in
|
|
|
67
109
|
|
|
68
110
|
See the gitleaks documentation for how to create rules and [examples](https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml) or use the [online rule wizard](https://gitleaks.io/playground).
|
|
69
111
|
|
|
112
|
+
### Running hooks manually
|
|
113
|
+
|
|
114
|
+
You can run all hooks manually using:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
prek run --all-files
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Or run specific hooks:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
prek run gitleaks
|
|
124
|
+
prek run lint
|
|
125
|
+
```
|
|
126
|
+
|
|
70
127
|
### Testing that hooks are configured correctly
|
|
71
128
|
|
|
72
129
|
Secret protection can be tested using the following command:
|
|
@@ -92,7 +149,7 @@ Attempting to commit file containing secret
|
|
|
92
149
|
○ ░
|
|
93
150
|
░ gitleaks
|
|
94
151
|
|
|
95
|
-
Finding:
|
|
152
|
+
Finding: fake__key=REDACTED
|
|
96
153
|
Secret: REDACTED
|
|
97
154
|
RuleID: aws-access-token
|
|
98
155
|
Entropy: 3.546439
|
package/bin/init.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
#
|
|
3
|
-
# Used to install
|
|
3
|
+
# Used to install prek with gitleaks
|
|
4
4
|
#
|
|
5
5
|
|
|
6
6
|
set -euo pipefail
|
|
@@ -44,22 +44,13 @@ else
|
|
|
44
44
|
npm --silent install
|
|
45
45
|
fi
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
npm pkg --silent set scripts.precommit:verify="npm run typecheck && npm test"
|
|
51
|
-
endStage " ✅"
|
|
47
|
+
# Copy default-hooks.yaml to target location
|
|
48
|
+
SOURCE_HOOKS="./node_modules/@ministryofjustice/hmpps-precommit-hooks/default-hooks.yaml"
|
|
49
|
+
TARGET_HOOKS=".pre-commit-config.yaml"
|
|
52
50
|
|
|
53
|
-
startStage "
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"#!/bin/bash" \
|
|
57
|
-
"NODE_ENV=dev \\" \
|
|
58
|
-
"npm run precommit:secrets \\" \
|
|
59
|
-
"&& npm run precommit:lint \\" \
|
|
60
|
-
"&& npm run precommit:verify" \
|
|
61
|
-
> .husky/pre-commit
|
|
62
|
-
endStage " ✅"
|
|
51
|
+
startStage "Creating .pre-commit-config.yaml"
|
|
52
|
+
cp "$SOURCE_HOOKS" "$TARGET_HOOKS"
|
|
53
|
+
endStage " ✅ "
|
|
63
54
|
|
|
64
55
|
startStage " * Creating .gitleaksignore "
|
|
65
56
|
mkdir -p .gitleaks
|
package/bin/prepare.sh
CHANGED
|
@@ -22,18 +22,58 @@ if [ "$CI" = "true" ] || [ "$SKIP_PRECOMMIT_INIT" = "true" ]; then
|
|
|
22
22
|
exit 0
|
|
23
23
|
fi
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
# Remove husky if installed
|
|
27
|
+
if [ -f "node_modules/.bin/husky" ]; then
|
|
28
|
+
startStage "Removing husky"
|
|
29
|
+
npm uninstall husky
|
|
30
|
+
endStage " ✅ "
|
|
31
|
+
|
|
32
|
+
if [ -f ".husky/pre-commit" ]; then
|
|
33
|
+
startStage "Deleting existing husky pre-commit hook"
|
|
34
|
+
rm .husky/pre-commit
|
|
35
|
+
endStage " ✅ "
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
27
38
|
|
|
28
39
|
# Check brew exists
|
|
29
40
|
if ! command -v brew > /dev/null 2> /dev/null; then
|
|
30
|
-
printError "Brew is not installed. You will need to install
|
|
41
|
+
printError "Brew is not installed. You will need to install prek separately and ensure it's on your PATH. exiting..."
|
|
31
42
|
exit 0
|
|
32
43
|
fi
|
|
33
44
|
|
|
34
|
-
#
|
|
45
|
+
# Install gitleaks if not present - this will be used by prek for secret scanning until we move over to devsecops hooks
|
|
35
46
|
if ! command -v gitleaks > /dev/null 2> /dev/null; then
|
|
36
47
|
startStage "Installing gitleaks"
|
|
37
48
|
brew install gitleaks
|
|
38
49
|
endStage " ✅ "
|
|
39
50
|
fi
|
|
51
|
+
|
|
52
|
+
# Install prek
|
|
53
|
+
if ! command -v prek > /dev/null 2> /dev/null; then
|
|
54
|
+
startStage "Installing prek"
|
|
55
|
+
brew install prek
|
|
56
|
+
endStage " ✅ "
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# Copy default-hooks.yaml to target location
|
|
60
|
+
SOURCE_HOOKS="./node_modules/@ministryofjustice/hmpps-precommit-hooks/default-hooks.yaml"
|
|
61
|
+
TARGET_HOOKS=".pre-commit-config.yaml"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if [ ! -f "$TARGET_HOOKS" ]; then
|
|
65
|
+
startStage "Creating .pre-commit-config.yaml"
|
|
66
|
+
cp "$SOURCE_HOOKS" "$TARGET_HOOKS"
|
|
67
|
+
endStage " ✅ "
|
|
68
|
+
|
|
69
|
+
startStage "Deleting existing precommit scripts"
|
|
70
|
+
npm pkg --silent delete scripts.precommit:secrets
|
|
71
|
+
npm pkg --silent delete scripts.precommit:lint
|
|
72
|
+
npm pkg --silent delete scripts.precommit:verify
|
|
73
|
+
endStage " ✅ "
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
startStage "Initialising prek hooks on this repo"
|
|
77
|
+
git config --unset-all --local core.hooksPath || true
|
|
78
|
+
prek install
|
|
79
|
+
endStage " ✅ "
|
package/bin/test.sh
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
# Test that secret protection is set up correctly.
|
|
4
4
|
# This will create a separate file ./demo-password.txt which will need to be deleted separately.
|
|
5
5
|
|
|
6
|
-
RANDOM_NUMBER="$(LC_ALL=C tr -cd '[:digit:]' < /dev/urandom | fold -w
|
|
7
|
-
|
|
6
|
+
RANDOM_NUMBER="$(LC_ALL=C tr -cd '[:digit:]' < /dev/urandom | fold -w 10 | head -n 1)"
|
|
7
|
+
FAKE_KEY="sk-${RANDOM_NUMBER}abcdef"
|
|
8
8
|
|
|
9
|
-
echo "Creating test file containing dummy
|
|
10
|
-
echo "
|
|
9
|
+
echo "Creating test file containing dummy key: 'fake_key=${FAKE_KEY}'"
|
|
10
|
+
echo "fake_key=${FAKE_KEY}" > ./demo-password.txt
|
|
11
11
|
|
|
12
12
|
echo "Attempting to commit file containing secret"
|
|
13
|
-
git add ./demo-password.txt && git commit -m "This should fail due to detecting dummy
|
|
13
|
+
git add ./demo-password.txt && git commit -m "This should fail due to detecting dummy creds"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Pre-commit hook configuration file
|
|
2
|
+
#
|
|
3
|
+
# This contains the list of hooks to be run before committing code.
|
|
4
|
+
# The devsecops-hooks baseline hook is temporarily disabled while we investigate issues with it but will eventually become compulsory.
|
|
5
|
+
# Other hooks maybe added or removed as needed to suit individual project requirements.
|
|
6
|
+
|
|
7
|
+
repos:
|
|
8
|
+
#. Temporary disabled while we investigate issues with it
|
|
9
|
+
# - repo: https://github.com/ministryofjustice/devsecops-hooks
|
|
10
|
+
# rev: v1.1.0
|
|
11
|
+
# hooks:
|
|
12
|
+
# - id: baseline
|
|
13
|
+
- repo: local
|
|
14
|
+
hooks:
|
|
15
|
+
- id: gitleaks
|
|
16
|
+
name: Scan commit for secrets
|
|
17
|
+
language: system
|
|
18
|
+
entry: gitleaks git --pre-commit --redact --staged --verbose --config .gitleaks/config.toml --gitleaks-ignore-path .gitleaks/.gitleaksignore
|
|
19
|
+
require_serial: true
|
|
20
|
+
pass_filenames: false
|
|
21
|
+
- id: lint
|
|
22
|
+
name: linting code
|
|
23
|
+
language: system
|
|
24
|
+
entry: npm run lint
|
|
25
|
+
types: [ts]
|
|
26
|
+
require_serial: true
|
|
27
|
+
pass_filenames: false
|
|
28
|
+
- id: typecheck
|
|
29
|
+
name: verify types
|
|
30
|
+
language: system
|
|
31
|
+
entry: npm run typecheck
|
|
32
|
+
types: [ts]
|
|
33
|
+
require_serial: true
|
|
34
|
+
pass_filenames: false
|
|
35
|
+
- id: test
|
|
36
|
+
name: running tests
|
|
37
|
+
language: system
|
|
38
|
+
entry: npm run test
|
|
39
|
+
types: [ts]
|
|
40
|
+
require_serial: true
|
|
41
|
+
pass_filenames: false
|
|
42
|
+
- repo: builtin
|
|
43
|
+
hooks:
|
|
44
|
+
- id: end-of-file-fixer
|
|
45
|
+
- id: trailing-whitespace
|
|
46
|
+
- id: check-json
|
|
47
|
+
- id: check-yaml
|
|
48
|
+
- id: check-merge-conflict
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ministryofjustice/hmpps-precommit-hooks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
4
|
"description": "Precommit hooks for HMPPS typescript projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"precommit"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public",
|
|
17
|
-
"tag": "
|
|
17
|
+
"tag": "beta"
|
|
18
18
|
},
|
|
19
19
|
"bin": {
|
|
20
20
|
"hmpps-precommit-hooks-prepare": "bin/prepare.sh",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"*.md",
|
|
29
29
|
"bin/*.sh",
|
|
30
|
-
"config.toml"
|
|
30
|
+
"config.toml",
|
|
31
|
+
"default-hooks.yaml"
|
|
31
32
|
],
|
|
32
33
|
"engines": {
|
|
33
34
|
"node": "20 || 22 || 24"
|