This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: USBIP Authenticator Check | ||
| on: | ||
| push: | ||
| pull_request: | ||
| workflow_dispatch: | ||
| jobs: | ||
| usbip-authenticator: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| env: | ||
| RUST_LOG: debug | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| - name: Install Rust toolchain | ||
| uses: dtolnay/rust-toolchain@stable | ||
| - name: Install usbip tooling | ||
| run: | | ||
| set -euxo pipefail | ||
| sudo apt-get update | ||
| packages=( | ||
| "linux-tools-$(uname -r)" | ||
| "linux-cloud-tools-$(uname -r)" | ||
| linux-tools-generic | ||
| linux-cloud-tools-generic | ||
| linux-tools-virtual | ||
| linux-cloud-tools-virtual | ||
| usbip | ||
| ) | ||
| for pkg in "${packages[@]}"; do | ||
| if apt-cache show "$pkg" >/dev/null 2>&1; then | ||
| sudo apt-get install -y "$pkg" | ||
| fi | ||
| done | ||
| if ! command -v usbip >/dev/null 2>&1; then | ||
| echo "usbip CLI was not installed" >&2 | ||
| exit 1 | ||
| fi | ||
| - name: Start authenticator USB/IP server | ||
| run: | | ||
| set -euxo pipefail | ||
| cd pc-usbip-runner | ||
| nohup cargo run --release --example authenticator > "$GITHUB_WORKSPACE/authenticator.log" 2>&1 & | ||
| echo "AUTH_PID=$!" >> "$GITHUB_ENV" | ||
| sleep 10 | ||
| - name: Load vhci-hcd kernel module | ||
| run: sudo modprobe vhci-hcd | ||
| - name: Discover USB/IP bus ID | ||
| run: | | ||
| set -euo pipefail | ||
| python - <<'PY' | ||
| import os | ||
| import re | ||
| import subprocess | ||
| import sys | ||
| import time | ||
| from typing import Optional | ||
| def find_bus_id(output: str) -> Optional[str]: | ||
| pattern = re.compile( | ||
| r"^\s*(?:-\s*busid\s+)?([0-9]+-[0-9]+)(?::|\s).*Feitian", | ||
| re.MULTILINE, | ||
| ) | ||
| match = pattern.search(output) | ||
| if match: | ||
| return match.group(1) | ||
| return None | ||
| for attempt in range(15): | ||
| try: | ||
| result = subprocess.run([ | ||
| "usbip", "list", "-r", "localhost" | ||
| ], check=True, text=True, capture_output=True) | ||
| output = result.stdout | ||
| except subprocess.CalledProcessError as exc: | ||
| output = (exc.stdout or "") + (exc.stderr or "") | ||
| print(output) | ||
| bus_id = find_bus_id(output) | ||
| if bus_id: | ||
| print(f"Found bus ID: {bus_id}") | ||
| with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env_file: | ||
| env_file.write(f"BUS_ID={bus_id}\n") | ||
| sys.exit(0) | ||
| time.sleep(2) | ||
| print("Failed to locate Feitian authenticator bus ID", file=sys.stderr) | ||
| sys.exit(1) | ||
| PY | ||
| - name: Attach USB/IP device | ||
| run: | | ||
| set -euxo pipefail | ||
| ATTACH_OUTPUT=$(sudo usbip attach -r localhost -b "$BUS_ID") | ||
| echo "$ATTACH_OUTPUT" | ||
| PORT=$(printf '%s' "$ATTACH_OUTPUT" | sed -n 's/.*vhci_hcd port \([0-9][0-9]*\).*/\1/p') | ||
| if [ -z "$PORT" ]; then | ||
| echo "Unable to parse attached port" >&2 | ||
| exit 1 | ||
| fi | ||
| echo "USBIP_PORT=$PORT" >> "$GITHUB_ENV" | ||
| - name: Verify attached ports | ||
| run: | | ||
| sudo usbip port | ||
| lsusb | ||
| - name: Upload authenticator logs | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: authenticator-log | ||
| path: ${{ github.workspace }}/authenticator.log | ||
| - name: Cleanup | ||
| if: always() | ||
| run: | | ||
| set +e | ||
| if [ -n "${USBIP_PORT:-}" ]; then | ||
| sudo usbip detach -p "$USBIP_PORT" | ||
| fi | ||
| if [ -n "${AUTH_PID:-}" ]; then | ||
| kill "$AUTH_PID" || true | ||
| fi | ||