From 15b13aa572828fe7a4f8f9cd0653cadf86c6ac0a Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 28 Nov 2025 21:34:45 +0100 Subject: [PATCH 1/5] download: Move URL generation to runtime ... and add tests for part of it. --- src/micromamba/download.rs | 106 ++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 18 deletions(-) diff --git a/src/micromamba/download.rs b/src/micromamba/download.rs index ac9e9c1..6f7c9f6 100644 --- a/src/micromamba/download.rs +++ b/src/micromamba/download.rs @@ -3,6 +3,7 @@ use crate::csmrc::Config; use log::{debug, info}; use rustls::ClientConfig; use rustls_platform_verifier::ConfigVerifierExt; +use std::env; use std::error::Error; use std::fmt; use std::fs; @@ -100,29 +101,37 @@ fn csm_cache_dir(config: &Config) -> io::Result { Ok(cache) } -/// Determine the download URL for micromamba -fn micromamba_url() -> Result { - let os_arch = if cfg!(target_os = "linux") { - if cfg!(target_arch = "x86_64") { - "linux-64" - } else if cfg!(target_arch = "aarch64") { - "linux-aarch64" - } else { - return Err(DownloadError::IncompatibleArch); +struct OsArch { + os: &'static str, + arch: &'static str, +} + +impl OsArch { + pub fn from_env() -> Self { + OsArch { + os: env::consts::OS, + arch: env::consts::ARCH, } - } else if cfg!(target_os = "windows") { - if cfg!(target_arch = "x86_64") { - "win-64" - } else { - return Err(DownloadError::IncompatibleArch); + } + + fn micromamba_url_path(&self) -> Result<&'static str, DownloadError> { + match (self.os, self.arch) { + ("windows", "x86_64") => Ok("win-64"), + ("windows", _) => Err(DownloadError::IncompatibleArch), + ("linux", "x86_64") => Ok("linux-64"), + ("linux", "aarch64") => Ok("linux-aarch64"), + ("linux", _) => Err(DownloadError::IncompatibleArch), + _ => Err(DownloadError::IncompatibleOS), } - } else { - return Err(DownloadError::IncompatibleOS); - }; + } +} +/// Determine the download URL for micromamba +fn micromamba_url() -> Result { + let os_arch = OsArch::from_env().micromamba_url_path()?; Ok(format!( "https://micro.mamba.pm/api/micromamba/{}/latest", - os_arch + os_arch, )) } @@ -213,3 +222,64 @@ pub fn download_micromamba(config: &Config) -> Result { let entry = find_micromamba_in_archive(&mut tar_archive)?; write_micromamba(config, entry) } + +#[cfg(test)] +mod tests { + use super::{DownloadError, OsArch}; + + #[test] + fn test_os_arch_micromamba_url_path() { + let green_path_cases = [ + ("linux", "aarch64", "linux-aarch64"), + ("linux", "x86_64", "linux-64"), + ("windows", "x86_64", "win-64"), + ]; + for (os, arch, expected) in green_path_cases { + let os_arch = OsArch { os, arch }; + assert!( + matches!(os_arch.micromamba_url_path(), Ok(s) if s == expected), + "{}, {}", + os, + arch + ); + } + + let incompat_arch_cases = [ + ("linux", "m68k"), + ("windows", "aarch64"), + ("windows", "arm"), + ]; + for (os, arch) in incompat_arch_cases { + let os_arch = OsArch { os, arch }; + assert!( + matches!( + os_arch.micromamba_url_path(), + Err(DownloadError::IncompatibleArch), + ), + "{}, {}", + os, + arch + ); + } + + let incompat_os_cases = [ + ("freebsd", "m68k"), + ("openbsd", "aarch64"), + ("android", "arm"), + ("beos", "powerpc64"), + ("haiku", "powerpc"), + ]; + for (os, arch) in incompat_os_cases { + let os_arch = OsArch { os, arch }; + assert!( + matches!( + os_arch.micromamba_url_path(), + Err(DownloadError::IncompatibleOS), + ), + "{}, {}", + os, + arch + ); + } + } +} From efb368e6462bbebcac4bd4662f54f925d4777a24 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 28 Nov 2025 22:48:35 +0100 Subject: [PATCH 2/5] download: url generation for macos --- src/micromamba/download.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/micromamba/download.rs b/src/micromamba/download.rs index 6f7c9f6..e61711d 100644 --- a/src/micromamba/download.rs +++ b/src/micromamba/download.rs @@ -121,6 +121,9 @@ impl OsArch { ("linux", "x86_64") => Ok("linux-64"), ("linux", "aarch64") => Ok("linux-aarch64"), ("linux", _) => Err(DownloadError::IncompatibleArch), + ("macos", "x86_64") => Ok("osx-64"), + ("macos", "aarch64") => Ok("osx-arm64"), + ("macos", _) => Err(DownloadError::IncompatibleArch), _ => Err(DownloadError::IncompatibleOS), } } @@ -233,6 +236,8 @@ mod tests { ("linux", "aarch64", "linux-aarch64"), ("linux", "x86_64", "linux-64"), ("windows", "x86_64", "win-64"), + ("macos", "aarch64", "osx-arm64"), + ("macos", "x86_64", "osx-64"), ]; for (os, arch, expected) in green_path_cases { let os_arch = OsArch { os, arch }; @@ -248,6 +253,8 @@ mod tests { ("linux", "m68k"), ("windows", "aarch64"), ("windows", "arm"), + ("macos", "powerpc64"), + ("macos", "powerpc"), ]; for (os, arch) in incompat_arch_cases { let os_arch = OsArch { os, arch }; From 1be853f2c7f618e6d80bc6e17d760d4e5d8a20cc Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 28 Nov 2025 23:08:36 +0100 Subject: [PATCH 3/5] ci: add macos to the build matrix --- .github/workflows/ci-reusable.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/ci-reusable.yml b/.github/workflows/ci-reusable.yml index ba064ca..39d8858 100644 --- a/.github/workflows/ci-reusable.yml +++ b/.github/workflows/ci-reusable.yml @@ -49,3 +49,24 @@ jobs: if: always() - run: cargo build --release --features=__test_powershell if: always() + + macos: + runs-on: macos-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: clippy, rustfmt + rustflags: "" + - uses: mamba-org/setup-micromamba@v2 + env: + ACTIONS_STEP_DEBUG: true + - run: cargo test --no-default-features --features=__test_zsh + if: always() + - run: cargo fmt --check + if: always() + - run: cargo clippy --all-targets + if: always() + - run: cargo build --release --features=__test_zsh + if: always() From c197d6eb6dff6059a6d801c4e2cf5141870961e5 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 28 Nov 2025 23:14:21 +0100 Subject: [PATCH 4/5] download: Fix more conditionals for macos --- src/micromamba/download.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/micromamba/download.rs b/src/micromamba/download.rs index e61711d..1c966e3 100644 --- a/src/micromamba/download.rs +++ b/src/micromamba/download.rs @@ -74,7 +74,7 @@ impl fmt::Display for DownloadError { /// OS-target-specific: Return the final executable name #[inline] const fn micromamba_executable_name() -> Result<&'static str, DownloadError> { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "macos")) { Ok("micromamba") } else if cfg!(target_os = "windows") { Ok("micromamba.exe") @@ -169,7 +169,7 @@ fn write_micromamba( fn find_micromamba_in_archive<'a, R: Read>( tar_archive: &'a mut tar::Archive, ) -> Result, DownloadError> { - let archive_binary_dir = if cfg!(target_os = "linux") { + let archive_binary_dir = if cfg!(any(target_os = "linux", target_os = "macos")) { PathBuf::from("bin") } else if cfg!(target_os = "windows") { PathBuf::from("Library").join("bin") From 4579db727349848b39dc4f4fc5eebc57951c4270 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 28 Nov 2025 23:20:10 +0100 Subject: [PATCH 5/5] ci: add macos to release matrix Signed-off-by: Rick Elrod --- .github/workflows/release.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d50ce7..7b0ff3e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,6 +46,12 @@ jobs: - runs-on: ubuntu-latest target: aarch64-unknown-linux-musl + - runs-on: macos-latest + target: x86_64-apple-darwin + + - runs-on: macos-latest + target: aarch64-apple-darwin + steps: - uses: actions/checkout@v4 @@ -63,8 +69,8 @@ jobs: - name: Clean build cache run: cargo clean - - name: Build (Windows) - if: ${{ matrix.runs-on == 'windows-latest' }} + - name: Build (Windows, macOS) + if: ${{ matrix.runs-on != 'ubuntu-latest' }} run: cargo build --release --all-features --target=${{ matrix.target }} - name: Build (Linux, cross compile) @@ -80,9 +86,9 @@ jobs: cp target/${{ matrix.target }}/release/csm.exe release/ Compress-Archive -Path release/ -DestinationPath csm-${{ github.ref_name }}-${{ matrix.target }}.zip - - name: Create a tar.gz (linux) + - name: Create a tar.gz (Linux, macOS) id: create-tar - if: ${{ matrix.runs-on == 'ubuntu-latest' }} + if: ${{ matrix.runs-on != 'windows-latest' }} run: | mkdir release cp LICENSE release/ @@ -108,6 +114,7 @@ jobs: include: - runs-on: windows-latest - runs-on: ubuntu-latest + - runs-on: macos-latest steps: - name: Try latest release (linux) if: ${{ matrix.runs-on == 'ubuntu-latest' }} @@ -116,6 +123,13 @@ jobs: tar -xvf csm-*.tar.gz ./release/csm --version + - name: Try latest release (macOS) + if: ${{ matrix.runs-on == 'macos-latest' }} + run: | + wget https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/csm-${{ github.ref_name }}-aarch64-apple-darwin.tar.gz + tar -xvf csm-*.tar.gz + ./release/csm --version + - name: Try latest release (windows) if: ${{ matrix.runs-on == 'windows-latest' }} run: |