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
42 changes: 42 additions & 0 deletions crates/pixi_cli/src/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,45 @@ fn user_agent() -> String {
format!("pixi {}", consts::PIXI_VERSION)
}

/// Send a best-effort anonymous ping after a successful self-update, tagging
/// the OS, architecture and target version. It never blocks or fails the
/// update (short timeout, all errors ignored) and is skipped when
/// `PIXI_NO_TELEMETRY` or `DO_NOT_TRACK` is set.
async fn send_update_ping(
client: &reqwest_middleware::ClientWithMiddleware,
target_version: Option<&Version>,
) {
if std::env::var_os("PIXI_NO_TELEMETRY").is_some() || std::env::var_os("DO_NOT_TRACK").is_some()
{
return;
}

let version = target_version
.map(|v| v.to_string())
.unwrap_or_else(|| "latest".to_string());

// Encode the metadata as a synthetic page URL. Scarf reports on the `Page`
// dimension (normally inferred from the referrer), so each event/version/
// platform combination shows up as its own page in the dashboard.
let page = format!(
"https://pixi.sh/ping/self-update/{}/{}-{}",
version,
std::env::consts::OS,
std::env::consts::ARCH,
);

let _ = client

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we add a comment to tell we explicitly dont care if this fails?

.get(consts::INSTALL_PING_URL)
.query(&[
("x-pxid", consts::INSTALL_PING_PXID),
("Page", page.as_str()),
])
.header("User-Agent", user_agent())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this is already the default on the passed in client.

.timeout(std::time::Duration::from_secs(3))
.send()
.await;
}

fn default_archive_name() -> Option<String> {
if cfg!(target_os = "macos") {
if cfg!(target_arch = "x86_64") {
Expand Down Expand Up @@ -410,6 +449,9 @@ pub async fn execute(args: Args, global_options: &GlobalOptions) -> miette::Resu
tracing::warn!(fetch_release_warning);
}

// Best-effort anonymous ping; must not affect the update result.
send_update_ping(&client, target_version.as_ref()).await;

Ok(())
}

Expand Down
5 changes: 5 additions & 0 deletions crates/pixi_consts/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ pub const RELEASES_API_BY_TAG: &str = "https://api.github.com/repos/prefix-dev/p
pub const RELEASES_API_LATEST: &str =
"https://api.github.com/repos/prefix-dev/pixi/releases/latest";

/// Endpoint for the anonymous installation/update ping. The same pixel id is
/// used by the install scripts (`install/install.sh`, `install/install.ps1`).
pub const INSTALL_PING_URL: &str = "https://installation-ping.prefix.dev/a.png";
Comment thread
baszalmstra marked this conversation as resolved.
pub const INSTALL_PING_PXID: &str = "21354c5b-2936-42bc-9d4b-9d6253815afd";

pub const CLAP_CONFIG_OPTIONS: &str = "Config Options";
pub const CLAP_GIT_OPTIONS: &str = "Git Options";
pub const CLAP_GLOBAL_OPTIONS: &str = "Global Options";
Expand Down
10 changes: 10 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ its [compile steps](https://github.com/conda/rattler/tree/main#give-it-a-try).
| `PIXI_DOWNLOAD_URL` | Overrides the download URL for the Pixi binary (useful for mirrors or custom builds). | GitHub releases, e.g. [linux-64](https://github.com/prefix-dev/pixi/releases/latest/download/pixi-x86_64-unknown-linux-musl.tar.gz) |
| `NETRC` | Path to a custom `.netrc` file for authentication with private repositories. | |
| `TMP_DIR` | The temporary directory the script uses to download to and unpack the binary from. | `/tmp` |
| `PIXI_NO_TELEMETRY` | If set, the script will not send the anonymous installation ping (see note below). | |
| `DO_NOT_TRACK` | Same as `PIXI_NO_TELEMETRY`; honors the common `DO_NOT_TRACK` convention. | |

For example, on Apple Silicon, you can force the installation of the x86 version:
```shell
Expand Down Expand Up @@ -185,6 +187,8 @@ its [compile steps](https://github.com/conda/rattler/tree/main#give-it-a-try).
| `PIXI_HOME` | The location of the installation. | `$Env:USERPROFILE\.pixi` |
| `PIXI_NO_PATH_UPDATE`| If set, the `$PATH` will not be updated to add `pixi` to it. | `false` |
| `PIXI_DOWNLOAD_URL` | Overrides the download URL for the Pixi binary (useful for mirrors or custom builds). | GitHub releases, e.g. [win-64](https://github.com/prefix-dev/pixi/releases/latest/download/pixi-x86_64-pc-windows-msvc.zip) |
| `PIXI_NO_TELEMETRY` | If set, the script will not send the anonymous installation ping (see note below). | |
| `DO_NOT_TRACK` | Same as `PIXI_NO_TELEMETRY`; honors the common `DO_NOT_TRACK` convention. | |

For example, set the version:
```powershell
Expand All @@ -202,6 +206,12 @@ its [compile steps](https://github.com/conda/rattler/tree/main#give-it-a-try).
!!! tip "Security Note"
The PowerShell install script automatically masks any credentials embedded in the download URL when displaying messages, replacing them with `***:***@` to prevent credentials from appearing in logs or console output.

!!! note "Anonymous installation ping"
After a successful install, the script sends a single anonymous request that helps us estimate how many installations happen. It contains no personal data and is best-effort: it has a short timeout and never blocks or fails the installation. To disable it, set `PIXI_NO_TELEMETRY=1` or `DO_NOT_TRACK=1` before running the script:
```shell
curl -fsSL https://pixi.sh/install.sh | PIXI_NO_TELEMETRY=1 bash
```

## Autocompletion

To get autocompletion follow the instructions for your shell.
Expand Down
16 changes: 16 additions & 0 deletions install/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,22 @@ try {
Remove-Item -Path $ZIP_FILE
}

# Send an anonymous installation ping (best-effort, never fails the install).
# Opt out by setting PIXI_NO_TELEMETRY or DO_NOT_TRACK.
if (-not $Env:PIXI_NO_TELEMETRY -and -not $Env:DO_NOT_TRACK) {
try {
$PingArch = if ($ARCH -like 'aarch64*') { 'aarch64' } elseif ($ARCH -like 'i686*') { 'i686' } else { 'x86_64' }
# Metadata is encoded into the `Page` query parameter so it shows up as a
# distinct page in Scarf. Invoke-WebRequest URL-encodes the parameter value.
$Page = "https://pixi.sh/ping/install/$PixiVersion/windows-$PingArch"
$PingBase = 'https://installation-ping.prefix.dev/a.png'
$PingUrl = "$PingBase`?x-pxid=21354c5b-2936-42bc-9d4b-9d6253815afd&Page=$([uri]::EscapeDataString($Page))"
Invoke-WebRequest -Uri $PingUrl -UseBasicParsing -TimeoutSec 3 | Out-Null
} catch {
# Ignore telemetry errors
}
}

# Add pixi to PATH if the folder is not already in the PATH variable
if (!$NoPathUpdate) {
$PATH = Get-Env 'PATH'
Expand Down
20 changes: 20 additions & 0 deletions install/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,26 @@ __wrap__() {

echo "The 'pixi' binary is installed into '${PIXI_BIN_DIR}'"

# Send an anonymous installation ping (best-effort, never fails the install).
# Opt out by setting PIXI_NO_TELEMETRY or DO_NOT_TRACK.
if [ -z "${PIXI_NO_TELEMETRY:-}" ] && [ -z "${DO_NOT_TRACK:-}" ]; then
case "$PLATFORM" in
apple-darwin) OS_TAG="macos" ;;
*linux*) OS_TAG="linux" ;;
*windows*) OS_TAG="windows" ;;
*) OS_TAG="unknown" ;;
esac
# Metadata is encoded into the (pre-encoded) `Page` query parameter so it
# shows up as a distinct page in Scarf; '%2F' are the path separators.
PAGE="https%3A%2F%2Fpixi.sh%2Fping%2Finstall%2F${VERSION}%2F${OS_TAG}-${ARCH}"
PING_URL="https://installation-ping.prefix.dev/a.png?x-pxid=21354c5b-2936-42bc-9d4b-9d6253815afd&Page=${PAGE}"
if hash curl 2>/dev/null; then
curl -sSL --max-time 3 "$PING_URL" >/dev/null 2>&1 || true
elif hash wget 2>/dev/null; then
wget -q -T 3 -O /dev/null "$PING_URL" >/dev/null 2>&1 || true
fi
fi

# shell update can be suppressed by `PIXI_NO_PATH_UPDATE` env var
if [ -n "${PIXI_NO_PATH_UPDATE:-}" ]; then
echo "No path update because PIXI_NO_PATH_UPDATE is set"
Expand Down
Loading