rustd-resolved 0.2.3

Native DNS resolver and name-service daemon for RustD
name: Build and test

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  contents: read
  statuses: write

jobs:
  verify:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    concurrency:
      group: build-and-test-rust-${{ github.ref }}-${{ matrix.toolchain }}
      cancel-in-progress: true
    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - 1.74.0
          - stable
    env:
      RUSTUP_TOOLCHAIN: ${{ matrix.toolchain }}

    steps:
      - name: Publish pending status
        shell: bash
        env:
          GH_TOKEN: ${{ github.token }}
          STATUS_CONTEXT: build-and-test/rust-${{ matrix.toolchain }}
          STATUS_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          set -euo pipefail
          payload=$(printf '{"state":"pending","context":"%s","description":"Verification in progress","target_url":"%s"}' "$STATUS_CONTEXT" "$STATUS_URL")
          curl --fail-with-body --silent --show-error \
            --request POST \
            --header "Accept: application/vnd.github+json" \
            --header "Authorization: Bearer $GH_TOKEN" \
            --header "X-GitHub-Api-Version: 2022-11-28" \
            "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" \
            --data "$payload" >/dev/null

      - name: Check out source
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install native and D-Bus tools
        shell: bash
        run: |
          set -euo pipefail
          sudo apt-get update
          sudo apt-get install --yes --no-install-recommends dbus gfortran libssl-dev liburing-dev openssl python3 python3-dbus python3-gi python3-yaml

      - name: Install Rust toolchain
        shell: bash
        run: |
          set -euo pipefail
          rustup toolchain install "${{ matrix.toolchain }}" --profile minimal --component rustfmt,clippy
          rustc --version --verbose
          cargo --version --verbose
          rustup show active-toolchain

      - name: Check native ABI
        run: make check-native

      - name: Check RustD packaging
        run: make check-packaging

      - name: Check NSS integration
        if: ${{ matrix.toolchain == 'stable' }}
        run: make check-nss

      - name: Canonicalize Rust source
        run: cargo fmt --all

      - name: Package canonical source snapshot
        if: ${{ matrix.toolchain == 'stable' }}
        shell: bash
        run: |
          tar \
            --exclude=.git \
            --exclude=build \
            --exclude=target \
            --create \
            --gzip \
            --file=/tmp/resolved-source.tar.gz \
            .

      - name: Upload canonical source snapshot
        if: ${{ matrix.toolchain == 'stable' }}
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: resolved-source-${{ github.sha }}
          path: /tmp/resolved-source.tar.gz
          if-no-files-found: error
          retention-days: 14

      - name: Check formatting
        run: git diff --exit-code -- src

      - name: Run production Clippy
        shell: bash
        run: |
          set -o pipefail
          cargo clippy --all-targets --locked -- \
            -D clippy::correctness \
            -D clippy::suspicious \
            -D clippy::perf \
            -D deprecated \
            -D unused_must_use 2>&1 | tee /tmp/clippy.log

      - name: Run all-feature correctness sweep
        shell: bash
        run: |
          set -o pipefail
          cargo clippy --all-targets --all-features --locked -- \
            -D clippy::correctness \
            -D clippy::suspicious \
            -D clippy::perf 2>&1 | tee -a /tmp/clippy.log

      - name: Upload Rust diagnostics
        if: ${{ always() }}
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: rust-diagnostics-${{ matrix.toolchain }}
          path: |
            /tmp/clippy.log
            Cargo.lock
          if-no-files-found: error
          retention-days: 1

      - name: Run tests
        run: cargo test --all-targets --all-features --locked

      - name: Repeat transaction coalescing regression
        shell: bash
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            cargo test --locked concurrent_identical_queries_share_one_upstream_transaction
          done

      - name: Repeat cross-transaction redirect regressions
        shell: bash
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            cargo test --locked test_11_cross_transaction_redirects
          done

      - name: Repeat EDNS downgrade regressions
        shell: bash
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            cargo test --locked test_12_edns_feature_downgrade
          done

      - name: Repeat transport fallback regressions
        shell: bash
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            cargo test --locked test_13_transport_fallback
          done

      - name: Repeat root RRSIG regressions
        shell: bash
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            cargo test --locked test_14_root_rrsig_detection
          done

      - name: Build release binaries
        run: cargo build --release --locked

      - name: Check direct root privilege drop
        if: ${{ matrix.toolchain == 'stable' }}
        shell: bash
        run: bash tests/direct-root-privilege-drop.sh target/release/rustd-resolved

      - name: Check live DNS and Varlink path
        if: ${{ matrix.toolchain == 'stable' }}
        shell: bash
        run: python3 tests/live-dns.py target/release/rustd-resolved target/release/rustd-resolvectl

      - name: Check live D-Bus contracts
        if: ${{ matrix.toolchain == 'stable' }}
        shell: bash
        run: bash tests/dbus-introspection.sh target/release/rustd-resolved target/release/rustd-resolvectl

      - name: Publish final status
        if: ${{ always() }}
        shell: bash
        env:
          GH_TOKEN: ${{ github.token }}
          STATUS_CONTEXT: build-and-test/rust-${{ matrix.toolchain }}
          STATUS_STATE: ${{ job.status == 'success' && 'success' || 'failure' }}
          STATUS_DESCRIPTION: ${{ job.status == 'success' && 'Verification passed' || 'Verification failed' }}
          STATUS_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          set -euo pipefail
          payload=$(printf '{"state":"%s","context":"%s","description":"%s","target_url":"%s"}' "$STATUS_STATE" "$STATUS_CONTEXT" "$STATUS_DESCRIPTION" "$STATUS_URL")
          curl --fail-with-body --silent --show-error \
            --request POST \
            --header "Accept: application/vnd.github+json" \
            --header "Authorization: Bearer $GH_TOKEN" \
            --header "X-GitHub-Api-Version: 2022-11-28" \
            "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" \
            --data "$payload" >/dev/null

  formal:
    runs-on: ubuntu-latest
    timeout-minutes: 45
    concurrency:
      group: build-and-test-formal-${{ github.ref }}
      cancel-in-progress: false

    steps:
      - name: Publish pending formal status
        shell: bash
        env:
          GH_TOKEN: ${{ github.token }}
          STATUS_CONTEXT: build-and-test/formal
          STATUS_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          set -euo pipefail
          payload=$(printf '{"state":"pending","context":"%s","description":"Formal verification in progress","target_url":"%s"}' "$STATUS_CONTEXT" "$STATUS_URL")
          curl --fail-with-body --silent --show-error \
            --request POST \
            --header "Accept: application/vnd.github+json" \
            --header "Authorization: Bearer $GH_TOKEN" \
            --header "X-GitHub-Api-Version: 2022-11-28" \
            "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" \
            --data "$payload" >/dev/null

      - name: Check out source
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install formal toolchain dependencies
        shell: bash
        run: |
          set -euo pipefail
          sudo apt-get update
          sudo apt-get install --yes --no-install-recommends agda-bin chezscheme git libgmp-dev

      - name: Cache pinned Idris 2
        id: idris-cache
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ~/.idris2
          key: idris2-v0.8.0-${{ runner.os }}-${{ runner.arch }}

      - name: Bootstrap pinned Idris 2
        if: ${{ steps.idris-cache.outputs.cache-hit != 'true' }}
        shell: bash
        run: |
          set -euo pipefail
          rm -rf /tmp/Idris2
          git clone --depth 1 --branch v0.8.0 https://github.com/idris-lang/Idris2.git /tmp/Idris2
          make -C /tmp/Idris2 bootstrap SCHEME=chezscheme PREFIX="$HOME/.idris2"
          make -C /tmp/Idris2 install PREFIX="$HOME/.idris2"

      - name: Verify pinned formal compilers
        shell: bash
        run: |
          set -euo pipefail
          echo "$HOME/.idris2/bin" >> "$GITHUB_PATH"
          "$HOME/.idris2/bin/idris2" --version | grep '0.8.0'
          agda --version | grep '2.6.3'

      - name: Check Idris and Agda models
        shell: bash
        run: |
          set -euo pipefail
          export PATH="$HOME/.idris2/bin:$PATH"
          make check-formal

      - name: Publish final formal status
        if: ${{ always() }}
        shell: bash
        env:
          GH_TOKEN: ${{ github.token }}
          STATUS_CONTEXT: build-and-test/formal
          STATUS_STATE: ${{ job.status == 'success' && 'success' || 'failure' }}
          STATUS_DESCRIPTION: ${{ job.status == 'success' && 'Formal verification passed' || 'Formal verification failed' }}
          STATUS_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          set -euo pipefail
          payload=$(printf '{"state":"%s","context":"%s","description":"%s","target_url":"%s"}' "$STATUS_STATE" "$STATUS_CONTEXT" "$STATUS_DESCRIPTION" "$STATUS_URL")
          curl --fail-with-body --silent --show-error \
            --request POST \
            --header "Accept: application/vnd.github+json" \
            --header "Authorization: Bearer $GH_TOKEN" \
            --header "X-GitHub-Api-Version: 2022-11-28" \
            "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" \
            --data "$payload" >/dev/null