Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prompt user to install the override toolchain if its specified but not installed yet #656

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ci/build-channel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ anyhow = "1"
chrono = "0.4"
clap = { version = "3.2", features = ["cargo", "derive", "env"] }
component = { path = "../../component" }
fuelup = { path = "../../" }
once_cell = "1.17.0"
semver = { version = "1", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
Expand Down
9 changes: 5 additions & 4 deletions ci/build-channel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use anyhow::{bail, Result};
use clap::Parser;
use component::{Component, Components};
use fuelup::constants::GITHUB_API_ORG_URL;
use once_cell::sync::Lazy;
use semver::Version;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -113,8 +114,8 @@ fn get_version(component: &Component) -> Result<Version> {
let mut data = Vec::new();

let url = format!(
"https://api.github.com/repos/FuelLabs/{}/releases/latest",
component.repository_name
"{}{}/releases/latest",
GITHUB_API_ORG_URL, component.repository_name
);

let resp = handle.get(&url).call()?;
Expand Down Expand Up @@ -152,8 +153,8 @@ This could result in incompatibility between forc and fuel-core."
fn write_nightly_document(document: &mut Document, components: Vec<Component>) -> Result<()> {
let mut data = Vec::new();
let nightly_release_url = format!(
"https://api.github.com/repos/FuelLabs/sway-nightly-binaries/releases/tags/nightly-{}",
*TODAY
"{}{}/releases/tags/nightly-{}",
GITHUB_API_ORG_URL, "sway-nightly-binaries", *TODAY
);

let resp = ureq::get(&nightly_release_url).call()?;
Expand Down
1 change: 1 addition & 0 deletions ci/compare-versions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ publish = false
[dependencies]
anyhow = "1"
component = { path = "../../component" }
fuelup = { path = "../../" }
semver = "1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
21 changes: 7 additions & 14 deletions ci/compare-versions/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@

use anyhow::{bail, Result};
use component::Components;
use fuelup::constants::{CHANNEL_LATEST_URL_ACTUAL, GITHUB_API_ORG_URL};
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{io::Read, os::unix::process::CommandExt, process::Command, str::FromStr};
use toml_edit::Document;

const GITHUB_API_REPOS_BASE_URL: &str = "https://api.github.com/repos/FuelLabs/";
const ACTIONS_RUNS: &str = "actions/runs";
const SWAY_REPO: &str = "sway";
const FUEL_CORE_REPO: &str = "fuel-core";
const CHANNEL_FUEL_LATEST_TOML_URL: &str =
"https://raw.githubusercontent.com/FuelLabs/fuelup/gh-pages/channel-fuel-latest.toml";

#[derive(Debug, Serialize, Deserialize)]
struct WorkflowRunApiResponse {
Expand Down Expand Up @@ -61,8 +58,8 @@ const MAX_VERSIONS: usize = 3;

fn get_workflow_runs(repo: &str) -> Result<WorkflowRunApiResponse> {
let github_actions_runs_api_url = format!(
"{}{}/{}?event=release&status=success",
GITHUB_API_REPOS_BASE_URL, repo, ACTIONS_RUNS
"{}{}/actions/runs?event=release&status=success",
GITHUB_API_ORG_URL, repo
);
let handle = ureq::builder().user_agent("fuelup").build();
let resp = handle
Expand All @@ -78,11 +75,7 @@ fn get_workflow_runs(repo: &str) -> Result<WorkflowRunApiResponse> {
}

fn get_latest_release_version(repo: &str) -> Result<Version> {
let url = format!(
"https://api.github.com/repos/FuelLabs/{}/releases/latest",
repo
);

let url = format!("{}{}/releases/latest", GITHUB_API_ORG_URL, repo);
let handle = ureq::builder().user_agent("fuelup").build();
let response: LatestReleaseApiResponse = match handle.get(&url).call() {
Ok(r) => serde_json::from_reader(r.into_reader())?,
Expand Down Expand Up @@ -159,7 +152,7 @@ fn print_selected_versions(forc_versions: &[Version], fuel_core_versions: &[Vers
fn compare_rest() -> Result<()> {
let handle = ureq::builder().user_agent("fuelup").build();

let toml_resp = match handle.get(CHANNEL_FUEL_LATEST_TOML_URL).call() {
let toml_resp = match handle.get(CHANNEL_LATEST_URL_ACTUAL).call() {
Ok(r) => r
.into_string()
.expect("Could not convert channel to string"),
Expand Down Expand Up @@ -231,15 +224,15 @@ fn get_latest_version(repo: &str) -> Result<Version> {
fn compare_compatibility() -> Result<()> {
let handle = ureq::builder().user_agent("fuelup").build();

let toml_resp = match handle.get(CHANNEL_FUEL_LATEST_TOML_URL).call() {
let toml_resp = match handle.get(CHANNEL_LATEST_URL_ACTUAL).call() {
Ok(r) => r
.into_string()
.expect("Could not convert channel to string"),
Err(ureq::Error::Status(404, r)) => {
eprintln!(
"Error {}: Could not download channel-fuel-latest.toml from {}; re-generating channel.",
r.status(),
&CHANNEL_FUEL_LATEST_TOML_URL
&CHANNEL_LATEST_URL_ACTUAL
);

let sway_runs = get_workflow_runs(SWAY_REPO)?;
Expand Down
50 changes: 21 additions & 29 deletions src/channel.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
constants::{
CHANNEL_BETA_1_FILE_NAME, CHANNEL_BETA_2_FILE_NAME, CHANNEL_BETA_3_FILE_NAME,
CHANNEL_BETA_4_FILE_NAME, CHANNEL_BETA_5_FILE_NAME, CHANNEL_DEVNET_FILE_NAME,
CHANNEL_LATEST_FILE_NAME, CHANNEL_NIGHTLY_FILE_NAME, CHANNEL_TESTNET_FILE_NAME,
DATE_FORMAT_URL_FRIENDLY, FUELUP_GH_PAGES,
BETA_CHANNELS, CHANNEL_BETA_1_FILE_NAME, CHANNEL_BETA_2_FILE_NAME,
CHANNEL_BETA_3_FILE_NAME, CHANNEL_BETA_4_FILE_NAME, CHANNEL_BETA_5_FILE_NAME,
CHANNEL_DEVNET_FILE_NAME, CHANNEL_LATEST_FILE_NAME, CHANNEL_NIGHTLY_FILE_NAME,
CHANNEL_TESTNET_FILE_NAME, DATE_FORMAT_URL_FRIENDLY, GITHUB_USER_CONTENT_URL,
},
download::{download, DownloadCfg},
toolchain::{DistToolchainDescription, DistToolchainName},
Expand All @@ -17,21 +17,6 @@ use time::Date;
use toml_edit::de;
use tracing::warn;

pub const LATEST: &str = "latest";
pub const STABLE: &str = "stable";
pub const BETA_1: &str = "beta-1";
pub const BETA_2: &str = "beta-2";
pub const BETA_3: &str = "beta-3";
pub const BETA_4: &str = "beta-4";
pub const BETA_5: &str = "beta-5";
pub const DEVNET: &str = "devnet";
pub const TESTNET: &str = "testnet";
pub const NIGHTLY: &str = "nightly";

pub const CHANNELS: [&str; 9] = [
LATEST, NIGHTLY, BETA_1, BETA_2, BETA_3, BETA_4, BETA_5, DEVNET, TESTNET,
];

#[derive(Debug, Deserialize, Serialize)]
pub struct HashedBinary {
pub url: String,
Expand All @@ -50,14 +35,11 @@ pub struct Package {
pub fuels_version: Option<String>,
}

pub fn is_beta_toolchain(name: &str) -> bool {
name == BETA_1
|| name == BETA_2
|| name == BETA_3
|| name == BETA_4
|| name == BETA_5
|| name == DEVNET
|| name == TESTNET
pub fn is_beta_toolchain(name: &str) -> Option<&str> {
BETA_CHANNELS
.iter()
.find(|&beta_channel| name.starts_with(beta_channel))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this still be name == beta_channel?

.copied()
}

fn format_nightly_url(date: &Date) -> Result<String> {
Expand All @@ -68,7 +50,7 @@ fn format_nightly_url(date: &Date) -> Result<String> {
}

fn construct_channel_url(desc: &DistToolchainDescription) -> Result<String> {
let mut url = FUELUP_GH_PAGES.to_owned();
let mut url = format!("{}{}/gh-pages/", GITHUB_USER_CONTENT_URL, "fuelup");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep FUELUP_GH_PAGES as a constant and refactor this to not use a mutable url.

fn construct_channel_url(desc: &DistToolchainDescription) -> Result<String> {
    let channel_file = match desc.name {
        DistToolchainName::Latest => {
            if let Some(date) = desc.date {
                &format!("channels/latest/channel-fuel-latest-{date}.toml")
            } else {
                CHANNEL_LATEST_FILE_NAME
            }
        }

        DistToolchainName::Nightly => {
            let mut file = "".to_string();
            if let Some(date) = desc.date {
                file.push_str(&format_nightly_url(&date)?);
                file.push('/');
            }
            file.push_str(CHANNEL_NIGHTLY_FILE_NAME);
            &file
        }
        DistToolchainName::Beta1 => CHANNEL_BETA_1_FILE_NAME,
        DistToolchainName::Beta2 => CHANNEL_BETA_2_FILE_NAME,
        DistToolchainName::Beta3 => CHANNEL_BETA_3_FILE_NAME,
        DistToolchainName::Beta4 => CHANNEL_BETA_4_FILE_NAME,
        DistToolchainName::Beta5 => CHANNEL_BETA_5_FILE_NAME,
        DistToolchainName::Devnet => CHANNEL_DEVNET_FILE_NAME,
        DistToolchainName::Testnet => CHANNEL_TESTNET_FILE_NAME,
    };
    let mut url = format!("{}{}/gh-pages/", GITHUB_USER_CONTENT_URL, "fuelup");


    Ok(format!("{FUELUP_GH_PAGES}{channel_file}"))
}

match desc.name {
DistToolchainName::Latest => {
if let Some(date) = desc.date {
Expand Down Expand Up @@ -136,7 +118,7 @@ If this component should be downloadable, try running `fuelup self update` and r
#[cfg(test)]
mod tests {
use super::*;
use crate::{download::DownloadCfg, file::read_file};
use crate::{constants::CHANNELS, download::DownloadCfg, file::read_file};

#[test]
fn channel_from_toml() {
Expand Down Expand Up @@ -246,4 +228,14 @@ mod tests {
assert_eq!(cfgs[1].name, "fuel-core");
assert_eq!(cfgs[1].version, Version::parse("0.9.4").unwrap());
}

#[test]
fn test_all_channels_for_beta() {
for channel in CHANNELS.iter() {
assert_eq!(
is_beta_toolchain(channel).is_some(),
BETA_CHANNELS.contains(channel)
);
}
}
}
4 changes: 2 additions & 2 deletions src/commands/toolchain.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::constants::CHANNELS;
use crate::ops::fuelup_toolchain::{install::install, new::new, uninstall::uninstall};
use crate::target_triple::TargetTriple;
use crate::toolchain::RESERVED_TOOLCHAIN_NAMES;
use anyhow::{bail, Result};
use clap::Parser;

Expand Down Expand Up @@ -45,7 +45,7 @@ fn name_allowed(s: &str) -> Result<String> {
None => s,
};

if RESERVED_TOOLCHAIN_NAMES.contains(&name) {
if CHANNELS.contains(&name) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RESERVED_TOOLCHAIN_NAMES is different from CHANNELS. We want stable to be reserved even though it isn't currently a usable channel.

bail!(
"Cannot use distributable toolchain name '{}' as a custom toolchain name",
s
Expand Down
6 changes: 3 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::constants::CHANNELS;
use crate::fmt::format_toolchain_with_target;
use crate::path::toolchains_dir;
use crate::toolchain::RESERVED_TOOLCHAIN_NAMES;
use anyhow::Result;
use std::{fs, io, path::PathBuf};

Expand All @@ -25,7 +25,7 @@ impl Config {
.filter(|e| e.file_type().map(|f| f.is_dir()).unwrap_or(false))
{
let toolchain = dir_entry.file_name().to_string_lossy().to_string();
if RESERVED_TOOLCHAIN_NAMES
if CHANNELS
Copy link
Member

@sdankel sdankel Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here.

.iter()
.any(|t| toolchain == format_toolchain_with_target(t))
{
Expand Down Expand Up @@ -54,7 +54,7 @@ impl Config {
.map(|e| e.file_name().into_string().ok().unwrap_or_default())
.collect();

for name in RESERVED_TOOLCHAIN_NAMES {
for name in CHANNELS {
let dist_toolchain = format_toolchain_with_target(name);
if installed_toolchains.contains(&dist_toolchain) {
dist_toolchains.push(name.to_string());
Expand Down
59 changes: 56 additions & 3 deletions src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,62 @@
use time::{format_description::FormatItem, macros::format_description};

pub const FUELUP_GH_PAGES: &str = "https://raw.githubusercontent.com/FuelLabs/fuelup/gh-pages/";
pub const FUEL_TOOLCHAIN_TOML_FILE: &str = "fuel-toolchain.toml";
pub const FUELS_VERSION_FILE: &str = "fuels_version";
// Channels

pub const LATEST: &str = "latest";
pub const NIGHTLY: &str = "nightly";
pub const BETA_1: &str = "beta-1";
pub const BETA_2: &str = "beta-2";
pub const BETA_3: &str = "beta-3";
pub const BETA_4: &str = "beta-4";
pub const BETA_5: &str = "beta-5";
pub const DEVNET: &str = "devnet";
pub const TESTNET: &str = "testnet";
// Stable is reserved, although currently unused.
pub const STABLE: &str = "stable";

pub const BETA_CHANNELS: [&str; 7] = [BETA_1, BETA_2, BETA_3, BETA_4, BETA_5, DEVNET, TESTNET];

#[allow(clippy::indexing_slicing)]
pub const fn generate_all_channels<const N: usize>() -> [&'static str; N] {
let mut channels = [""; N];

channels[0] = LATEST;
channels[1] = NIGHTLY;

let mut i = 0;

while i < BETA_CHANNELS.len() {
channels[2 + i] = BETA_CHANNELS[i];
i += 1;
}

channels
}

pub const CHANNELS: [&str; 9] = generate_all_channels::<9>();

// URLs

pub const GITHUB_API_ORG_URL: &str = "https://api.github.com/repos/FuelLabs/";
pub const GITHUB_USER_CONTENT_URL: &str = "https://raw.githubusercontent.com/FuelLabs/";

// NOTE: Although this variable is named "LATEST", it needs to point to
// "testnet" until mainnet has launched. Once launched, we can then merge this
// variable with the `CHANNEL_LATEST_URL_ACTUAL` variable
pub const CHANNEL_LATEST_URL: &str =
"https://raw.githubusercontent.com/FuelLabs/fuelup/gh-pages/channel-fuel-testnet.toml";

// We need to point to the latest URL but we can't use `CHANNEL_LATEST_URL`
// until mainnet has launched (as `CHANNEL_LATEST_URL` currently points to
// testnet). So we dupilcate here for now and we can cleanup sometime later
pub const CHANNEL_LATEST_URL_ACTUAL: &str =
"https://raw.githubusercontent.com/FuelLabs/fuelup/gh-pages/channel-fuel-latest.toml";

// Filenames

pub const FUEL_TOOLCHAIN_TOML_FILE: &str = "fuel-toolchain.toml";
pub const FUELS_VERSION_FILE: &str = "fuels_version";

pub const CHANNEL_LATEST_FILE_NAME: &str = "channel-fuel-testnet.toml";
pub const CHANNEL_NIGHTLY_FILE_NAME: &str = "channel-fuel-nightly.toml";
pub const CHANNEL_BETA_1_FILE_NAME: &str = "channel-fuel-beta-1.toml";
Expand All @@ -16,5 +67,7 @@ pub const CHANNEL_BETA_5_FILE_NAME: &str = "channel-fuel-beta-5.toml";
pub const CHANNEL_DEVNET_FILE_NAME: &str = "channel-fuel-devnet.toml";
pub const CHANNEL_TESTNET_FILE_NAME: &str = "channel-fuel-testnet.toml";

// Misc

pub const DATE_FORMAT: &[FormatItem] = format_description!("[year]-[month]-[day]");
pub const DATE_FORMAT_URL_FRIENDLY: &[FormatItem] = format_description!("[year]/[month]/[day]");
21 changes: 12 additions & 9 deletions src/download.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
channel::{Channel, Package},
constants::CHANNEL_LATEST_URL,
constants::{CHANNEL_LATEST_URL, GITHUB_API_ORG_URL, GITHUB_USER_CONTENT_URL},
target_triple::TargetTriple,
toolchain::DistToolchainDescription,
};
Expand Down Expand Up @@ -128,9 +128,8 @@ pub fn get_latest_version(name: &str) -> Result<Version> {
let handle = build_agent()?;
let mut data = Vec::new();
if name == FUELUP {
const FUELUP_RELEASES_API_URL: &str =
"https://api.github.com/repos/FuelLabs/fuelup/releases/latest";
let resp = handle.get(FUELUP_RELEASES_API_URL).call()?;
let fuelup_latest_url = format!("{}{}/releases/latest", GITHUB_API_ORG_URL, FUELUP);
let resp = handle.get(&fuelup_latest_url).call()?;
resp.into_reader().read_to_end(&mut data)?;
let response: LatestReleaseApiResponse =
serde_json::from_str(&String::from_utf8_lossy(&data))?;
Expand Down Expand Up @@ -397,13 +396,13 @@ fn fuels_version_from_toml(toml: toml_edit::Document) -> Result<String> {
pub fn fetch_fuels_version(cfg: &DownloadCfg) -> Result<String> {
let url = match cfg.name.as_str() {
"forc" => format!(
"https://raw.githubusercontent.com/FuelLabs/sway/v{}/test/src/sdk-harness/Cargo.toml",
cfg.version
"{}{}/v{}/test/src/sdk-harness/Cargo.toml",
GITHUB_USER_CONTENT_URL, "sway", cfg.version
),
"forc-wallet" => {
format!(
"https://raw.githubusercontent.com/FuelLabs/forc-wallet/v{}/Cargo.toml",
cfg.version
"{}{}/v{}/Cargo.toml",
GITHUB_USER_CONTENT_URL, "forc-wallet", cfg.version
)
}
_ => bail!("invalid component to fetch fuels version for"),
Expand Down Expand Up @@ -562,7 +561,11 @@ mod tests {
fn test_agent() -> anyhow::Result<()> {
// this test case is used to illustrate the bug of ureq that sometimes doesn't return "Content-Length" header
let handle = build_agent()?;
let response = handle.get("https://raw.githubusercontent.com/FuelLabs/fuelup/gh-pages/channel-fuel-beta-4.toml").call()?;
let url = format!(
"{}{}/gh-pages/channel-fuel-beta-4.toml",
GITHUB_USER_CONTENT_URL, "fuelup"
);
let response = handle.get(&url).call()?;
assert!(response.header("Content-Length").is_none());
Ok(())
}
Expand Down
Loading
Loading