From 32d89c987dcbe43be2177cb31937d15f1e9865f5 Mon Sep 17 00:00:00 2001 From: nightness Date: Wed, 1 Apr 2026 09:00:42 -0500 Subject: [PATCH 1/2] ci: add criterion benchmark CI + git-cliff changelog generation - .github/workflows/bench.yml: runs cargo bench for all 7 crates with criterion benchmarks (rtp, rtcp, stun, sdp, srtp, turn, media) on every push/PR to master; uses github-action-benchmark to track regressions and alert on >10% slowdowns - .github/workflows/release.yml: on version tags, generates CHANGELOG.md via git-cliff and creates a GitHub Release with the generated notes - .cliff.toml: git-cliff config for conventional commits (feat/fix/perf/ refactor/doc/test/chore groups) Co-Authored-By: Claude Sonnet 4.6 --- .cliff.toml | 49 ++++++++++++++++++++++++ .github/workflows/bench.yml | 70 +++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 60 ++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 .cliff.toml create mode 100644 .github/workflows/bench.yml create mode 100644 .github/workflows/release.yml diff --git a/.cliff.toml b/.cliff.toml new file mode 100644 index 00000000..23744d23 --- /dev/null +++ b/.cliff.toml @@ -0,0 +1,49 @@ +[changelog] +header = """ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +""" +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [Unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.message | upper_first }}\ + {% if commit.breaking %} [**BREAKING**]{% endif %} \ + ([{{ commit.id | truncate(length=7, end="") }}]({{ commit.id }}))\ + {% endfor %} +{% endfor %}\n +""" +footer = "" +trim = true + +[git] +conventional_commits = true +filter_unconventional = true +split_commits = false +commit_preprocessors = [] +commit_parsers = [ + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactoring" }, + { message = "^doc", group = "Documentation" }, + { message = "^test", group = "Testing" }, + { message = "^chore|^ci|^build", group = "Miscellaneous" }, + { message = "^revert", group = "Reverted Commits" }, +] +protect_breaking_commits = false +filter_commits = false +tag_pattern = "v[0-9].*" +skip_tags = "" +ignore_tags = "" +topo_order = false +sort_commits = "oldest" diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 00000000..affd7773 --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,70 @@ +name: Benchmarks + +on: + push: + branches: [master] + pull_request: + branches: [master] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + benchmark: + name: Run criterion benchmarks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-bench-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-bench- + + - name: Run benchmarks (rtc-rtp) + run: cargo bench -p rtc-rtp -- --output-format bencher | tee bench-rtp.txt + + - name: Run benchmarks (rtc-rtcp) + run: cargo bench -p rtc-rtcp -- --output-format bencher | tee bench-rtcp.txt + + - name: Run benchmarks (rtc-stun) + run: cargo bench -p rtc-stun -- --output-format bencher | tee bench-stun.txt + + - name: Run benchmarks (rtc-sdp) + run: cargo bench -p rtc-sdp -- --output-format bencher | tee bench-sdp.txt + + - name: Run benchmarks (rtc-srtp) + run: cargo bench -p rtc-srtp -- --output-format bencher | tee bench-srtp.txt + + - name: Run benchmarks (rtc-turn) + run: cargo bench -p rtc-turn -- --output-format bencher | tee bench-turn.txt + + - name: Run benchmarks (rtc-media) + run: cargo bench -p rtc-media -- --output-format bencher | tee bench-media.txt + + - name: Store benchmark results + uses: benchmark-action/github-action-benchmark@v1 + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + with: + name: WebRTC-RS Criterion Benchmarks + tool: cargo + output-file-path: bench-rtp.txt + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + # Alert if performance degrades by more than 10% + alert-threshold: '110%' + comment-on-alert: true + fail-on-alert: false + benchmark-data-dir-path: docs/benchmarks diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..27a0fd7d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,60 @@ +name: Release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+*' + +env: + CARGO_TERM_COLOR: always + +jobs: + changelog: + name: Generate Changelog + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install git-cliff + uses: kenji-miyake/setup-git-cliff@v2 + + - name: Generate changelog for this release + run: | + git cliff --current --output CHANGELOG.md + + - name: Upload changelog artifact + uses: actions/upload-artifact@v4 + with: + name: changelog + path: CHANGELOG.md + + publish: + name: Publish to crates.io + runs-on: ubuntu-latest + needs: changelog + steps: + - uses: actions/checkout@v4 + + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Download changelog + uses: actions/download-artifact@v4 + with: + name: changelog + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + body_path: CHANGELOG.md + token: ${{ secrets.GITHUB_TOKEN }} + + # Uncomment and configure when ready to publish to crates.io: + # - name: Publish crates + # run: | + # cargo publish -p rtc-shared --token ${{ secrets.CRATES_IO_TOKEN }} + # cargo publish -p rtc-rtp --token ${{ secrets.CRATES_IO_TOKEN }} + # cargo publish -p rtc-rtcp --token ${{ secrets.CRATES_IO_TOKEN }} + # # ... remaining crates in dependency order From 6eb561765b7ed2bf1a2e092dde81ef9949400f52 Mon Sep 17 00:00:00 2001 From: nightness Date: Wed, 1 Apr 2026 09:01:58 -0500 Subject: [PATCH 2/2] ci: add automated fuzzing CI + OSS-Fuzz integration config - .github/workflows/fuzz.yml: daily scheduled fuzzing of all 87 targets across rtc-dtls (29), rtc-sctp (30), rtc-rtcp (24), rtc-sdp (2), rtc-stun (1), rtc-rtp (1) using cargo-fuzz with libfuzzer; crashes uploaded as artifacts for triage; can also be triggered manually with configurable duration - oss-fuzz/: configuration to submit to Google's OSS-Fuzz continuous fuzzing platform (project.yaml, Dockerfile, build.sh); submit via PR to https://github.com/google/oss-fuzz to enable cloud-scale fuzzing Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/fuzz.yml | 68 ++++++++++++++++++++++++++++++++++++++ oss-fuzz/Dockerfile | 11 ++++++ oss-fuzz/build.sh | 51 ++++++++++++++++++++++++++++ oss-fuzz/project.yaml | 12 +++++++ 4 files changed, 142 insertions(+) create mode 100644 .github/workflows/fuzz.yml create mode 100644 oss-fuzz/Dockerfile create mode 100755 oss-fuzz/build.sh create mode 100644 oss-fuzz/project.yaml diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml new file mode 100644 index 00000000..f1b5a35b --- /dev/null +++ b/.github/workflows/fuzz.yml @@ -0,0 +1,68 @@ +name: Fuzz + +on: + schedule: + # Run daily at 02:00 UTC + - cron: '0 2 * * *' + workflow_dispatch: + inputs: + duration: + description: 'Fuzzing duration per target in seconds' + required: false + default: '30' + +env: + CARGO_TERM_COLOR: always + FUZZ_DURATION: ${{ github.event.inputs.duration || '30' }} + +jobs: + fuzz: + name: Fuzz ${{ matrix.crate }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + crate: + - rtc-dtls + - rtc-sctp + - rtc-rtcp + - rtc-sdp + - rtc-stun + - rtc-rtp + steps: + - uses: actions/checkout@v4 + + - name: Install nightly toolchain (required by cargo-fuzz) + uses: dtolnay/rust-toolchain@nightly + + - name: Install cargo-fuzz + run: cargo install cargo-fuzz --locked + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-fuzz-${{ matrix.crate }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-fuzz-${{ matrix.crate }}- + + - name: Run fuzz targets (${{ matrix.crate }}) + working-directory: ${{ matrix.crate }}/fuzz + run: | + TARGETS=$(cargo fuzz list) + for TARGET in $TARGETS; do + echo "==> Fuzzing $TARGET for ${FUZZ_DURATION}s" + cargo fuzz run "$TARGET" -- \ + -max_total_time="${FUZZ_DURATION}" \ + -error_exitcode=77 \ + 2>&1 | tail -5 + done + + - name: Upload crash artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: fuzz-crashes-${{ matrix.crate }} + path: ${{ matrix.crate }}/fuzz/artifacts/ + if-no-files-found: ignore diff --git a/oss-fuzz/Dockerfile b/oss-fuzz/Dockerfile new file mode 100644 index 00000000..211e9fd6 --- /dev/null +++ b/oss-fuzz/Dockerfile @@ -0,0 +1,11 @@ +FROM gcr.io/oss-fuzz-base/base-builder-rust + +RUN apt-get update && apt-get install -y --no-install-recommends \ + cmake \ + libssl-dev \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +COPY . $SRC/webrtc-rs-rtc +COPY oss-fuzz/build.sh $SRC/build.sh +WORKDIR $SRC/webrtc-rs-rtc diff --git a/oss-fuzz/build.sh b/oss-fuzz/build.sh new file mode 100755 index 00000000..9333b554 --- /dev/null +++ b/oss-fuzz/build.sh @@ -0,0 +1,51 @@ +#!/bin/bash -eu +# +# OSS-Fuzz build script for webrtc-rs-rtc +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/rust-lang/ +# +# This script is run inside the OSS-Fuzz Docker container. +# $OUT is the output directory for fuzz target binaries. +# $LIB_FUZZING_ENGINE is the fuzzing engine flags. +# $CFLAGS / $CXXFLAGS / $RUSTFLAGS are set by the base image. + +cd "$SRC/webrtc-rs-rtc" + +# Build all fuzz targets for each crate. +# cargo-fuzz compiles with --release and links libFuzzer automatically +# when RUSTFLAGS contains the libfuzzer flags provided by oss-fuzz. + +FUZZ_CRATES=( + rtc-dtls + rtc-sctp + rtc-rtcp + rtc-sdp + rtc-stun + rtc-rtp +) + +for CRATE in "${FUZZ_CRATES[@]}"; do + pushd "$CRATE/fuzz" + + # List all fuzz targets for this crate + TARGETS=$(cargo fuzz list 2>/dev/null || true) + + for TARGET in $TARGETS; do + cargo fuzz build \ + --fuzz-dir . \ + --release \ + -O \ + "$TARGET" \ + -- \ + $LIB_FUZZING_ENGINE \ + $RUSTFLAGS + + # Copy the compiled binary to $OUT + cp "target/x86_64-unknown-linux-gnu/release/$TARGET" "$OUT/${CRATE//-/_}_$TARGET" || \ + cp "target/release/fuzzing/$TARGET" "$OUT/${CRATE//-/_}_$TARGET" || true + done + + popd +done + +echo "OSS-Fuzz build complete. Targets in $OUT:" +ls "$OUT/" | grep -v '\.options$' || true diff --git a/oss-fuzz/project.yaml b/oss-fuzz/project.yaml new file mode 100644 index 00000000..7df0653b --- /dev/null +++ b/oss-fuzz/project.yaml @@ -0,0 +1,12 @@ +homepage: "https://github.com/webrtc-rs/rtc" +language: rust +primary_contact: "maintainer@example.com" +auto_ccs: + - "maintainer@example.com" +fuzzing_engines: + - libfuzzer + - afl + - honggfuzz +sanitizers: + - address + - undefined