CI #234
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| changes: | |
| name: Changes | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| outputs: | |
| native: ${{ steps.classify.outputs.native }} | |
| package_artifact: ${{ steps.classify.outputs.package_artifact }} | |
| wpt: ${{ steps.classify.outputs.wpt }} | |
| chrome_e2e: ${{ steps.classify.outputs.chrome_e2e }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: classify | |
| name: Classify changed files | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| base="$(node -e "const e = require(process.env.GITHUB_EVENT_PATH); process.stdout.write(e.pull_request?.base?.sha || e.before || '')")" | |
| head="$GITHUB_SHA" | |
| if [ -z "$base" ] || [[ "$base" =~ ^0+$ ]]; then | |
| echo "native=true" >> "$GITHUB_OUTPUT" | |
| echo "package_artifact=true" >> "$GITHUB_OUTPUT" | |
| echo "wpt=true" >> "$GITHUB_OUTPUT" | |
| echo "chrome_e2e=true" >> "$GITHUB_OUTPUT" | |
| echo "No comparable base commit; running full CI." >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| fi | |
| if ! git fetch --no-tags --depth=1 origin "$base"; then | |
| echo "native=true" >> "$GITHUB_OUTPUT" | |
| echo "package_artifact=true" >> "$GITHUB_OUTPUT" | |
| echo "wpt=true" >> "$GITHUB_OUTPUT" | |
| echo "chrome_e2e=true" >> "$GITHUB_OUTPUT" | |
| echo "Could not fetch base commit; running full CI." >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| fi | |
| git diff --name-only "$base" "$head" > changed-files.txt | |
| cat changed-files.txt | |
| native_changed="false" | |
| package_changed="false" | |
| wpt_changed="false" | |
| chrome_e2e_changed="false" | |
| workflow_changed="false" | |
| while IFS= read -r file; do | |
| [ -z "$file" ] && continue | |
| case "$file" in | |
| .github/workflows/*|.github/actions/*) | |
| workflow_changed="true" | |
| ;; | |
| esac | |
| case "$file" in | |
| packages/*|vcpkg.json|package.json|package-lock.json) | |
| native_changed="true" | |
| ;; | |
| esac | |
| case "$file" in | |
| packages/*|vcpkg.json|build-containers/*|package.json|package-lock.json) | |
| package_changed="true" | |
| ;; | |
| esac | |
| case "$file" in | |
| wpt-manifest.json|scripts/check-wpt-*|scripts/ensure-wpt.js|scripts/run-wpt-*|scripts/write-wpt-report.js) | |
| wpt_changed="true" | |
| ;; | |
| esac | |
| case "$file" in | |
| packages/*|package.json|package-lock.json) | |
| chrome_e2e_changed="true" | |
| ;; | |
| esac | |
| done < changed-files.txt | |
| if [ "$workflow_changed" = "true" ]; then | |
| native_changed="true" | |
| package_changed="true" | |
| wpt_changed="true" | |
| chrome_e2e_changed="true" | |
| fi | |
| echo "native=$native_changed" >> "$GITHUB_OUTPUT" | |
| echo "package_artifact=$package_changed" >> "$GITHUB_OUTPUT" | |
| echo "wpt=$wpt_changed" >> "$GITHUB_OUTPUT" | |
| echo "chrome_e2e=$chrome_e2e_changed" >> "$GITHUB_OUTPUT" | |
| if [ "$workflow_changed" = "true" ]; then | |
| echo "Workflow/action files changed; running full CI." >> "$GITHUB_STEP_SUMMARY" | |
| elif [ "$native_changed" = "true" ] || [ "$package_changed" = "true" ] || [ "$wpt_changed" = "true" ] || [ "$chrome_e2e_changed" = "true" ]; then | |
| echo "Relevant files changed; running targeted CI jobs." >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| echo "No native, package, or WPT files changed; skipping heavy CI jobs." >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| quality: | |
| name: Quality | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run check | |
| - run: npm run types:check | |
| - run: npm run package:check | |
| package-artifact: | |
| name: Package artifact | |
| runs-on: ubuntu-latest | |
| needs: [changes, quality] | |
| if: needs.changes.outputs.native == 'true' || needs.changes.outputs.package_artifact == 'true' | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - uses: ./.github/actions/setup-native-build | |
| - run: npm ci | |
| - run: npm run build -w @webrtc-node/webrtc | |
| - name: Pack source artifact | |
| id: pack | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| tarball="$(npm pack -w @webrtc-node/webrtc --json | node -e "let input = ''; process.stdin.on('data', chunk => input += chunk); process.stdin.on('end', () => process.stdout.write(JSON.parse(input)[0].filename));")" | |
| echo "tarball=$tarball" >> "$GITHUB_OUTPUT" | |
| - name: Verify packed package API | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p ci-artifacts/packages | |
| cp "${{ steps.pack.outputs.tarball }}" ci-artifacts/packages/ | |
| workdir="$(mktemp -d)" | |
| cd "$workdir" | |
| npm init -y >/dev/null | |
| npm install --ignore-scripts "$OLDPWD/ci-artifacts/packages/${{ steps.pack.outputs.tarball }}" | |
| WEBRTC_NODE_NATIVE_PATH="$OLDPWD/packages/webrtc/build/Release/webrtc_node.node" node "$OLDPWD/scripts/smoke-installed-workspace.js" | |
| - name: Verify packed source build | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| workdir="$(mktemp -d)" | |
| tar -xzf "${{ steps.pack.outputs.tarball }}" -C "$workdir" | |
| cd "$workdir/package" | |
| npm install | |
| npm run build | |
| node -e "const { RTCPeerConnection } = require('./'); const pc = new RTCPeerConnection(); pc.close(); console.log('packed source require ok');" | |
| - name: Verify static Linux addon build | |
| shell: bash | |
| run: | | |
| docker build \ | |
| -f build-containers/Dockerfile.debian \ | |
| --build-arg NODE_VERSION=20 \ | |
| --build-arg DEBIAN_VERSION=bullseye \ | |
| -t webrtc-node-ci-debian . | |
| docker run --rm \ | |
| -v "$PWD:/usr/app" \ | |
| -w /usr/app \ | |
| webrtc-node-ci-debian \ | |
| sh -lc "npm ci --ignore-scripts && npm run build -- --CDWEBRTC_NODE_STATIC_OPENSSL=ON && node -e \"const { RTCPeerConnection } = require('@webrtc-node/webrtc'); const pc = new RTCPeerConnection(); pc.close();\"" | |
| build-test: | |
| name: ${{ matrix.os }} / Node ${{ matrix.node }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [changes, quality] | |
| if: needs.changes.outputs.native == 'true' | |
| timeout-minutes: 90 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| node: [20, 22, 24] | |
| include: | |
| - os: windows-11-arm | |
| node: 24 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: npm | |
| - uses: ./.github/actions/setup-native-build | |
| - run: npm ci | |
| - run: npm run native:check | |
| - run: npm run build | |
| - run: npm test | |
| - run: npm run api:check | |
| - run: npm run types:check | |
| wpt-smoke: | |
| name: WPT smoke | |
| runs-on: ubuntu-latest | |
| needs: [changes, quality] | |
| if: needs.changes.outputs.native == 'true' || needs.changes.outputs.wpt == 'true' | |
| timeout-minutes: 30 | |
| env: | |
| WPT_TEST_TIMEOUT_MS: 180000 | |
| WPT_WORKER_TIMEOUT_MS: 600000 | |
| WPT_WORKER_DELAY_MS: 2000 | |
| WPT_CLEANUP_DELAY_MS: 3000 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - uses: ./.github/actions/setup-native-build | |
| - run: npm ci | |
| - run: npm run wpt:ensure | |
| - run: npm run native:check | |
| - run: npm run build | |
| - run: npm run wpt:selection:check | |
| - run: npm run wpt:smoke | |
| - run: npm run wpt:smoke:check | |
| - run: npm run wpt:report -- --output wpt-report.md --expected-total 4 | |
| if: always() && hashFiles('wpt-results.json') != '' | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: wpt-smoke | |
| path: | | |
| wpt-manifest.json | |
| wpt-report.md | |
| wpt-results.json | |
| chrome-e2e: | |
| name: Chrome E2E | |
| runs-on: ubuntu-latest | |
| needs: [changes, quality] | |
| if: needs.changes.outputs.chrome_e2e == 'true' | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - uses: ./.github/actions/setup-native-build | |
| - run: npm ci | |
| - run: npm run native:check | |
| - run: npm run build | |
| - name: Verify Chrome installation | |
| shell: bash | |
| run: | | |
| if command -v google-chrome >/dev/null 2>&1; then | |
| google-chrome --version | |
| else | |
| google-chrome-stable --version | |
| fi | |
| - name: Run Chrome E2E | |
| run: npm run e2e:chrome | |
| ci-required: | |
| name: CI required | |
| runs-on: ubuntu-latest | |
| needs: | |
| - changes | |
| - quality | |
| - package-artifact | |
| - build-test | |
| - wpt-smoke | |
| - chrome-e2e | |
| if: always() | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Verify required CI jobs | |
| env: | |
| JOB_RESULTS: ${{ toJSON(needs) }} | |
| shell: bash | |
| run: | | |
| node <<'NODE' | |
| const jobs = JSON.parse(process.env.JOB_RESULTS); | |
| const failed = Object.entries(jobs).filter( | |
| ([, job]) => job.result !== "success" && job.result !== "skipped", | |
| ); | |
| if (failed.length > 0) { | |
| for (const [name, job] of failed) { | |
| console.error(`${name}: ${job.result}`); | |
| } | |
| process.exit(1); | |
| } | |
| console.log("All required CI jobs passed or were intentionally skipped."); | |
| NODE |