Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .githooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
# Commit message hook - validates Conventional Commits format.
# PR title CI remains the merge-blocking guard for GitHub merge subjects.

set -e

ROOT="$(git rev-parse --show-toplevel)"
cd "$ROOT"

if ! command -v npx >/dev/null 2>&1; then
echo "Warning: npx not found; skipping local commitlint check." >&2
echo "CI still requires a semantic PR title before merge." >&2
exit 0
fi

if ! output=$(npx --yes \
--package @commitlint/cli \
--package @commitlint/config-conventional \
commitlint --edit "$1" 2>&1); then
if printf '%s\n' "$output" | grep -qE '^(npm (ERR!|error) )?(network|code (ENOTFOUND|EAI_AGAIN|ECONNRESET|ECONNREFUSED|ETIMEDOUT)|could not determine executable)|^Error: could not determine executable'; then
echo "Warning: commitlint unavailable; skipping local check." >&2
echo "CI still requires a semantic PR title before merge." >&2
exit 0
fi
printf '%s\n' "$output" >&2
exit 1
fi
35 changes: 35 additions & 0 deletions .github/workflows/semantic-pr-title.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Semantic PR Title

on:
pull_request_target:
types: [opened, edited, synchronize, reopened, ready_for_review]

permissions:
pull-requests: read

concurrency:
group: semantic-pr-title-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
validate:
name: Semantic PR Title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
build
chore
ci
deps
docs
feat
fix
perf
refactor
revert
style
test
25 changes: 25 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Contributing

Use Conventional Commit style for commit subjects and PR titles:

```text
feat: add workspace snapshot filtering
fix(meta_git_cli): preserve child repo commit type
ci: enforce semantic PR titles
docs: clarify plugin installation
```

If you are working from an internal GitKB task, include the task wikilink in
commit messages:

```text
fix: remove legacy meta agent workspace entry [[tasks/harmony-678]]
```

GitHub merge subjects are derived from PR titles, so the semantic PR title check
is the merge-blocking guard for release notes. Local hooks catch malformed commit
messages before push when installed with:

```sh
make install-hooks
```
15 changes: 14 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ clean-plugins:

rebuild-plugins: clean-plugins build-plugins

# Install git hooks (commit-msg validates release-safe subjects; pre-push runs CI checks locally)
# Uses git rev-parse to handle worktrees and submodules correctly
install-hooks:
@echo "Installing git hooks..."
@chmod +x .githooks/commit-msg
@chmod +x .githooks/pre-commit
@chmod +x .githooks/pre-push
@mkdir -p "$$(git rev-parse --git-path hooks)"
@hooks_dir="$$(git rev-parse --git-path hooks)" && root="$$(git rev-parse --show-toplevel)" && rel="$$(python3 -c 'import os, sys; print(os.path.relpath(sys.argv[1], sys.argv[2]))' "$$root/.githooks/commit-msg" "$$hooks_dir")" && ln -sf "$$rel" "$$hooks_dir/commit-msg"
@hooks_dir="$$(git rev-parse --git-path hooks)" && root="$$(git rev-parse --show-toplevel)" && rel="$$(python3 -c 'import os, sys; print(os.path.relpath(sys.argv[1], sys.argv[2]))' "$$root/.githooks/pre-commit" "$$hooks_dir")" && ln -sf "$$rel" "$$hooks_dir/pre-commit"
@hooks_dir="$$(git rev-parse --git-path hooks)" && root="$$(git rev-parse --show-toplevel)" && rel="$$(python3 -c 'import os, sys; print(os.path.relpath(sys.argv[1], sys.argv[2]))' "$$root/.githooks/pre-push" "$$hooks_dir")" && ln -sf "$$rel" "$$hooks_dir/pre-push"
@echo "Commit-msg, pre-commit, and pre-push hooks installed."

release:
cargo build --release

Expand Down Expand Up @@ -103,4 +116,4 @@ uninstall:
cargo uninstall meta_rust_cli 2>/dev/null || true
rm -f ~/.meta/plugins/meta-git ~/.meta/plugins/meta-project ~/.meta/plugins/meta-rust

.PHONY: install build run test bats release integration-test
.PHONY: install install-hooks build run test bats release integration-test
23 changes: 23 additions & 0 deletions commitlint.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
[
"build",
"chore",
"ci",
"deps",
"docs",
"feat",
"fix",
"perf",
"refactor",
"revert",
"style",
"test",
],
],
},
};
Loading