diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 0638e3e..2813607 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -38,5 +38,17 @@ jobs: - name: Test workspace run: cargo test --workspace --locked + - name: Install Linux musl target + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + rustup target add x86_64-unknown-linux-musl + + - name: Check Linux musl release build + env: + CC_x86_64_unknown_linux_musl: musl-gcc + OPENSSL_STATIC: "1" + run: cargo build --profile dist --locked --target x86_64-unknown-linux-musl -p exedev-ctl -p exedev-k8s + - name: Validate example YAML run: ruby -e 'require "yaml"; YAML.load_file("fleet.example.yaml"); YAML.load_file("k8s/examples/project-task-deployment.yaml")' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3badb36..22c533e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,10 +28,10 @@ jobs: include: - platform: linux-amd64 os: ubuntu-24.04 - target: x86_64-unknown-linux-gnu + target: x86_64-unknown-linux-musl - platform: linux-arm64 os: ubuntu-24.04-arm - target: aarch64-unknown-linux-gnu + target: aarch64-unknown-linux-musl - platform: macos-amd64 os: macos-15-intel target: x86_64-apple-darwin @@ -55,6 +55,23 @@ jobs: with: key: ${{ matrix.target }} + - name: Configure Linux musl build + if: startsWith(matrix.os, 'ubuntu-') + shell: bash + run: | + set -euo pipefail + sudo apt-get update + sudo apt-get install -y musl-tools + echo "OPENSSL_STATIC=1" >> "${GITHUB_ENV}" + case "${{ matrix.target }}" in + x86_64-unknown-linux-musl) + echo "CC_x86_64_unknown_linux_musl=musl-gcc" >> "${GITHUB_ENV}" + ;; + aarch64-unknown-linux-musl) + echo "CC_aarch64_unknown_linux_musl=musl-gcc" >> "${GITHUB_ENV}" + ;; + esac + - name: Build optimized release binaries run: cargo build --profile dist --locked --target ${{ matrix.target }} -p exedev-ctl -p exedev-k8s @@ -71,10 +88,17 @@ jobs: archive="exedev-clis-${tag}-${{ matrix.platform }}.tar.gz" mkdir -p package dist - cp "target/${{ matrix.target }}/dist/exedev-ctl" package/ - cp "target/${{ matrix.target }}/dist/exedev-k8s" package/ + + cp "target/${{ matrix.target }}/dist/exedev-ctl" "package/exedev-ctl" + cp "target/${{ matrix.target }}/dist/exedev-k8s" "package/exedev-k8s" + if [[ "${{ matrix.os }}" == ubuntu-* ]]; then + strip --strip-all package/exedev-ctl package/exedev-k8s + else + strip -x package/exedev-ctl package/exedev-k8s + fi + cp README.md README.zh-CN.md LICENSE .env.example fleet.example.yaml package/ - tar -czf "dist/${archive}" -C package . + tar -cf - -C package . | gzip -9 -n > "dist/${archive}" echo "archive=${archive}" >> "${GITHUB_OUTPUT}" - name: Upload archive artifact diff --git a/Cargo.lock b/Cargo.lock index 1ec1666..98489d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,28 +20,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "aws-lc-rs" -version = "1.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - [[package]] name = "base64" version = "0.22.1" @@ -73,8 +51,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -84,12 +60,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "chacha20" version = "0.10.0" @@ -98,7 +68,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures", - "rand_core 0.10.1", + "rand_core", ] [[package]] @@ -140,25 +110,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "comfy-table" version = "7.2.2" @@ -266,12 +217,6 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -325,13 +270,19 @@ dependencies = [ "clap", "dialoguer", "exedev-cli-core", - "rand 0.10.1", + "rand", "serde", "serde_json", "serde_yaml", "tokio", ] +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -344,6 +295,21 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -353,12 +319,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures-channel" version = "0.3.32" @@ -392,19 +352,6 @@ dependencies = [ "slab", ] -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - [[package]] name = "getrandom" version = "0.3.4" @@ -412,11 +359,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] @@ -428,7 +373,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.1", + "rand_core", "wasip2", "wasip3", ] @@ -514,17 +459,18 @@ dependencies = [ ] [[package]] -name = "hyper-rustls" -version = "0.27.9" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ - "http", + "bytes", + "http-body-util", "hyper", "hyper-util", - "rustls", + "native-tls", "tokio", - "tokio-rustls", + "tokio-native-tls", "tower-service", ] @@ -694,65 +640,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys", - "log", - "simd_cesu8", - "thiserror", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "simd_cesu8", - "syn", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - [[package]] name = "js-sys" version = "0.3.95" @@ -810,12 +697,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "memchr" version = "2.8.0" @@ -833,18 +714,83 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "openssl" +version = "0.10.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "openssl-src" +version = "300.6.0+3.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e8cbfd3a4a8c8f089147fd7aaa33cf8c7450c4d09f8f80698a0cf093abeff4" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -880,6 +826,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + [[package]] name = "potential_utf" version = "0.1.5" @@ -889,15 +841,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -917,62 +860,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" -dependencies = [ - "aws-lc-rs", - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.4", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - [[package]] name = "quote" version = "1.0.45" @@ -994,16 +881,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha", - "rand_core 0.9.5", -] - [[package]] name = "rand" version = "0.10.1" @@ -1012,26 +889,7 @@ checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", "getrandom 0.4.2", - "rand_core 0.10.1", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", + "rand_core", ] [[package]] @@ -1062,19 +920,17 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-rustls", + "hyper-tls", "hyper-util", "js-sys", "log", + "native-tls", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", "rustls-pki-types", - "rustls-platform-verifier", "sync_wrapper", "tokio", - "tokio-rustls", + "tokio-native-tls", "tower", "tower-http", "tower-service", @@ -1084,35 +940,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "1.1.4" @@ -1126,81 +953,15 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.23.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" -dependencies = [ - "aws-lc-rs", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pki-types" version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ - "web-time", "zeroize", ] -[[package]] -name = "rustls-platform-verifier" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - -[[package]] -name = "rustls-webpki" -version = "0.103.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.22" @@ -1213,15 +974,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "schannel" version = "0.1.29" @@ -1344,22 +1096,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd_cesu8" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" -dependencies = [ - "rustc_version", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "slab" version = "0.4.12" @@ -1394,12 +1130,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "2.0.117" @@ -1431,6 +1161,19 @@ dependencies = [ "syn", ] +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "thiserror" version = "2.0.18" @@ -1461,21 +1204,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.52.3" @@ -1504,12 +1232,12 @@ dependencies = [ ] [[package]] -name = "tokio-rustls" -version = "0.26.4" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "rustls", + "native-tls", "tokio", ] @@ -1613,12 +1341,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.5.8" @@ -1638,14 +1360,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "walkdir" -version = "2.5.0" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "want" @@ -1779,25 +1497,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1814,15 +1513,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2114,26 +1804,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerofrom" version = "0.1.7" diff --git a/Cargo.toml b/Cargo.toml index b89266a..5fc378a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ dialoguer = { version = "0.12", default-features = false } dotenvy = "0.15" exedev-core = { package = "exedev-cli-core", version = "0.1.10", path = "core" } rand = { version = "0.10", default-features = false, features = ["thread_rng"] } -reqwest = { version = "0.13", default-features = false, features = ["rustls"] } +reqwest = { version = "0.13", default-features = false, features = ["native-tls-vendored"] } serde = { version = "1.0", default-features = false, features = ["derive", "std"] } serde_json = { version = "1.0", default-features = false, features = ["std"] } serde_yaml = "0.9" @@ -25,6 +25,8 @@ tokio = { version = "1.52", default-features = false, features = ["macros", "pro [profile.dist] inherits = "release" +debug = 0 +incremental = false opt-level = "z" lto = "fat" codegen-units = 1 diff --git a/README.md b/README.md index 8bd9e8c..c432d94 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Common operations: ```sh exedev-ctl new --name p1-a-1 --image ubuntu:22.04 --no-email exedev-ctl share port p1-a-1 8080 +exedev-ctl domain add p1-a-1 app.example.com exedev-ctl rm p1-a-1 ``` @@ -55,6 +56,21 @@ Detailed documentation: - [`docs/exedev-automation.md`](docs/exedev-automation.md): exe.dev HTTPS `POST /exec`, token generation, and automation boundaries. +## exeuntu + +[`exeuntu`](https://github.com/lollipopkit/exeuntu) is the default exe.dev base +image. It is a developer/agent-oriented Ubuntu 24.04 image with systemd and a +broader set of apt-installed tools than a minimal container image. Published +images are available from `ghcr.io/lollipopkit/exeuntu`. + +## Release Compatibility + +Release archives include Linux musl binaries for `x86_64` and `aarch64`, plus +native macOS binaries for Intel and Apple Silicon. Linux release binaries are +built with vendored native TLS and static OpenSSL so they do not require a +compatible system `libssl.so` at runtime. CI validates the Linux musl dist build +before release packaging. + ## exedev-k8s `exedev-k8s` is the Kubernetes fleet management CLI. It reads `fleet.yaml`, diff --git a/README.zh-CN.md b/README.zh-CN.md index 4f97932..9a89deb 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -39,6 +39,7 @@ exedev-ctl --transport http ls ```sh exedev-ctl new --name p1-a-1 --image ubuntu:22.04 --no-email exedev-ctl share port p1-a-1 8080 +exedev-ctl domain add p1-a-1 app.example.com exedev-ctl rm p1-a-1 ``` @@ -54,6 +55,20 @@ automation 已经审阅过 action plan 后才使用 `--yes`。 - [`docs/exedev-automation.md`](docs/exedev-automation.md):exe.dev HTTPS `POST /exec`、token generation 和 automation boundary。 +## exeuntu + +[`exeuntu`](https://github.com/lollipopkit/exeuntu) 是 exe.dev 的默认 base +image。它基于 Ubuntu 24.04,面向 developer/agent 使用场景,包含 systemd, +并预装了比 minimal container image 更完整的一组 apt 工具。已发布镜像位于 +`ghcr.io/lollipopkit/exeuntu`。 + +## Release Compatibility + +Release archives 包含面向 `x86_64` 和 `aarch64` 的 Linux musl binaries,以及 +面向 Intel 和 Apple Silicon 的原生 macOS binaries。Linux release binaries +使用 vendored native TLS 和 static OpenSSL 构建,运行时不依赖系统里的兼容 +`libssl.so`。CI 会在 release packaging 前验证 Linux musl dist build。 + ## exedev-k8s `exedev-k8s` 是 Kubernetes fleet 管理 CLI。它读取 `fleet.yaml`,创建或复用 diff --git a/cli/README.md b/cli/README.md index c9d0d53..cc0fb4c 100644 --- a/cli/README.md +++ b/cli/README.md @@ -113,6 +113,14 @@ Make the HTTP proxy public: exedev-ctl share set-public p1-a-1 ``` +Register a custom domain after DNS points at the VM: + +```sh +exedev-ctl domain add p1-a-1 app.example.com +exedev-ctl domain ls p1-a-1 +exedev-ctl domain rm p1-a-1 app.example.com +``` + Run a raw exe.dev command: ```sh @@ -151,7 +159,7 @@ These commands require local SSH access to exe.dev. The CLI covers the top-level commands from the exe.dev CLI Reference: ```text -help doc ls new rm restart rename tag stat cp resize share team whoami +help doc ls new rm restart rename tag stat cp resize share domain team whoami ssh-key set-region integrations billing shelley browser ssh grant-support-root exit exec ``` diff --git a/cli/README.zh-CN.md b/cli/README.zh-CN.md index 1e456ac..9040db8 100644 --- a/cli/README.zh-CN.md +++ b/cli/README.zh-CN.md @@ -111,6 +111,14 @@ exedev-ctl share port p1-a-1 8080 exedev-ctl share set-public p1-a-1 ``` +DNS 已指向 VM 后注册 custom domain: + +```sh +exedev-ctl domain add p1-a-1 app.example.com +exedev-ctl domain ls p1-a-1 +exedev-ctl domain rm p1-a-1 app.example.com +``` + 运行原始 exe.dev command: ```sh @@ -149,7 +157,7 @@ ssh exe.dev ... CLI 覆盖 exe.dev CLI Reference 中的 top-level commands: ```text -help doc ls new rm restart rename tag stat cp resize share team whoami +help doc ls new rm restart rename tag stat cp resize share domain team whoami ssh-key set-region integrations billing shelley browser ssh grant-support-root exit exec ``` diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 81e63be..23c2646 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -55,6 +55,8 @@ pub(crate) enum Commands { Resize(ResizeCmd), /// Share HTTPS VM access. Share(ShareCmd), + /// Manage custom domains. + Domain(DomainCmd), /// View and manage your team. Team(TeamCmd), /// Show current user information. @@ -251,6 +253,35 @@ pub(crate) struct ShareAccessCmd { pub(crate) vm: String, } +#[derive(Debug, Args)] +pub(crate) struct DomainCmd { + #[command(subcommand)] + pub(crate) command: DomainSubcommand, +} + +#[derive(Debug, Subcommand)] +pub(crate) enum DomainSubcommand { + /// Register a custom domain for a VM. + Add(DomainVmDomainCmd), + /// List registered custom domains. + Ls(DomainLsCmd), + /// Remove a custom domain from a VM. + Rm(DomainVmDomainCmd), +} + +#[derive(Debug, Args)] +pub(crate) struct DomainVmDomainCmd { + pub(crate) vm: String, + pub(crate) domain: String, +} + +#[derive(Debug, Args)] +pub(crate) struct DomainLsCmd { + #[arg(short = 'a', long = "all")] + pub(crate) all: bool, + pub(crate) vm: Option, +} + #[derive(Debug, Args)] pub(crate) struct TeamCmd { #[command(subcommand)] diff --git a/cli/src/cli_command.rs b/cli/src/cli_command.rs index adfc9ce..4f1bcd2 100644 --- a/cli/src/cli_command.rs +++ b/cli/src/cli_command.rs @@ -85,6 +85,7 @@ pub(crate) fn build_command(command: &Commands) -> Result { format!("--disk={}", cmd.disk), ]), Commands::Share(cmd) => build_share_command(&mut words, &cmd.command), + Commands::Domain(cmd) => build_domain_command(&mut words, &cmd.command)?, Commands::Team(cmd) => build_team_command(&mut words, &cmd.command), Commands::Whoami => words.push("whoami".into()), Commands::SshKey(cmd) => build_ssh_key_command(&mut words, &cmd.command), @@ -170,6 +171,31 @@ fn build_share_command(words: &mut Vec, command: &ShareSubcommand) { } } +fn build_domain_command(words: &mut Vec, command: &DomainSubcommand) -> Result<()> { + words.push("domain".into()); + match command { + DomainSubcommand::Add(cmd) => { + words.extend(["add".into(), cmd.vm.clone(), cmd.domain.clone()]); + } + DomainSubcommand::Ls(cmd) => { + match (cmd.all, cmd.vm.as_ref()) { + (false, None) => bail!("domain ls requires either or -a"), + (true, Some(_)) => bail!("domain ls accepts either or -a, not both"), + _ => {} + } + words.push("ls".into()); + if cmd.all { + words.push("-a".into()); + } + push_opt(words, cmd.vm.as_ref()); + } + DomainSubcommand::Rm(cmd) => { + words.extend(["rm".into(), cmd.vm.clone(), cmd.domain.clone()]); + } + } + Ok(()) +} + fn build_team_command(words: &mut Vec, command: &TeamSubcommand) { words.push("team".into()); match command { @@ -348,6 +374,35 @@ mod tests { ); } + #[test] + fn builds_domain_commands() { + let built = command_from(&["exedev-ctl", "domain", "add", "mybox", "app.example.com"]); + assert_eq!(shell_join(&built.words), "domain add mybox app.example.com"); + + let built = command_from(&["exedev-ctl", "domain", "ls", "mybox"]); + assert_eq!(shell_join(&built.words), "domain ls mybox"); + + let built = command_from(&["exedev-ctl", "domain", "ls", "-a"]); + assert_eq!(shell_join(&built.words), "domain ls -a"); + + let built = command_from(&["exedev-ctl", "domain", "rm", "mybox", "app.example.com"]); + assert_eq!(shell_join(&built.words), "domain rm mybox app.example.com"); + } + + #[test] + fn rejects_invalid_domain_ls_args() { + let cli = Cli::parse_from(["exedev-ctl", "domain", "ls"]); + let err = build_command(&cli.command).unwrap_err(); + assert_eq!(err.to_string(), "domain ls requires either or -a"); + + let cli = Cli::parse_from(["exedev-ctl", "domain", "ls", "-a", "mybox"]); + let err = build_command(&cli.command).unwrap_err(); + assert_eq!( + err.to_string(), + "domain ls accepts either or -a, not both" + ); + } + #[test] fn builds_raw_exec_command() { let built = command_from(&["exedev-ctl", "exec", "--", "whoami"]); diff --git a/skills/exedev-ctl/SKILL.md b/skills/exedev-ctl/SKILL.md index 73460ae..e03b6a9 100644 --- a/skills/exedev-ctl/SKILL.md +++ b/skills/exedev-ctl/SKILL.md @@ -38,7 +38,7 @@ Check the current environment and scope before proposing changes: ## Command Selection -Use typed wrappers for supported commands: `ls`, `new`, `rm`, `restart`, `rename`, `tag`, `stat`, `cp`, `resize`, `share`, `team`, `whoami`, `ssh-key`, `set-region`, `integrations`, `billing`, `shelley`, `browser`, `ssh`, and `grant-support-root`. +Use typed wrappers for supported commands: `ls`, `new`, `rm`, `restart`, `rename`, `tag`, `stat`, `cp`, `resize`, `share`, `domain`, `team`, `whoami`, `ssh-key`, `set-region`, `integrations`, `billing`, `shelley`, `browser`, `ssh`, and `grant-support-root`. Use `exec -- ` only for raw exe.dev commands that do not yet have a typed wrapper. diff --git a/skills/exedev-ctl/references/exedev-ctl.md b/skills/exedev-ctl/references/exedev-ctl.md index 2b0bcf8..df26ce5 100644 --- a/skills/exedev-ctl/references/exedev-ctl.md +++ b/skills/exedev-ctl/references/exedev-ctl.md @@ -171,6 +171,15 @@ exedev-ctl share set-public p1-a-1 exedev-ctl share set-private p1-a-1 ``` +Manage custom domains after DNS points at the VM: + +```sh +exedev-ctl domain add p1-a-1 app.example.com +exedev-ctl domain ls p1-a-1 +exedev-ctl domain ls -a +exedev-ctl domain rm p1-a-1 app.example.com +``` + SSH into a VM: ```sh @@ -189,7 +198,7 @@ exedev-ctl exec -- whoami The `exedev-ctl` wrapper supports exe.dev token generation: ```sh -exedev-ctl ssh-key generate-api-key --label automation --cmds "ls,new,whoami,share show,share port" --exp 1798761600 +exedev-ctl ssh-key generate-api-key --label automation --cmds "ls,new,whoami,share show,share port,domain add,domain ls,domain rm" --exp 1798761600 ``` For destructive operations, include commands intentionally and narrowly, for example `rm`, `restart`, or `rename` only when needed.