Skip to content

Commit 29b600e

Browse files
committed
feat(*): Create precise-commits
0 parents  commit 29b600e

40 files changed

+6364
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
yarn.lock -diff

.gitignore

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Runtime data
7+
pids
8+
*.pid
9+
*.seed
10+
11+
# Directory for instrumented libs generated by jscoverage/JSCover
12+
lib-cov
13+
14+
# Coverage directory used by tools like istanbul
15+
coverage
16+
17+
# nyc test coverage
18+
.nyc_output
19+
20+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21+
.grunt
22+
23+
# node-waf configuration
24+
.lock-wscript
25+
26+
# Compiled binary addons (http://nodejs.org/api/addons.html)
27+
build/Release
28+
29+
# Dependency directories
30+
node_modules
31+
jspm_packages
32+
33+
# Optional npm cache directory
34+
.npm
35+
36+
# Optional REPL history
37+
.node_repl_history
38+
39+
# Generated lib directory containing the final code
40+
lib
41+
42+
# Temp directory created during testing
43+
tmp

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.json

.prettierrc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"trailingComma": "all",
5+
"overrides": [
6+
{
7+
"files": "bin/*.js",
8+
"options": {
9+
"trailingComma": "es5"
10+
}
11+
},
12+
{
13+
"files": "*.ts",
14+
"options": {
15+
"parser": "typescript"
16+
}
17+
},
18+
{
19+
"files": "*.md",
20+
"options": {
21+
"parser": "markdown"
22+
}
23+
}
24+
]
25+
}

.travis.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
language: node_js
2+
cache:
3+
yarn: true
4+
directories:
5+
- node_modules
6+
notifications:
7+
email: false
8+
node_js:
9+
- '9'
10+
- '8'
11+
script:
12+
- yarn test
13+
- yarn build
14+
after_success:
15+
- npm run travis-deploy-once "npm run semantic-release"
16+
branches:
17+
except:
18+
- /^v\d+\.\d+\.\d+$/

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"editor.formatOnSave": true
3+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 James Henry
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<h1 align="center">Precise Commits</h1>
2+
3+
<p align="center">
4+
<a href="https://travis-ci.org/JamesHenry/precise-commits"><img src="https://img.shields.io/travis/JamesHenry/precise-commits.svg?style=flat-square" alt="Travis"/></a>
5+
<a href="https://github.com/JamesHenry/precise-commits/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/precise-commits.svg?style=flat-square" alt="GitHub license" /></a>
6+
<a href="https://www.npmjs.com/package/precise-commits"><img src="https://img.shields.io/npm/v/precise-commits.svg?style=flat-square" alt="NPM Version" /></a>
7+
<a href="https://www.npmjs.com/package/precise-commits"><img src="https://img.shields.io/npm/dt/precise-commits.svg?style=flat-square" alt="NPM Downloads" /></a>
8+
<a href="http://commitizen.github.io/cz-cli/"><img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly" /></a>
9+
<a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square" alt="semantic-release" /></a>
10+
</p>
11+
12+
<br>
13+
14+
# Why `precise-commits`?
15+
16+
🔎 It is simply **the most exact and least disruptive way** to add consistent code formatting (by [Prettier](https://prettier.io)) to an existing codebase.
17+
18+
✨ You only **reformat the exact code you have modified anyway** as part of your normal development!
19+
20+
| Tool | Staged files | Existing commits | PR Build | Arbitrary commands | Precision |
21+
| ------------------- | ------------ | ---------------- | -------- | ------------------ | ------------------------------- |
22+
| **precise-commits** ||||| **Individual character ranges** |
23+
| lint-staged ||||| Entire File |
24+
| pretty-quick ||||| Entire File |
25+
26+
<br>
27+
28+
# Background
29+
30+
Implementing a new code-style in an existing codebase can be really tricky.
31+
32+
[Prettier](https://prettier.io) is an amazing automated code formatting tool, but that does not mean that introducing it into an existing codebase is trivial.
33+
34+
Regardless of how consistent the existing code-style might be, introducing [Prettier](https://prettier.io) will result in larger diffs, which:
35+
36+
1. Increases the complexity and review time burden of PRs on senior team members.
37+
2. Potentially increases the amount of time it takes to complete a PR in the first place.
38+
3. Can block concurrent work on the same codebase and/or result in nasty merge conflicts with outstanding feature branches.
39+
40+
Other tools, such as `lint-staged`, made an excellent first step towards mitigating the scope of the impact of the points above, by only running linters and formatters on files which have changed.
41+
42+
This is great for small codebases, in which the authors do not mind much that they are polluting the git history of the files they are touching, but **it is not enough**.
43+
44+
In large and enterprise codebases (particularly those organized as monorepos), the git history of each file is really important.
45+
46+
> If I make a change on line 10 of a 4000 line file, I shouldn't be forced to reformat all 4000s lines (thus making me the last git user to update all of them) as part of my PR.
47+
>
48+
> I should just need to reformat line 10.
49+
50+
This is where `precise-commits` comes in!
51+
52+
<br>
53+
54+
# Our ideal end-goal...
55+
56+
1. All developers on our team develop using consistent, automated formatting as they write their code.
57+
e.g. Running an IDE-based plugin, such as "vscode-prettier" with "format on save" enabled.
58+
59+
2. Each time they commit, a precommit hook is triggered to _ensure_ that the staged code is formatted consistently.
60+
61+
3. Each time a Pull Request opened on our remote repo, a build is triggered on a CI server, during which the formatting
62+
is checked to ensure that all the files touched for that PR were formatted consistently.
63+
64+
<br>
65+
66+
# How `precise-commits` helps us get there...
67+
68+
1. All developers on our team write their code as they always have.
69+
70+
2. Each time they commit, a precommit hook is triggered which will run `precise-commits` on the code and ensure that **the exact code they already modified** is formatted consistently. Any untouched existing code will not be mutated.
71+
72+
3. Each time a Pull Request opened on our remote repo, a build is triggered on a CI server, during which `precise-commits`
73+
runs to ensure that all the **committed lines of code** for that PR was formatted consistently.
74+
75+
<br>
76+
77+
...and after enough time has passed, **our codebase will be formatted consistently, despite us never having to disrupt our feature-building momentum!**
78+
79+
<br>
80+
81+
# How it works
82+
83+
Through analyzing your staged files (or any files modified between two given commit SHAs) `precise-commits` will work out exactly what lines and characters within those files have actually been changed or added.
84+
85+
It then uses this information to run [Prettier](https://prettier.io) in a very focused way, allowing it to only reformat what is relevant for your current work, and allowing you to keep your PRs small and explicit!
86+
87+
<br>
88+
89+
# Installation
90+
91+
`precise-commits` expects `prettier` to be available as a `peerDependency`, so you will need to install this yourself as a `devDependency` of your project.
92+
93+
```sh
94+
npm install --save-dev prettier precise-commits
95+
```
96+
97+
<br>
98+
99+
# Usage
100+
101+
It is intended that you will run `precise-commits` as a CLI, and it will automatically pick up on any of the standard [Prettier configuration files](https://prettier.io/docs/en/configuration) you may have in your project, including [`.prettierignore`](https://prettier.io/docs/en/ignore#ignoring-files) files.
102+
103+
## 1. Running it manually
104+
105+
1. Add an npm script to your package.json, such as:
106+
107+
```js
108+
{
109+
//...
110+
"scripts": {
111+
"precise-commits": "precise-commits"
112+
}
113+
//...
114+
}
115+
```
116+
117+
2. Execute the npm script, e.g. for the one above run:
118+
119+
```sh
120+
npm run precise-commits
121+
```
122+
123+
## 2. "Precommit" Hook
124+
125+
The recommended way to run `precise-commits` is as a "precommit" hook.
126+
127+
A great tool for setting up the hook is [`husky`](https://github.com/typicode/husky). You can install and run it as follows:
128+
129+
```sh
130+
npm install --save-dev husky
131+
```
132+
133+
Update the `"scripts"` section of your `package.json`:
134+
135+
```js
136+
{
137+
//...
138+
"scripts": {
139+
"precise-commits": "precise-commits",
140+
"precommit": "npm run precise-commits"
141+
}
142+
//...
143+
}
144+
```
145+
146+
## 3. As part of a PR build
147+
148+
When running a build for your PR, you can run `precise-commits` to ensure that the author's changes are all formatted consistently.
149+
150+
The key things you need to configure are:
151+
152+
1. The `--check-only` flag for `precise-commits` so that it will error out if it finds any inconsistent formatting
153+
2. The `--head` and `--base` flags so that `precise-commits` knows what commits it should consider when resolving modified files. Most CI servers will have environment variables you can use to resolve these.
154+
155+
For example, if your PR is building on [Travis](https://travis-ci.com/), your config might look like this:
156+
157+
**.travis.yml**
158+
159+
```yaml
160+
# ... Other config options here ...
161+
install:
162+
- yarn install
163+
script:
164+
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then precise-commits --whitelist="src/**/*.ts" --check-only --head=$TRAVIS_PULL_REQUEST_SHA --base=$(git merge-base HEAD $TRAVIS_BRANCH); fi'
165+
- yarn test
166+
- yarn e2e
167+
# ... Other config options here ...
168+
```
169+
170+
<br>
171+
172+
# CLI Configuration Options
173+
174+
As was hinted at above, the `precise-commits` CLI supports a few different configuration options:
175+
176+
* `--whitelist`: **[String, Default: `"*"`]**
177+
* Whitelist is a glob pattern ([the glob syntax from the glob module is used](https://github.com/isaacs/node-glob/blob/master/README.md#glob-primer)).
178+
* It is used to inform what files are considered when resolving modified files (by default all are considered).
179+
* Don't forget the quotes around the globs! The quotes make sure that `precise-commits` expands the globs rather than your shell.
180+
181+
<br>
182+
183+
* `--formatter`: **[String, Default: `"prettier"`]**
184+
* Currently only prettier is supported
185+
* If you are interested in adding support for a different formatter, all you need to do is provide an object which [implements this interface](https://github.com/JamesHenry/precise-commits/blob/master/src/precise-formatter.ts).
186+
187+
<br>
188+
189+
* `--check-only`: **[Boolean, Default: `false`]**
190+
* Only check the code formatting is consistent with the resolved config
191+
192+
<br>
193+
194+
* `--base`: **[String, NO DEFAULT]**
195+
* Base commit SHA to be used in conjunction with the `--head` flag
196+
197+
<br>
198+
199+
* `--head`: **[String, CONDITIONAL DEFAULT]**
200+
* Later commit SHA (e.g. the `HEAD` of a PR branch) to be used in conjunction with the `--base` flag
201+
* NOTE on conditional default: If no value is provided for `--head`, but a value is given for `--base`, it will default to checking "HEAD"

0 commit comments

Comments
 (0)