diff --git a/.github/workflows/_build_artifacts.yml b/.github/workflows/_build_artifacts.yml index 71a267c5e..59523aaef 100644 --- a/.github/workflows/_build_artifacts.yml +++ b/.github/workflows/_build_artifacts.yml @@ -149,23 +149,23 @@ jobs: arch: - target: x86_64-unknown-linux-musl - shortname: x64 + shortname: x86_64 platform: linux/amd64 - target: aarch64-unknown-linux-musl # E.g. AWS Graviton - shortname: arm64 + shortname: aarch64 platform: linux/arm64 - target: armv7-unknown-linux-musleabihf # E.g. Raspberry Pi platform: linux/arm/v7 - shortname: arm + shortname: armv7 name: - package: firezone-linux-client - artifact: linux-client + artifact: firezone-client-headless-linux image_name: client - package: firezone-relay - artifact: relay + artifact: firezone-relay image_name: relay - package: firezone-gateway - artifact: gateway + artifact: firezone-gateway image_name: gateway - package: snownet-tests artifact: snownet-tests @@ -174,7 +174,8 @@ jobs: artifact: http-test-server image_name: http-test-server env: - BINARY_DEST_PATH: ${{ matrix.name.artifact }}-${{ matrix.arch.shortname }} + # mark:automatic-version + BINARY_DEST_PATH: ${{ matrix.name.artifact }}_1.0.0_${{ matrix.arch.shortname }} outputs: client_image: ${{ steps.image-name.outputs.client_image }} relay_image: ${{ steps.image-name.outputs.relay_image }} diff --git a/.github/workflows/_tauri.yml b/.github/workflows/_tauri.yml index 336c388f0..b45019a9d 100644 --- a/.github/workflows/_tauri.yml +++ b/.github/workflows/_tauri.yml @@ -36,12 +36,12 @@ jobs: syms-artifact: rust/gui-client/firezone-linux-gui-client-amd64.dwp pkg-artifact: rust/gui-client/firezone-linux-gui-client_amd64.deb - runs-on: windows-2019 - binary-dest-path: firezone-windows-client + binary-dest-path: firezone-client-gui-windows rename-script: ../../scripts/build/tauri-rename-windows.sh upload-script: ../../scripts/build/tauri-upload-windows.sh - exe-artifact: rust/gui-client/firezone-windows-client-x64.exe - syms-artifact: rust/gui-client/firezone-windows-client-x64.pdb - pkg-artifact: rust/gui-client/firezone-windows-client-x64.msi + exe-artifact: rust/gui-client/firezone-client-gui-windows-x86_64.exe + syms-artifact: rust/gui-client/firezone-client-gui-windows-x86_64.pdb + pkg-artifact: rust/gui-client/firezone-client-gui-windows-x86_64.msi env: BINARY_DEST_PATH: ${{ matrix.binary-dest-path }} AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} @@ -83,21 +83,21 @@ jobs: - name: Upload exe uses: actions/upload-artifact@v4 with: - name: ${{ matrix.binary-dest-path }}-exe + name: ${{ matrix.binary-dest-path }}-x86_64-exe path: | ${{ matrix.exe-artifact }} if-no-files-found: error - name: Upload debug symbols uses: actions/upload-artifact@v4 with: - name: ${{ matrix.binary-dest-path }}-syms + name: ${{ matrix.binary-dest-path }}-x86_64-syms path: | ${{ matrix.syms-artifact }} if-no-files-found: error - name: Upload package uses: actions/upload-artifact@v4 with: - name: ${{ matrix.binary-dest-path }}-pkg + name: ${{ matrix.binary-dest-path }}-x86_64-pkg path: | ${{ matrix.pkg-artifact }} if-no-files-found: error diff --git a/rust/gui-client/src-tauri/src/client/debug_commands.rs b/rust/gui-client/src-tauri/src/client/debug_commands.rs index 4e26b4a72..856194426 100644 --- a/rust/gui-client/src-tauri/src/client/debug_commands.rs +++ b/rust/gui-client/src-tauri/src/client/debug_commands.rs @@ -29,8 +29,9 @@ fn check_for_updates() -> Result<()> { client::logging::debug_command_setup()?; let rt = tokio::runtime::Runtime::new().unwrap(); - let release = rt.block_on(client::updates::check()); - tracing::info!("{:?}", release.as_ref().map(serde_json::to_string)); + let release = rt.block_on(client::updates::check())?; + tracing::info!("{:#?}", serde_json::to_string(&release)); + tracing::info!("{:?}", release.download_url()); Ok(()) } diff --git a/rust/gui-client/src-tauri/src/client/gui.rs b/rust/gui-client/src-tauri/src/client/gui.rs index 5d7343547..5bc99dd65 100644 --- a/rust/gui-client/src-tauri/src/client/gui.rs +++ b/rust/gui-client/src-tauri/src/client/gui.rs @@ -17,6 +17,7 @@ use system_tray_menu::Event as TrayMenuEvent; use tauri::{Manager, SystemTray, SystemTrayEvent}; use tokio::sync::{mpsc, oneshot, Notify}; use tunnel_wrapper::CallbackHandler; +use url::Url; use ControllerRequest as Req; @@ -403,16 +404,22 @@ async fn check_for_updates(ctlr_tx: CtlrTx, always_show_update_notification: boo let release = client::updates::check() .await .context("Error in client::updates::check")?; + let Some(download_url) = release.download_url() else { + tracing::warn!("No installer for this OS/arch online"); + return Ok(()); + }; let our_version = client::updates::current_version()?; - let github_version = &release.tag_name; if always_show_update_notification || (our_version < release.tag_name) { - tracing::info!(?our_version, ?github_version, "Github has a new release"); + tracing::info!(?our_version, ?release.tag_name, "There is a new release"); // We don't necessarily need to route through the Controller here, but if we // want a persistent "Click here to download the new MSI" button, this would allow that. ctlr_tx - .send(ControllerRequest::UpdateAvailable(release)) + .send(ControllerRequest::UpdateAvailable { + download_url: download_url.clone(), + version_to_download: release.tag_name, + }) .await .context("Error while sending UpdateAvailable to Controller")?; return Ok(()); @@ -420,8 +427,8 @@ async fn check_for_updates(ctlr_tx: CtlrTx, always_show_update_notification: boo tracing::info!( ?our_version, - ?github_version, - "Our release is newer than, or the same as Github's latest" + ?release.tag_name, + "Our release is newer than, or the same as, the latest" ); Ok(()) } @@ -474,8 +481,11 @@ pub(crate) enum ControllerRequest { SignIn, SystemTrayMenu(TrayMenuEvent), TunnelReady, - UpdateAvailable(client::updates::Release), - UpdateNotificationClicked(client::updates::Release), + UpdateAvailable { + download_url: Url, + version_to_download: semver::Version, + }, + UpdateNotificationClicked(Url), } struct Controller { @@ -655,8 +665,11 @@ impl Controller { self.tunnel_ready = true; self.refresh_system_tray_menu()?; } - Req::UpdateAvailable(release) => { - let title = format!("Firezone {} available for download", release.tag_name); + Req::UpdateAvailable { + download_url, + version_to_download, + } => { + let title = format!("Firezone {} available for download", version_to_download); // We don't need to route through the controller here either, we could // use the `open` crate directly instead of Tauri's wrapper @@ -665,16 +678,12 @@ impl Controller { &title, "Click here to download the new version.", self.ctlr_tx.clone(), - Req::UpdateNotificationClicked(release), + Req::UpdateNotificationClicked(download_url), )?; } - Req::UpdateNotificationClicked(release) => { + Req::UpdateNotificationClicked(download_url) => { tracing::info!("UpdateNotificationClicked in run_controller!"); - tauri::api::shell::open( - &self.app.shell_scope(), - release.browser_download_url, - None, - )?; + tauri::api::shell::open(&self.app.shell_scope(), download_url, None)?; } } Ok(()) diff --git a/rust/gui-client/src-tauri/src/client/updates.rs b/rust/gui-client/src-tauri/src/client/updates.rs index 44ff2a295..e14e71073 100644 --- a/rust/gui-client/src-tauri/src/client/updates.rs +++ b/rust/gui-client/src-tauri/src/client/updates.rs @@ -1,58 +1,61 @@ //! Module to check the Github repo for new releases use crate::client::about::get_cargo_version; -use std::{fmt, str::FromStr}; +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use std::str::FromStr; use url::Url; /// GUI-friendly release struct -#[derive(serde::Serialize)] +/// +/// Serialize is derived for debugging +#[derive(Deserialize, Serialize)] pub(crate) struct Release { - /// URL that will instantly try to download the MSI to disk + /// All assets in a given release + assets: Vec, + /// Git tag name / Cargo version name /// - /// e.g. - pub browser_download_url: Url, - /// Git tag name - /// - /// e.g. 1.0.0-pre.8 + /// e.g. 1.0.1 pub tag_name: semver::Version, } -impl Release { - /// Parses the release JSON, finds the MSI asset, and returns info about the latest MSI - fn from_str(s: &str) -> Result { - let ReleaseDetails { assets, tag_name } = serde_json::from_str(s)?; - let asset = assets - .into_iter() - .find(|asset| asset.name == ASSET_NAME) - .ok_or(Error::NoSuchAsset)?; - - Ok(Release { - browser_download_url: asset.browser_download_url, - tag_name, - }) - } +#[derive(Deserialize, Serialize)] +struct Asset { + browser_download_url: Url, + /// Name of the asset, e.g. `firezone-client-gui-windows-x86_64.msi` + name: String, } -impl fmt::Debug for Release { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Release") - .field( - "browser_download_url", - &self.browser_download_url.to_string(), - ) - .field("tag_name", &self.tag_name.to_string()) - .finish() +impl Release { + /// Download URL for current OS and arch + pub fn download_url(&self) -> Option<&Url> { + self.download_url_for(std::env::consts::ARCH, std::env::consts::OS) + } + + /// Download URL for the first asset that matches the given arch, OS, and package type + fn download_url_for(&self, arch: &str, os: &str) -> Option<&Url> { + let package = match os { + "linux" => "deb", + "macos" => "dmg", // Unused in practice + "windows" => "msi", + _ => panic!("Don't know what package this OS uses"), + }; + + let prefix = format!("firezone-client-gui-{os}_"); + let suffix = format!("_{arch}.{package}"); + + let mut iter = self + .assets + .iter() + .filter(|x| x.name.starts_with(&prefix) && x.name.ends_with(&suffix)); + iter.next().map(|asset| &asset.browser_download_url) } } #[derive(Debug, thiserror::Error)] pub(crate) enum Error { - #[error("Non-OK HTTP status")] - HttpStatus(reqwest::StatusCode), #[error(transparent)] JsonParse(#[from] serde_json::Error), - #[error("No such asset `{ASSET_NAME}` in the latest release")] - NoSuchAsset, #[error("Our own semver in the exe is invalid, this should be impossible")] OurVersionIsInvalid(semver::Error), #[error(transparent)] @@ -65,30 +68,14 @@ const LATEST_RELEASE_API_URL: &str = /// const GITHUB_API_VERSION: &str = "2022-11-28"; -/// The name of the Windows MSI / Linux deb asset. -/// -/// These ultimately come from `cd.yml`, `git grep WCPYPXZF` -#[cfg(target_os = "linux")] -const ASSET_NAME: &str = "firezone-linux-gui-client_amd64.deb"; - -/// Unused - The Tauri client is not supported for macOS -#[cfg(target_os = "macos")] -const ASSET_NAME: &str = "firezone-mac-unused-client_aarch64.dmg"; - -#[cfg(target_os = "windows")] -const ASSET_NAME: &str = "firezone-windows-client-x64.msi"; - /// Returns the latest release, even if ours is already newer -pub(crate) async fn check() -> Result { +pub(crate) async fn check() -> Result { let client = reqwest::Client::builder().build()?; + let arch = std::env::consts::ARCH; + let os = std::env::consts::OS; // - // This would change for aarch64 support - let user_agent = format!( - // TODO: remove 'windows' - "Firezone Client/{:?} (Windows; Win64; x64)", - current_version() - ); + let user_agent = format!("Firezone Client/{:?} ({os}; {arch})", current_version()); // Reqwest follows up to 10 redirects by default // https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.redirect @@ -101,11 +88,11 @@ pub(crate) async fn check() -> Result { .await?; let status = response.status(); if status != reqwest::StatusCode::OK { - return Err(Error::HttpStatus(status)); + anyhow::bail!("HTTP status: {status}"); } let response = response.text().await?; - Release::from_str(&response) + Ok(serde_json::from_str(&response)?) } // TODO: DRY with about.rs @@ -113,156 +100,109 @@ pub(crate) fn current_version() -> Result { semver::Version::from_str(&get_cargo_version()).map_err(Error::OurVersionIsInvalid) } -/// Deserializable struct that matches Github's JSON -#[derive(serde::Deserialize)] -struct ReleaseDetails { - assets: Vec, - tag_name: semver::Version, -} - -#[derive(serde::Deserialize)] -struct Asset { - browser_download_url: Url, - /// Name of the asset, e.g. `firezone-windows-client-x64.msi` - name: String, -} - #[cfg(test)] mod tests { use std::str::FromStr; - /// A cut-down example of the real JSON from Github's API - /// - /// The real one is about 32 KB, most of which is details about the assets, - /// so it'll get bigger over time if new assets are added. - /// - /// The GraphQL API couldn't be used because it needs a token. - const RELEASES_LATEST_JSON: &str = r#" - { - "url": "https://api.github.com/repos/firezone/firezone/releases/138228264", - "assets_url": "https://api.github.com/repos/firezone/firezone/releases/138228264/assets", - "upload_url": "https://uploads.github.com/repos/firezone/firezone/releases/138228264/assets{?name,label}", - "html_url": "https://github.com/firezone/firezone/releases/tag/1.0.0-pre.8", - "id": 138228264, - "author": { - "login": "github-actions[bot]", - "id": 41898282, - "node_id": "MDM6Qm90NDE4OTgyODI=", - "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/github-actions%5Bbot%5D", - "html_url": "https://github.com/apps/github-actions", - "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers", - "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}", - "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}", - "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions", - "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs", - "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos", - "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}", - "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events", - "type": "Bot", - "site_admin": false - }, - "node_id": "RE_kwDOD12Hpc4IPTIo", - "tag_name": "1.0.0-pre.8", - "target_commitish": "refs/heads/main", - "name": "1.0.0-pre.8", - "draft": false, - "prerelease": false, - "created_at": "2024-01-24T00:23:23Z", - "published_at": "2024-01-24T04:34:44Z", - "assets": [ - { - "url": "https://api.github.com/repos/firezone/firezone/releases/assets/147443613", - "id": 147443613, - "node_id": "RA_kwDOD12Hpc4Iyc-c", - "name": "firezone-linux-gui-client_amd64.deb", - "label": "", - "uploader": { - "login": "github-actions[bot]", - "id": 41898282, - "node_id": "MDM6Qm90NDE4OTgyODI=", - "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/github-actions%5Bbot%5D", - "html_url": "https://github.com/apps/github-actions", - "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers", - "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}", - "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}", - "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions", - "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs", - "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos", - "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}", - "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events", - "type": "Bot", - "site_admin": false - }, - "content_type": "application/octet-stream", - "state": "uploaded", - "size": 8376320, - "download_count": 10, - "created_at": "2024-01-24T04:33:53Z", - "updated_at": "2024-01-24T04:33:53Z", - "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/firezone-linux-gui-client_amd64.deb" - }, - { - "url": "https://api.github.com/repos/firezone/firezone/releases/assets/147443612", - "id": 147443612, - "node_id": "RA_kwDOD12Hpc4Iyc-c", - "name": "firezone-windows-client-x64.msi", - "label": "", - "uploader": { - "login": "github-actions[bot]", - "id": 41898282, - "node_id": "MDM6Qm90NDE4OTgyODI=", - "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/github-actions%5Bbot%5D", - "html_url": "https://github.com/apps/github-actions", - "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers", - "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}", - "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}", - "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions", - "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs", - "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos", - "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}", - "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events", - "type": "Bot", - "site_admin": false - }, - "content_type": "application/octet-stream", - "state": "uploaded", - "size": 8376320, - "download_count": 10, - "created_at": "2024-01-24T04:33:53Z", - "updated_at": "2024-01-24T04:33:53Z", - "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/firezone-windows-client-x64.msi" - } - ] - }"#; - #[test] - fn test() { - let asset_name = super::ASSET_NAME; - let release = super::Release::from_str(RELEASES_LATEST_JSON).unwrap(); - let expected_url = format!( - "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/{asset_name}" + fn new_format() { + let s = r#" + { + "tag_name": "1.0.0-pre.14", + "assets": [ + { + "name": "firezone-client-gui-linux_1.0.0-pre.14_aarch64.deb", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-gui-linux_1.0.0-pre.14_aarch64.deb" + }, + { + "name": "firezone-client-gui-linux_1.0.0-pre.14_x86_64.deb", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-gui-linux_1.0.0-pre.14_x86_64.deb" + }, + { + "name": "firezone-client-gui-windows_1.0.0-pre.14_aarch64.msi", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-gui-windows_1.0.0-pre.14_aarch64.msi" + }, + { + "name": "firezone-client-gui-windows_1.0.0-pre.14_x86_64.msi", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-gui-windows_1.0.0-pre.14_x86_64.msi" + }, + + { + "name": "firezone-client-headless-linux_1.0.0-pre.14_aarch64.deb", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-headless-linux_1.0.0-pre.14_aarch64.deb" + }, + { + "name": "firezone-client-headless-linux_1.0.0-pre.14_x86_64.deb", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-headless-linux_1.0.0-pre.14_x86_64.deb" + }, + { + "name": "firezone-client-headless-windows_1.0.0-pre.14_aarch64.msi", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-headless-windows_1.0.0-pre.14_aarch64.msi" + }, + { + "name": "firezone-client-headless-windows_1.0.0-pre.14_x86_64.msi", + "browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-headless-windows_1.0.0-pre.14_x86_64.msi" + } + ] + }"#; + + let release: super::Release = serde_json::from_str(s).unwrap(); + let expected_url = "https://github.com/firezone/firezone/releases/download/1.0.0-pre.14/firezone-client-gui-windows_1.0.0-pre.14_x86_64.msi"; + assert_eq!( + release + .download_url_for("x86_64", "windows") + .unwrap() + .to_string(), + expected_url ); - assert_eq!(release.browser_download_url.to_string(), expected_url); - assert_eq!(release.tag_name.to_string(), "1.0.0-pre.8"); + assert_eq!(release.tag_name.to_string(), "1.0.0-pre.14"); assert!( semver::Version::from_str("1.0.0").unwrap() - > semver::Version::from_str("1.0.0-pre.8").unwrap() + > semver::Version::from_str("1.0.0-pre.14").unwrap() ); assert!( - semver::Version::from_str("1.0.0-pre.8").unwrap() + semver::Version::from_str("1.0.0-pre.14").unwrap() > semver::Version::from_str("0.7.0").unwrap() ); assert!(super::current_version().is_ok()); } + + #[test] + fn pick_asset() { + let asset_names = [ + "firezone-client-gui-linux_1.0.0-pre.14_aarch64.deb", + "firezone-client-gui-linux_1.0.0-pre.14_x86_64.deb", + "firezone-client-gui-windows_1.0.0-pre.14_aarch64.msi", + "firezone-client-gui-windows_1.0.0-pre.14_x86_64.msi", + "firezone-client-headless-linux_1.0.0-pre.14_aarch64.deb", + "firezone-client-headless-linux_1.0.0-pre.14_x86_64.deb", + "firezone-client-headless-windows_1.0.0-pre.14_aarch64.msi", + "firezone-client-headless-windows_1.0.0-pre.14_x86_64.msi", + "firezone-gateway-linux_1.0.0-pre.14_aarch64.deb", + "firezone-gateway-linux_1.0.0-pre.14_x86_64.deb", + "firezone-gateway-windows_1.0.0-pre.14_aarch64.msi", + "firezone-gateway-windows_1.0.0-pre.14_x86_64.msi", + ]; + + let product = "client-gui"; + let arch = "x86_64"; + let os = "windows"; + let package = "msi"; + + let prefix = format!("firezone-{product}-{os}_"); + let suffix = format!("_{arch}.{package}"); + + let mut iter = asset_names + .into_iter() + .filter(|x| x.starts_with(&prefix) && x.ends_with(&suffix)); + let asset_name = iter.next().unwrap(); + assert!(iter.next().is_none()); + + assert_eq!( + asset_name, + "firezone-client-gui-windows_1.0.0-pre.14_x86_64.msi" + ); + } } diff --git a/scripts/Makefile b/scripts/Makefile index 81d603e88..abdd208f0 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -22,10 +22,10 @@ android-version: @find kotlin/ -name "*.gradle.kts" -exec sed $(SEDARG) -e '/mark:automatic-version/{n;s/versionName =.*/versionName = "$(android-version)"/;}' {} \; cargo-version: - @find rust/ -name "Cargo.toml" -exec sed $(SEDARG) -e '/mark:automatic-version/{n;s/[0-9]*\.[0-9]*\.[0-9]*/$(rust-version)/;}' {} \; - # TODO: This can fail on some platforms. You may need to specify the package - # to avoid hitting the wrong codepaths for your platform. - @cd rust && cargo check + @# The website hosts permalinks to our published packages and binaries + @find website/ -name "redirects.js" -exec sed $(SEDARG) -e '/mark:automatic-version/{n;s/[0-9]*\.[0-9]*\.[0-9]*/$(cargo-version)/g;}' {} \; + @find rust/ -name "Cargo.toml" -exec sed $(SEDARG) -e '/mark:automatic-version/{n;s/[0-9]*\.[0-9]*\.[0-9]*/$(cargo-version)/;}' {} \; + @cd rust && cargo update --workspace ci-version: @find .github/ -name "*.yml" -exec sed $(SEDARG) -e '/mark:automatic-version/{n;s/[0-9]*\.[0-9]*\.[0-9]*/$(ci-version)/;}' {} \; diff --git a/scripts/build/tauri-rename-windows.sh b/scripts/build/tauri-rename-windows.sh index 7f0e64c5c..3a7efae61 100755 --- a/scripts/build/tauri-rename-windows.sh +++ b/scripts/build/tauri-rename-windows.sh @@ -1,19 +1,19 @@ #!/usr/bin/env bash -set -euo pipefail +set -euox pipefail # For debugging ls ../target/release ../target/release/bundle/msi # Used for release artifact # In release mode the name comes from tauri.conf.json -cp ../target/release/Firezone.exe "$BINARY_DEST_PATH-x64.exe" -cp ../target/release/bundle/msi/*.msi "$BINARY_DEST_PATH-x64.msi" -cp ../target/release/firezone_gui_client.pdb "$BINARY_DEST_PATH-x64.pdb" +cp ../target/release/Firezone.exe "$BINARY_DEST_PATH-x86_64.exe" +cp ../target/release/bundle/msi/*.msi "$BINARY_DEST_PATH-x86_64.msi" +cp ../target/release/firezone_gui_client.pdb "$BINARY_DEST_PATH-x86_64.pdb" function make_hash() { sha256sum "$1"> "$1.sha256sum.txt" } -make_hash "$BINARY_DEST_PATH-x64.exe" -make_hash "$BINARY_DEST_PATH-x64.msi" -make_hash "$BINARY_DEST_PATH-x64.pdb" +make_hash "$BINARY_DEST_PATH-x86_64.exe" +make_hash "$BINARY_DEST_PATH-x86_64.msi" +make_hash "$BINARY_DEST_PATH-x86_64.pdb" diff --git a/scripts/build/tauri-upload-windows.sh b/scripts/build/tauri-upload-windows.sh index a797f078e..f433e7761 100755 --- a/scripts/build/tauri-upload-windows.sh +++ b/scripts/build/tauri-upload-windows.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash -set -euo pipefail +set -euox pipefail # This artifact name is tied to the update checker in `gui-client/src-tauri/src/client/updates.rs` # So we can't put the version number in it until we stop using Github for update checks. gh release upload "$TAG_NAME" \ - "$BINARY_DEST_PATH"-x64.msi \ - "$BINARY_DEST_PATH"-x64.msi.sha256sum.txt \ + "$BINARY_DEST_PATH"_"$TAG_NAME"_x86_64.msi \ + "$BINARY_DEST_PATH"_"$TAG_NAME"_x86_64.msi.sha256sum.txt \ --clobber \ --repo "$REPOSITORY" diff --git a/scripts/gateway-systemd-install.sh b/scripts/gateway-systemd-install.sh index c44f1c670..ed9816c83 100755 --- a/scripts/gateway-systemd-install.sh +++ b/scripts/gateway-systemd-install.sh @@ -57,21 +57,9 @@ set -ue if [ ! -e /usr/local/bin/firezone-gateway ]; then echo "/usr/local/bin/firezone-gateway not found. Downloading latest version..." arch=\$(uname -m) - case \$arch in - aarch64) - bin="gateway-arm64" - ;; - armv7l) - bin="gateway-arm" - ;; - x86_64) - bin="gateway-x64" - ;; - *) - echo "Unsupported architecture" - exit 1 - esac - curl -Ls https://github.com/firezone/firezone/releases/latest/download/\$bin -o /usr/local/bin/firezone-gateway + + # See https://www.github.com/firezone/firezone/releases for available binaries + curl -fsSL https://www.firezone.dev/dl/firezone-gateway/latest/\$arch -o /usr/local/bin/firezone-gateway else echo "/usr/local/bin/firezone-gateway found. Skipping download." fi diff --git a/website/next.config.mjs b/website/next.config.mjs index 7b18db623..bfc920bcc 100644 --- a/website/next.config.mjs +++ b/website/next.config.mjs @@ -4,6 +4,7 @@ import remarkGfm from "remark-gfm"; import remarkParse from "remark-parse"; import rehypeStringify from "rehype-stringify"; import rehypeHighlight from "rehype-highlight"; +import redirects from "./redirects.js"; // Add IDs to headings import rehypeSlug from "rehype-slug"; @@ -34,6 +35,9 @@ const nextConfig = { experimental: { typedRoutes: true, }, + async redirects() { + return redirects; + }, // Proxy GitHub requests to avoid CORS issues async rewrites() { return [ diff --git a/website/redirects.js b/website/redirects.js new file mode 100644 index 000000000..9af03801c --- /dev/null +++ b/website/redirects.js @@ -0,0 +1,142 @@ +// Add all server-side redirects here. Will be loaded by next.config.mjs. + +module.exports = [ + /* + * + * Windows Client + * + */ + // latest + { + source: "/dl/firezone-client-gui-windows/latest/x86_64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-client-gui-windows_1.0.0_x86_64.msi", + permanent: false, + }, + // versioned + { + source: "/dl/firezone-client-gui-windows/:version/x86_64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-client-gui-windows_:version_x86_64.msi", + permanent: false, + }, + /* + * + * Linux Client + * + */ + // latest + { + source: "/dl/firezone-client-gui-linux/latest/x86_64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-client-gui-linux_1.0.0_x86_64.deb", + permanent: false, + }, + { + source: "/dl/firezone-client-gui-linux/latest/aarch64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-client-gui-linux_1.0.0_aarch64.deb", + permanent: false, + }, + { + source: "/dl/firezone-client-headless-linux/latest/x86_64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-client-headless-linux_1.0.0_x86_64", + permanent: false, + }, + { + source: "/dl/firezone-client-headless-linux/latest/aarch64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-client-headless-linux_1.0.0_aarch64", + permanent: false, + }, + { + source: "/dl/firezone-client-headless-linux/latest/armv7", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-client-headless-linux_1.0.0_armv7", + permanent: false, + }, + // versioned + { + source: "/dl/firezone-client-gui-linux/:version/x86_64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-client-gui-linux_:version_x86_64.deb", + permanent: false, + }, + { + source: "/dl/firezone-client-gui-linux/:version/aarch64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-client-gui-linux_:version_aarch64.deb", + permanent: false, + }, + { + source: "/dl/firezone-client-headless-linux/:version/x86_64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-client-headless-linux_:version_x86_64", + permanent: false, + }, + { + source: "/dl/firezone-client-headless-linux/:version/aarch64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-client-headless-linux_:version_aarch64", + permanent: false, + }, + { + source: "/dl/firezone-client-headless-linux/:version/armv7", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-client-headless-linux_:version_armv7", + permanent: false, + }, + /* + * + * Gateway + * + */ + // latest + { + source: "/dl/firezone-gateway/latest/x86_64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-gateway_1.0.0_x86_64", + permanent: false, + }, + { + source: "/dl/firezone-gateway/latest/aarch64", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-gateway_1.0.0_aarch64", + permanent: false, + }, + { + source: "/dl/firezone-gateway/latest/armv7", + destination: + // mark:automatic-version + "https://www.github.com/firezone/firezone/releases/download/1.0.0/firezone-gateway_1.0.0_armv7", + permanent: false, + }, + // versioned + { + source: "/dl/firezone-gateway/:version/x86_64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-gateway_:version_x86_64", + permanent: false, + }, + { + source: "/dl/firezone-gateway/:version/aarch64", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-gateway_:version_aarch64", + permanent: false, + }, + { + source: "/dl/firezone-gateway/:version/armv7", + destination: + "https://www.github.com/firezone/firezone/releases/download/:version/firezone-gateway_:version_armv7", + permanent: false, + }, +]; diff --git a/website/src/app/blog/mar-2024-update/readme.mdx b/website/src/app/blog/mar-2024-update/readme.mdx index 04eaf901f..d51146678 100644 --- a/website/src/app/blog/mar-2024-update/readme.mdx +++ b/website/src/app/blog/mar-2024-update/readme.mdx @@ -39,8 +39,7 @@ The Firezone Windows client is now available for beta testing! You'll need Windows 10 or higher and an x86-64 CPU to run the client. [See the docs](/kb/user-guides/windows-client) for more information and download -links, or use -[this direct link](https://github.com/firezone/firezone/releases/latest/download/firezone-windows-client-x64.msi) +links, or use [this direct link](/dl/firezone-client-gui-windows/latest/x86_64) to get started right away. **Note**: Be sure to click **Allow** when prompted by the User Account Control diff --git a/website/src/app/kb/user-guides/linux-client/readme.mdx b/website/src/app/kb/user-guides/linux-client/readme.mdx index cf990299d..d655c915f 100644 --- a/website/src/app/kb/user-guides/linux-client/readme.mdx +++ b/website/src/app/kb/user-guides/linux-client/readme.mdx @@ -21,9 +21,9 @@ The Linux Client is currently in beta and can be downloaded from our [main repository's releases page](https://github.com/firezone/firezone/releases). Alternatively, download the latest Client binary using one of the links below: -- [Download the Linux Client for `x86-64`](https://github.com/firezone/firezone/releases/latest/download/linux-client-x64) -- [Download the Linux Client for `ARMv7l`](https://github.com/firezone/firezone/releases/latest/download/linux-client-arm) -- [Download the Linux Client for `ARM64`](https://github.com/firezone/firezone/releases/latest/download/linux-client-arm64) +- [Download the Linux Client for `x86-64`](/dl/firezone-client-headless-linux/latest/x86_64) +- [Download the Linux Client for `ARMv7l`](/dl/firezone-client-headless-linux/latest/armv7) +- [Download the Linux Client for `ARM64`](/dl/firezone-client-headless/linux/latest/aarch64) ## Usage diff --git a/website/src/app/kb/user-guides/windows-client/readme.mdx b/website/src/app/kb/user-guides/windows-client/readme.mdx index 086825098..c42b8df29 100644 --- a/website/src/app/kb/user-guides/windows-client/readme.mdx +++ b/website/src/app/kb/user-guides/windows-client/readme.mdx @@ -13,7 +13,7 @@ architecture. The Windows Client is currently in beta and can be downloaded from the following link: -- [Download the MSI installer package](https://github.com/firezone/firezone/releases/latest/download/firezone-windows-client-x64.msi) +- [Download the MSI installer package](/dl/firezone-client-gui-windows/latest/x86_64) ## Usage