Skip to content

chore: nss-rs@0.10.0 #1229

chore: nss-rs@0.10.0

chore: nss-rs@0.10.0 #1229

Workflow file for this run

# Run QNS (QUIC Network Simulator) on PRs to test interop between the
# changes in the PR and its base branch.
name: QNS PR
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: read
env:
DELIM: "vs."
TIMEOUT: 20
jobs:
docker-image:
name: Build Docker images for QNS
if: github.actor != 'dependabot[bot]'
runs-on: ubuntu-24.04
strategy:
matrix:
include:
- name: pr
ref: ${{ github.event.pull_request.head.sha }}
- name: baseline
ref: ${{ github.event.pull_request.base.sha }}
steps:
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
with:
cache-binary: true
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
ref: ${{ matrix.ref }}
- uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
id: meta
with:
images: ghcr.io/${{ github.repository }}-qns-${{ matrix.name }}
tags: type=ref,event=pr
- uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
push: false
tags: ${{ steps.meta.outputs.tags }}
file: qns/Dockerfile
build-args: RUST_VERSION=stable
# GITHUB_TOKEN is used to avoid GitHub rate limits when fetching
# nss-versions.env from mozilla/actions. It is safe to pass here
# because PR runs require manual approval before any untrusted code
# executes.
secrets: github_token=${{ secrets.GITHUB_TOKEN }}
platforms: linux/amd64
outputs: type=docker,dest=/tmp/${{ matrix.name }}.tar
cache-from: type=gha
cache-to: type=gha,mode=min
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.name }} Docker image
path: /tmp/${{ matrix.name }}.tar
implementations:
name: Determine interop pairs
needs: docker-image
runs-on: ubuntu-24.04
outputs:
pairs: ${{ steps.config.outputs.pairs }}
implementations: ${{ steps.config.outputs.implementations }}
env:
URL: https://github.com/mozilla/neqo
ROLE: both
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: "* Docker image"
path: /tmp
merge-multiple: true
- env:
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
for IMAGE in pr baseline; do
docker load --input "/tmp/$IMAGE.tar"
echo "${IMAGE^^}_IMAGE=ghcr.io/$REPO-qns-$IMAGE:pr-$PR_NUMBER" >> "$GITHUB_ENV"
done
- id: config
run: |
# Add neqo-pr, neqo-baseline, and some non-default implementations
# tquic: https://github.com/quic-interop/quic-interop-runner/pull/385/files
# openssl: https://github.com/quic-interop/quic-interop-runner/pull/402/files
# linuxquic: https://github.com/quic-interop/quic-interop-runner/pull/428
# quic-zig: https://github.com/quic-interop/quic-interop-runner/pull/491
cat <<EOF > additional.json
{
"neqo-pr": {
"image": "$PR_IMAGE",
"url": "$URL",
"role": "$ROLE"
},
"neqo-baseline": {
"image": "$BASELINE_IMAGE",
"url": "$URL",
"role": "$ROLE"
},
"tquic": {
"image": "tquicgroup/tquic:latest",
"url": "https://github.com/Tencent/tquic/",
"role": "both"
},
"openssl": {
"image": "quay.io/openssl-ci/openssl-quic-interop",
"url": "https://github.com/openssl/openssl",
"role": "client"
},
"linuxquic": {
"image": "quay.io/lxin/linuxquic-interop:latest",
"url": "https://github.com/lxin/quic",
"role": "both"
},
"quic-zig": {
"image": "ghcr.io/endel/quic-zig:latest",
"url": "https://github.com/endel/quic-zig",
"role": "both"
}
}
EOF
curl -o runner.json https://raw.githubusercontent.com/quic-interop/quic-interop-runner/master/implementations_quic.json
jq '. += input' runner.json additional.json > implementations_quic.json
{
echo "implementations<<EOF"
cat implementations_quic.json
echo "EOF"
} >> "$GITHUB_OUTPUT"
# Determine valid interop pairs: all combinations involving neqo-pr or neqo-baseline
# shellcheck disable=SC2016
jq < implementations_quic.json '[
[to_entries[] | select(.value.role=="server" or .value.role=="both").key] as $servers |
[to_entries[] | select(.value.role=="client" or .value.role=="both").key] as $clients |
$clients[] as $client |
$servers[] as $server |
$client + " '"$DELIM"' " + $server |
select((contains("neqo-pr") or contains("neqo-baseline")) and ($client != $server))
]' > pairs.json
{
echo "pairs<<EOF"
cat pairs.json
echo "EOF"
} >> "$GITHUB_OUTPUT"
run-qns:
name: Run QNS
needs: implementations
strategy:
fail-fast: false
matrix:
pair: ${{ fromJson(needs.implementations.outputs.pairs) }}
runs-on: ubuntu-24.04
steps:
# quic-interop-runner requires Docker v28.1. GitHub's ubuntu-24.04 comes
# with v28.0.4. Install newer version.
- name: Set up Docker
uses: docker/setup-docker-action@b2189fbf2a6592b51fee7cdd93ee2bfaeba733db # v5.1.0
with:
version: "v28.1.0"
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: "pr Docker image"
path: /tmp
- run: docker load --input "/tmp/pr.tar"
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
if: contains(matrix.pair, 'neqo-baseline')
with:
name: "baseline Docker image"
path: /tmp
- if: contains(matrix.pair, 'neqo-baseline')
run: docker load --input /tmp/baseline.tar
- id: depair
env:
PAIR: ${{ matrix.pair }}
run: |
PAIR="${PAIR/ $DELIM /%}"
echo "client=$(echo "$PAIR" | cut -d% -f1)" >> "$GITHUB_OUTPUT"
echo "server=$(echo "$PAIR" | cut -d% -f2)" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# TODO: Replace once https://github.com/quic-interop/quic-interop-runner/pull/356 is merged.
- uses: ./.github/actions/quic-interop-runner
timeout-minutes: ${{ fromJSON(env.TIMEOUT) }}
continue-on-error: true
id: run
with:
client: ${{ steps.depair.outputs.client }}
server: ${{ steps.depair.outputs.server }}
implementations: ${{ needs.implementations.outputs.implementations }}
- if: always()
env:
RESULT: ${{ steps.run.outputs.result }}
run: test "$RESULT" != "error"
report:
name: Report results
if: ${{ !cancelled() }}
needs: [docker-image, run-qns, implementations]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: "*results"
path: results
- run: sudo apt-get install -y --no-install-recommends wdiff cmark-gfm
- env:
PAIRS: ${{ needs.implementations.outputs.pairs }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
PR: "neqo-pr"
run: |
# shellcheck disable=SC2153
mapfile -t LIST < <(echo "$PAIRS" | jq '.[]' | sort)
for PREFIX in "${LIST[@]}"; do
PREFIX=$(echo "$PREFIX" | tr -d '"')
# Skip neqo-baseline results as they're only used as baseline
[[ "$PREFIX" == *"neqo-baseline"* ]] && continue
CLIENT=$(echo "$PREFIX" | cut -f1 -d " ")
SERVER=$(echo "$PREFIX" | cut -f3 -d " ")
if [ "$CLIENT" == "$PR" ]; then
ROLE=client
else
ROLE=server
fi
RUN="results/${PREFIX} results"
PAIR="$CLIENT $DELIM $SERVER"
if [ ! -e "$RUN/result.json" ]; then
echo "* $PAIR: run cancelled after $TIMEOUT min" >> "$ROLE.failed.md"
continue
fi
BASELINE_RUN="${RUN/$PR/neqo-baseline}"
if [ ! -s "$BASELINE_RUN/result.json" ]; then
echo "* $PAIR: baseline result missing" >> "$ROLE.failed.md"
continue
fi
for BRANCH in "$RUN" "$BASELINE_RUN"; do
if [ ! -s "$BRANCH/result.json" ]; then
echo "* $PAIR: $BRANCH result missing" >> "$ROLE.failed.md"
continue 2
fi
# Skip if .results is null or missing
if ! jq -e '.results' "$BRANCH/result.json" > /dev/null 2>&1; then
echo "* $PAIR: $BRANCH has no results" >> "$ROLE.failed.md"
continue 2
fi
jq < "$BRANCH/result.json" '
. as $data |
.results[][].result //= "failed" |
{
results: [.results[] | group_by(.result)[] | {(.[0].result): [.[] | .abbr]}] |
add
} |
. + {log_url: $data.log_url}
' > "$BRANCH/$ROLE.grouped.json"
done
for ROLE in client server; do
[ ! -e "$RUN/$ROLE.grouped.json" ] && continue
for GROUP in $(jq -r < "$RUN/$ROLE.grouped.json" '.results | keys[]'); do
PR_RESULT=$(jq < "$RUN/$ROLE.grouped.json" -r '.results.'"$GROUP"'[]' | fmt -w 1000)
LOG=$(jq -r < "$RUN/$ROLE.grouped.json" -r '.log_url')
# Get baseline from neqo-baseline if available
BASELINE=$(mktemp)
BASELINE_GROUPED="$BASELINE_RUN/$ROLE.grouped.json"
if [ -s "$BASELINE_GROUPED" ]; then
jq < "$BASELINE_GROUPED" -r '.results.'"$GROUP"'[]' | fmt -w 1000 > "$BASELINE"
fi
[ -n "$PR_RESULT" ] || continue
DIFF=$(wdiff -n "$BASELINE" - <<< "$PR_RESULT" || true)
ADD=""
ADD_DELIM=""
DEL=""
DEL_DELIM=""
if [ "$GROUP" == "failed" ]; then
ADD=":warning:"
ADD_DELIM="\*\*"
DEL=":rocket:"
DEL_DELIM="~~"
elif [ "$GROUP" == "succeeded" ]; then
ADD=":rocket:"
ADD_DELIM="~~"
DEL=":warning:"
DEL_DELIM="\*\*"
fi
RESULT=$(echo "$DIFF" | sed -E "s/\[-/ $DEL$DEL_DELIM/g; s/-\]/$DEL_DELIM /g; s/\{\+/ $ADD$ADD_DELIM/g; s/\+\}/$ADD_DELIM /g")
echo "* [$PAIR]($LOG): $RESULT" >> "$ROLE.$GROUP.md"
done
done
done
{
echo "### Failed Interop Tests"
if [ -e client.failed.md ] || [ -e server.failed.md ]; then
echo -n "[QUIC Interop Runner](https://github.com/quic-interop/quic-interop-runner), *client* vs. *server*"
if [ "$BASE_SHA" ]; then
echo -n ", differences relative to \`$BASE_REF\` at ${BASE_SHA}"
fi
echo "."
echo
echo "<table><tr><th align=\"left\">$PR as client</th><th align=\"left\">$PR as server</th></tr>"
echo -n "<tr><td valign=\"top\">"
if [ -e client.failed.md ]; then
cmark-gfm -e strikethrough -e autolink client.failed.md | tr -d '\n' | sed 's/<\/*ul>//g; s/<li>//g; s/<\/li>/<br>/g'
fi
echo -n "</td><td valign=\"top\">"
if [ -e server.failed.md ]; then
cmark-gfm -e strikethrough -e autolink server.failed.md | tr -d '\n' | sed 's/<\/*ul>//g; s/<li>//g; s/<\/li>/<br>/g'
fi
echo "</td></tr></table>"
else
echo -n "None "
if [ -e "client.succeeded.md" ] || [ -e "server.succeeded.md" ] || [ -e "client.unsupported.md" ] || [ -e "server.unsupported.md" ]; then
echo ":tada:"
else
echo ":question:"
fi
fi
echo "<details><summary>All results</summary>"
echo
for GROUP in succeeded unsupported; do
echo "### ${GROUP^} Interop Tests"
echo "[QUIC Interop Runner](https://github.com/quic-interop/quic-interop-runner), *client* vs. *server*"
echo "#### $PR as client"
cat "client.$GROUP.md" 2>/dev/null || echo "None :question:"
echo "#### $PR as server"
cat "server.$GROUP.md" 2>/dev/null || echo "None :question:"
done
echo
echo "</details>"
} >> comment.md
- uses: ./.github/actions/pr-comment-data-export
with:
name: ${{ github.workflow }}
contents: comment.md