numa 0.14.2

Portable DNS resolver in Rust — .numa local domains, ad blocking, developer overrides, DNS-over-HTTPS
Documentation
name: CI

on:
  push:
    branches: [main]
    paths-ignore:
      - 'site/**'
      - 'blog/**'
      - 'drafts/**'
      - '*.md'
      - 'scripts/serve-site.sh'
      - 'scripts/generate-blog-index.sh'
  pull_request:
    branches: [main]
    paths-ignore:
      - 'site/**'
      - 'blog/**'
      - 'drafts/**'
      - '*.md'
      - 'scripts/serve-site.sh'
      - 'scripts/generate-blog-index.sh'

env:
  CARGO_TERM_COLOR: always

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@v2
      - name: fmt
        run: cargo fmt --check
      - name: clippy
        run: cargo clippy -- -D warnings
      - name: test
        run: cargo test
      - name: audit
        run: cargo install cargo-audit && cargo audit

  check-macos:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: clippy
        run: cargo clippy -- -D warnings
      - name: test
        run: cargo test

  check-windows:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: build
        run: cargo build
      - name: clippy
        run: cargo clippy -- -D warnings
      - name: test
        run: cargo test
      - name: Upload binary
        uses: actions/upload-artifact@v7
        with:
          name: numa-windows-x86_64
          path: target/debug/numa.exe

  integration-linux:
    needs: [check]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: build
        run: cargo build --release
      - name: install / verify / re-install / uninstall
        run: |
          sudo ./target/release/numa install
          sleep 2
          curl -sf http://127.0.0.1:5380/health
          dig @127.0.0.1 example.com +short +timeout=5 | grep -q '.'
          user=$(ps -o user= -p "$(systemctl show -p MainPID --value numa)" | tr -d ' ')
          echo "numa running as: $user"
          test "$user" != "root"
          sudo ./target/release/numa install
          sleep 2
          curl -sf http://127.0.0.1:5380/health
          sudo ./target/release/numa uninstall
          sleep 1
          ! curl -sf http://127.0.0.1:5380/health 2>/dev/null
      - name: diagnostics on failure
        if: failure()
        run: |
          echo "=== systemctl status numa ==="
          sudo systemctl status numa --no-pager -l || true
          echo "=== journalctl -u numa (last 200) ==="
          sudo journalctl -u numa --no-pager -n 200 || true
          echo "=== ss -tulnp on 53/80/443/853/5380 ==="
          sudo ss -tulnp 2>/dev/null | grep -E ':(53|80|443|853|5380)\b' || true
          echo "=== systemctl is-active systemd-resolved ==="
          systemctl is-active systemd-resolved || true
      - name: cleanup
        if: always()
        run: |
          sudo ./target/release/numa uninstall 2>/dev/null || true
          # systemd-resolved has a ~40s DNS reconfiguration stall after
          # restart (systemd issue #22521) that breaks the runner agent's
          # connection to GitHub. Bridge it by replacing the stub-resolv
          # symlink with a direct upstream — DNS works instantly and the
          # runner can phone home for post-job steps.
          sudo rm -f /etc/resolv.conf
          echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf > /dev/null
          getent hosts github.com >/dev/null

  integration-macos:
    needs: [check-macos]
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: build
        run: cargo build --release
      - name: install / verify / re-install / uninstall
        run: |
          sudo ./target/release/numa install
          sleep 2
          curl -sf http://127.0.0.1:5380/health
          dig @127.0.0.1 example.com +short +timeout=5 | grep -q '.'
          sudo ./target/release/numa install
          sleep 2
          curl -sf http://127.0.0.1:5380/health
          sudo ./target/release/numa uninstall
          sleep 1
          ! curl -sf http://127.0.0.1:5380/health 2>/dev/null
      - name: cleanup
        if: always()
        run: sudo ./target/release/numa uninstall 2>/dev/null || true