1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

refactor(upgrade): make fetching latest version async (#24919)

Additionally some renames in preparation to support "LTS" and "RC"
channels.
This commit is contained in:
Bartek Iwańczuk 2024-08-07 09:29:23 +01:00 committed by GitHub
parent 04473c04ed
commit d1b2a9822d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -87,17 +87,19 @@ enum UpgradeCheckKind {
#[async_trait(?Send)] #[async_trait(?Send)]
trait VersionProvider: Clone { trait VersionProvider: Clone {
fn is_canary(&self) -> bool; /// Fetch latest available version for the given release channel
async fn latest_version(&self) -> Result<String, AnyError>; async fn latest_version(
&self,
release_channel: ReleaseChannel,
) -> Result<String, AnyError>;
// TODO(bartlomieju): what this one actually returns?
fn current_version(&self) -> Cow<str>; fn current_version(&self) -> Cow<str>;
fn release_kind(&self) -> UpgradeReleaseKind { // TODO(bartlomieju): update to handle `Lts` and `Rc` channels
if self.is_canary() { async fn get_current_exe_release_channel(
UpgradeReleaseKind::Canary &self,
} else { ) -> Result<ReleaseChannel, AnyError>;
UpgradeReleaseKind::Stable
}
}
} }
#[derive(Clone)] #[derive(Clone)]
@ -120,14 +122,13 @@ impl RealVersionProvider {
#[async_trait(?Send)] #[async_trait(?Send)]
impl VersionProvider for RealVersionProvider { impl VersionProvider for RealVersionProvider {
fn is_canary(&self) -> bool { async fn latest_version(
version::is_canary() &self,
} release_channel: ReleaseChannel,
) -> Result<String, AnyError> {
async fn latest_version(&self) -> Result<String, AnyError> { fetch_latest_version(
get_latest_version(
&self.http_client_provider.get_or_create()?, &self.http_client_provider.get_or_create()?,
self.release_kind(), release_channel,
self.check_kind, self.check_kind,
) )
.await .await
@ -136,6 +137,17 @@ impl VersionProvider for RealVersionProvider {
fn current_version(&self) -> Cow<str> { fn current_version(&self) -> Cow<str> {
Cow::Borrowed(version::release_version_or_canary_commit_hash()) Cow::Borrowed(version::release_version_or_canary_commit_hash())
} }
// TODO(bartlomieju): update to handle `Lts` and `Rc` channels
async fn get_current_exe_release_channel(
&self,
) -> Result<ReleaseChannel, AnyError> {
if version::is_canary() {
Ok(ReleaseChannel::Canary)
} else {
Ok(ReleaseChannel::Stable)
}
}
} }
struct UpdateChecker< struct UpdateChecker<
@ -301,6 +313,7 @@ pub fn check_for_upgrades(
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct LspVersionUpgradeInfo { pub struct LspVersionUpgradeInfo {
pub latest_version: String, pub latest_version: String,
// TODO(bartlomieju): use `ReleaseChannel` instead
pub is_canary: bool, pub is_canary: bool,
} }
@ -319,27 +332,40 @@ pub async fn check_for_upgrades_for_lsp(
async fn check_for_upgrades_for_lsp_with_provider( async fn check_for_upgrades_for_lsp_with_provider(
version_provider: &impl VersionProvider, version_provider: &impl VersionProvider,
) -> Result<Option<LspVersionUpgradeInfo>, AnyError> { ) -> Result<Option<LspVersionUpgradeInfo>, AnyError> {
let latest_version = version_provider.latest_version().await?; let release_channel =
version_provider.get_current_exe_release_channel().await?;
let latest_version = version_provider.latest_version(release_channel).await?;
let current_version = version_provider.current_version(); let current_version = version_provider.current_version();
// Nothing to upgrade
if current_version == latest_version { if current_version == latest_version {
Ok(None) // nothing to upgrade return Ok(None);
} else if version_provider.is_canary() { }
Ok(Some(LspVersionUpgradeInfo {
latest_version, match release_channel {
is_canary: true, ReleaseChannel::Stable => {
})) if let Ok(current) = Version::parse_standard(&current_version) {
} else { if let Ok(latest) = Version::parse_standard(&latest_version) {
if let Ok(current) = Version::parse_standard(&current_version) { if current >= latest {
if let Ok(latest) = Version::parse_standard(&latest_version) { return Ok(None); // nothing to upgrade
if current >= latest { }
return Ok(None); // nothing to upgrade
} }
} }
Ok(Some(LspVersionUpgradeInfo {
latest_version,
is_canary: false,
}))
} }
Ok(Some(LspVersionUpgradeInfo {
ReleaseChannel::Canary => Ok(Some(LspVersionUpgradeInfo {
latest_version, latest_version,
is_canary: false, is_canary: true,
})) })),
// TODO(bartlomieju)
ReleaseChannel::Lts => unreachable!(),
// TODO(bartlomieju)
ReleaseChannel::Rc => unreachable!(),
} }
} }
@ -351,9 +377,15 @@ async fn fetch_and_store_latest_version<
version_provider: &TVersionProvider, version_provider: &TVersionProvider,
) { ) {
// Fetch latest version or commit hash from server. // Fetch latest version or commit hash from server.
let latest_version = match version_provider.latest_version().await { let Ok(release_channel) =
Ok(latest_version) => latest_version, version_provider.get_current_exe_release_channel().await
Err(_) => return, else {
return;
};
let Ok(latest_version) =
version_provider.latest_version(release_channel).await
else {
return;
}; };
env.write_check_file( env.write_check_file(
@ -446,17 +478,20 @@ pub async fn upgrade(
passed_version passed_version
} }
None => { None => {
let release_kind = if upgrade_flags.canary { let release_channel = if upgrade_flags.canary {
log::info!("Looking up latest canary version"); log::info!("Looking up latest canary version");
UpgradeReleaseKind::Canary ReleaseChannel::Canary
} else { } else {
log::info!("Looking up latest version"); log::info!("Looking up latest version");
UpgradeReleaseKind::Stable ReleaseChannel::Stable
}; };
let latest_version = let latest_version = fetch_latest_version(
get_latest_version(&client, release_kind, UpgradeCheckKind::Execution) &client,
.await?; release_channel,
UpgradeCheckKind::Execution,
)
.await?;
let current_is_most_recent = if upgrade_flags.canary { let current_is_most_recent = if upgrade_flags.canary {
let latest_hash = &latest_version; let latest_hash = &latest_version;
@ -565,42 +600,55 @@ pub async fn upgrade(
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum UpgradeReleaseKind { enum ReleaseChannel {
/// Stable version, eg. 1.45.4, 2.0.0, 2.1.0
Stable, Stable,
/// Pointing to a git hash
Canary, Canary,
/// Long term support release
#[allow(unused)]
Lts,
/// Release candidate
#[allow(unused)]
Rc,
} }
async fn get_latest_version( async fn fetch_latest_version(
client: &HttpClient, client: &HttpClient,
release_kind: UpgradeReleaseKind, release_channel: ReleaseChannel,
check_kind: UpgradeCheckKind, check_kind: UpgradeCheckKind,
) -> Result<String, AnyError> { ) -> Result<String, AnyError> {
let url = get_url(release_kind, env!("TARGET"), check_kind); let url = get_latest_version_url(release_channel, env!("TARGET"), check_kind);
let text = client.download_text(url.parse()?).await?; let text = client.download_text(url.parse()?).await?;
Ok(normalize_version_from_server(release_kind, &text)) Ok(normalize_version_from_server(release_channel, &text))
} }
fn normalize_version_from_server( fn normalize_version_from_server(
release_kind: UpgradeReleaseKind, release_channel: ReleaseChannel,
text: &str, text: &str,
) -> String { ) -> String {
let text = text.trim(); let text = text.trim();
match release_kind { match release_channel {
UpgradeReleaseKind::Stable => text.trim_start_matches('v').to_string(), ReleaseChannel::Stable => text.trim_start_matches('v').to_string(),
UpgradeReleaseKind::Canary => text.to_string(), ReleaseChannel::Canary => text.to_string(),
_ => unreachable!(),
} }
} }
fn get_url( fn get_latest_version_url(
release_kind: UpgradeReleaseKind, release_channel: ReleaseChannel,
target_tuple: &str, target_tuple: &str,
check_kind: UpgradeCheckKind, check_kind: UpgradeCheckKind,
) -> String { ) -> String {
let file_name = match release_kind { let file_name = match release_channel {
UpgradeReleaseKind::Stable => Cow::Borrowed("release-latest.txt"), ReleaseChannel::Stable => Cow::Borrowed("release-latest.txt"),
UpgradeReleaseKind::Canary => { ReleaseChannel::Canary => {
Cow::Owned(format!("canary-{target_tuple}-latest.txt")) Cow::Owned(format!("canary-{target_tuple}-latest.txt"))
} }
_ => unreachable!(),
}; };
let query_param = match check_kind { let query_param = match check_kind {
UpgradeCheckKind::Execution => "", UpgradeCheckKind::Execution => "",
@ -828,11 +876,11 @@ mod test {
#[async_trait(?Send)] #[async_trait(?Send)]
impl VersionProvider for TestUpdateCheckerEnvironment { impl VersionProvider for TestUpdateCheckerEnvironment {
fn is_canary(&self) -> bool { // TODO(bartlomieju): update to handle `Lts` and `Rc` channels
*self.is_canary.borrow() async fn latest_version(
} &self,
_release_channel: ReleaseChannel,
async fn latest_version(&self) -> Result<String, AnyError> { ) -> Result<String, AnyError> {
match self.latest_version.borrow().clone() { match self.latest_version.borrow().clone() {
Ok(result) => Ok(result), Ok(result) => Ok(result),
Err(err) => bail!("{}", err), Err(err) => bail!("{}", err),
@ -842,6 +890,17 @@ mod test {
fn current_version(&self) -> Cow<str> { fn current_version(&self) -> Cow<str> {
Cow::Owned(self.current_version.borrow().clone()) Cow::Owned(self.current_version.borrow().clone())
} }
// TODO(bartlomieju): update to handle `Lts` and `Rc` channels
async fn get_current_exe_release_channel(
&self,
) -> Result<ReleaseChannel, AnyError> {
if *self.is_canary.borrow() {
Ok(ReleaseChannel::Canary)
} else {
Ok(ReleaseChannel::Stable)
}
}
} }
impl UpdateCheckerEnvironment for TestUpdateCheckerEnvironment { impl UpdateCheckerEnvironment for TestUpdateCheckerEnvironment {
@ -967,66 +1026,66 @@ mod test {
} }
#[test] #[test]
fn test_get_url() { fn test_get_latest_version_url() {
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Canary, ReleaseChannel::Canary,
"aarch64-apple-darwin", "aarch64-apple-darwin",
UpgradeCheckKind::Execution UpgradeCheckKind::Execution
), ),
"https://dl.deno.land/canary-aarch64-apple-darwin-latest.txt" "https://dl.deno.land/canary-aarch64-apple-darwin-latest.txt"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Canary, ReleaseChannel::Canary,
"aarch64-apple-darwin", "aarch64-apple-darwin",
UpgradeCheckKind::Lsp UpgradeCheckKind::Lsp
), ),
"https://dl.deno.land/canary-aarch64-apple-darwin-latest.txt?lsp" "https://dl.deno.land/canary-aarch64-apple-darwin-latest.txt?lsp"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Canary, ReleaseChannel::Canary,
"x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc",
UpgradeCheckKind::Execution UpgradeCheckKind::Execution
), ),
"https://dl.deno.land/canary-x86_64-pc-windows-msvc-latest.txt" "https://dl.deno.land/canary-x86_64-pc-windows-msvc-latest.txt"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Canary, ReleaseChannel::Canary,
"x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc",
UpgradeCheckKind::Lsp UpgradeCheckKind::Lsp
), ),
"https://dl.deno.land/canary-x86_64-pc-windows-msvc-latest.txt?lsp" "https://dl.deno.land/canary-x86_64-pc-windows-msvc-latest.txt?lsp"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Stable, ReleaseChannel::Stable,
"aarch64-apple-darwin", "aarch64-apple-darwin",
UpgradeCheckKind::Execution UpgradeCheckKind::Execution
), ),
"https://dl.deno.land/release-latest.txt" "https://dl.deno.land/release-latest.txt"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Stable, ReleaseChannel::Stable,
"aarch64-apple-darwin", "aarch64-apple-darwin",
UpgradeCheckKind::Lsp UpgradeCheckKind::Lsp
), ),
"https://dl.deno.land/release-latest.txt?lsp" "https://dl.deno.land/release-latest.txt?lsp"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Stable, ReleaseChannel::Stable,
"x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc",
UpgradeCheckKind::Execution UpgradeCheckKind::Execution
), ),
"https://dl.deno.land/release-latest.txt" "https://dl.deno.land/release-latest.txt"
); );
assert_eq!( assert_eq!(
get_url( get_latest_version_url(
UpgradeReleaseKind::Stable, ReleaseChannel::Stable,
"x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc",
UpgradeCheckKind::Lsp UpgradeCheckKind::Lsp
), ),
@ -1038,13 +1097,13 @@ mod test {
fn test_normalize_version_server() { fn test_normalize_version_server() {
// should strip v for stable // should strip v for stable
assert_eq!( assert_eq!(
normalize_version_from_server(UpgradeReleaseKind::Stable, "v1.0.0"), normalize_version_from_server(ReleaseChannel::Stable, "v1.0.0"),
"1.0.0" "1.0.0"
); );
// should not replace v after start // should not replace v after start
assert_eq!( assert_eq!(
normalize_version_from_server( normalize_version_from_server(
UpgradeReleaseKind::Stable, ReleaseChannel::Stable,
" v1.0.0-test-v\n\n " " v1.0.0-test-v\n\n "
), ),
"1.0.0-test-v" "1.0.0-test-v"
@ -1052,7 +1111,7 @@ mod test {
// should not strip v for canary // should not strip v for canary
assert_eq!( assert_eq!(
normalize_version_from_server( normalize_version_from_server(
UpgradeReleaseKind::Canary, ReleaseChannel::Canary,
" v1452345asdf \n\n " " v1452345asdf \n\n "
), ),
"v1452345asdf" "v1452345asdf"