@@ -4617,7 +4617,7 @@ impl CommandLineStep for RemoteTestClientTests {
46174617}
46184618
46194619fn check_if_cargo_semver_checks_is_installed ( builder : & Builder < ' _ > ) -> bool {
4620- command ( "cargo" )
4620+ command ( & builder . initial_cargo )
46214621 . allow_failure ( )
46224622 . arg ( "semver-checks" )
46234623 . arg ( "--version" )
@@ -4630,7 +4630,13 @@ fn check_if_cargo_semver_checks_is_installed(builder: &Builder<'_>) -> bool {
46304630/// Run cargo-semver-checks on the standard library and compare its API
46314631/// versus a previous baseline, using rustdoc JSON data.
46324632///
4633+ /// The baseline commit can be configured using `rust.stdlib-semver-baseline`.
4634+ /// If unset, the first upstream parent commit will be used.
4635+ ///
46334636/// Fails if a semver-breaking change is detected.
4637+ ///
4638+ /// If you want to allow a breaking change in a given PR, or if cargo-semver-checks has a false
4639+ /// positive, modify the `src/bootstrap/stdlib-semver-check-stamp` file.
46344640#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
46354641pub struct StdSemverCheck {
46364642 build_compiler : Compiler ,
@@ -4651,19 +4657,22 @@ impl CommandLineStep for StdSemverCheck {
46514657 panic ! ( "cargo-semver-checks was not found, please install it" ) ;
46524658 }
46534659
4654- let baseline_commit = match get_closest_upstream_commit (
4655- Some ( & run. builder . config . src ) ,
4656- & run. builder . config . git_config ( ) ,
4657- run. builder . config . ci_env ,
4658- ) {
4659- Ok ( Some ( commit) ) => commit,
4660- Ok ( None ) => {
4661- panic ! ( "No baseline parent commit found for std-semver-check" ) ;
4662- }
4663- Err ( error) => {
4664- panic ! ( "Cannot get baseline parent commit for std-semver-check: {error:?}" ) ;
4665- }
4666- } ;
4660+ let baseline_commit =
4661+ run. builder . config . stdlib_semver_baseline . clone ( ) . unwrap_or_else ( || {
4662+ match get_closest_upstream_commit (
4663+ Some ( & run. builder . config . src ) ,
4664+ & run. builder . config . git_config ( ) ,
4665+ run. builder . config . ci_env ,
4666+ ) {
4667+ Ok ( Some ( commit) ) => commit,
4668+ Ok ( None ) => {
4669+ panic ! ( "No baseline parent commit found for std-semver-check" ) ;
4670+ }
4671+ Err ( error) => {
4672+ panic ! ( "Cannot get baseline parent commit for std-semver-check: {error:?}" ) ;
4673+ }
4674+ }
4675+ } ) ;
46674676
46684677 run. builder . ensure ( Self {
46694678 build_compiler : run. builder . compiler_for_std ( run. builder . top_stage ) ,
@@ -4673,6 +4682,15 @@ impl CommandLineStep for StdSemverCheck {
46734682 }
46744683
46754684 fn run ( self , builder : & Builder < ' _ > ) {
4685+ const STDLIB_SEMVER_CHECK_STAMP_PATH : & str = "src/bootstrap/stdlib-semver-check-stamp" ;
4686+
4687+ if builder. config . ci_env . is_running_in_ci ( )
4688+ && builder. config . has_changes_from_upstream ( & [ STDLIB_SEMVER_CHECK_STAMP_PATH ] )
4689+ {
4690+ builder. info ( & format ! ( "Skipping stdlib semver check, because {STDLIB_SEMVER_CHECK_STAMP_PATH} was modified." ) ) ;
4691+ return ;
4692+ }
4693+
46764694 let Some ( docs_dir) = builder. config . download_std_json_docs ( self . target , & self . commit )
46774695 else {
46784696 return ;
@@ -4687,7 +4705,7 @@ impl CommandLineStep for StdSemverCheck {
46874705
46884706 for library in [ "core" , "alloc" , "std" ] {
46894707 println ! ( "Checking semver compatibility of {library}" ) ;
4690- let mut cmd = command ( "cargo" ) ;
4708+ let mut cmd = command ( & builder . initial_cargo ) ;
46914709 cmd. arg ( "semver-checks" )
46924710 . arg ( "-Z" )
46934711 . arg ( "unstable-options" )
@@ -4698,7 +4716,41 @@ impl CommandLineStep for StdSemverCheck {
46984716 . arg ( directory. join ( format ! ( "{library}.json" ) ) )
46994717 . arg ( "--baseline-rustdoc" )
47004718 . arg ( baseline_dir. join ( format ! ( "{library}.json" ) ) ) ;
4701- cmd. run ( builder) ;
4719+
4720+ // We use run_capture to get the exit status
4721+ let res = cmd. allow_failure ( ) . run_capture ( builder) ;
4722+ match res. status ( ) {
4723+ Some ( status) if status. success ( ) => {
4724+ println ! ( "{}\n {}" , res. stdout( ) , res. stderr( ) ) ;
4725+ }
4726+ // 101 marks that csc was unable to parse the JSON data, but it did not fail with a
4727+ // semver breakage.
4728+ Some ( status) if status. code ( ) == Some ( 101 ) => {
4729+ eprintln ! (
4730+ "cargo-semver-checks was unable to process {library} (this is not a fatal error)\n {}\n {}" ,
4731+ res. stderr( ) ,
4732+ res. stdout( )
4733+ ) ;
4734+ }
4735+ // 100 marks semver breakage
4736+ Some ( status) if status. code ( ) == Some ( 100 ) => {
4737+ let error = format ! (
4738+ "cargo-semver-checks found semver breakage in {library}\n {}\n {}" ,
4739+ res. stderr( ) ,
4740+ res. stdout( )
4741+ ) ;
4742+ if builder. fail_fast {
4743+ eprintln ! ( "{error}" , ) ;
4744+ exit ! ( 1 ) ;
4745+ } else {
4746+ builder. config . exec_ctx ( ) . add_to_delay_failure ( error) ;
4747+ }
4748+ }
4749+ _ => {
4750+ eprintln ! ( "cargo-semver-checks failed.\n {}\n {}" , res. stderr( ) , res. stdout( ) ) ;
4751+ exit ! ( 1 ) ;
4752+ }
4753+ }
47024754 }
47034755 }
47044756}
0 commit comments