@casomoltd/tooling 0.27.0 → 0.28.0

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 CHANGED
@@ -21,7 +21,8 @@ Shared linting, formatting, commit config, and CLI tools for Casomo Ltd's repos.
21
21
  | Command | Description |
22
22
  |---|---|
23
23
  | `check-version` | Pre-push guard — rejects push if `package.json` version hasn't changed vs `origin/main` |
24
- | `pre-push` | Husky pre-push hook — runs check, build, then version/tag guards |
24
+ | `check-linear` | Pre-push guard — rejects a push that would put a merge commit on the remote. History is linear; a branch catches up by rebasing. Only what the push adds is judged, so merges already on the remote stay |
25
+ | `pre-push` | Husky pre-push hook — runs check, then the version, tag and linear-history guards |
25
26
  | `pre-commit` | Husky pre-commit hook — runs `npm run check` |
26
27
  | `commit-msg` | Husky commit-msg hook — runs commitlint |
27
28
  | `readability` | Measure reading difficulty of page content |
@@ -0,0 +1,47 @@
1
+ #!/bin/sh
2
+ # Refuse a push that would put a merge commit on the remote.
3
+ #
4
+ # History is linear here: a branch catches up by rebasing, never by merging.
5
+ # A merge commit costs the thing a linear history is kept for — `git log` on a
6
+ # file stops being the list of changes to it, `git bisect` has two parents to
7
+ # choose between, and a revert has to name which side it means.
8
+ #
9
+ # The forge refuses merges made through its own UI; this refuses the other
10
+ # route, which is a local `git merge` followed by an ordinary push. Both are
11
+ # needed: neither covers the other.
12
+ #
13
+ # Only what the push would ADD is judged. A merge already on the remote stays
14
+ # where it is, because rewriting shared history to satisfy a new rule costs
15
+ # more than the rule is worth.
16
+
17
+ STATUS=0
18
+
19
+ while read -r _ LOCAL_SHA REMOTE_REF REMOTE_SHA; do
20
+ # A deletion pushes the zero sha and adds nothing.
21
+ case "$LOCAL_SHA" in
22
+ *[!0]*) ;;
23
+ *) continue ;;
24
+ esac
25
+
26
+ case "$REMOTE_SHA" in
27
+ # A new branch: everything on it that no remote already has.
28
+ *[!0]*) RANGE="$REMOTE_SHA..$LOCAL_SHA" ;;
29
+ *) RANGE="$LOCAL_SHA --not --remotes" ;;
30
+ esac
31
+
32
+ # shellcheck disable=SC2086 # RANGE carries its own arguments.
33
+ MERGES=$(git rev-list --merges $RANGE 2>/dev/null)
34
+
35
+ if [ -n "$MERGES" ]; then
36
+ COUNT=$(printf '%s\n' "$MERGES" | wc -l | tr -d ' ')
37
+ echo "$REMOTE_REF would gain $COUNT merge commit(s):"
38
+ printf '%s\n' "$MERGES" | while read -r SHA; do
39
+ echo " $(git log --format='%h %s' -1 "$SHA")"
40
+ done
41
+ echo "History is linear here. Rebase instead:"
42
+ echo " git rebase main"
43
+ STATUS=1
44
+ fi
45
+ done
46
+
47
+ exit $STATUS
package/bin/pre-push.sh CHANGED
@@ -16,4 +16,5 @@ export PRE_PUSH_REFS
16
16
  # simply doesn't.
17
17
  npm run check \
18
18
  && echo "$PRE_PUSH_REFS" | check-version \
19
- && echo "$PRE_PUSH_REFS" | check-tags
19
+ && echo "$PRE_PUSH_REFS" | check-tags \
20
+ && echo "$PRE_PUSH_REFS" | check-linear
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@casomoltd/tooling",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "Casomo's shared dev config: ESLint, Prettier, commitlint, knip & jscpd presets and dev CLIs (git hooks, readability, screenshots)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -49,6 +49,7 @@
49
49
  "bin": {
50
50
  "build-report": "./bin/build-report.mjs",
51
51
  "check-gates": "./bin/check-gates.mjs",
52
+ "check-linear": "./bin/check-linear.sh",
52
53
  "check-private-refs": "./bin/check-private-refs.mjs",
53
54
  "check-tags": "./bin/check-tags.sh",
54
55
  "check-version": "./bin/check-version.sh",