diff --git a/.claude/agents/git-pr-manager.md b/.claude/agents/git-pr-manager.md index c319ea8fa10..a23e22bf5e9 100644 --- a/.claude/agents/git-pr-manager.md +++ b/.claude/agents/git-pr-manager.md @@ -22,6 +22,29 @@ Your responsibilities: * `fix(api): resolve race condition in user creation` * `chore(deps): update dependencies` + **Special Case - Release Commits (staging→production)**: + - Always use: `chore(release): staging to production - YYYY.MM.DD` + - Include detailed release notes in commit body with: + * Summary of features added + * Bug fixes included + * Breaking changes (if any) + * Migration steps (if any) + - Example: + ``` + chore(release): staging to production - 2025.11.03 + + ## Features + - feat(chat): add artifact rendering support + - feat(chat): add file upload to UI + + ## Bug Fixes + - fix(auth): resolve token refresh issue + - fix(api): fix race condition in chat creation + + ## Notes + - Requires database migration (run `pnpm db:migrate`) + ``` + 3. **Execute Git Operations**: - Stage appropriate files (ask for confirmation if unexpected files are present) - Commit with properly formatted message @@ -29,15 +52,27 @@ Your responsibilities: - Use `--no-verify` flag if pre-commit hooks are failing and user confirms 4. **Create Pull Requests**: - - ALWAYS target the `staging` branch (never main or master) + - **Default**: ALWAYS target the `staging` branch (never main or master) + - **Exception**: When creating a release PR, target `production` branch - Generate clear PR title matching commit convention - Create comprehensive PR description including: * Summary of changes - * Type of change (feature/fix/chore) + * Type of change (feature/fix/chore/release) * Testing performed * Related issues (if any) - Follow repository PR templates if they exist + **Release PR Format (staging→production)**: + - Title: `chore(release): staging to production - YYYY.MM.DD` + - Description must include: + * List of features (grouped by area) + * List of bug fixes + * Breaking changes section (if any) + * Migration instructions (if database changes) + * Testing checklist + - Use `git log production..staging --format="%s"` to gather all commits + - Parse conventional commits and group by type (feat/fix/chore) + 5. **Handle Edge Cases**: - If multiple unrelated changes exist, suggest splitting into separate commits - If commit history is messy, offer to help clean it up @@ -67,10 +102,31 @@ Your responsibilities: - Ensure commits are functional and complete **Decision Framework**: -1. Assess changes → Determine semver impact -2. Craft commit message → Validate format -3. Execute git operations → Verify success -4. Create PR → Target staging branch -5. Provide summary → Include PR link +1. **Detect scenario**: + - Check current branch name + - Check if this is a release (staging→production) + - Identify if it's a feature, fix, or chore +2. **Assess changes** → Determine semver impact +3. **Craft commit message** → Validate format (MUST be conventional commits) +4. **Execute git operations** → Verify success +5. **Create PR** → Target correct branch (staging for features, production for releases) +6. **Provide summary** → Include PR link + +**Commit Message Validation**: +Before creating any commit, verify: +- ✅ Follows `type(scope): description` format +- ✅ Type is one of: feat, fix, chore, docs, refactor, test, style, perf, ci, build +- ✅ Description starts with lowercase verb in imperative mood +- ✅ Subject line is ≤72 characters +- ✅ For releases: uses `chore(release): staging to production - DATE` format +- ❌ Never use free-form text like "Release: Staging to Production" +- ❌ Never use past tense like "Added" or "Fixed" + +**Automatic Release Detection**: +If current branch is `staging` AND user wants to create PR to `production`: +1. Automatically use release commit format +2. Generate release notes from git log +3. Group commits by type (Features/Bug Fixes/Chore) +4. Include migration warnings if detected When uncertain about the scope or impact of changes, ask the user for clarification before proceeding. Your goal is to maintain a clean, semantic git history that integrates seamlessly with the repository's release process. diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 00000000000..0773b4d98b6 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,47 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# Validate commit message follows conventional commits format +commit_msg_file=$1 +commit_msg=$(cat "$commit_msg_file") + +# Conventional commit pattern: type(scope): description +# type: feat, fix, chore, docs, style, refactor, perf, test, build, ci, revert +# scope: optional +# description: required +pattern="^(feat|fix|chore|docs|style|refactor|perf|test|build|ci|revert)(\([a-zA-Z0-9_\-]+\))?: .+$" + +# Allow merge commits +if echo "$commit_msg" | grep -qE "^Merge "; then + exit 0 +fi + +# Allow revert commits +if echo "$commit_msg" | grep -qE "^Revert "; then + exit 0 +fi + +# Validate commit message +if ! echo "$commit_msg" | grep -qE "$pattern"; then + echo "❌ Invalid commit message format!" + echo "" + echo "Commit message must follow conventional commits format:" + echo " type(scope): description" + echo "" + echo "Types: feat, fix, chore, docs, style, refactor, perf, test, build, ci, revert" + echo "Scope: optional (e.g., auth, api, ui)" + echo "" + echo "Examples:" + echo " ✅ feat(auth): add OAuth2 support" + echo " ✅ fix(api): resolve race condition" + echo " ✅ chore(release): staging to production - 2025.11.03" + echo " ✅ docs: update README" + echo "" + echo "Your message:" + echo " ❌ $commit_msg" + echo "" + exit 1 +fi + +echo "✅ Commit message format is valid" +exit 0 diff --git a/.releaserc.json b/.releaserc.json index e0fc8bbbe1c..a15d9c8cb49 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -5,17 +5,39 @@ [ "@semantic-release/commit-analyzer", { + "preset": "conventionalcommits", "releaseRules": [ - { "type": "Release", "release": "patch" }, - { "type": "HOTFIX", "release": "patch" }, { "type": "feat", "release": "minor" }, { "type": "fix", "release": "patch" }, { "type": "perf", "release": "patch" }, - { "type": "revert", "release": "patch" } - ] + { "type": "revert", "release": "patch" }, + { "type": "docs", "release": "patch" }, + { "type": "chore", "scope": "release", "release": "patch" }, + { "type": "refactor", "release": "patch" }, + { "breaking": true, "release": "major" } + ], + "parserOpts": { + "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"] + } + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { "type": "feat", "section": "Features" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "perf", "section": "Performance Improvements" }, + { "type": "revert", "section": "Reverts" }, + { "type": "docs", "section": "Documentation" }, + { "type": "refactor", "section": "Code Refactoring" }, + { "type": "chore", "section": "Maintenance", "hidden": false } + ] + } } ], - "@semantic-release/release-notes-generator", "@semantic-release/github" ] }