From e6349469a5961dc918fa465289c74f7826c75bdf Mon Sep 17 00:00:00 2001 From: mertushka Date: Sun, 11 Oct 2026 19:14:30 +0300 Subject: [PATCH 1/4] chore: prepare 0.2.2 release --- .github/workflows/published-install.yml | 16 ++- .github/workflows/release.yml | 148 ++++++++++++++++++------ docs/README.md | 1 + docs/releasing.md | 36 ++++++ package-lock.json | 4 +- package.json | 2 +- scripts/validate-prebuild-install.js | 123 ++++++++++++++++++++ 7 files changed, 287 insertions(+), 43 deletions(-) create mode 100644 docs/releasing.md create mode 100644 scripts/validate-prebuild-install.js diff --git a/.github/workflows/published-install.yml b/.github/workflows/published-install.yml index adf8011..a896f52 100644 --- a/.github/workflows/published-install.yml +++ b/.github/workflows/published-install.yml @@ -17,7 +17,7 @@ permissions: jobs: package: name: Resolve package - if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' + if: github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'release') runs-on: ubuntu-latest timeout-minutes: 5 outputs: @@ -47,7 +47,7 @@ jobs: fi for attempt in 1 2 3 4 5 6; do - if npm view "$spec" version; then + if version="$(npm view "$spec" version)"; then break fi if [ "$attempt" = "6" ]; then @@ -56,6 +56,7 @@ jobs: sleep $((attempt * 10)) done + spec="@webrtc-node/webrtc@$version" echo "spec=$spec" >> "$GITHUB_OUTPUT" echo "Testing $spec" >> "$GITHUB_STEP_SUMMARY" @@ -79,11 +80,15 @@ jobs: image: node:24-bookworm steps: + - uses: actions/checkout@v7 + with: + ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }} - name: Install published package env: PACKAGE_SPEC: ${{ needs.package.outputs.spec }} run: | docker run --rm \ + -v "$PWD/examples/datachannel.js:/smoke-source.js:ro" \ -e PACKAGE_SPEC \ -e WEBRTC_NODE_PREBUILD_ONLY=1 \ "${{ matrix.image }}" \ @@ -102,6 +107,8 @@ jobs: done node -e "const { RTCPeerConnection } = require(\"@webrtc-node/webrtc\"); const pc = new RTCPeerConnection(); pc.close(); console.log(\"cjs ok\");" node --input-type=module -e "import { RTCPeerConnection } from \"@webrtc-node/webrtc\"; const pc = new RTCPeerConnection(); pc.close(); console.log(\"esm ok\");" + sed "s|require(\"..\")|require(\"@webrtc-node/webrtc\")|" /smoke-source.js > smoke.cjs + node smoke.cjs ' hosted: @@ -123,6 +130,9 @@ jobs: os: windows-11-arm steps: + - uses: actions/checkout@v7 + with: + ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }} - uses: actions/setup-node@v6 with: node-version: 24 @@ -149,3 +159,5 @@ jobs: done node -e "const { RTCPeerConnection } = require('@webrtc-node/webrtc'); const pc = new RTCPeerConnection(); pc.close(); console.log('cjs ok');" node --input-type=module -e "import { RTCPeerConnection } from '@webrtc-node/webrtc'; const pc = new RTCPeerConnection(); pc.close(); console.log('esm ok');" + sed 's|require("..")|require("@webrtc-node/webrtc")|' "$GITHUB_WORKSPACE/examples/datachannel.js" > smoke.cjs + node smoke.cjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 093793b..4026a2a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,16 +2,6 @@ name: Release on: workflow_dispatch: - inputs: - npm_tag: - description: npm distribution tag (used only when publish_npm is enabled) - required: true - default: next - publish_npm: - description: Publish to npm after uploading prebuild assets (explicit opt-in) - required: true - type: boolean - default: false release: types: [published] @@ -52,11 +42,11 @@ jobs: steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.sha }} - name: Build Linux prebuild run: | - docker build \ + docker build --no-cache --pull \ -f "${{ matrix.dockerfile }}" \ ${{ matrix.build_args }} \ -t "${{ matrix.image }}" . @@ -64,7 +54,24 @@ jobs: -v "$PWD:/usr/app" \ -w /usr/app \ "${{ matrix.image }}" \ - sh -lc "npm ci --ignore-scripts && npm run build -- --CDWEBRTC_NODE_STATIC_OPENSSL=ON && npm run prebuild:package -- --platform=linux --arch=${{ matrix.arch }} --libc=${{ matrix.libc }} && node -e \"const { RTCPeerConnection } = require('./'); const pc = new RTCPeerConnection(); pc.close();\"" + sh -lc "npm ci --ignore-scripts && npm run build -- --CDWEBRTC_NODE_STATIC_OPENSSL=ON && npm run native:check && npm test && npm run api:check && npm run types:check && npm run prebuild:package -- --platform=linux --arch=${{ matrix.arch }} --libc=${{ matrix.libc }} && node -e \"const { RTCPeerConnection } = require('./'); const pc = new RTCPeerConnection(); pc.close();\" && npm exec -c \"node scripts/validate-prebuild-install.js\"" + + - name: Inspect Linux addon linkage + run: | + docker run --rm -v "$PWD:/usr/app" -w /usr/app "${{ matrix.image }}" sh -lc 'set -eu + cmake --version + readelf -h build/Release/webrtc_node.node + readelf -d build/Release/webrtc_node.node > /tmp/addon-dependencies + cat /tmp/addon-dependencies + readelf --version-info build/Release/webrtc_node.node + ! grep -E "Shared library:.*(libssl|libcrypto)" /tmp/addon-dependencies + test "$(grep -Ec "OPENSSL_(CRYPTO|SSL)_LIBRARY:FILEPATH=.*\.a$" build/CMakeCache.txt)" = 2 + if [ "${{ matrix.libc }}" = glibc ]; then + test "$(getconf GNU_LIBC_VERSION)" = "glibc 2.31" + newest="$(readelf --version-info build/Release/webrtc_node.node | grep -oE "GLIBC_[0-9.]+" | sed "s/GLIBC_//" | sort -Vu | tail -1)" + test "$(printf "%s\n" "$newest" 2.31 | sort -V | tail -1)" = 2.31 + fi + ' - uses: actions/upload-artifact@v7 with: @@ -89,7 +96,7 @@ jobs: steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.sha }} - uses: actions/setup-node@v6 with: @@ -102,10 +109,22 @@ jobs: - run: npm run build -- --arch=${{ matrix.arch }} --CDWEBRTC_NODE_STATIC_OPENSSL=ON + - name: Verify static OpenSSL selection + shell: bash + run: | + test "$(grep -Ec 'OPENSSL_(CRYPTO|SSL)_LIBRARY:FILEPATH=.*\.(a|lib)$' build/CMakeCache.txt)" = 2 + + - run: npm run native:check + - run: npm test + - run: npm run api:check + - run: npm run types:check + - run: npm run prebuild:package -- --platform=darwin --arch=${{ matrix.arch }} - run: node -e "const { RTCPeerConnection } = require('./'); const pc = new RTCPeerConnection(); pc.close();" + - run: npm exec -c "node scripts/validate-prebuild-install.js" + - uses: actions/upload-artifact@v7 with: name: prebuild-${{ matrix.target }} @@ -129,7 +148,7 @@ jobs: steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.sha }} - uses: actions/setup-node@v6 with: @@ -142,32 +161,54 @@ jobs: - run: npm run build -- --arch=${{ matrix.arch }} --CDWEBRTC_NODE_STATIC_OPENSSL=ON + - name: Verify static OpenSSL selection + shell: bash + run: | + test "$(grep -Ec 'OPENSSL_(CRYPTO|SSL)_LIBRARY:FILEPATH=.*\.(a|lib)$' build/CMakeCache.txt)" = 2 + + - run: npm run native:check + - run: npm test + - run: npm run api:check + - run: npm run types:check + - run: npm run prebuild:package -- --platform=win32 --arch=${{ matrix.arch }} - run: node -e "const { RTCPeerConnection } = require('./'); const pc = new RTCPeerConnection(); pc.close();" + - run: npm exec -c "node scripts/validate-prebuild-install.js" + - uses: actions/upload-artifact@v7 with: name: prebuild-${{ matrix.target }} path: prebuild-artifacts/* - publish: - name: Publish npm package + source-fallback: + name: Linux ARM64 musl source fallback + runs-on: ubuntu-24.04-arm + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + with: + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.sha }} + - name: Verify unsupported prebuild falls back to source + run: | + docker build --no-cache --pull -f build-containers/Dockerfile.alpine --build-arg NODE_VERSION=20 --build-arg ALPINE_VERSION=3.20 -t webrtc-node-fallback . + docker run --rm -v "$PWD:/usr/app" -w /usr/app webrtc-node-fallback sh -lc 'npm ci --ignore-scripts && npm exec -c "node scripts/validate-prebuild-install.js --source-fallback"' + + validate: + name: Validate prebuild assets runs-on: ubuntu-latest - permissions: - contents: write - id-token: write needs: - prebuild-linux - prebuild-macos - prebuild-windows + - source-fallback timeout-minutes: 20 - environment: npm steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.sha }} - uses: actions/setup-node@v6 with: @@ -199,33 +240,64 @@ jobs: exit 1 fi - - name: Upload prebuild release assets + publish: + name: Publish npm package + if: github.event_name == 'release' + needs: validate + runs-on: ubuntu-latest + timeout-minutes: 20 + environment: npm + permissions: + contents: write + id-token: write + + steps: + - uses: actions/checkout@v7 + with: + ref: ${{ github.event.release.tag_name }} + - uses: actions/setup-node@v6 + with: + node-version: 24 + package-manager-cache: false + registry-url: https://registry.npmjs.org + - uses: actions/download-artifact@v8 + with: + pattern: prebuild-* + path: prebuild-artifacts + merge-multiple: true + - run: npm ci --ignore-scripts + - run: npm run prebuild:check + + - name: Refuse an existing npm version or release asset env: GH_TOKEN: ${{ github.token }} - EVENT_NAME: ${{ github.event_name }} RELEASE_TAG: ${{ github.event.release.tag_name }} run: | set -euo pipefail - tag="$RELEASE_TAG" - if [ "$EVENT_NAME" != "release" ]; then - tag="v$(node -p "require('./package.json').version")" + node --input-type=module <<'NODE' + import { readFileSync } from 'node:fs'; + const { name, version } = JSON.parse(readFileSync('package.json', 'utf8')); + const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name)}/${version}`); + if (response.status !== 404) throw new Error(`Publication requires an unused npm version; registry returned ${response.status}`); + NODE + if [ "$(gh release view "$RELEASE_TAG" --json assets --jq '.assets | length')" != "0" ]; then + echo "Release already has assets; inspect publication state before retrying." + exit 1 fi - gh release view "$tag" >/dev/null - gh release upload "$tag" prebuild-artifacts/* --clobber + + - name: Upload prebuild release assets + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: gh release upload "$RELEASE_TAG" prebuild-artifacts/* - name: Publish to npm - if: github.event_name != 'workflow_dispatch' || inputs.publish_npm env: - EVENT_NAME: ${{ github.event_name }} - INPUT_NPM_TAG: ${{ inputs.npm_tag }} RELEASE_PRERELEASE: ${{ github.event.release.prerelease }} run: | set -euo pipefail - npm_tag="$INPUT_NPM_TAG" - if [ "$EVENT_NAME" != "workflow_dispatch" ]; then - npm_tag="latest" - if [ "$RELEASE_PRERELEASE" = "true" ]; then - npm_tag="next" - fi + npm_tag="latest" + if [ "$RELEASE_PRERELEASE" = "true" ]; then + npm_tag="next" fi npm publish --access public --tag "$npm_tag" --provenance diff --git a/docs/README.md b/docs/README.md index 3c9f298..b75abea 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,3 +10,4 @@ Project-facing docs: - [Development](development.md) - [Intentional Divergences](divergences.md) - [Nonstandard libdatachannel Extensions](nonstandard.md) +- [Releasing](releasing.md) diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000..edc3d44 --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,36 @@ +# Releasing + +Stable releases use matching `package.json`, lockfile, and `v` tags. +Choose the next unused patch version for compatible fixes and additional +prebuild targets. Check npm versions and distribution tags and GitHub tags and +releases before preparing it. Published versions and released tags are immutable. + +Prepare a focused release pull request with the version bump and release notes. +Describe new platform support and make clear that its prebuilds require the new +package version. Validate the final commit with ordinary CI and a manual +`Release` workflow dispatch against that commit's branch. + +Manual `Release` dispatch builds and tests all seven supported prebuild targets, +checks installation from the unpublished archives, checks ARM64 musl source +fallback, and aggregates the archives and checksums with `npm run prebuild:check`. +It does not upload release assets or publish npm. Linux builds use fresh Debian +Bullseye or Alpine containers; the glibc prebuilds retain the glibc 2.31 baseline. + +After all validation passes, merge the preparation, ensure the merged commit +matches the validated tree, and create the matching tag and GitHub release. +Publishing the GitHub release starts the publishing workflow once. It rebuilds +and validates the artifacts, uploads them without overwriting existing assets, +then publishes npm through trusted publishing with provenance. Stable releases +use `latest`; prereleases use `next`. The `npm` GitHub environment and the npm +trusted publisher must permit `.github/workflows/release.yml` in this repository. + +The workflow refuses an existing npm version or any existing release assets. +If publication fails partway, inspect npm and the release assets before choosing +a recovery action. Do not blindly rerun publication, delete published versions, +move released tags, or overwrite validated assets. + +`Published Install` runs after a successful publication and can also be +dispatched with an exact package version. It installs with source fallback +disabled on all seven targets, checks CommonJS and ESM loading, and exchanges a +data-channel message. Confirm the exact npm version, `latest`, all fourteen +release assets, their checksums, and this workflow before reporting success. diff --git a/package-lock.json b/package-lock.json index efebd32..a5fb915 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@webrtc-node/webrtc", - "version": "0.2.1", + "version": "0.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@webrtc-node/webrtc", - "version": "0.2.1", + "version": "0.2.2", "hasInstallScript": true, "license": "MPL-2.0", "dependencies": { diff --git a/package.json b/package.json index 0f2456c..dc50aaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@webrtc-node/webrtc", - "version": "0.2.1", + "version": "0.2.2", "description": "Data-channel-first WebRTC for Node.js with W3C-style RTCPeerConnection and RTCDataChannel APIs.", "author": "webrtc-node contributors", "homepage": "https://github.com/webrtc-node/webrtc#readme", diff --git a/scripts/validate-prebuild-install.js b/scripts/validate-prebuild-install.js new file mode 100644 index 0000000..ce4963e --- /dev/null +++ b/scripts/validate-prebuild-install.js @@ -0,0 +1,123 @@ +"use strict"; + +const assert = require("node:assert/strict"); +const fs = require("node:fs"); +const os = require("node:os"); +const path = require("node:path"); +const { spawnSync } = require("node:child_process"); +const libc = require("detect-libc"); +const { validateArchiveFile } = require("./prebuild-integrity"); + +const root = path.resolve(__dirname, ".."); +const packageJson = require("../package.json"); +const sourceFallback = process.argv.includes("--source-fallback"); +const libcTag = process.platform === "linux" ? libc.familySync() : null; +const tuple = [process.platform, process.arch, libcTag].filter(Boolean).join("-"); +const archiveName = `webrtc-node-v${packageJson.version}-napi-v8-${tuple}.tar.gz`; +const artifacts = path.join(root, "prebuild-artifacts"); +const scratch = fs.mkdtempSync(path.join(os.tmpdir(), "webrtc-install-validation-")); + +function run(command, args, options = {}) { + const result = spawnSync(command, args, { + cwd: scratch, + stdio: "inherit", + timeout: 600000, + ...options, + }); + if (result.error) throw result.error; + assert.equal(result.signal, null, `unexpected signal from ${command}`); + assert.equal(result.status, 0, `${command} failed`); +} + +function npm(args, options) { + assert.ok(process.env.npm_execpath, "invoke this check through npm exec"); + run(process.execPath, [process.env.npm_execpath, ...args], options); +} + +async function main() { + if (sourceFallback) { + assert.equal(tuple, "linux-arm64-musl"); + } else { + const archivePath = path.join(artifacts, archiveName); + const options = { + archivePath, + archiveName, + checksumContents: fs.readFileSync(`${archivePath}.sha256`, "utf8"), + platform: process.platform, + arch: process.arch, + libcTag, + }; + const addon = await validateArchiveFile(options); + fs.rmSync(path.dirname(addon), { recursive: true, force: true }); + await assert.rejects( + validateArchiveFile({ ...options, arch: process.arch === "arm64" ? "x64" : "arm64" }), + /target mismatch|unsupported Linux libc target/, + ); + if (libcTag) { + await assert.rejects( + validateArchiveFile({ ...options, libcTag: libcTag === "glibc" ? "musl" : "glibc" }), + /target mismatch|unsupported Linux libc target/, + ); + } + } + + npm(["pack", "--pack-destination", scratch], { cwd: root }); + const tarball = fs.readdirSync(scratch).find((file) => file.endsWith(".tgz")); + assert.ok(tarball); + fs.writeFileSync(path.join(scratch, "package.json"), '{"private":true}\n'); + npm(["install", path.join(scratch, tarball), "--ignore-scripts"]); + const installedRoot = path.join(scratch, "node_modules", "@webrtc-node", "webrtc"); + const installedAddon = path.join(installedRoot, "build", "Release", "webrtc_node.node"); + assert.equal(fs.existsSync(installedAddon), false); + + // Serve the unpublished archive locally while exercising the real downloader, + // checksum validation, extraction, target checks, and install lifecycle script. + const preload = path.join(scratch, "prebuild-fetch.cjs"); + fs.writeFileSync( + preload, + `const fs = require('node:fs'); +const expected = ${JSON.stringify(archiveName)}; +globalThis.fetch = async (url) => { + const parsed = new URL(url); + if (parsed.origin !== 'https://github.com' || !parsed.pathname.startsWith('/webrtc-node/webrtc/releases/download/v${packageJson.version}/')) throw new Error('unexpected download URL ' + url); + const name = parsed.pathname.split('/').pop(); + if (name !== expected && name !== expected + '.sha256') throw new Error('unexpected asset ' + name); + console.log('Installer requested ' + name); + ${sourceFallback ? "return new Response('', {status: 404, statusText: 'Not Found'});" : `return new Response(fs.readFileSync(require('node:path').join(${JSON.stringify(artifacts)}, name)));`} +}; +`, + ); + run(process.execPath, ["--require", preload, "scripts/install-native.js"], { + cwd: installedRoot, + env: { + ...process.env, + WEBRTC_NODE_PREBUILD_ONLY: sourceFallback ? "0" : "1", + npm_config_build_from_source: "false", + WEBRTC_NODE_NATIVE_PATH: "", + }, + }); + assert.ok(fs.existsSync(installedAddon)); + assert.equal(require(path.join(installedRoot, "package.json")).version, packageJson.version); + run(process.execPath, [ + "-e", + "const { RTCPeerConnection } = require('@webrtc-node/webrtc'); const pc = new RTCPeerConnection(); pc.close(); console.log('cjs ok');", + ]); + run(process.execPath, [ + "--input-type=module", + "-e", + "import { RTCPeerConnection } from '@webrtc-node/webrtc'; const pc = new RTCPeerConnection(); pc.close(); console.log('esm ok');", + ]); + const smoke = fs + .readFileSync(path.join(root, "examples", "datachannel.js"), "utf8") + .replace('require("..")', 'require("@webrtc-node/webrtc")'); + fs.writeFileSync(path.join(scratch, "smoke.cjs"), smoke); + run(process.execPath, ["smoke.cjs"], { timeout: 30000 }); + console.log( + `${sourceFallback ? "Source fallback" : "Prebuild-only installation"} verified for ${tuple}`, + ); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); From 24c6a2957ee7a1fd2d95569f1400c5505fbacaa5 Mon Sep 17 00:00:00 2001 From: mertushka Date: Sun, 11 Oct 2026 19:28:00 +0300 Subject: [PATCH 2/4] ci: verify Windows static OpenSSL with Windows cache keys --- .github/workflows/release.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4026a2a..e175c92 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -162,9 +162,26 @@ jobs: - run: npm run build -- --arch=${{ matrix.arch }} --CDWEBRTC_NODE_STATIC_OPENSSL=ON - name: Verify static OpenSSL selection - shell: bash + shell: pwsh run: | - test "$(grep -Ec 'OPENSSL_(CRYPTO|SSL)_LIBRARY:FILEPATH=.*\.(a|lib)$' build/CMakeCache.txt)" = 2 + $cache = Get-Content build/CMakeCache.txt + foreach ($library in @('LIB_EAY_RELEASE', 'SSL_EAY_RELEASE')) { + if (-not ($cache -match "^${library}:FILEPATH=.*vcpkg_installed/${{ matrix.arch }}-windows-static/lib/lib(crypto|ssl)\.lib$")) { + throw "Expected a static vcpkg release library for $library" + } + } + $vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio/Installer/vswhere.exe' + $vsRoot = & $vswhere -latest -products '*' -property installationPath + $dumpbin = Get-ChildItem (Join-Path $vsRoot 'VC/Tools/MSVC') -Filter dumpbin.exe -Recurse | + Where-Object { $_.FullName -match 'bin\\Host(x64|arm64)\\${{ matrix.arch }}\\dumpbin.exe$' } | + Select-Object -First 1 + if (-not $dumpbin) { throw 'dumpbin was not found' } + $dependencies = & $dumpbin.FullName /DEPENDENTS build/Release/webrtc_node.node + if ($LASTEXITCODE -ne 0) { throw 'dumpbin failed' } + $dependencies + if ($dependencies -match '(?i)(libcrypto|libssl|ssleay|libeay).*\.dll') { + throw 'The release addon must not depend on an OpenSSL DLL' + } - run: npm run native:check - run: npm test From 8999a9006b20c6989a08c44e38437ba87c8e1cbc Mon Sep 17 00:00:00 2001 From: mertushka Date: Sun, 11 Oct 2026 19:42:52 +0300 Subject: [PATCH 3/4] ci: inspect macOS release addon runtime linkage --- .github/workflows/release.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e175c92..f8d2b61 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -114,6 +114,11 @@ jobs: run: | test "$(grep -Ec 'OPENSSL_(CRYPTO|SSL)_LIBRARY:FILEPATH=.*\.(a|lib)$' build/CMakeCache.txt)" = 2 + - name: Inspect macOS addon linkage + run: | + otool -L build/Release/webrtc_node.node | tee /tmp/addon-dependencies + ! grep -Ei '/(libssl|libcrypto)[^/]*\.dylib' /tmp/addon-dependencies + - run: npm run native:check - run: npm test - run: npm run api:check From a004d3373884f97d84936180d49dc65054a693b8 Mon Sep 17 00:00:00 2001 From: mertushka Date: Sun, 11 Oct 2026 20:09:53 +0300 Subject: [PATCH 4/4] chore: keep release procedure in workflow and PR --- docs/README.md | 1 - docs/releasing.md | 36 ------------------------------------ 2 files changed, 37 deletions(-) delete mode 100644 docs/releasing.md diff --git a/docs/README.md b/docs/README.md index b75abea..3c9f298 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,4 +10,3 @@ Project-facing docs: - [Development](development.md) - [Intentional Divergences](divergences.md) - [Nonstandard libdatachannel Extensions](nonstandard.md) -- [Releasing](releasing.md) diff --git a/docs/releasing.md b/docs/releasing.md deleted file mode 100644 index edc3d44..0000000 --- a/docs/releasing.md +++ /dev/null @@ -1,36 +0,0 @@ -# Releasing - -Stable releases use matching `package.json`, lockfile, and `v` tags. -Choose the next unused patch version for compatible fixes and additional -prebuild targets. Check npm versions and distribution tags and GitHub tags and -releases before preparing it. Published versions and released tags are immutable. - -Prepare a focused release pull request with the version bump and release notes. -Describe new platform support and make clear that its prebuilds require the new -package version. Validate the final commit with ordinary CI and a manual -`Release` workflow dispatch against that commit's branch. - -Manual `Release` dispatch builds and tests all seven supported prebuild targets, -checks installation from the unpublished archives, checks ARM64 musl source -fallback, and aggregates the archives and checksums with `npm run prebuild:check`. -It does not upload release assets or publish npm. Linux builds use fresh Debian -Bullseye or Alpine containers; the glibc prebuilds retain the glibc 2.31 baseline. - -After all validation passes, merge the preparation, ensure the merged commit -matches the validated tree, and create the matching tag and GitHub release. -Publishing the GitHub release starts the publishing workflow once. It rebuilds -and validates the artifacts, uploads them without overwriting existing assets, -then publishes npm through trusted publishing with provenance. Stable releases -use `latest`; prereleases use `next`. The `npm` GitHub environment and the npm -trusted publisher must permit `.github/workflows/release.yml` in this repository. - -The workflow refuses an existing npm version or any existing release assets. -If publication fails partway, inspect npm and the release assets before choosing -a recovery action. Do not blindly rerun publication, delete published versions, -move released tags, or overwrite validated assets. - -`Published Install` runs after a successful publication and can also be -dispatched with an exact package version. It installs with source fallback -disabled on all seven targets, checks CommonJS and ESM loading, and exchanges a -data-channel message. Confirm the exact npm version, `latest`, all fourteen -release assets, their checksums, and this workflow before reporting success.