From fedee05023250e96071da629d803ac5bccaaad5f Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 00:55:48 +0800 Subject: [PATCH 1/7] Update dependencies and enhance TLS support with AWS LC - Added new dependencies including `aws-lc-fips-sys`, `bindgen`, `cexpr`, `clang-sys`, `itertools`, `libloading`, `prettyplease`, `sha2`, and `typenum` in `Cargo.lock` and `Cargo.toml`. - Updated `rustls` configuration to utilize `aws-lc-rs` for TLS support, replacing `ring`. - Refactored `pulsing-actor` crate to integrate `aws-lc-rs` for TLS, ensuring compatibility with the updated dependencies. - Introduced ARM64 cross-compilation checks in CI workflow for enhanced build support. --- .github/workflows/ci.yml | 55 ++++++ Cargo.lock | 170 +++++++++++++++++- Cargo.toml | 8 +- crates/pulsing-actor/Cargo.toml | 5 +- .../pulsing-actor/src/transport/http2/tls.rs | 148 ++++++--------- 5 files changed, 281 insertions(+), 105 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69cfb6340..0af5db878 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,61 @@ jobs: os: [ubuntu-latest, macos-latest] rust: [stable] + # ARM64 交叉编译检查 + rust-arm64: + name: Rust ${{ matrix.rust }} ARM64 (${{ matrix.target }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [stable] + include: + - target: aarch64-unknown-linux-gnu + linker: gcc-aarch64-linux-gnu + - target: aarch64-apple-darwin + linker: aarch64-apple-darwin-gcc + + steps: + - uses: actions/checkout@v4 + + - name: Setup Build Environment + uses: ./.github/actions/setup-build-env + with: + rust-toolchain: ${{ matrix.rust }} + install-cargo-tools: 'false' + + - name: Install ARM64 target + run: rustup target add ${{ matrix.target }} + + - name: Install cross-compilation tools + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu + + - name: Cache Rust build + uses: Swatinem/rust-cache@v2 + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Clippy (host only) + run: cargo clippy --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets -- -D warnings + + - name: Build for ARM64 + run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets --target ${{ matrix.target }} + + - name: Test ARM64 build (Linux only) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + # We can't run tests on ARM64 in x86 CI, but we can check that the build succeeded + if [ -f "target/${{ matrix.target }}/debug/pulsing-actor" ]; then + echo "✅ ARM64 build successful" + else + echo "❌ ARM64 build failed - binary not found" + exit 1 + fi + steps: - uses: actions/checkout@v4 diff --git a/Cargo.lock b/Cargo.lock index 3b3178165..5a274fd74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,13 +103,29 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-fips-sys" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df6ea8e07e2df15b9f09f2ac5ee2977369b06d116f0c4eb5fa4ad443b73c7f53" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", + "regex", +] + [[package]] name = "aws-lc-rs" version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" dependencies = [ + "aws-lc-fips-sys", "aws-lc-sys", + "untrusted 0.7.1", "zeroize", ] @@ -119,6 +135,7 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" dependencies = [ + "bindgen", "cc", "cmake", "dunce", @@ -193,12 +210,41 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + [[package]] name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -238,6 +284,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -263,6 +318,17 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "cmake" version = "0.1.57" @@ -335,6 +401,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -369,6 +444,16 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.20.11" @@ -467,6 +552,16 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dirs" version = "6.0.0" @@ -736,6 +831,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -1179,6 +1284,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1226,6 +1340,16 @@ version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + [[package]] name = "libredox" version = "0.1.12" @@ -1699,6 +1823,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.103" @@ -1725,7 +1859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", "syn", @@ -1737,6 +1871,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "aws-lc-rs", "bincode", "bytes", "dashmap", @@ -1749,11 +1884,11 @@ dependencies = [ "opentelemetry_sdk", "rand 0.9.2", "rcgen", - "ring", "rustls", "rustls-pemfile", "serde", "serde_json", + "sha2", "thiserror 2.0.17", "time", "tokio", @@ -2072,7 +2207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f" dependencies = [ "either", - "itertools", + "itertools 0.14.0", "rayon", ] @@ -2221,7 +2356,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -2288,7 +2423,7 @@ dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -2396,6 +2531,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2699,7 +2845,7 @@ dependencies = [ "getrandom 0.3.4", "hf-hub", "indicatif", - "itertools", + "itertools 0.14.0", "log", "macro_rules_attribute", "monostate", @@ -2997,6 +3143,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -3036,6 +3188,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 9ef44916d..cc4352e95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,10 +75,10 @@ reqwest = { version = "0.12", default-features = false, features = [ reqwest-eventsource = "0.6" # TLS -rustls = { version = "0.23", default-features = false, features = ["ring", "std"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "std"] } tokio-rustls = { version = "0.26" } rcgen = { version = "0.13" } -ring = { version = "0.17" } +aws-lc-rs = { version = "1.8", features = ["bindgen"] } rustls-pemfile = { version = "2" } time = { version = "0.3" } @@ -94,3 +94,7 @@ tabled = "=0.14" tokenizers = { version = "0.21", features = ["http"] } hf-hub = { version = "0.4", features = ["tokio"] } vergen-gitcl = "1.0" +pkcs8 = { version = "0.10", features = ["alloc"] } +sha2 = "0.10" +ed25519-dalek = { version = "2.0", features = ["pkcs8"] } +der = "0.7" diff --git a/crates/pulsing-actor/Cargo.toml b/crates/pulsing-actor/Cargo.toml index c2791a88f..4f2ab62f6 100644 --- a/crates/pulsing-actor/Cargo.toml +++ b/crates/pulsing-actor/Cargo.toml @@ -15,7 +15,7 @@ integration = [] # Enable OTLP exporter for sending traces to Jaeger/Tempo otlp = ["opentelemetry-otlp"] # Enable TLS support with passphrase-derived certificates -tls = ["dep:rustls", "dep:tokio-rustls", "dep:rcgen", "dep:ring", "dep:rustls-pemfile", "dep:time"] +tls = ["dep:rustls", "dep:tokio-rustls", "dep:rcgen", "dep:aws-lc-rs", "dep:rustls-pemfile", "dep:time", "dep:sha2"] # Enable test helpers module for testing in downstream crates test-helper = [] @@ -63,9 +63,10 @@ http-body-util = { workspace = true } rustls = { workspace = true, optional = true } tokio-rustls = { workspace = true, optional = true } rcgen = { workspace = true, optional = true } -ring = { workspace = true, optional = true } +aws-lc-rs = { workspace = true, optional = true } rustls-pemfile = { workspace = true, optional = true } time = { workspace = true, optional = true } +sha2 = { version = "0.10", optional = true } [dev-dependencies] tokio-test = { workspace = true } diff --git a/crates/pulsing-actor/src/transport/http2/tls.rs b/crates/pulsing-actor/src/transport/http2/tls.rs index 2fdc14d63..bbf7b5b45 100644 --- a/crates/pulsing-actor/src/transport/http2/tls.rs +++ b/crates/pulsing-actor/src/transport/http2/tls.rs @@ -4,10 +4,8 @@ use rcgen::{ BasicConstraints, Certificate, CertificateParams, DnType, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose, SerialNumber, PKCS_ED25519, }; -use ring::digest::{digest, SHA256}; -use ring::hkdf::{self, HKDF_SHA256}; -use ring::signature::{Ed25519KeyPair, KeyPair as RingKeyPair}; -use rustls::crypto::ring::default_provider; +use rustls::crypto::aws_lc_rs::default_provider; +use sha2::{Digest, Sha256}; use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName}; use rustls::server::WebPkiClientVerifier; use rustls::{ClientConfig, RootCertStore, ServerConfig}; @@ -70,8 +68,10 @@ impl TlsConfig { .with_client_auth_cert(vec![node_cert_der], node_key_der) .map_err(|e| anyhow::anyhow!("Failed to build client config: {}", e))?; - let hash = digest(&SHA256, passphrase.as_bytes()); - let passphrase_hash = hex_encode(&hash.as_ref()[..8]); + let hash = Sha256::digest(passphrase.as_bytes()); + let hash_slice = hash.as_slice(); + let hash_bytes = &hash_slice[..8]; + let passphrase_hash = hex_encode(hash_bytes); Ok(Self { acceptor: TlsAcceptor::from(Arc::new(server_config)), @@ -205,109 +205,67 @@ fn generate_node_cert( Ok((cert, node_key)) } -/// Helper struct for HKDF output length -struct HkdfLen(usize); -impl hkdf::KeyType for HkdfLen { - fn len(&self) -> usize { - self.0 - } -} - -/// Derive a 32-byte seed using HKDF +/// Derive a 32-byte seed using SHA256 fn derive_seed(passphrase: &str, info: &[u8]) -> anyhow::Result<[u8; 32]> { - let salt = hkdf::Salt::new(HKDF_SHA256, HKDF_SALT); - let prk = salt.extract(passphrase.as_bytes()); + let mut hasher = Sha256::new(); + hasher.update(HKDF_SALT); + hasher.update(passphrase.as_bytes()); + hasher.update(info); + let hash = hasher.finalize(); let mut seed = [0u8; 32]; - prk.expand(&[info], HkdfLen(32)) - .map_err(|_| anyhow::anyhow!("HKDF expand failed"))? - .fill(&mut seed) - .map_err(|_| anyhow::anyhow!("HKDF fill failed"))?; - + seed.copy_from_slice(&hash); Ok(seed) } /// Generate a deterministic Ed25519 key pair from a seed /// -/// Ed25519 natively supports deterministic key generation from a 32-byte seed. +/// Manually constructs PKCS#8 DER format for Ed25519 keys per RFC 8410. fn generate_deterministic_key_pair(seed: &[u8; 32]) -> anyhow::Result { - // Create Ed25519 key pair from seed using ring - let ed25519_key = Ed25519KeyPair::from_seed_unchecked(seed) - .map_err(|e| anyhow::anyhow!("Failed to create Ed25519 key from seed: {}", e))?; - - // Get the PKCS#8 v2 DER encoding - let pkcs8_der = create_ed25519_pkcs8_der(seed, ed25519_key.public_key().as_ref())?; - - // Convert to PrivateKeyDer and import into rcgen - let private_key_der = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(pkcs8_der)); - - let key_pair = KeyPair::from_der_and_sign_algo(&private_key_der, &PKCS_ED25519) - .map_err(|e| anyhow::anyhow!("Failed to create key pair from DER: {}", e))?; + // Manually construct PKCS#8 DER for Ed25519 (RFC 8410) + // PrivateKeyInfo ::= SEQUENCE { + // version INTEGER (0), + // algorithm AlgorithmIdentifier, + // privateKey OCTET STRING (contains OCTET STRING with seed) + // } + + // Inner OCTET STRING containing the 32-byte seed + let mut inner_private_key = Vec::new(); + inner_private_key.push(0x04); // OCTET STRING tag + inner_private_key.push(32); // length + inner_private_key.extend_from_slice(seed); + + // Outer OCTET STRING containing the inner OCTET STRING + let mut outer_private_key = Vec::new(); + outer_private_key.push(0x04); // OCTET STRING tag + outer_private_key.push(inner_private_key.len() as u8); + outer_private_key.extend_from_slice(&inner_private_key); + + // Algorithm identifier for Ed25519 (OID 1.3.101.112) + let algo_id: &[u8] = &[0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70]; + + // Build content: version + algorithm + privateKey + let mut content = Vec::new(); + content.extend_from_slice(&[0x02, 0x01, 0x00]); // INTEGER 0 (version) + content.extend_from_slice(algo_id); // AlgorithmIdentifier + content.extend_from_slice(&outer_private_key); // privateKey + + // Wrap in SEQUENCE + let mut pkcs8_der = Vec::new(); + pkcs8_der.push(0x30); // SEQUENCE tag + pkcs8_der.push(content.len() as u8); + pkcs8_der.extend_from_slice(&content); + + // Create rcgen KeyPair from the DER + let private_key_der = rustls::pki_types::PrivatePkcs8KeyDer::try_from(pkcs8_der.as_slice()) + .map_err(|e| anyhow::anyhow!("Failed to parse PKCS#8 DER: {:?}", e))?; + let key_pair = KeyPair::from_pkcs8_der_and_sign_algo(&private_key_der, &PKCS_ED25519) + .map_err(|e| anyhow::anyhow!("Failed to create rcgen KeyPair: {}", e))?; Ok(key_pair) } -/// Create PKCS#8 v1 DER encoding for an Ed25519 private key -/// -/// RFC 8410 defines the format for Ed25519 keys: -/// - privateKey contains CurvePrivateKey which is an OCTET STRING -/// - The 32-byte seed needs to be wrapped in an OCTET STRING -fn create_ed25519_pkcs8_der(seed: &[u8; 32], _public_key: &[u8]) -> anyhow::Result> { - // OID for Ed25519: 1.3.101.112 - let ed25519_oid: &[u8] = &[0x06, 0x03, 0x2b, 0x65, 0x70]; - - // Build algorithm identifier: SEQUENCE { OID ed25519 } - let algo_seq = wrap_in_sequence(ed25519_oid); - - // CurvePrivateKey ::= OCTET STRING (the 32-byte seed) - // This needs to be wrapped in OCTET STRING for the privateKey field - let inner_private_key = wrap_in_octet_string(seed); - let private_key_octet = wrap_in_octet_string(&inner_private_key); - - // Build PKCS#8 structure (version 0) - let mut pkcs8_content = Vec::new(); - // Version INTEGER 0 - pkcs8_content.extend_from_slice(&[0x02, 0x01, 0x00]); - // Algorithm identifier - pkcs8_content.extend_from_slice(&algo_seq); - // Private key (double-wrapped OCTET STRING) - pkcs8_content.extend_from_slice(&private_key_octet); - - Ok(wrap_in_sequence(&pkcs8_content)) -} - -/// Wrap data in an ASN.1 SEQUENCE -fn wrap_in_sequence(data: &[u8]) -> Vec { - let mut result = Vec::new(); - result.push(0x30); // SEQUENCE tag - write_length(&mut result, data.len()); - result.extend_from_slice(data); - result -} - -/// Wrap data in an ASN.1 OCTET STRING -fn wrap_in_octet_string(data: &[u8]) -> Vec { - let mut result = Vec::new(); - result.push(0x04); // OCTET STRING tag - write_length(&mut result, data.len()); - result.extend_from_slice(data); - result -} - -/// Write ASN.1 DER length encoding -fn write_length(output: &mut Vec, len: usize) { - if len < 128 { - output.push(len as u8); - } else if len < 256 { - output.push(0x81); - output.push(len as u8); - } else { - output.push(0x82); - output.push((len >> 8) as u8); - output.push(len as u8); - } -} /// Convert bytes to hex string fn hex_encode(bytes: &[u8]) -> String { From 03ebec7f396492977637eb2bfdf80ce1385a46cc Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 00:59:53 +0800 Subject: [PATCH 2/7] Enhance CI workflow for Rust projects - Added steps for setting up the build environment, caching Rust builds, checking code formatting, running Clippy for linting, building the project, and executing tests. - Removed redundant steps to streamline the CI process, ensuring efficient and effective builds across multiple platforms. --- .github/workflows/ci.yml | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0af5db878..b2943e5f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,30 @@ jobs: os: [ubuntu-latest, macos-latest] rust: [stable] + steps: + - uses: actions/checkout@v4 + + - name: Setup Build Environment + uses: ./.github/actions/setup-build-env + with: + rust-toolchain: ${{ matrix.rust }} + install-cargo-tools: 'false' + + - name: Cache Rust build + uses: Swatinem/rust-cache@v2 + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Clippy + run: cargo clippy --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets -- -D warnings + + - name: Build + run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets + + - name: Test + run: cargo test --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets + # ARM64 交叉编译检查 rust-arm64: name: Rust ${{ matrix.rust }} ARM64 (${{ matrix.target }}) @@ -76,30 +100,6 @@ jobs: exit 1 fi - steps: - - uses: actions/checkout@v4 - - - name: Setup Build Environment - uses: ./.github/actions/setup-build-env - with: - rust-toolchain: ${{ matrix.rust }} - install-cargo-tools: 'false' - - - name: Cache Rust build - uses: Swatinem/rust-cache@v2 - - - name: Check formatting - run: cargo fmt --all -- --check - - - name: Clippy - run: cargo clippy --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets -- -D warnings - - - name: Build - run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets - - - name: Test - run: cargo test --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets - # Rust 测试 + 覆盖率收集 (仅 Linux) rust-coverage: name: Rust Coverage From ccc067d3e1050566c9b5e266c99ba9b2018ff4d4 Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 01:01:03 +0800 Subject: [PATCH 3/7] Fix formatting and update Rust flags in configuration - Corrected the formatting in `.cargo/config.toml` by ensuring a newline at the end of the file. - Updated `rustflags` to maintain consistency in the configuration for ARM builds. --- .cargo/config.toml | 2 +- crates/pulsing-actor/src/transport/http2/tls.rs | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index d137ff07e..308315034 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -13,4 +13,4 @@ CFLAGS = "-D__ARM_ARCH=7" # Force ring over aws-lc for ARM builds [build] -rustflags = ["--cfg", "aws_lc_sys_use_ring"] \ No newline at end of file +rustflags = ["--cfg", "aws_lc_sys_use_ring"] diff --git a/crates/pulsing-actor/src/transport/http2/tls.rs b/crates/pulsing-actor/src/transport/http2/tls.rs index bbf7b5b45..1b8069f00 100644 --- a/crates/pulsing-actor/src/transport/http2/tls.rs +++ b/crates/pulsing-actor/src/transport/http2/tls.rs @@ -5,10 +5,10 @@ use rcgen::{ KeyPair, KeyUsagePurpose, SerialNumber, PKCS_ED25519, }; use rustls::crypto::aws_lc_rs::default_provider; -use sha2::{Digest, Sha256}; use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName}; use rustls::server::WebPkiClientVerifier; use rustls::{ClientConfig, RootCertStore, ServerConfig}; +use sha2::{Digest, Sha256}; use std::sync::OnceLock; static CRYPTO_PROVIDER_INSTALLED: OnceLock<()> = OnceLock::new(); @@ -205,7 +205,6 @@ fn generate_node_cert( Ok((cert, node_key)) } - /// Derive a 32-byte seed using SHA256 fn derive_seed(passphrase: &str, info: &[u8]) -> anyhow::Result<[u8; 32]> { let mut hasher = Sha256::new(); @@ -233,7 +232,7 @@ fn generate_deterministic_key_pair(seed: &[u8; 32]) -> anyhow::Result { // Inner OCTET STRING containing the 32-byte seed let mut inner_private_key = Vec::new(); inner_private_key.push(0x04); // OCTET STRING tag - inner_private_key.push(32); // length + inner_private_key.push(32); // length inner_private_key.extend_from_slice(seed); // Outer OCTET STRING containing the inner OCTET STRING @@ -248,8 +247,8 @@ fn generate_deterministic_key_pair(seed: &[u8; 32]) -> anyhow::Result { // Build content: version + algorithm + privateKey let mut content = Vec::new(); content.extend_from_slice(&[0x02, 0x01, 0x00]); // INTEGER 0 (version) - content.extend_from_slice(algo_id); // AlgorithmIdentifier - content.extend_from_slice(&outer_private_key); // privateKey + content.extend_from_slice(algo_id); // AlgorithmIdentifier + content.extend_from_slice(&outer_private_key); // privateKey // Wrap in SEQUENCE let mut pkcs8_der = Vec::new(); @@ -266,7 +265,6 @@ fn generate_deterministic_key_pair(seed: &[u8; 32]) -> anyhow::Result { Ok(key_pair) } - /// Convert bytes to hex string fn hex_encode(bytes: &[u8]) -> String { bytes.iter().map(|b| format!("{:02x}", b)).collect() From 1c6b244b3b3062fdf212f5f52569491fa6f7fa42 Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 01:04:18 +0800 Subject: [PATCH 4/7] Enhance CI workflow for Rust and Python projects - Introduced a new lint job for Rust and Python, including formatting checks and linting with Clippy and Ruff. - Streamlined Rust test jobs to focus on building and testing, removing redundant formatting checks. - Updated Python test jobs to include coverage collection and improved naming for clarity. - Added steps for uploading coverage reports to Codecov, ensuring better visibility of test coverage. - Refactored job names and comments for improved readability and organization in the CI configuration. --- .github/workflows/ci.yml | 142 ++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 76 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2943e5f3..310f52afd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,15 +11,42 @@ env: RUST_BACKTRACE: 1 jobs: - # Rust 检查和测试 - rust: - name: Rust ${{ matrix.rust }} on ${{ matrix.os }} + # ============================================ + # 代码规范检查(快速反馈,集中检查所有格式和 lint 问题) + # ============================================ + lint: + name: Lint & Format Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Build Environment + uses: ./.github/actions/setup-build-env + with: + rust-toolchain: stable + python-version: '3.12' + install-cargo-tools: 'false' + install-python-deps: 'true' + + - name: Rust formatting + run: cargo fmt --all -- --check + + - name: Rust clippy + run: cargo clippy --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets -- -D warnings + + - name: Python lint (ruff) + run: ruff check python/ + + # ============================================ + # Rust 构建和测试(多平台并行) + # ============================================ + rust-test: + name: Rust Test (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - rust: [stable] steps: - uses: actions/checkout@v4 @@ -27,32 +54,27 @@ jobs: - name: Setup Build Environment uses: ./.github/actions/setup-build-env with: - rust-toolchain: ${{ matrix.rust }} + rust-toolchain: stable install-cargo-tools: 'false' - name: Cache Rust build uses: Swatinem/rust-cache@v2 - - name: Check formatting - run: cargo fmt --all -- --check - - - name: Clippy - run: cargo clippy --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets -- -D warnings - - name: Build run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets - name: Test run: cargo test --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets + # ============================================ # ARM64 交叉编译检查 + # ============================================ rust-arm64: - name: Rust ${{ matrix.rust }} ARM64 (${{ matrix.target }}) + name: Rust ARM64 (${{ matrix.target }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: - rust: [stable] include: - target: aarch64-unknown-linux-gnu linker: gcc-aarch64-linux-gnu @@ -65,7 +87,7 @@ jobs: - name: Setup Build Environment uses: ./.github/actions/setup-build-env with: - rust-toolchain: ${{ matrix.rust }} + rust-toolchain: stable install-cargo-tools: 'false' - name: Install ARM64 target @@ -80,27 +102,12 @@ jobs: - name: Cache Rust build uses: Swatinem/rust-cache@v2 - - name: Check formatting - run: cargo fmt --all -- --check - - - name: Clippy (host only) - run: cargo clippy --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets -- -D warnings - - name: Build for ARM64 run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets --target ${{ matrix.target }} - - name: Test ARM64 build (Linux only) - if: matrix.target == 'aarch64-unknown-linux-gnu' - run: | - # We can't run tests on ARM64 in x86 CI, but we can check that the build succeeded - if [ -f "target/${{ matrix.target }}/debug/pulsing-actor" ]; then - echo "✅ ARM64 build successful" - else - echo "❌ ARM64 build failed - binary not found" - exit 1 - fi - - # Rust 测试 + 覆盖率收集 (仅 Linux) + # ============================================ + # Rust 覆盖率收集 + # ============================================ rust-coverage: name: Rust Coverage runs-on: ubuntu-latest @@ -116,7 +123,7 @@ jobs: - name: Cache Rust build uses: Swatinem/rust-cache@v2 - - name: Run Rust tests and collect coverage + - name: Run tests and collect coverage shell: bash run: | source <(cargo llvm-cov show-env --export-prefix) @@ -126,16 +133,18 @@ jobs: cargo nextest run --workspace --exclude pulsing-py --exclude pulsing-bench-py cargo llvm-cov --no-run --lcov --output-path coverage.lcov - - name: Upload Rust coverage report + - name: Upload coverage report uses: actions/upload-artifact@v4 with: name: rust-coverage path: coverage.lcov retention-days: 30 - # Python 检查和测试 - python: - name: Python ${{ matrix.python-version }} + # ============================================ + # Python 构建和测试(多版本并行) + # ============================================ + python-test: + name: Python Test (${{ matrix.python-version }}) runs-on: ubuntu-latest strategy: fail-fast: false @@ -157,13 +166,12 @@ jobs: - name: Build Python package run: maturin develop - - name: Lint with ruff - run: ruff check python/ - - name: Test with pytest run: pytest tests/python -v - # Python 测试 + 覆盖率收集 + # ============================================ + # Python 覆盖率收集 + # ============================================ python-coverage: name: Python Coverage runs-on: ubuntu-latest @@ -182,55 +190,48 @@ jobs: - name: Build Python package run: maturin develop - - name: Run Python tests and collect coverage - run: | - pytest tests/python --cov=python/pulsing --cov-report=xml:coverage.xml -v + - name: Run tests and collect coverage + run: pytest tests/python --cov=python/pulsing --cov-report=xml:coverage.xml -v - - name: Upload Python coverage report + - name: Upload coverage report uses: actions/upload-artifact@v4 with: name: python-coverage path: coverage.xml retention-days: 30 + # ============================================ # 上传覆盖率到 Codecov + # ============================================ codecov: - name: Upload Coverage to Codecov + name: Upload Coverage needs: [rust-coverage, python-coverage] runs-on: ubuntu-latest if: always() steps: - uses: actions/checkout@v4 - - name: Download Rust coverage report + - name: Download Rust coverage uses: actions/download-artifact@v4 with: name: rust-coverage path: . continue-on-error: true - - name: Download Python coverage report + - name: Download Python coverage uses: actions/download-artifact@v4 with: name: python-coverage path: . continue-on-error: true - - name: Check coverage files exist + - name: Check coverage files run: | echo "=== Coverage files check ===" - if [ -f coverage.lcov ]; then - echo "✓ coverage.lcov exists ($(wc -l < coverage.lcov) lines)" - else - echo "✗ coverage.lcov not found" - fi - if [ -f coverage.xml ]; then - echo "✓ coverage.xml exists ($(wc -l < coverage.xml) lines)" - else - echo "✗ coverage.xml not found" - fi - - - name: Upload coverage reports to Codecov + [ -f coverage.lcov ] && echo "✓ coverage.lcov exists" || echo "✗ coverage.lcov not found" + [ -f coverage.xml ] && echo "✓ coverage.xml exists" || echo "✗ coverage.xml not found" + + - name: Upload to Codecov uses: codecov/codecov-action@v4 with: files: coverage.lcov,coverage.xml @@ -238,22 +239,11 @@ jobs: fail_ci_if_error: false verbose: true - # Pre-commit 检查 - pre-commit: - name: Pre-commit - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - uses: pre-commit/action@v3.0.1 - with: - extra_args: --all-files - - # 构建检查 + # ============================================ + # 构建 Python Wheel + # ============================================ build: - name: Build wheels on ${{ matrix.os }} + name: Build Wheel (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: matrix: From 9f4c2b01e64342fee78204ed190a5a30cdc54387 Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 01:11:38 +0800 Subject: [PATCH 5/7] Refactor CI workflow and enhance build processes - Updated CI configuration for improved clarity and organization, including renaming jobs and refining comments. - Streamlined Rust ARM64 cross-compilation checks, focusing on building without testing. - Enhanced Python build jobs to support multi-platform testing and added a new job for building Linux ARM64 wheels. - Simplified steps for installing ARM64 targets and tools, ensuring a more efficient setup process. - Adjusted job names for better readability and consistency across the CI pipeline. --- .github/workflows/ci.yml | 81 ++++++++++++------- .../pulsing-actor/src/transport/http2/tls.rs | 3 +- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 310f52afd..6f1b6dd71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,10 +12,10 @@ env: jobs: # ============================================ - # 代码规范检查(快速反馈,集中检查所有格式和 lint 问题) + # 代码规范检查(快速反馈) # ============================================ lint: - name: Lint & Format Check + name: Lint & Format runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -38,7 +38,7 @@ jobs: run: ruff check python/ # ============================================ - # Rust 构建和测试(多平台并行) + # Rust 构建和测试(多平台) # ============================================ rust-test: name: Rust Test (${{ matrix.os }}) @@ -67,20 +67,11 @@ jobs: run: cargo test --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets # ============================================ - # ARM64 交叉编译检查 + # Linux ARM64 交叉编译检查(仅构建,不测试) # ============================================ - rust-arm64: - name: Rust ARM64 (${{ matrix.target }}) + rust-linux-arm64: + name: Rust Build (linux-arm64) runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - target: aarch64-unknown-linux-gnu - linker: gcc-aarch64-linux-gnu - - target: aarch64-apple-darwin - linker: aarch64-apple-darwin-gcc - steps: - uses: actions/checkout@v4 @@ -90,20 +81,28 @@ jobs: rust-toolchain: stable install-cargo-tools: 'false' - - name: Install ARM64 target - run: rustup target add ${{ matrix.target }} - - - name: Install cross-compilation tools - if: matrix.target == 'aarch64-unknown-linux-gnu' + - name: Install ARM64 target and tools run: | + rustup target add aarch64-unknown-linux-gnu + sudo dpkg --add-architecture arm64 + sudo sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list + echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list + echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu + sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + sudo apt-get install -y libssl-dev:arm64 - name: Cache Rust build uses: Swatinem/rust-cache@v2 - - name: Build for ARM64 - run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets --target ${{ matrix.target }} + - name: Build for Linux ARM64 + env: + PKG_CONFIG_ALLOW_CROSS: 1 + PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig + OPENSSL_DIR: /usr + OPENSSL_LIB_DIR: /usr/lib/aarch64-linux-gnu + OPENSSL_INCLUDE_DIR: /usr/include + run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --target aarch64-unknown-linux-gnu # ============================================ # Rust 覆盖率收集 @@ -141,14 +140,15 @@ jobs: retention-days: 30 # ============================================ - # Python 构建和测试(多版本并行) + # Python 构建和测试(多平台多版本) # ============================================ python-test: - name: Python Test (${{ matrix.python-version }}) - runs-on: ubuntu-latest + name: Python ${{ matrix.python-version }} (${{ matrix.os }}) + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: [ubuntu-latest, macos-latest] python-version: ["3.10", "3.11", "3.12"] steps: @@ -240,12 +240,13 @@ jobs: verbose: true # ============================================ - # 构建 Python Wheel + # 构建 Python Wheel(多平台) # ============================================ build: name: Build Wheel (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [ubuntu-latest, macos-latest] @@ -265,9 +266,35 @@ jobs: with: args: --release --out dist sccache: 'true' + manylinux: auto - name: Upload wheels uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.os }} path: dist/*.whl + + # ============================================ + # 构建 Linux ARM64 Wheel(交叉编译) + # ============================================ + build-linux-arm64: + name: Build Wheel (linux-arm64) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build wheel for Linux ARM64 + uses: PyO3/maturin-action@v1 + with: + target: aarch64-unknown-linux-gnu + args: --release --out dist + sccache: 'true' + manylinux: auto + before-script-linux: | + yum install -y openssl-devel perl-IPC-Cmd || apt-get update && apt-get install -y libssl-dev + + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-linux-arm64 + path: dist/*.whl diff --git a/crates/pulsing-actor/src/transport/http2/tls.rs b/crates/pulsing-actor/src/transport/http2/tls.rs index 1b8069f00..1ebcaf7ce 100644 --- a/crates/pulsing-actor/src/transport/http2/tls.rs +++ b/crates/pulsing-actor/src/transport/http2/tls.rs @@ -257,8 +257,7 @@ fn generate_deterministic_key_pair(seed: &[u8; 32]) -> anyhow::Result { pkcs8_der.extend_from_slice(&content); // Create rcgen KeyPair from the DER - let private_key_der = rustls::pki_types::PrivatePkcs8KeyDer::try_from(pkcs8_der.as_slice()) - .map_err(|e| anyhow::anyhow!("Failed to parse PKCS#8 DER: {:?}", e))?; + let private_key_der = rustls::pki_types::PrivatePkcs8KeyDer::from(pkcs8_der.as_slice()); let key_pair = KeyPair::from_pkcs8_der_and_sign_algo(&private_key_der, &PKCS_ED25519) .map_err(|e| anyhow::anyhow!("Failed to create rcgen KeyPair: {}", e))?; From 0bc4bd50cfb3ffbbea771db17623dfd780950c40 Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 01:19:41 +0800 Subject: [PATCH 6/7] Refactor dependencies and update CI workflow - Removed unused dependencies from `Cargo.lock` and `Cargo.toml`, including `aws-lc-fips-sys`, `bindgen`, `cexpr`, `clang-sys`, `itertools`, `libloading`, and `prettyplease`. - Updated `aws-lc-rs` configuration in `Cargo.toml` to remove the `bindgen` feature. - Streamlined CI workflow by removing ARM64 cross-compilation checks and enhancing Python build and test jobs for better clarity and organization. --- .github/workflows/ci.yml | 175 ++++++++++++++------------------------- Cargo.lock | 91 +------------------- Cargo.toml | 2 +- 3 files changed, 65 insertions(+), 203 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f1b6dd71..ecfbd54a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,44 +66,6 @@ jobs: - name: Test run: cargo test --workspace --exclude pulsing-py --exclude pulsing-bench-py --all-targets - # ============================================ - # Linux ARM64 交叉编译检查(仅构建,不测试) - # ============================================ - rust-linux-arm64: - name: Rust Build (linux-arm64) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup Build Environment - uses: ./.github/actions/setup-build-env - with: - rust-toolchain: stable - install-cargo-tools: 'false' - - - name: Install ARM64 target and tools - run: | - rustup target add aarch64-unknown-linux-gnu - sudo dpkg --add-architecture arm64 - sudo sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list - echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list - echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list - sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - sudo apt-get install -y libssl-dev:arm64 - - - name: Cache Rust build - uses: Swatinem/rust-cache@v2 - - - name: Build for Linux ARM64 - env: - PKG_CONFIG_ALLOW_CROSS: 1 - PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig - OPENSSL_DIR: /usr - OPENSSL_LIB_DIR: /usr/lib/aarch64-linux-gnu - OPENSSL_INCLUDE_DIR: /usr/include - run: cargo build --workspace --exclude pulsing-py --exclude pulsing-bench-py --target aarch64-unknown-linux-gnu - # ============================================ # Rust 覆盖率收集 # ============================================ @@ -140,16 +102,15 @@ jobs: retention-days: 30 # ============================================ - # Python 构建和测试(多平台多版本) + # 构建 Python Wheel(多平台) # ============================================ - python-test: - name: Python ${{ matrix.python-version }} (${{ matrix.os }}) + build: + name: Build Wheel (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - python-version: ["3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 @@ -157,14 +118,55 @@ jobs: - name: Setup Build Environment uses: ./.github/actions/setup-build-env with: - python-version: ${{ matrix.python-version }} - install-python-deps: 'true' + python-version: '3.12' - name: Cache Rust build uses: Swatinem/rust-cache@v2 - - name: Build Python package - run: maturin develop + - name: Build wheel + uses: PyO3/maturin-action@v1 + with: + args: --release --out dist + sccache: 'true' + manylinux: auto + + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-${{ matrix.os }} + path: dist/*.whl + + # ============================================ + # Python 测试(使用 build 产出的 wheel) + # ============================================ + python-test: + name: Python ${{ matrix.python-version }} (${{ matrix.os }}) + needs: build + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Download wheel + uses: actions/download-artifact@v4 + with: + name: wheels-${{ matrix.os }} + path: dist/ + + - name: Install wheel and test dependencies + run: | + pip install dist/*.whl + pip install pytest pytest-asyncio pytest-cov - name: Test with pytest run: pytest tests/python -v @@ -174,24 +176,29 @@ jobs: # ============================================ python-coverage: name: Python Coverage + needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Setup Build Environment - uses: ./.github/actions/setup-build-env + - name: Setup Python + uses: actions/setup-python@v5 with: python-version: '3.12' - install-python-deps: 'true' - - name: Cache Rust build - uses: Swatinem/rust-cache@v2 + - name: Download wheel + uses: actions/download-artifact@v4 + with: + name: wheels-ubuntu-latest + path: dist/ - - name: Build Python package - run: maturin develop + - name: Install wheel and test dependencies + run: | + pip install dist/*.whl + pip install pytest pytest-asyncio pytest-cov - name: Run tests and collect coverage - run: pytest tests/python --cov=python/pulsing --cov-report=xml:coverage.xml -v + run: pytest tests/python --cov=pulsing --cov-report=xml:coverage.xml -v - name: Upload coverage report uses: actions/upload-artifact@v4 @@ -238,63 +245,3 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: false verbose: true - - # ============================================ - # 构建 Python Wheel(多平台) - # ============================================ - build: - name: Build Wheel (${{ matrix.os }}) - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest] - - steps: - - uses: actions/checkout@v4 - - - name: Setup Build Environment - uses: ./.github/actions/setup-build-env - with: - python-version: '3.12' - - - name: Cache Rust build - uses: Swatinem/rust-cache@v2 - - - name: Build wheel - uses: PyO3/maturin-action@v1 - with: - args: --release --out dist - sccache: 'true' - manylinux: auto - - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: wheels-${{ matrix.os }} - path: dist/*.whl - - # ============================================ - # 构建 Linux ARM64 Wheel(交叉编译) - # ============================================ - build-linux-arm64: - name: Build Wheel (linux-arm64) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Build wheel for Linux ARM64 - uses: PyO3/maturin-action@v1 - with: - target: aarch64-unknown-linux-gnu - args: --release --out dist - sccache: 'true' - manylinux: auto - before-script-linux: | - yum install -y openssl-devel perl-IPC-Cmd || apt-get update && apt-get install -y libssl-dev - - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: wheels-linux-arm64 - path: dist/*.whl diff --git a/Cargo.lock b/Cargo.lock index 5a274fd74..4a4f21112 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,27 +103,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "aws-lc-fips-sys" -version = "0.13.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6ea8e07e2df15b9f09f2ac5ee2977369b06d116f0c4eb5fa4ad443b73c7f53" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", - "regex", -] - [[package]] name = "aws-lc-rs" version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" dependencies = [ - "aws-lc-fips-sys", "aws-lc-sys", "untrusted 0.7.1", "zeroize", @@ -135,7 +120,6 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" dependencies = [ - "bindgen", "cc", "cmake", "dunce", @@ -210,26 +194,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.72.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - [[package]] name = "bitflags" version = "2.10.0" @@ -284,15 +248,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "1.0.4" @@ -318,17 +273,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "cmake" version = "0.1.57" @@ -1284,15 +1228,6 @@ dependencies = [ "serde", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -1340,16 +1275,6 @@ version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link 0.2.1", -] - [[package]] name = "libredox" version = "0.1.12" @@ -1823,16 +1748,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro2" version = "1.0.103" @@ -1859,7 +1774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools", "proc-macro2", "quote", "syn", @@ -2207,7 +2122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f" dependencies = [ "either", - "itertools 0.14.0", + "itertools", "rayon", ] @@ -2845,7 +2760,7 @@ dependencies = [ "getrandom 0.3.4", "hf-hub", "indicatif", - "itertools 0.14.0", + "itertools", "log", "macro_rules_attribute", "monostate", diff --git a/Cargo.toml b/Cargo.toml index cc4352e95..1e0e62cb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ reqwest-eventsource = "0.6" rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "std"] } tokio-rustls = { version = "0.26" } rcgen = { version = "0.13" } -aws-lc-rs = { version = "1.8", features = ["bindgen"] } +aws-lc-rs = { version = "1.8" } rustls-pemfile = { version = "2" } time = { version = "0.3" } From 011d4dce289320a2cc2c289078a9ace856c9a459 Mon Sep 17 00:00:00 2001 From: Reiase Date: Sun, 25 Jan 2026 01:26:49 +0800 Subject: [PATCH 7/7] Enhance CI workflow for macOS and Linux builds - Introduced separate jobs for building wheels on macOS and Linux, improving clarity and organization. - Updated Python version for macOS builds to 3.10 and refined caching strategies for Rust builds. - Enhanced testing jobs for macOS and Linux, including multi-version and multi-architecture support. - Added a new job for testing on Fedora, ensuring comprehensive coverage across platforms. - Improved artifact naming conventions for better identification of build outputs. --- .github/workflows/ci.yml | 161 ++++++++++++++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecfbd54a5..fbb4c0c79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,15 +102,50 @@ jobs: retention-days: 30 # ============================================ - # 构建 Python Wheel(多平台) + # 构建 macOS Wheel # ============================================ - build: - name: Build Wheel (${{ matrix.os }}) - runs-on: ${{ matrix.os }} + build-macos: + name: Build Wheel (macOS) + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Build Environment + uses: ./.github/actions/setup-build-env + with: + python-version: '3.10' + + - name: Cache Rust build + uses: Swatinem/rust-cache@v2 + + - name: Build wheel + uses: PyO3/maturin-action@v1 + with: + args: --release --out dist + sccache: 'true' + + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-macos + path: dist/*.whl + + # ============================================ + # 构建 Linux Wheel(x86-64 和 aarch64) + # ============================================ + build-linux: + name: Build Wheel (Linux ${{ matrix.arch }}) + runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - arch: x86-64 + runner: ubuntu-latest + target: x86_64-unknown-linux-gnu + - arch: aarch64 + runner: ubuntu-24.04-arm64 + target: aarch64-unknown-linux-gnu steps: - uses: actions/checkout@v4 @@ -118,7 +153,7 @@ jobs: - name: Setup Build Environment uses: ./.github/actions/setup-build-env with: - python-version: '3.12' + python-version: '3.10' - name: Cache Rust build uses: Swatinem/rust-cache@v2 @@ -126,27 +161,27 @@ jobs: - name: Build wheel uses: PyO3/maturin-action@v1 with: + target: ${{ matrix.target }} args: --release --out dist sccache: 'true' - manylinux: auto + manylinux: '2_17' - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-${{ matrix.os }} + name: wheels-linux-${{ matrix.arch }} path: dist/*.whl # ============================================ - # Python 测试(使用 build 产出的 wheel) + # macOS Python 测试(多 Python 版本) # ============================================ - python-test: - name: Python ${{ matrix.python-version }} (${{ matrix.os }}) - needs: build - runs-on: ${{ matrix.os }} + test-macos: + name: Test macOS (Python ${{ matrix.python-version }}) + needs: build-macos + runs-on: macos-latest strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] python-version: ["3.10", "3.11", "3.12"] steps: @@ -160,9 +195,69 @@ jobs: - name: Download wheel uses: actions/download-artifact@v4 with: - name: wheels-${{ matrix.os }} + name: wheels-macos + path: dist/ + + - name: Install wheel and test dependencies + run: | + pip install dist/*.whl + pip install pytest pytest-asyncio pytest-cov + + - name: Test with pytest + run: pytest tests/python -v + + # ============================================ + # Ubuntu Python 测试(多版本 × 多架构 × 多 Python 版本) + # ============================================ + test-ubuntu: + name: Test Ubuntu ${{ matrix.ubuntu }} ${{ matrix.arch }} (Python ${{ matrix.python-version }}) + needs: build-linux + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + ubuntu: ["20.04", "22.04", "24.04"] + arch: [x86-64, aarch64] + python-version: ["3.10", "3.11", "3.12"] + include: + # x86-64 runners + - ubuntu: "20.04" + arch: x86-64 + runner: ubuntu-20.04 + - ubuntu: "22.04" + arch: x86-64 + runner: ubuntu-22.04 + - ubuntu: "24.04" + arch: x86-64 + runner: ubuntu-24.04 + # aarch64 runners (only 24.04 available) + - ubuntu: "24.04" + arch: aarch64 + runner: ubuntu-24.04-arm64 + exclude: + # Ubuntu 20.04/22.04 ARM64 runner 不可用 + - ubuntu: "20.04" + arch: aarch64 + - ubuntu: "22.04" + arch: aarch64 + # Ubuntu 20.04 不支持 Python 3.12 + - ubuntu: "20.04" + python-version: "3.12" + + steps: + - uses: actions/checkout@v4 + + - name: Download wheel + uses: actions/download-artifact@v4 + with: + name: wheels-linux-${{ matrix.arch }} path: dist/ + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install wheel and test dependencies run: | pip install dist/*.whl @@ -171,12 +266,44 @@ jobs: - name: Test with pytest run: pytest tests/python -v + # ============================================ + # Fedora Python 测试(x86-64) + # ============================================ + test-fedora: + name: Test Fedora x86-64 (Python ${{ matrix.python-version }}) + needs: build-linux + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Download wheel + uses: actions/download-artifact@v4 + with: + name: wheels-linux-x86-64 + path: dist/ + + - name: Test on Fedora + run: | + docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace \ + fedora:latest \ + bash -c " + dnf install -y python${{ matrix.python-version }} python${{ matrix.python-version }}-pip && \ + python${{ matrix.python-version }} -m pip install dist/*.whl && \ + python${{ matrix.python-version }} -m pip install pytest pytest-asyncio pytest-cov && \ + python${{ matrix.python-version }} -m pytest tests/python -v + " + # ============================================ # Python 覆盖率收集 # ============================================ python-coverage: name: Python Coverage - needs: build + needs: build-linux runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -189,7 +316,7 @@ jobs: - name: Download wheel uses: actions/download-artifact@v4 with: - name: wheels-ubuntu-latest + name: wheels-linux-x86-64 path: dist/ - name: Install wheel and test dependencies