diff --git a/.claude/skills/bflow/SKILL.md b/.claude/skills/bflow/SKILL.md index 6fd012d..9f023ec 100644 --- a/.claude/skills/bflow/SKILL.md +++ b/.claude/skills/bflow/SKILL.md @@ -41,7 +41,7 @@ bflow finish --abort # discard an in-progress release/hotfix finish ``` - **Work branches** (feature/fix/chore/docs/refactor) → asks about breaking changes (feat/fix/refactor only), creates PR to base branch. If breaking, PR title gets `!` (e.g., `feat!: name`). Use `--breaking` flag in non-interactive mode to skip the prompt. -- **Release-fix / hotfix-fix** → creates PR to parent release/hotfix branch +- **Release-fix / hotfix-fix** → creates PR to parent release/hotfix branch, title `fix: {name}` with dashes converted to spaces (e.g. `null-crash` → `fix: null crash`) - **Release** → merges to main + develop, tags, cleans up - **Hotfix** → merges to main + develop + every open `release/*`, tags, cleans up. If a release branch already exists, the hotfix is propagated into it so the upcoming release ships the fix; the operator must then run `bflow bump` to cut a new RC for staging validation. diff --git a/README.md b/README.md index ab69a48..1648df4 100644 --- a/README.md +++ b/README.md @@ -368,6 +368,10 @@ All commits and PR titles generated by bflow follow [Conventional Commits](https | `chore/{name}` | `chore: {name}` | | `docs/{name}` | `docs: {name}` | | `refactor/{name}` | `refactor: {name}` | +| `release-fix/{v}/{name}` | `fix: {name}` (dashes → spaces) | +| `hotfix-fix/{v}/{name}` | `fix: {name}` (dashes → spaces) | + +For `release-fix` and `hotfix-fix`, dashes in the branch name are converted to spaces in the PR title (e.g. `hotfix-fix/2.1.0/null-crash` → `fix: null crash`), keeping the squash-merged history readable. Merge commits and tags also follow the convention: - `chore: create release branch 2.6.0` diff --git a/src/flows/finish_work.rs b/src/flows/finish_work.rs index 629eb53..e69764b 100644 --- a/src/flows/finish_work.rs +++ b/src/flows/finish_work.rs @@ -113,12 +113,14 @@ pub fn finish_release_fix(git: &dyn Git, hosting: &dyn HostingPlatform, branch_t let BranchType::ReleaseFix { major, minor, patch, name } = branch_type else { return Err("Cannot finish: not on a release-fix branch".to_string()); }; - push_and_create_pr(git, hosting, &format!("release/{major}.{minor}.{patch}"), &format!("fix: {name}"), branch_type) + let title = format!("fix: {}", name.replace('-', " ")); + push_and_create_pr(git, hosting, &format!("release/{major}.{minor}.{patch}"), &title, branch_type) } pub fn finish_hotfix_fix(git: &dyn Git, hosting: &dyn HostingPlatform, branch_type: &BranchType) -> Result<(), String> { let BranchType::HotfixFix { major, minor, patch, name } = branch_type else { return Err("Cannot finish: not on a hotfix-fix branch".to_string()); }; - push_and_create_pr(git, hosting, &format!("hotfix/{major}.{minor}.{patch}"), &format!("fix: {name}"), branch_type) + let title = format!("fix: {}", name.replace('-', " ")); + push_and_create_pr(git, hosting, &format!("hotfix/{major}.{minor}.{patch}"), &title, branch_type) } diff --git a/tests/finish_work_test.rs b/tests/finish_work_test.rs index 7af8267..2496d93 100644 --- a/tests/finish_work_test.rs +++ b/tests/finish_work_test.rs @@ -19,7 +19,7 @@ fn finish_release_fix_pushes_and_creates_pr() { ]); assert_eq!(hosting.calls(), vec![ - "create_or_get_pr:release-fix/1.1.0/login-bug:release/1.1.0:fix: login-bug", + "create_or_get_pr:release-fix/1.1.0/login-bug:release/1.1.0:fix: login bug", "open_url:https://github.com/org/repo/pull/1", ]); } @@ -39,7 +39,7 @@ fn finish_hotfix_fix_pushes_and_creates_pr() { ]); assert_eq!(hosting.calls(), vec![ - "create_or_get_pr:hotfix-fix/1.0.1/crash-fix:hotfix/1.0.1:fix: crash-fix", + "create_or_get_pr:hotfix-fix/1.0.1/crash-fix:hotfix/1.0.1:fix: crash fix", "open_url:https://github.com/org/repo/pull/1", ]); }