mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 18:18:55 +00:00
build(rust): bump to Rust 1.91.0 (#10767)
Rust 1.91 has been released and brings with it a few new lints that we need to tidy up. In addition, it also stabilizes `BTreeMap::extract_if`: A really nifty std-lib function that allows us to conditionally take elements from a map. We need that in a bunch of places.
This commit is contained in:
14
.github/actions/setup-rust/action.yml
vendored
14
.github/actions/setup-rust/action.yml
vendored
@@ -74,10 +74,10 @@ runs:
|
||||
echo "SCCACHE_AZURE_BLOB_CONTAINER=sccache" >> $GITHUB_ENV
|
||||
echo "RUSTC_WRAPPER=$SCCACHE_PATH" >> $GITHUB_ENV
|
||||
|
||||
- name: Install nightly Rust
|
||||
- name: Install nightly Rust to use for certain tools (fuzzing, cargo-udeps)
|
||||
id: nightly
|
||||
run: |
|
||||
NIGHTLY="nightly-2025-05-30"
|
||||
NIGHTLY="nightly-2025-09-30"
|
||||
# Check if nightly toolchain is already installed
|
||||
if ! rustup toolchain list | grep -q "$NIGHTLY"; then
|
||||
rustup toolchain install $NIGHTLY
|
||||
@@ -86,6 +86,16 @@ runs:
|
||||
echo "nightly=$NIGHTLY" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Install nightly Rust for compiling eBPF code
|
||||
run: |
|
||||
NIGHTLY="nightly-2025-05-30"
|
||||
# Check if nightly toolchain is already installed
|
||||
if ! rustup toolchain list | grep -q "$NIGHTLY"; then
|
||||
rustup toolchain install $NIGHTLY
|
||||
rustup component add rust-src --toolchain $NIGHTLY
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
- name: Start sccache
|
||||
run: $SCCACHE_PATH --start-server
|
||||
shell: bash
|
||||
|
||||
24
rust/Cargo.lock
generated
24
rust/Cargo.lock
generated
@@ -3861,17 +3861,6 @@ dependencies = [
|
||||
"mach2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ip-packet"
|
||||
version = "0.1.0"
|
||||
@@ -8028,30 +8017,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.47.1"
|
||||
version = "1.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
|
||||
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"socket2 0.6.0",
|
||||
"tokio-macros",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -185,7 +185,7 @@ test-case = "3.3.1"
|
||||
test-strategy = "0.4.3"
|
||||
thiserror = "2.0.17"
|
||||
time = "0.3.43"
|
||||
tokio = "1.47"
|
||||
tokio = "1.48.0"
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-tungstenite = "0.28.0"
|
||||
tokio-util = "0.7.16"
|
||||
|
||||
@@ -63,7 +63,7 @@ COPY ${PACKAGE} .
|
||||
FROM runtime AS dev
|
||||
|
||||
ARG PACKAGE
|
||||
ARG RUST_VERSION="1.90.0" # Keep in sync with `rust-toolchain.toml`
|
||||
ARG RUST_VERSION="1.91.0" # Keep in sync with `rust-toolchain.toml`
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::{net::IpAddr, process::Command, str::FromStr};
|
||||
|
||||
mod etc_resolv_conf;
|
||||
|
||||
#[derive(clap::ValueEnum, Clone, Copy, Debug)]
|
||||
#[derive(clap::ValueEnum, Clone, Copy, Debug, Default)]
|
||||
pub enum DnsControlMethod {
|
||||
/// Explicitly disable DNS control.
|
||||
///
|
||||
@@ -22,15 +22,10 @@ pub enum DnsControlMethod {
|
||||
/// Cooperate with `systemd-resolved`
|
||||
///
|
||||
/// Suitable for most Ubuntu systems, probably
|
||||
#[default]
|
||||
SystemdResolved,
|
||||
}
|
||||
|
||||
impl Default for DnsControlMethod {
|
||||
fn default() -> Self {
|
||||
Self::SystemdResolved
|
||||
}
|
||||
}
|
||||
|
||||
impl DnsController {
|
||||
pub fn deactivate(&mut self) -> Result<()> {
|
||||
tracing::debug!("Deactivating DNS control...");
|
||||
|
||||
@@ -793,7 +793,7 @@ fn set_non_blocking(fd: RawFd) -> io::Result<()> {
|
||||
}
|
||||
|
||||
fn create_tun_device() -> io::Result<()> {
|
||||
let path = Path::new(TUN_FILE.to_str().expect("path is valid utf-8"));
|
||||
let path = Path::new(TUN_FILE.to_str().map_err(io::Error::other)?);
|
||||
|
||||
if path.exists() {
|
||||
return Ok(());
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use backoff::ExponentialBackoffBuilder;
|
||||
use firezone_logging::sentry_layer;
|
||||
use firezone_telemetry::{Telemetry, analytics};
|
||||
@@ -563,7 +563,7 @@ fn init_logging(log_dir: &Path, log_filter: String) -> Result<()> {
|
||||
|
||||
LOGGER_STATE
|
||||
.set((handle, reload_handle))
|
||||
.expect("Logging guard should never be initialized twice");
|
||||
.map_err(|_| anyhow!("Logging guard should never be initialized twice"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ fn get_websocket_path<E>(
|
||||
{
|
||||
let mut paths = api_url
|
||||
.path_segments_mut()
|
||||
.expect("scheme guarantees valid URL");
|
||||
.map_err(|_| LoginUrlError::MissingHost)?;
|
||||
|
||||
paths.pop_if_empty();
|
||||
paths.push(mode);
|
||||
@@ -321,7 +321,7 @@ fn set_ws_scheme<E>(url: &mut Url) -> Result<(), LoginUrlError<E>> {
|
||||
};
|
||||
|
||||
url.set_scheme(scheme)
|
||||
.expect("Developer error: the match before this should make sure we can set this");
|
||||
.map_err(|_| LoginUrlError::InvalidUrlScheme(scheme.to_owned()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1756,7 +1756,6 @@ impl PeerSocket {
|
||||
matches!(self, Self::RelayToPeer { .. } | Self::RelayToRelay { .. })
|
||||
}
|
||||
|
||||
// TODO: Return `Arguments` here once we hit 1.89
|
||||
fn fmt<RId>(&self, relay: RId) -> String
|
||||
where
|
||||
RId: fmt::Display,
|
||||
|
||||
@@ -49,36 +49,23 @@ where
|
||||
const RECENT_DISCONNECT_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
pub(crate) fn handle_timeout(&mut self, events: &mut VecDeque<Event<TId>>, now: Instant) {
|
||||
self.initial.retain(|id, conn| {
|
||||
if conn.is_failed {
|
||||
events.push_back(Event::ConnectionFailed(*id));
|
||||
return false;
|
||||
for (id, _) in self.initial.extract_if(.., |_, conn| conn.is_failed) {
|
||||
events.push_back(Event::ConnectionFailed(id));
|
||||
}
|
||||
|
||||
for (id, conn) in self.established.extract_if(.., |_, conn| conn.is_failed()) {
|
||||
events.push_back(Event::ConnectionFailed(id));
|
||||
|
||||
for (index, _) in self
|
||||
.established_by_wireguard_session_index
|
||||
.extract_if(.., |_, c| *c == id)
|
||||
{
|
||||
self.disconnected_session_indices.insert(index, now);
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
|
||||
self.established.retain(|id, conn| {
|
||||
if conn.is_failed() {
|
||||
events.push_back(Event::ConnectionFailed(*id));
|
||||
self.established_by_wireguard_session_index
|
||||
.retain(|index, c| {
|
||||
if c == id {
|
||||
self.disconnected_session_indices.insert(*index, now);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
self.disconnected_public_keys
|
||||
.insert(conn.tunnel.remote_static_public().to_bytes(), now);
|
||||
self.disconnected_ids.insert(*id, now);
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
self.disconnected_public_keys
|
||||
.insert(conn.tunnel.remote_static_public().to_bytes(), now);
|
||||
self.disconnected_ids.insert(id, now);
|
||||
}
|
||||
|
||||
self.disconnected_ids
|
||||
.retain(|_, v| now.duration_since(*v) < Self::RECENT_DISCONNECT_TIMEOUT);
|
||||
|
||||
@@ -174,17 +174,10 @@ impl ClientOnGateway {
|
||||
let cid = self.id;
|
||||
let mut any_expired = false;
|
||||
|
||||
// TODO: Replace with `extract_if` once we are on Rust 1.91
|
||||
self.resources.retain(|rid, r| {
|
||||
if r.is_allowed(&now) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (rid, _) in self.resources.extract_if(.., |_, r| !r.is_allowed(&now)) {
|
||||
tracing::info!(%cid, %rid, "Access to resource expired");
|
||||
|
||||
any_expired = true;
|
||||
false
|
||||
});
|
||||
}
|
||||
|
||||
if any_expired {
|
||||
self.recalculate_filters();
|
||||
@@ -252,15 +245,12 @@ impl ClientOnGateway {
|
||||
}
|
||||
|
||||
pub(crate) fn retain_authorizations(&mut self, authorization: BTreeSet<ResourceId>) {
|
||||
// TODO: Replace with `extract_if` once we are on Rust 1.91
|
||||
self.resources.retain(|rid, _| {
|
||||
if authorization.contains(rid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (rid, _) in self
|
||||
.resources
|
||||
.extract_if(.., |rid, _| !authorization.contains(rid))
|
||||
{
|
||||
tracing::info!(%rid, "Revoking resource authorization");
|
||||
false
|
||||
});
|
||||
}
|
||||
|
||||
self.recalculate_filters();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![cfg_attr(test, allow(clippy::unwrap_used))]
|
||||
|
||||
use anyhow::anyhow;
|
||||
use clap::Parser as _;
|
||||
use firezone_bin_shared::{DnsControlMethod, TOKEN_ENV_KEY};
|
||||
use firezone_gui_client::service;
|
||||
@@ -8,7 +9,7 @@ use std::path::PathBuf;
|
||||
fn main() -> anyhow::Result<()> {
|
||||
rustls::crypto::ring::default_provider()
|
||||
.install_default()
|
||||
.expect("Calling `install_default` only once per process should always succeed");
|
||||
.map_err(|_| anyhow!("Failed to install default crypto provider"))?;
|
||||
|
||||
// Docs indicate that `remove_var` should actually be marked unsafe
|
||||
// SAFETY: We haven't spawned any other threads, this code should be the first
|
||||
@@ -58,22 +59,17 @@ pub struct Cli {
|
||||
max_partition_time: Option<humantime::Duration>,
|
||||
}
|
||||
|
||||
#[derive(clap::Subcommand)]
|
||||
#[derive(clap::Subcommand, Default)]
|
||||
enum Cmd {
|
||||
/// Needed to test the Tunnel service on aarch64 Windows,
|
||||
/// where the Tauri MSI bundler doesn't work yet
|
||||
Install,
|
||||
#[default]
|
||||
Run,
|
||||
RunDebug,
|
||||
RunSmokeTest,
|
||||
}
|
||||
|
||||
impl Default for Cmd {
|
||||
fn default() -> Self {
|
||||
Self::Run
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Cli, Cmd};
|
||||
|
||||
@@ -115,9 +115,10 @@ pub enum Failure {
|
||||
Panic,
|
||||
}
|
||||
|
||||
#[derive(derive_more::Debug)]
|
||||
#[derive(derive_more::Debug, Default)]
|
||||
pub enum Status {
|
||||
/// Firezone is disconnected.
|
||||
#[default]
|
||||
Disconnected,
|
||||
Quitting, // The user asked to quit and we're waiting for the tunnel daemon to gracefully disconnect so we can flush telemetry.
|
||||
/// Firezone is ready to use.
|
||||
@@ -131,12 +132,6 @@ pub enum Status {
|
||||
WaitingForTunnel,
|
||||
}
|
||||
|
||||
impl Default for Status {
|
||||
fn default() -> Self {
|
||||
Self::Disconnected
|
||||
}
|
||||
}
|
||||
|
||||
impl Status {
|
||||
/// True if we should react to `OnUpdateResources`
|
||||
fn needs_resource_updates(&self) -> bool {
|
||||
|
||||
@@ -804,7 +804,7 @@ mod tests {
|
||||
"MyCorp GitLab",
|
||||
Menu::default()
|
||||
.item(
|
||||
Event::Url("https://gitlab.mycorp.com".parse().unwrap()),
|
||||
Event::Url("https://gitlab.mycorp.com".parse()?),
|
||||
"<https://gitlab.mycorp.com>",
|
||||
)
|
||||
.separator()
|
||||
@@ -864,7 +864,7 @@ mod tests {
|
||||
actual,
|
||||
expected,
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&actual).unwrap()
|
||||
serde_json::to_string_pretty(&actual)?
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -910,7 +910,7 @@ mod tests {
|
||||
"MyCorp GitLab",
|
||||
Menu::default()
|
||||
.item(
|
||||
Event::Url("https://gitlab.mycorp.com".parse().unwrap()),
|
||||
Event::Url("https://gitlab.mycorp.com".parse()?),
|
||||
"<https://gitlab.mycorp.com>",
|
||||
)
|
||||
.separator()
|
||||
@@ -946,7 +946,7 @@ mod tests {
|
||||
actual,
|
||||
expected,
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&actual).unwrap(),
|
||||
serde_json::to_string_pretty(&actual)?,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -188,7 +188,7 @@ fn main() {
|
||||
fn try_main() -> Result<()> {
|
||||
rustls::crypto::ring::default_provider()
|
||||
.install_default()
|
||||
.expect("Calling `install_default` only once per process should always succeed");
|
||||
.map_err(|_| anyhow!("Failed to install default crypto provider"))?;
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
|
||||
@@ -1021,43 +1021,39 @@ where
|
||||
|
||||
let port = allocation.port;
|
||||
|
||||
self.channels_by_client_and_number
|
||||
.retain(|(cs, number), c| {
|
||||
if c.allocation != port {
|
||||
return true;
|
||||
}
|
||||
for ((cs, number), c) in self
|
||||
.channels_by_client_and_number
|
||||
.extract_if(.., |_, c| c.allocation == port)
|
||||
{
|
||||
debug_assert_eq!(cs, client, "internal state should be consistent");
|
||||
|
||||
debug_assert_eq!(cs, &client, "internal state should be consistent");
|
||||
let peer = c.peer_address;
|
||||
|
||||
let peer = c.peer_address;
|
||||
if let Some(existing) = self
|
||||
.channel_numbers_by_client_and_peer
|
||||
.remove(&(client, peer))
|
||||
{
|
||||
debug_assert_eq!(existing, number, "internal state should be consistent");
|
||||
}
|
||||
|
||||
if let Some(existing) = self
|
||||
.channel_numbers_by_client_and_peer
|
||||
.remove(&(client, peer))
|
||||
{
|
||||
debug_assert_eq!(existing, *number, "internal state should be consistent");
|
||||
}
|
||||
if let Some((existing_cs, existing_n)) = self
|
||||
.channel_and_client_by_port_and_peer
|
||||
.remove(&(port, peer))
|
||||
{
|
||||
debug_assert_eq!(existing_cs, cs, "internal state should be consistent");
|
||||
debug_assert_eq!(existing_n, number, "internal state should be consistent");
|
||||
}
|
||||
|
||||
if let Some((existing_cs, existing_n)) = self
|
||||
.channel_and_client_by_port_and_peer
|
||||
.remove(&(port, peer))
|
||||
{
|
||||
debug_assert_eq!(&existing_cs, cs, "internal state should be consistent");
|
||||
debug_assert_eq!(&existing_n, number, "internal state should be consistent");
|
||||
}
|
||||
self.pending_commands
|
||||
.push_back(Command::DeleteChannelBinding {
|
||||
client: cs,
|
||||
channel_number: number,
|
||||
peer: c.peer_address,
|
||||
allocation_port: c.allocation,
|
||||
});
|
||||
|
||||
self.pending_commands
|
||||
.push_back(Command::DeleteChannelBinding {
|
||||
client: *cs,
|
||||
channel_number: *number,
|
||||
peer: c.peer_address,
|
||||
allocation_port: c.allocation,
|
||||
});
|
||||
|
||||
tracing::info!(%peer, %number, allocation = %port, "Deleted channel binding");
|
||||
|
||||
false
|
||||
});
|
||||
tracing::info!(%peer, %number, allocation = %port, "Deleted channel binding");
|
||||
}
|
||||
|
||||
self.allocations_up_down_counter.add(-1, &[]);
|
||||
self.pending_commands.push_back(Command::FreeAllocation {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "1.90.0" # Keep in sync with `Dockerfile`
|
||||
channel = "1.91.0" # Keep in sync with `Dockerfile`
|
||||
components = ["rust-src", "rust-analyzer", "clippy"]
|
||||
targets = ["x86_64-unknown-linux-musl"]
|
||||
|
||||
Reference in New Issue
Block a user