diff --git a/.github/workflows/ci-rust.yml b/.github/workflows/ci-rust.yml index 6b165b69cc05f..3c11bf0e51c83 100644 --- a/.github/workflows/ci-rust.yml +++ b/.github/workflows/ci-rust.yml @@ -35,6 +35,7 @@ jobs: include: - os: macos - os: ubuntu + - os: ubuntu-24.04-arm - os: windows with: name: Tests (${{ matrix.os }}) @@ -119,17 +120,28 @@ jobs: - name: "Install cross" run: | cargo install cross --git https://github.com/cross-rs/cross - - name: "Build release binary" + - name: "Build release binary (x64)" run: cross build --target x86_64-unknown-linux-musl --release working-directory: rust + - name: "Build release binary (arm64)" + run: cross build --target aarch64-unknown-linux-musl --release + working-directory: rust - name: "Rename binary" - run: mv rust/target/x86_64-unknown-linux-musl/release/selenium-manager selenium-manager-linux + run: | + mv rust/target/x86_64-unknown-linux-musl/release/selenium-manager selenium-manager-linux + mv rust/target/aarch64-unknown-linux-musl/release/selenium-manager selenium-manager-linux-arm64 - name: "Upload release binary" uses: actions/upload-artifact@v4 with: name: selenium-manager-linux path: selenium-manager-linux retention-days: 6 + - name: "Upload release binary" + uses: actions/upload-artifact@v4 + with: + name: selenium-manager-linux-arm64 + path: selenium-manager-linux-arm64 + retention-days: 6 linux-debug: name: "Linux Debug" @@ -148,18 +160,30 @@ jobs: - name: "Install cross" run: | cargo install cross --git https://github.com/cross-rs/cross - - name: "Build release binary" + - name: "Build release binary (x64)" run: | cross build --target x86_64-unknown-linux-musl --profile dev cd target/x86_64-unknown-linux-musl/debug tar -cvf ../../../../selenium-manager-linux-debug.tar selenium-manager working-directory: rust + - name: "Build release binary (arm64)" + run: | + cross build --target aarch64-unknown-linux-musl --profile dev + cd target/aarch64-unknown-linux-musl/debug + tar -cvf ../../../../selenium-manager-linux-arm64-debug.tar selenium-manager + working-directory: rust - name: "Upload release binary" uses: actions/upload-artifact@v4 with: name: selenium-manager-linux-debug path: selenium-manager-linux-debug.tar retention-days: 6 + - name: "Upload release binary" + uses: actions/upload-artifact@v4 + with: + name: selenium-manager-linux-arm64-debug + path: selenium-manager-linux-arm64-debug.tar + retention-days: 6 macos-stable: name: "MacOS Stable" @@ -245,9 +269,10 @@ jobs: - name: "Prepare and Commit" run: | linux_sha=$(shasum -a 256 artifacts/selenium-manager-linux/selenium-manager-linux | awk '{print $1}') + linux_arm64_sha=$(shasum -a 256 artifacts/selenium-manager-linux-arm64/selenium-manager-linux-arm64 | awk '{print $1}') macos_sha=$(shasum -a 256 artifacts/selenium-manager-macos/selenium-manager-macos | awk '{print $1}') windows_sha=$(shasum -a 256 artifacts/selenium-manager-windows/selenium-manager-windows.exe | awk '{print $1}') - echo "{\"macos\": \"$macos_sha\", \"windows\": \"$windows_sha\", \"linux\": \"$linux_sha\"}" > latest.json + echo "{\"macos\": \"$macos_sha\", \"windows\": \"$windows_sha\", \"linux\": \"$linux_sha\", \"linux-arm64\": \"$linux_arm64_sha\" }" > latest.json git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" git add latest.json @@ -266,6 +291,7 @@ jobs: prerelease: false files: | artifacts/selenium-manager-linux/selenium-manager-linux + artifacts/selenium-manager-linux-arm64/selenium-manager-linux-arm64 artifacts/selenium-manager-macos/selenium-manager-macos artifacts/selenium-manager-windows/selenium-manager-windows.exe artifacts/selenium-manager-linux-debug/selenium-manager-linux-debug.tar diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 9467faa6d091b..3aad66ae6144b 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -383,6 +383,10 @@ impl SeleniumManager for ChromeManager { } else { "mac64" } + } else if LINUX.is(os) && ARM64.is(arch) { + return Err(anyhow!( + "Linux arm64 is not supported yet by Google Chrome. Please try another browser." + )); } else { "linux64" }; diff --git a/rust/src/edge.rs b/rust/src/edge.rs index 3c26d2f666fc4..a77cdccc8ee74 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -28,6 +28,7 @@ use crate::{ DASH_DASH_VERSION, DEV, ENV_PROGRAM_FILES_X86, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_PV_ARG, REG_VERSION_ARG, STABLE, }; +use anyhow::anyhow; use anyhow::Error; use reqwest::Client; use serde::{Deserialize, Serialize}; @@ -288,6 +289,10 @@ impl SeleniumManager for EdgeManager { } else { "mac64" } + } else if LINUX.is(os) && ARM64.is(arch) { + return Err(anyhow!( + "Linux arm64 is not supported yet by Microsoft Edge. Please try another browser." + )); } else { "linux64" }; diff --git a/rust/tests/browser_download_tests.rs b/rust/tests/browser_download_tests.rs index 23214694a4218..d72cbebef37e0 100644 --- a/rust/tests/browser_download_tests.rs +++ b/rust/tests/browser_download_tests.rs @@ -18,6 +18,7 @@ use crate::common::{assert_browser, assert_driver, get_selenium_manager}; use rstest::rstest; +use std::env::consts::ARCH; use std::env::consts::OS; mod common; @@ -27,23 +28,27 @@ mod common; #[case("firefox")] #[case("edge")] fn browser_latest_download_test(#[case] browser: String) { - if !browser.eq("edge") || !OS.eq("windows") { - let mut cmd = get_selenium_manager(); - cmd.args([ - "--browser", - &browser, - "--force-browser-download", - "--output", - "json", - "--debug", - ]) - .assert() - .success() - .code(0); - - assert_driver(&mut cmd); - assert_browser(&mut cmd); + if browser.eq("edge") && OS.eq("windows") { + return; + } else if OS.eq("linux") && ARCH.eq("aarch64") && !browser.eq("firefox") { + return; } + + let mut cmd = get_selenium_manager(); + cmd.args([ + "--browser", + &browser, + "--force-browser-download", + "--output", + "json", + "--debug", + ]) + .assert() + .success() + .code(0); + + assert_driver(&mut cmd); + assert_browser(&mut cmd); } #[rstest] @@ -59,6 +64,8 @@ fn browser_latest_download_test(#[case] browser: String) { fn browser_version_download_test(#[case] browser: String, #[case] browser_version: String) { if OS.eq("windows") && browser.eq("edge") { println!("Skipping Edge download test on Windows since the installation requires admin privileges"); + } else if OS.eq("linux") && ARCH.eq("aarch64") && !browser.eq("firefox") { + println!("Skipping non-Firefox download test on Linux arm64 since no other browsers are supported yet"); } else { let mut cmd = get_selenium_manager(); cmd.args([ diff --git a/rust/tests/browser_tests.rs b/rust/tests/browser_tests.rs index 13bf093a12564..be9f7d9c01e91 100644 --- a/rust/tests/browser_tests.rs +++ b/rust/tests/browser_tests.rs @@ -19,6 +19,7 @@ use crate::common::{assert_output, get_selenium_manager, get_stdout}; use exitcode::DATAERR; use rstest::rstest; +use std::env::consts::ARCH; use std::env::consts::OS; use std::path::Path; @@ -40,6 +41,10 @@ fn browser_version_test( #[case] browser_version: String, #[case] driver_version: String, ) { + if OS.eq("linux") && ARCH.eq("aarch64") && !browser.eq("firefox") { + return; + } + let mut cmd = get_selenium_manager(); cmd.args([ "--browser", @@ -78,6 +83,10 @@ fn wrong_parameters_test( #[case] driver_version: String, #[case] error_code: i32, ) { + if OS.eq("linux") && ARCH.eq("aarch64") && !browser.eq("firefox") { + return; + } + let mut cmd = get_selenium_manager(); let result = cmd .args([ diff --git a/rust/tests/cache_tests.rs b/rust/tests/cache_tests.rs index 68478fb73826f..18ef1ad23aa4f 100644 --- a/rust/tests/cache_tests.rs +++ b/rust/tests/cache_tests.rs @@ -23,6 +23,7 @@ use std::path::Path; mod common; +#[cfg(not(all(target_os = "linux", target_arch = "aarch64")))] #[rstest] #[case("../tmp")] #[case("../áèîö")] diff --git a/rust/tests/common.rs b/rust/tests/common.rs index ae8c820b1d4e6..746de1d8c7aa3 100644 --- a/rust/tests/common.rs +++ b/rust/tests/common.rs @@ -23,6 +23,7 @@ use selenium_manager::logger::JsonOutput; use selenium_manager::shell; use selenium_manager::shell::run_shell_command_by_os; use std::borrow::BorrowMut; +use std::env::consts::ARCH; use std::env::consts::OS; use std::path::{Path, PathBuf}; @@ -119,3 +120,8 @@ pub fn assert_output( .contains(&error_code.to_string())); } } + +#[allow(dead_code)] +pub fn is_linux_arm64() -> bool { + OS == "linux" && ARCH == "aarch64" +} diff --git a/rust/tests/config_tests.rs b/rust/tests/config_tests.rs index df41f9c29bf01..ad872a2eb1af2 100644 --- a/rust/tests/config_tests.rs +++ b/rust/tests/config_tests.rs @@ -19,6 +19,8 @@ use crate::common::{assert_browser, assert_driver, get_selenium_manager, get_std use rstest::rstest; +use std::env::consts::ARCH; +use std::env::consts::OS; use std::fs::File; use std::io::{BufWriter, Write}; use tempfile::Builder; @@ -30,6 +32,9 @@ mod common; #[case("firefox")] #[case("edge")] fn config_test(#[case] browser_name: String) { + if OS.eq("linux") && ARCH.eq("aarch64") && !browser_name.eq("firefox") { + return; + } let tmp_dir = Builder::new().prefix("sm-config-test").tempdir().unwrap(); let config_path = tmp_dir.path().join("se-config.toml"); let config_file = File::create(config_path.as_path()).unwrap(); diff --git a/rust/tests/exec_driver_tests.rs b/rust/tests/exec_driver_tests.rs index da6db43ecb304..33e394730f838 100644 --- a/rust/tests/exec_driver_tests.rs +++ b/rust/tests/exec_driver_tests.rs @@ -18,6 +18,7 @@ use crate::common::{assert_browser, assert_driver, exec_driver, get_selenium_manager}; use rstest::rstest; +use std::env::consts::ARCH; use std::env::consts::OS; mod common; @@ -28,6 +29,10 @@ mod common; #[case("firefox", "geckodriver")] #[case("iexplorer", "IEDriverServer")] fn exec_driver_test(#[case] browser_name: String, #[case] driver_name: String) { + if OS.eq("linux") && ARCH.eq("aarch64") && !browser_name.eq("firefox") { + return; + } + let mut cmd = get_selenium_manager(); cmd.args(["--browser", &browser_name, "--output", "json"]) .assert() diff --git a/rust/tests/mirror_tests.rs b/rust/tests/mirror_tests.rs index 127fb37f17b86..737a9413462ff 100644 --- a/rust/tests/mirror_tests.rs +++ b/rust/tests/mirror_tests.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use crate::common::{assert_driver, get_selenium_manager}; +use crate::common::{assert_driver, get_selenium_manager, is_linux_arm64}; mod common; @@ -24,7 +24,11 @@ fn mirror_test() { let mut cmd = get_selenium_manager(); cmd.args([ "--browser", - "chrome", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, "--driver-mirror-url", "https://registry.npmmirror.com/-/binary/chromedriver/", "--browser-version", diff --git a/rust/tests/offline_tests.rs b/rust/tests/offline_tests.rs index 2d1020a4532f3..114b8e9982117 100644 --- a/rust/tests/offline_tests.rs +++ b/rust/tests/offline_tests.rs @@ -15,17 +15,26 @@ // specific language governing permissions and limitations // under the License. -use crate::common::{get_selenium_manager, get_stdout}; +use crate::common::{get_selenium_manager, get_stdout, is_linux_arm64}; mod common; #[test] fn offline_test() { let mut cmd = get_selenium_manager(); - cmd.args(["--debug", "--browser", "chrome", "--offline"]) - .assert() - .success() - .code(0); + cmd.args([ + "--debug", + "--browser", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, + "--offline", + ]) + .assert() + .success() + .code(0); let stdout = get_stdout(&mut cmd); diff --git a/rust/tests/output_tests.rs b/rust/tests/output_tests.rs index 96eb7104c5d21..a99f247aa6393 100644 --- a/rust/tests/output_tests.rs +++ b/rust/tests/output_tests.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use crate::common::{get_selenium_manager, get_stderr, get_stdout}; +use crate::common::{get_selenium_manager, get_stderr, get_stdout, is_linux_arm64}; use selenium_manager::logger::{JsonOutput, MinimalJson, DRIVER_PATH}; use std::path::Path; @@ -25,10 +25,19 @@ mod common; #[test] fn json_output_test() { let mut cmd = get_selenium_manager(); - cmd.args(["--browser", "chrome", "--output", "json"]) - .assert() - .success() - .code(0); + cmd.args([ + "--browser", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, + "--output", + "json", + ]) + .assert() + .success() + .code(0); let stdout = get_stdout(&mut cmd); @@ -45,10 +54,19 @@ fn json_output_test() { #[test] fn shell_output_test() { let mut cmd = get_selenium_manager(); - cmd.args(["--browser", "chrome", "--output", "shell"]) - .assert() - .success() - .code(0); + cmd.args([ + "--browser", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, + "--output", + "shell", + ]) + .assert() + .success() + .code(0); let stdout = get_stdout(&mut cmd); assert!(stdout.contains(DRIVER_PATH)); @@ -57,10 +75,19 @@ fn shell_output_test() { #[test] fn mixed_output_test() { let mut cmd = get_selenium_manager(); - cmd.args(["--browser", "chrome", "--output", "mixed"]) - .assert() - .success() - .code(0); + cmd.args([ + "--browser", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, + "--output", + "mixed", + ]) + .assert() + .success() + .code(0); let stdout = get_stdout(&mut cmd); let json: MinimalJson = serde_json::from_str(&stdout).unwrap(); diff --git a/rust/tests/proxy_tests.rs b/rust/tests/proxy_tests.rs index f66cc0a2b1037..9e01a827de676 100644 --- a/rust/tests/proxy_tests.rs +++ b/rust/tests/proxy_tests.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use crate::common::{assert_output, get_selenium_manager}; +use crate::common::{assert_output, get_selenium_manager, is_linux_arm64}; use exitcode::DATAERR; @@ -28,7 +28,11 @@ async fn wrong_proxy_test() { .args([ "--debug", "--browser", - "chrome", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, "--proxy", "http://localhost:12345", ]) @@ -37,11 +41,21 @@ async fn wrong_proxy_test() { assert_output(&mut cmd, result, vec!["in PATH"], DATAERR); } + #[test] fn wrong_protocol_proxy_test() { let mut cmd = get_selenium_manager(); let result = cmd - .args(["--browser", "chrome", "--proxy", "wrong:://proxy"]) + .args([ + "--browser", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, + "--proxy", + "wrong:://proxy", + ]) .assert() .try_success(); @@ -54,7 +68,11 @@ fn wrong_port_proxy_test() { let result = cmd .args([ "--browser", - "chrome", + if is_linux_arm64() { + "firefox" + } else { + "chrome" + }, "--proxy", "https:://localhost:1234567", ]) diff --git a/rust/tests/stable_browser_tests.rs b/rust/tests/stable_browser_tests.rs index c51ab8720889e..05266a5798153 100644 --- a/rust/tests/stable_browser_tests.rs +++ b/rust/tests/stable_browser_tests.rs @@ -18,6 +18,8 @@ use crate::common::{assert_browser, assert_driver, get_selenium_manager}; use rstest::rstest; +use std::env::consts::ARCH; +use std::env::consts::OS; mod common; @@ -26,6 +28,10 @@ mod common; #[case("firefox")] #[case("edge")] fn stable_browser_test(#[case] browser_name: String) { + if OS.eq("linux") && ARCH.eq("aarch64") && !browser_name.eq("firefox") { + return; + } + let mut cmd = get_selenium_manager(); cmd.args([ "--browser", diff --git a/rust/tests/webview_tests.rs b/rust/tests/webview_tests.rs index 1356f6973652e..7f89b7f302c41 100644 --- a/rust/tests/webview_tests.rs +++ b/rust/tests/webview_tests.rs @@ -19,6 +19,7 @@ use crate::common::{assert_driver, get_selenium_manager}; mod common; +#[cfg(not(all(target_os = "linux", target_arch = "aarch64")))] #[test] fn webview2_test() { let mut cmd = get_selenium_manager();