@@ -394,6 +394,23 @@ fn resolved_publish_tag_falls_back_to_manifest_tag() {
394394 assert_eq ! ( resolved_publish_tag( & plan, & make_release_options( ) ) , Some ( "next" ) ) ;
395395}
396396
397+ #[ test]
398+ fn resolved_publish_tag_uses_prerelease_channel_from_target_version ( ) {
399+ let mut plan = make_release_plan ( "pkg-a" , & [ ] , & [ ] ) ;
400+ plan. next_version = Version :: parse ( "1.0.1-beta.2" ) . unwrap ( ) ;
401+ plan. publish_tag = Some ( "next" . into ( ) ) ;
402+
403+ assert_eq ! ( resolved_publish_tag( & plan, & make_release_options( ) ) , Some ( "beta" ) ) ;
404+ }
405+
406+ #[ test]
407+ fn resolved_publish_tag_supports_custom_prerelease_channels ( ) {
408+ let mut plan = make_release_plan ( "pkg-a" , & [ ] , & [ ] ) ;
409+ plan. next_version = Version :: parse ( "1.0.1-canary.0" ) . unwrap ( ) ;
410+
411+ assert_eq ! ( resolved_publish_tag( & plan, & make_release_options( ) ) , Some ( "canary" ) ) ;
412+ }
413+
397414#[ test]
398415fn build_manifest_edits_updates_simple_internal_dependency_ranges ( ) {
399416 let mut pkg_a = make_release_plan ( "pkg-a" , & [ ] , & [ ] ) ;
@@ -445,6 +462,24 @@ fn build_manifest_edits_rejects_complex_internal_dependency_ranges() {
445462 assert ! ( error. to_string( ) . contains( "Use `workspace:` or a simple exact/^/~ version" ) ) ;
446463}
447464
465+ #[ test]
466+ fn build_manifest_edits_supports_tag_sourced_zero_versions ( ) {
467+ let mut plan = make_release_plan ( "pkg-a" , & [ ] , & [ ] ) ;
468+ plan. current_version = Version :: parse ( "0.0.0-16aec32" ) . unwrap ( ) ;
469+ plan. next_version = Version :: parse ( "1.2.3" ) . unwrap ( ) ;
470+ plan. manifest . version = "0.0.0" . into ( ) ;
471+ plan. manifest_contents = r#"{
472+ "name": "pkg-a",
473+ "version": "0.0.0"
474+ }
475+ "#
476+ . into ( ) ;
477+
478+ let edits = build_manifest_edits ( & [ plan] ) . unwrap ( ) ;
479+ assert_eq ! ( edits. len( ) , 1 ) ;
480+ assert ! ( edits[ 0 ] . updated_contents. contains( r#""version": "1.2.3""# ) ) ;
481+ }
482+
448483#[ test]
449484fn readiness_report_collects_workspace_and_package_scripts ( ) {
450485 let workspace_manifest: PackageManifest = serde_json:: from_str (
@@ -705,6 +740,64 @@ fn summarize_release_artifacts_counts_manifests_and_changelogs() {
705740 assert_eq ! ( summary. total_file_count( ) , 5 ) ;
706741}
707742
743+ #[ test]
744+ fn apply_manifest_edits_rolls_back_partial_updates ( ) {
745+ let temp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
746+ let workspace_root = AbsolutePathBuf :: new ( temp_dir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ;
747+ let good_path = workspace_root. join ( "packages/pkg-a/package.json" ) ;
748+ std:: fs:: create_dir_all ( good_path. as_path ( ) . parent ( ) . unwrap ( ) ) . unwrap ( ) ;
749+ std:: fs:: write ( & good_path, "{\" version\" :\" 1.0.0\" }" ) . unwrap ( ) ;
750+
751+ let bad_path = workspace_root. join ( "missing/pkg-b/package.json" ) ;
752+ let edits = vec ! [
753+ ManifestEdit {
754+ package: "pkg-a" . into( ) ,
755+ path: good_path. clone( ) ,
756+ original_contents: "{\" version\" :\" 1.0.0\" }" . into( ) ,
757+ updated_contents: "{\" version\" :\" 1.0.1\" }" . into( ) ,
758+ } ,
759+ ManifestEdit {
760+ package: "pkg-b" . into( ) ,
761+ path: bad_path,
762+ original_contents: "{\" version\" :\" 1.0.0\" }" . into( ) ,
763+ updated_contents: "{\" version\" :\" 1.0.1\" }" . into( ) ,
764+ } ,
765+ ] ;
766+
767+ let error = apply_manifest_edits ( & edits, false ) . unwrap_err ( ) ;
768+ assert ! ( error. to_string( ) . contains( "rolled back" ) ) ;
769+ assert_eq ! ( std:: fs:: read_to_string( & good_path) . unwrap( ) , "{\" version\" :\" 1.0.0\" }" ) ;
770+ }
771+
772+ #[ test]
773+ fn apply_manifest_edits_rolls_back_partial_restore_to_updated_state ( ) {
774+ let temp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
775+ let workspace_root = AbsolutePathBuf :: new ( temp_dir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ;
776+ let good_path = workspace_root. join ( "packages/pkg-a/package.json" ) ;
777+ std:: fs:: create_dir_all ( good_path. as_path ( ) . parent ( ) . unwrap ( ) ) . unwrap ( ) ;
778+ std:: fs:: write ( & good_path, "{\" version\" :\" 1.0.1\" }" ) . unwrap ( ) ;
779+
780+ let bad_path = workspace_root. join ( "missing/pkg-b/package.json" ) ;
781+ let edits = vec ! [
782+ ManifestEdit {
783+ package: "pkg-a" . into( ) ,
784+ path: good_path. clone( ) ,
785+ original_contents: "{\" version\" :\" 1.0.0\" }" . into( ) ,
786+ updated_contents: "{\" version\" :\" 1.0.1\" }" . into( ) ,
787+ } ,
788+ ManifestEdit {
789+ package: "pkg-b" . into( ) ,
790+ path: bad_path,
791+ original_contents: "{\" version\" :\" 1.0.0\" }" . into( ) ,
792+ updated_contents: "{\" version\" :\" 1.0.1\" }" . into( ) ,
793+ } ,
794+ ] ;
795+
796+ let error = apply_manifest_edits ( & edits, true ) . unwrap_err ( ) ;
797+ assert ! ( error. to_string( ) . contains( "rolled back" ) ) ;
798+ assert_eq ! ( std:: fs:: read_to_string( & good_path) . unwrap( ) , "{\" version\" :\" 1.0.1\" }" ) ;
799+ }
800+
708801#[ test]
709802fn rollback_release_artifact_edits_restores_and_removes_files ( ) {
710803 let temp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
@@ -923,7 +1016,7 @@ fn invalid_release_tags_are_ignored() {
9231016}
9241017
9251018#[ test]
926- fn repository_release_tags_accept_stable_and_standard_prereleases_only ( ) {
1019+ fn repository_release_tags_accept_stable_and_numbered_prereleases ( ) {
9271020 assert_eq ! (
9281021 parse_repository_release_tag_version_for_tests( "v1.2.3" ) . unwrap( ) . to_string( ) ,
9291022 "1.2.3"
@@ -932,7 +1025,14 @@ fn repository_release_tags_accept_stable_and_standard_prereleases_only() {
9321025 parse_repository_release_tag_version_for_tests( "v1.2.4-alpha.1" ) . unwrap( ) . to_string( ) ,
9331026 "1.2.4-alpha.1"
9341027 ) ;
1028+ assert_eq ! (
1029+ parse_repository_release_tag_version_for_tests( "v1.2.5-canary.0" ) . unwrap( ) . to_string( ) ,
1030+ "1.2.5-canary.0"
1031+ ) ;
9351032 assert ! ( parse_repository_release_tag_version_for_tests( "v0.0.0-16aec32" ) . is_none( ) ) ;
1033+ assert ! (
1034+ parse_repository_release_tag_version_for_tests( "v0.0.0-0bfcc90f.20260209-0731" ) . is_none( )
1035+ ) ;
9361036 assert ! ( parse_repository_release_tag_version_for_tests( "release/pkg-a/v1.0.0" ) . is_none( ) ) ;
9371037}
9381038
0 commit comments