Files
EasyTier/.github/workflows/test.yml
T
KKRainbow 6154b550c1 fix(tls): select ring explicitly across application entry points
Building easytier and easytier-web together enabled both ring and aws-lc
through reqwest 0.13. HTTPS endpoint discovery used rustls automatic
provider selection and could panic before sending a ClientHello.

Use reqwest rustls-no-provider to share ring, and explicitly install the
process default before starting CLI, GUI and web services. Initialize it
for standalone webhook construction too, retaining any provider already
selected by the host.

Pass ring directly to HTTPS discovery and WebSocket TLS builders so
library use is independent of application initialization order. Keep
existing certificate verification, SNI and protocol settings.

Add a duplex-stream regression that reproduces the original panic with
both backends enabled, and run it in CI. Explain provider selection and
feature-unification constraints next to the relevant code.

Validation: the new regression fails before the fix and passes after it.
Docker tests pass: 10 discovery, 13 webhook, 2 WebSocket, WSS three-node
AES-GCM relay, and WSS credential connectivity. Clippy with warnings
denied and fmt pass. GUI, browser, WASI, minimal native, endpoint-only
and WebSocket-only compile checks pass. Linux and Windows release
dependency trees contain only the ring runtime backend.

Fixes #2607
2026-10-08 23:14:40 +08:00

207 lines
6.3 KiB
YAML

name: EasyTier Test
on:
push:
branches: [ "develop", "main" ]
pull_request:
branches: [ "develop", "main" ]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
# RUSTC_WRAPPER: "sccache"
# SCCACHE_GHA_ENABLED: "true"
defaults:
run:
# necessary for windows
shell: bash
jobs:
pre_job:
runs-on: ubuntu-latest
env:
RELEVANT_PATHS: >-
["Cargo.toml", "Cargo.lock", "rust-toolchain.toml", ".cargo/**",
"pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "easytier/**",
"easytier-core/**", "easytier-proto/**", "easytier-rpc-build/**",
"easytier-web/**", "easytier-gui/src-tauri/**",
"tauri-plugin-vpnservice/**", "easytier-contrib/**",
".github/workflows/test.yml", ".github/actions/**"]
outputs:
should_skip: >-
${{
steps.skip_check.outputs.should_skip == 'true' ||
(
github.event_name == 'pull_request' &&
steps.path_filter.outputs.relevant != 'true'
)
}}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
concurrent_skipping: 'never'
skip_after_successful_duplicate: 'true'
paths: ${{ env.RELEVANT_PATHS }}
- id: path_filter
if: >-
github.event_name == 'pull_request' &&
steps.skip_check.outputs.should_skip != 'true'
uses: dorny/paths-filter@v4
with:
filters: |
relevant: ${{ env.RELEVANT_PATHS }}
check:
name: Run linters & check
runs-on: ubuntu-latest
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/checkout@v5
- name: Prepare build environment
uses: ./.github/actions/prepare-build
with:
gui: true
pnpm: true
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rustfmt,clippy
target: wasm32-wasip1
rustflags: ''
- uses: taiki-e/install-action@cargo-hack
- name: Check formatting
if: ${{ !cancelled() }}
run: cargo fmt --all -- --check
- name: Check Clippy
if: ${{ !cancelled() }}
run: cargo clippy --all-targets --features full --all -- -D warnings
- name: Check features
if: ${{ !cancelled() }}
run: cargo hack check --package easytier --each-feature --exclude-features macos-ne --verbose
- name: Check WASI
if: ${{ !cancelled() }}
run: >-
cargo check --package easytier-core --lib --target wasm32-wasip1
--features management-rpc,proxy-smoltcp-stack,ring-crypto,wasi-crypto-offload
- name: Check Cargo.lock is up to date
if: ${{ !cancelled() }}
run: |
if ! cargo metadata --format-version 1 --locked > /dev/null; then
echo "::error::Cargo.lock is out of date. Run cargo generate-lockfile or cargo build locally, then commit Cargo.lock."
exit 1
fi
pre-test:
name: Build test
runs-on: ubuntu-latest
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/checkout@v5
- name: Prepare build environment
uses: ./.github/actions/prepare-build
with:
gui: true
pnpm: true
token: ${{ secrets.GITHUB_TOKEN }}
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@nextest
- name: Test HTTPS discovery with both rustls backends
# Catch provider-selection panics even when release features use only ring.
run: >-
cargo test --locked --package easytier-core --lib
--features rustls/aws_lc_rs
https_fetch_reaches_tls_handshake_without_global_provider
- name: Archive test
run: >-
cargo nextest archive --archive-file tests.tar.zst
--package easytier --package easytier-core --features full
- uses: actions/upload-artifact@v5
with:
name: tests
path: tests.tar.zst
retention-days: 1
test_matrix:
name: Test (${{ matrix.name }})
runs-on: ubuntu-latest
needs: [ pre_job, pre-test ]
if: needs.pre_job.outputs.should_skip != 'true'
strategy:
fail-fast: false
matrix:
include:
- name: "easytier"
opts: "-E 'not test(tests::three_node)' --test-threads 1 --no-fail-fast"
- name: "three_node"
opts: "-E 'test(tests::three_node) and not test(subnet_proxy_three_node_test)' --test-threads 1 --no-fail-fast"
- name: "three_node::subnet_proxy_three_node_test"
opts: "-E 'test(subnet_proxy_three_node_test)' --test-threads 1 --no-fail-fast"
steps:
- uses: actions/checkout@v5
- name: Setup tools for test
run: sudo apt install bridge-utils
- name: Setup upnpd for test
run: |
sudo apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y miniupnpd miniupnpd-iptables iptables
- name: Setup system for test
run: |
sudo modprobe br_netfilter
sudo modprobe tun
if [ ! -e /dev/net/tun ]; then
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
fi
sudo sysctl net.bridge.bridge-nf-call-iptables=0
sudo sysctl net.bridge.bridge-nf-call-ip6tables=0
sudo sysctl net.ipv6.conf.lo.disable_ipv6=0
sudo ip addr add 2001:db8::2/64 dev lo
- uses: taiki-e/install-action@nextest
- name: Download tests
uses: actions/download-artifact@v4
with:
name: tests
- name: Run tests
run: |
sudo prlimit --pid $$ --nofile=1048576:1048576
sudo -E env "PATH=$PATH" EASYTIER_LINUX_BPF_INTEGRATION=required \
cargo nextest run --archive-file tests.tar.zst ${{ matrix.opts }}
test:
runs-on: ubuntu-latest
needs: [ pre_job, check, test_matrix ]
if: needs.pre_job.result == 'success' && needs.pre_job.outputs.should_skip != 'true' && !cancelled()
steps:
- name: Mark result as failed
if: contains(needs.*.result, 'failure')
run: exit 1