Repository: denoland/deno
Pull request: feat(upgrade): print info links for Deno 2 RC releases

In addition to printing a blog post information (if it's available), this will also
print a link to migration guide and the bug tracker.

Changed files:
filename: cli/tools/upgrade.rs
patch: @@ -226,15 +226,70 @@ impl<
   }
 }
 
-fn get_minor_version(version: &str) -> &str {
-  version.rsplitn(2, '.').collect::<Vec<&str>>()[1]
+fn get_minor_version_blog_post_url(semver: &Version) -> String {
+  format!("https://deno.com/blog/v{}.{}", semver.major, semver.minor)
 }
 
-fn print_release_notes(current_version: &str, new_version: &str) {
-  // TODO(bartlomieju): we might want to reconsider this one for RC releases.
-  // TODO(bartlomieju): also maybe just parse using `Version::standard` instead
-  // of using `get_minor_version`?
-  if get_minor_version(current_version) == get_minor_version(new_version) {
+fn get_rc_version_blog_post_url(semver: &Version) -> String {
+  format!(
+    "https://deno.com/blog/v{}.{}-rc-{}",
+    semver.major, semver.minor, semver.pre[1]
+  )
+}
+
+async fn print_release_notes(
+  current_version: &str,
+  new_version: &str,
+  client: &HttpClient,
+) {
+  let Ok(current_semver) = Version::parse_standard(current_version) else {
+    return;
+  };
+  let Ok(new_semver) = Version::parse_standard(new_version) else {
+    return;
+  };
+
+  let is_switching_from_deno1_to_deno2 =
+    new_semver.major == 2 && current_semver.major == 1;
+  let is_deno_2_rc = new_semver.major == 2
+    && new_semver.minor == 0
+    && new_semver.patch == 0
+    && new_semver.pre.first() == Some(&"rc".to_string());
+
+  if is_deno_2_rc || is_switching_from_deno1_to_deno2 {
+    log::info!(
+      "{}\n\n  {}\n",
+      colors::gray("Migration guide:"),
+      colors::bold(
+        "https://docs.deno.com/runtime/manual/advanced/migrate_deprecations"
+      )
+    );
+  }
+
+  if is_deno_2_rc {
+    log::info!(
+      "{}\n\n  {}\n",
+      colors::gray("If you find a bug, please report to:"),
+      colors::bold("https://github.com/denoland/deno/issues/new")
+    );
+
+    // Check if there's blog post entry for this release
+    let blog_url_str = get_rc_version_blog_post_url(&new_semver);
+    let blog_url = Url::parse(&blog_url_str).unwrap();
+    if client.download(blog_url).await.is_ok() {
+      log::info!(
+        "{}\n\n  {}\n",
+        colors::gray("Blog post:"),
+        colors::bold(blog_url_str)
+      );
+    }
+    return;
+  }
+
+  let should_print = current_semver.major != new_semver.major
+    || current_semver.minor != new_semver.minor;
+
+  if !should_print {
     return;
   }
 
@@ -249,10 +304,7 @@ fn print_release_notes(current_version: &str, new_version: &str) {
   log::info!(
     "{}\n\n  {}\n",
     colors::gray("Blog post:"),
-    colors::bold(format!(
-      "https://deno.com/blog/v{}",
-      get_minor_version(new_version)
-    ))
+    colors::bold(get_minor_version_blog_post_url(&new_semver))
   );
 }
 
@@ -512,7 +564,9 @@ pub async fn upgrade(
       print_release_notes(
         version::DENO_VERSION_INFO.deno,
         &selected_version_to_upgrade.version_or_hash,
-      );
+        &client,
+      )
+      .await;
     }
     drop(temp_dir);
     return Ok(());
@@ -540,7 +594,9 @@ pub async fn upgrade(
     print_release_notes(
       version::DENO_VERSION_INFO.deno,
       &selected_version_to_upgrade.version_or_hash,
-    );
+      &client,
+    )
+    .await;
   }
 
   drop(temp_dir); // delete the temp dir
@@ -1692,4 +1748,31 @@ mod test {
       );
     }
   }
+
+  #[test]
+  fn blog_post_links() {
+    let version = Version::parse_standard("1.46.0").unwrap();
+    assert_eq!(
+      get_minor_version_blog_post_url(&version),
+      "https://deno.com/blog/v1.46"
+    );
+
+    let version = Version::parse_standard("2.1.1").unwrap();
+    assert_eq!(
+      get_minor_version_blog_post_url(&version),
+      "https://deno.com/blog/v2.1"
+    );
+
+    let version = Version::parse_standard("2.0.0-rc.0").unwrap();
+    assert_eq!(
+      get_rc_version_blog_post_url(&version),
+      "https://deno.com/blog/v2.0-rc-0"
+    );
+
+    let version = Version::parse_standard("2.0.0-rc.2").unwrap();
+    assert_eq!(
+      get_rc_version_blog_post_url(&version),
+      "https://deno.com/blog/v2.0-rc-2"
+    );
+  }
 }