Skip to content

Commit b8e5277

Browse files
chore: add automated semantic versioning and commit enforcement
- Add commitlint with conventional commit validation (local hook + CI) - Add husky hooks for pre-commit linting and commit-msg validation - Add commit-and-tag-version for auto-detected semver bumps and CHANGELOG generation - Add CI workflow for PR commit and branch name validation - Add PR template, admin guide for GitHub settings - Update publish.yml to use commit-and-tag-version instead of manual npm version - Update CONTRIBUTING.md with branch naming, breaking changes, expanded commit types
1 parent df19486 commit b8e5277

File tree

11 files changed

+3527
-233
lines changed

11 files changed

+3527
-233
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Summary
2+
3+
<!-- Briefly describe what this PR does and why -->
4+
5+
## Type of change
6+
7+
- [ ] Bug fix (`fix:`)
8+
- [ ] New feature (`feat:`)
9+
- [ ] Breaking change (`feat!:` or `fix!:`)
10+
- [ ] Refactoring (`refactor:`)
11+
- [ ] Documentation (`docs:`)
12+
- [ ] Tests (`test:`)
13+
- [ ] Maintenance (`chore:`, `ci:`, `build:`)
14+
15+
## Testing checklist
16+
17+
- [ ] I ran `npm test` and all tests pass
18+
- [ ] I ran `npm run lint` with no errors
19+
- [ ] I added/updated tests for my changes (if applicable)
20+
21+
## Breaking changes
22+
23+
<!-- If this is a breaking change, describe what breaks and the migration path -->
24+
25+
N/A
26+
27+
## Related issues
28+
29+
<!-- Link related issues: Fixes #123, Closes #456 -->

.github/workflows/commitlint.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Commitlint
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
validate-commits:
12+
name: Validate commits
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- uses: actions/setup-node@v4
20+
with:
21+
node-version: "22"
22+
23+
- run: npm install
24+
25+
- name: Validate PR commits
26+
run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
27+
28+
validate-branch-name:
29+
name: Validate branch name
30+
runs-on: ubuntu-latest
31+
steps:
32+
- name: Check branch name
33+
run: |
34+
BRANCH="${{ github.head_ref }}"
35+
PATTERN="^(feat|fix|docs|refactor|test|chore|ci|perf|build|release|dependabot|revert)/"
36+
if [[ ! "$BRANCH" =~ $PATTERN ]]; then
37+
echo "::error::Branch name '$BRANCH' does not match the required pattern."
38+
echo "Branch names must start with one of: feat/, fix/, docs/, refactor/, test/, chore/, ci/, perf/, build/, release/, dependabot/, revert/"
39+
exit 1
40+
fi
41+
echo "Branch name '$BRANCH' is valid."

.husky/commit-msg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npx --no -- commitlint --edit $1

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npm run lint

.npmignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
.git/
22
.github/
33
.codegraph/
4+
.husky/
45
tests/
6+
docs/
57
*.db
68
.codegraphrc.json
9+
.versionrc.json
10+
commitlint.config.js
711
codegraph-improvements.md

.versionrc.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"types": [
3+
{ "type": "feat", "section": "Features" },
4+
{ "type": "fix", "section": "Bug Fixes" },
5+
{ "type": "perf", "section": "Performance" },
6+
{ "type": "refactor", "section": "Refactoring" },
7+
{ "type": "revert", "section": "Reverts" },
8+
{ "type": "docs", "hidden": true },
9+
{ "type": "test", "hidden": true },
10+
{ "type": "chore", "hidden": true },
11+
{ "type": "ci", "hidden": true },
12+
{ "type": "build", "hidden": true },
13+
{ "type": "style", "hidden": true },
14+
{ "type": "release", "hidden": true }
15+
],
16+
"releaseCommitMessageFormat": "release: v{{currentTag}}",
17+
"tagPrefix": "v",
18+
"scripts": {
19+
"postbump": "node scripts/sync-native-versions.js"
20+
}
21+
}

CLAUDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ Releases are triggered via the `publish.yml` workflow (`workflow_dispatch`). By
9090

9191
The workflow can be overridden with a specific version via the `version-override` input. Locally, `npm run release:dry-run` previews the bump and changelog.
9292

93+
## Git Conventions
94+
95+
- Never add AI co-authorship lines (`Co-Authored-By` or similar) to commit messages.
96+
9397
## Node Version
9498

9599
Requires Node >= 20.

CONTRIBUTING.md

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@ kinds — bug fixes, new features, documentation, and new language support.
1111
```bash
1212
git clone https://github.com/optave/codegraph.git
1313
cd codegraph
14-
npm install
14+
npm install # also installs git hooks via husky
1515
npm test # run the full test suite
1616
```
1717

1818
**Requirements:** Node.js >= 20
1919

20+
After `npm install`, [Husky](https://typicode.github.io/husky/) automatically
21+
installs two git hooks:
22+
23+
- **pre-commit** — runs `npm run lint` (Biome) before each commit
24+
- **commit-msg** — validates your commit message against the [commit convention](#commit-convention)
25+
2026
## Project Structure
2127

2228
```
@@ -61,9 +67,22 @@ npx vitest run -t "finds cycles" # Single test by name
6167
npm run build:wasm # Rebuild WASM grammars
6268
```
6369

70+
## Branch Naming Convention
71+
72+
Branch names **must** match one of these prefixes:
73+
74+
```
75+
feat/ fix/ docs/ refactor/ test/ chore/
76+
ci/ perf/ build/ release/ revert/ dependabot/
77+
```
78+
79+
Examples: `feat/add-cpp-support`, `fix/cycle-detection-edge-case`,
80+
`chore/update-deps`. This is enforced in CI on pull requests.
81+
6482
## Commit Convention
6583

66-
We use short conventional-style prefixes:
84+
We use [Conventional Commits](https://www.conventionalcommits.org/). Messages
85+
are validated locally by a `commit-msg` hook and in CI on pull requests.
6786

6887
| Prefix | Use for |
6988
|--------|---------|
@@ -72,16 +91,38 @@ We use short conventional-style prefixes:
7291
| `docs:` | Documentation only |
7392
| `refactor:` | Code changes that don't fix bugs or add features |
7493
| `test:` | Adding or updating tests |
75-
| `chore:` | Maintenance, dependencies, CI |
94+
| `chore:` | Maintenance, dependencies |
95+
| `ci:` | CI/CD changes |
96+
| `perf:` | Performance improvements |
97+
| `build:` | Build system or external dependencies |
98+
| `style:` | Code style (formatting, whitespace) |
99+
| `revert:` | Reverting a previous commit |
76100

77101
Examples:
78102
```
79103
feat: add C language support
80104
fix: resolve false positive cycles in HCL modules
81105
docs: update adding-a-language guide
82106
test: add parity tests for Python extractor
107+
perf: cache tree-sitter parser instances
108+
ci: add branch naming check to PR workflow
83109
```
84110

111+
### Breaking Changes
112+
113+
For breaking changes, add a `!` after the type or include a `BREAKING CHANGE:`
114+
footer:
115+
116+
```
117+
feat!: rename --output flag to --format
118+
119+
fix: change default export format
120+
121+
BREAKING CHANGE: JSON export now uses camelCase keys instead of snake_case.
122+
```
123+
124+
Breaking changes trigger a **major** version bump during release.
125+
85126
## Testing
86127

87128
Tests use [vitest](https://vitest.dev/) with a 30-second timeout and globals
@@ -175,7 +216,9 @@ Use [GitHub Issues](https://github.com/optave/codegraph/issues) with:
175216
## Code Style
176217

177218
- All source is plain JavaScript (ES modules) — no transpilation
178-
- No linter is currently configured; keep style consistent with existing code
219+
- [Biome](https://biomejs.dev/) is used for linting and formatting (config in `biome.json`)
220+
- Run `npm run lint` to check and `npm run lint:fix` to auto-fix
221+
- The pre-commit hook runs the linter automatically
179222
- Use `const`/`let` (no `var`)
180223
- Prefer early returns over deep nesting
181224
- Keep functions focused and reasonably sized

commitlint.config.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export default {
2+
extends: ["@commitlint/config-conventional"],
3+
rules: {
4+
"type-enum": [
5+
2,
6+
"always",
7+
[
8+
"feat",
9+
"fix",
10+
"docs",
11+
"refactor",
12+
"test",
13+
"chore",
14+
"ci",
15+
"perf",
16+
"build",
17+
"style",
18+
"revert",
19+
"release",
20+
],
21+
],
22+
"header-max-length": [2, "always", 100],
23+
},
24+
};

docs/admin-guide.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Admin Guide — GitHub Repository Settings
2+
3+
This document describes the recommended GitHub settings for the codegraph
4+
repository. These must be configured manually by a repository admin.
5+
6+
---
7+
8+
## Branch Protection on `main`
9+
10+
Go to **Settings > Branches > Add branch protection rule** for `main`:
11+
12+
| Setting | Value |
13+
|---------|-------|
14+
| Require a pull request before merging | Yes |
15+
| Required approvals | 1 |
16+
| Dismiss stale pull request approvals when new commits are pushed | Yes |
17+
| Require status checks to pass before merging | Yes |
18+
| Required status checks | `Preflight checks` (CI), `Lint` (CI), `Validate commits` (Commitlint), `Validate branch name` (Commitlint) |
19+
| Require branches to be up to date before merging | Yes |
20+
| Require conversation resolution before merging | Yes |
21+
| Restrict who can push to matching branches | Optional (recommended for teams) |
22+
23+
## Merge Strategy
24+
25+
Go to **Settings > General > Pull Requests**:
26+
27+
| Setting | Value |
28+
|---------|-------|
29+
| Allow merge commits | Yes |
30+
| Allow squash merging | Yes |
31+
| Allow rebase merging | No |
32+
| Automatically delete head branches | Yes |
33+
34+
Disabling rebase merge ensures conventional commit history is preserved on
35+
`main`. Squash merging is allowed so that messy PR branches can be collapsed
36+
into a single conventional commit.
37+
38+
## Environment Protection
39+
40+
Go to **Settings > Environments** and create an environment called
41+
`npm-publish`:
42+
43+
| Setting | Value |
44+
|---------|-------|
45+
| Required reviewers | At least 1 (e.g. project lead) |
46+
| Deployment branches | `main` only |
47+
48+
This ensures that the publish workflow (`publish.yml`) requires manual
49+
approval before publishing to npm.
50+
51+
## Secrets and Variables
52+
53+
Go to **Settings > Secrets and variables > Actions**:
54+
55+
| Secret | Purpose |
56+
|--------|---------|
57+
| `ANTHROPIC_API_KEY` | Used by the Claude workflow (if enabled) |
58+
59+
**npm publishing** uses OIDC provenance (`--provenance` flag), so no
60+
`NPM_TOKEN` secret is needed — the publish workflow uses the built-in
61+
`id-token: write` permission with `setup-node`'s registry-url.
62+
63+
## Dependabot
64+
65+
Dependabot is already configured via `.github/dependabot.yml`. No additional
66+
admin setup is needed. Dependabot branches (`dependabot/`) are explicitly
67+
allowed by the branch naming convention.

0 commit comments

Comments
 (0)