11use crate :: component;
22use crate :: deploy:: { self , DeployConfig } ;
3+ use crate :: engine:: command;
34use crate :: error:: { Error , Result } ;
45use crate :: git;
56
@@ -23,6 +24,10 @@ pub fn run_command(input: ReleaseCommandInput) -> Result<(ReleaseCommandResult,
2324 } ,
2425 ) ?;
2526
27+ if !input. dry_run {
28+ ensure_release_on_default_branch ( & component. local_path ) ?;
29+ }
30+
2631 let monorepo = git:: MonorepoContext :: detect ( & component. local_path , & input. component_id ) ;
2732 let ( auto_bump_type, releasable_count) =
2833 match resolve_bump ( & component. local_path , monorepo. as_ref ( ) ) ? {
@@ -288,6 +293,47 @@ fn format_tag(version: &str, monorepo: Option<&git::MonorepoContext>) -> String
288293 }
289294}
290295
296+ fn ensure_release_on_default_branch ( local_path : & str ) -> Result < ( ) > {
297+ let current_branch =
298+ command:: run_in_optional ( local_path, "git" , & [ "symbolic-ref" , "--short" , "HEAD" ] )
299+ . ok_or_else ( || {
300+ Error :: validation_invalid_argument (
301+ "release" ,
302+ "Refusing to release from detached HEAD" ,
303+ None ,
304+ Some ( vec ! [
305+ "Check out the default branch before releasing" . to_string( )
306+ ] ) ,
307+ )
308+ } ) ?;
309+
310+ let default_branch = command:: run_in_optional (
311+ local_path,
312+ "git" ,
313+ & [ "symbolic-ref" , "--short" , "refs/remotes/origin/HEAD" ] ,
314+ )
315+ . map ( |value| value. trim ( ) . trim_start_matches ( "origin/" ) . to_string ( ) )
316+ . filter ( |value| !value. is_empty ( ) )
317+ . unwrap_or_else ( || "main" . to_string ( ) ) ;
318+
319+ if current_branch == default_branch {
320+ return Ok ( ( ) ) ;
321+ }
322+
323+ Err ( Error :: validation_invalid_argument (
324+ "release" ,
325+ format ! (
326+ "Refusing to release from non-default branch '{}' (default: '{}')" ,
327+ current_branch, default_branch
328+ ) ,
329+ None ,
330+ Some ( vec ! [
331+ format!( "Check out '{}' before releasing" , default_branch) ,
332+ "If you only want a preview, use --dry-run" . to_string( ) ,
333+ ] ) ,
334+ ) )
335+ }
336+
291337fn extract_new_version_from_plan ( plan : & ReleasePlan ) -> Option < String > {
292338 plan. steps
293339 . iter ( )
0 commit comments