Skip to content
Open
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
41 changes: 41 additions & 0 deletions fuelup-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ main() {
add_path_message
fi

# Prompt for telemetry
prompt_telemetry

return "$_retval"
}

Expand Down Expand Up @@ -182,6 +185,44 @@ fish_add_path ~/.fuelup/bin
EOF
}

prompt_telemetry() {
# Skip if the file already exists (user might have already been prompted)
if [ -f "$FUELUP_DIR/.telemetry_opt_in" ]; then
return
fi

# Check if running in a non-interactive environment (CI/CD, Docker, etc.)
# If no terminal is available, default to telemetry disabled
if [ ! -t 0 ] && [ ! -t 1 ]; then
printf "0" >"$FUELUP_DIR/.telemetry_opt_in"
return
fi

cat 1>&2 <<EOF

Telemetry helps improve the Fuel toolchain by collecting anonymous usage data.
You can change this setting at any time by running:
fuelup telemetry enable # to enable telemetry
fuelup telemetry disable # to disable telemetry

Would you like to enable telemetry? (Y/n)
EOF

# Default to yes if user just presses enter
read -r answer </dev/tty
case $answer in
"n" | "N" | "no" | "No" | "NO")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Shell script missing case pattern for "nO" input

Low Severity

The case statement handling the telemetry prompt response explicitly enumerates case variations of "no" ("n" | "N" | "no" | "No" | "NO") but is missing "nO". If a user types nO, it falls through to the default * case and enables telemetry, contrary to the user's intent to decline. The Rust implementation handles this correctly by converting input to lowercase before matching.

Fix in Cursor Fix in Web

printf "0" >"$FUELUP_DIR/.telemetry_opt_in"
printf "\nTelemetry disabled. You can enable it later with 'fuelup telemetry enable'.\n\n"
;;
*)
printf "1" >"$FUELUP_DIR/.telemetry_opt_in"
printf "\nTelemetry enabled. Thank you for helping improve the Fuel toolchain!\n"
printf "You can disable it at any time with 'fuelup telemetry disable'.\n\n"
;;
esac
}
Comment thread
cursor[bot] marked this conversation as resolved.

get_architecture() {
local _ostype _cputype
_ostype="$(uname -s)"
Expand Down
1 change: 1 addition & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ pub mod completions;
pub mod component;
pub mod default;
pub mod fuelup;
pub mod telemetry;
pub mod toolchain;
pub mod upgrade;
87 changes: 87 additions & 0 deletions src/commands/telemetry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use crate::fmt::{bold, colored_bold};
use crate::telemetry::{get_telemetry_status, set_telemetry_status, TelemetryStatus};
use anyhow::Result;
use clap::Parser;
use tracing::info;

#[derive(Debug, Parser)]
pub enum TelemetryCommand {
/// Show the current telemetry status
Status,
/// Enable telemetry (opt-in)
Enable,
/// Disable telemetry (opt-out)
Disable,
}

pub fn exec(command: TelemetryCommand) -> Result<()> {
match command {
TelemetryCommand::Status => show_status(),
TelemetryCommand::Enable => enable(),
TelemetryCommand::Disable => disable(),
}
}

fn show_status() -> Result<()> {
match get_telemetry_status()? {
Some(TelemetryStatus::Enabled) => {
info!(
"Telemetry is {}",
colored_bold(ansiterm::Color::Green, "enabled")
);
info!("");
info!("Telemetry helps improve the Fuel toolchain by collecting usage data.");
info!("To disable, run: {}", bold("fuelup telemetry disable"));
}
Some(TelemetryStatus::Disabled) => {
info!(
"Telemetry is {}",
colored_bold(ansiterm::Color::Yellow, "disabled")
);
info!("");
info!("Telemetry is currently disabled. No usage data will be collected.");
info!("To enable, run: {}", bold("fuelup telemetry enable"));
}
None => {
info!(
"Telemetry status is {}",
colored_bold(ansiterm::Color::Yellow, "not set")
);
info!("");
info!("Telemetry preference has not been set. It will be disabled by default.");
info!("To enable, run: {}", bold("fuelup telemetry enable"));
info!("To disable, run: {}", bold("fuelup telemetry disable"));
}
}
Ok(())
}

fn enable() -> Result<()> {
set_telemetry_status(TelemetryStatus::Enabled)?;
info!(
"Telemetry has been {}",
colored_bold(ansiterm::Color::Green, "enabled")
);
info!("");
info!("Thank you for helping improve the Fuel toolchain!");
info!(
"To disable at any time, run: {}",
bold("fuelup telemetry disable")
);
Ok(())
}

fn disable() -> Result<()> {
set_telemetry_status(TelemetryStatus::Disabled)?;
info!(
"Telemetry has been {}",
colored_bold(ansiterm::Color::Yellow, "disabled")
);
info!("");
info!("Telemetry will no longer collect usage data.");
info!(
"To enable at any time, run: {}",
bold("fuelup telemetry enable")
);
Ok(())
}
5 changes: 5 additions & 0 deletions src/fuelup_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::commands::{
component::{self, ComponentCommand},
default::{self, DefaultCommand},
fuelup::{self, FuelupCommand},
telemetry::{self, TelemetryCommand},
toolchain::{self, ToolchainCommand},
upgrade::{self, UpgradeCommand},
};
Expand Down Expand Up @@ -32,6 +33,9 @@ enum Commands {
/// Manage your fuelup installation.
#[clap(name = "self", subcommand)]
Fuelup(FuelupCommand),
/// Manage telemetry settings
#[clap(subcommand)]
Telemetry(TelemetryCommand),
/// Install new toolchains or modify/query installed toolchains
#[clap(subcommand)]
Toolchain(ToolchainCommand),
Expand All @@ -55,6 +59,7 @@ pub fn fuelup_cli() -> Result<()> {
FuelupCommand::Update(update) => fuelup::update_exec(update.force),
FuelupCommand::Uninstall(remove) => fuelup::remove_exec(remove.force),
},
Commands::Telemetry(command) => telemetry::exec(command),
Commands::Show => fuelup_show::show(),
Commands::Toolchain(command) => toolchain::exec(command),
Commands::Update => fuelup_update::update(),
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ pub mod settings;
pub mod shell;
pub mod store;
pub mod target_triple;
pub mod telemetry;
pub mod toolchain;
pub mod toolchain_override;
5 changes: 5 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use fuelup::{
fuelup_cli,
logging::{init_tracing, log_command, log_environment},
proxy_cli,
telemetry::prompt_telemetry_if_needed,
};
use std::{env, panic, path::PathBuf};
use tracing::error;
Expand All @@ -18,6 +19,10 @@ fn run() -> Result<()> {
.and_then(std::ffi::OsStr::to_str)
.map(String::from);

// Prompt for telemetry opt-in if needed (for both fuelup and proxy commands)
// This is a one-time prompt that creates the opt-in file
let _ = prompt_telemetry_if_needed();

match process_name.as_deref() {
Some(component::FUELUP) => {
if let Err(e) = fuelup_cli::fuelup_cli() {
Expand Down
10 changes: 10 additions & 0 deletions src/proxy_cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
download::DownloadCfg,
target_triple::TargetTriple,
telemetry::is_telemetry_enabled,
toolchain::{DistToolchainDescription, Toolchain},
toolchain_override::{ComponentSpec, ToolchainOverride},
};
Expand Down Expand Up @@ -92,6 +93,15 @@ fn direct_proxy(proc_name: &str, args: &[OsString], toolchain: &Toolchain) -> Re
cmd.args(args);
cmd.stdin(Stdio::inherit());

// Set FUELUP_NO_TELEMETRY based on user's opt-in preference
// FUELUP_NO_TELEMETRY disables telemetry, so we set it when user has opted out
// and explicitly remove it when user has opted in (to override any inherited value)
if is_telemetry_enabled() {
cmd.env_remove("FUELUP_NO_TELEMETRY");
} else {
cmd.env("FUELUP_NO_TELEMETRY", "1");
}
Comment thread
cursor[bot] marked this conversation as resolved.

return exec(&mut cmd, proc_name, &toolchain_name).map_err(anyhow::Error::from);

fn exec(cmd: &mut Command, proc_name: &str, toolchain_name: &str) -> io::Result<ExitCode> {
Expand Down
Loading
Loading