diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..942803d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + pull_request: + branches: + - master + +jobs: + test: + name: Test (node-${{ matrix.node-version }}) + runs-on: ubuntu-latest + strategy: + matrix: + node-version: ['16.x', '20.6.1', '22.18.0'] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Install MDNS tools + run: | + sudo apt-get update + sudo apt-get -y install avahi-daemon avahi-discover avahi-utils libnss-mdns mdns-scan libavahi-compat-libdnssd-dev + + - name: Start avahi daemon + run: | + sudo service dbus start + sudo service avahi-daemon start + # Wait until avahi is ready to accept connections + timeout 10 sh -c 'until avahi-daemon --check; do sleep 0.5; done' + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1a29a7c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,59 @@ +name: Release +on: + push: + tags: + - 'v*.*.*' + workflow_dispatch: + +jobs: + build: + name: Build and Upload (${{ matrix.os }}, node-${{ matrix.node-version }}) + runs-on: ${{ matrix.os }} + environment: release + strategy: + matrix: + os: [macos-14, macos-13, ubuntu-latest] + node-version: ['16.x', '20.6.1', '22.18.0'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Install MDNS tools (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get -y install avahi-daemon avahi-discover avahi-utils libnss-mdns mdns-scan libavahi-compat-libdnssd-dev + + - name: Install dependencies + run: npm ci --ignore-scripts + + - name: Build and upload + env: + AWS_ACCESS_KEY_ID: ${{ secrets.NODE_PRE_GYP_AWS_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.NODE_PRE_GYP_AWS_KEY }} + run: sh ./utils/build.sh + + publish: + name: Publish to registry + runs-on: ubuntu-latest + environment: release + needs: build + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '22.18.0' + registry-url: ${{ secrets.REGISTRY_URL }} + + - run: npm ci --ignore-scripts + + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.REGISTRY_TOKEN }} diff --git a/.github/workflows/upload_binaries.yml b/.github/workflows/upload_binaries.yml deleted file mode 100644 index bac27d2..0000000 --- a/.github/workflows/upload_binaries.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Upload pre-built binaries -on: workflow_dispatch - -jobs: - linux: - runs-on: ubuntu-latest - name: Build and Upload mdns binding - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version: '20.6.1' - - - name: Install MDNS tools - run: | - sudo apt-get update - sudo apt-get -y install avahi-daemon avahi-discover avahi-utils libnss-mdns mdns-scan libavahi-compat-libdnssd-dev - - - name: Build and upload - run: | - echo "AWS_ACCESS_KEY_ID=${{ secrets.NODE_PRE_GYP_AWS_ID }}" >> .env - echo "AWS_SECRET_ACCESS_KEY=${{ secrets.NODE_PRE_GYP_AWS_KEY }}" >> .env - npm run build \ No newline at end of file diff --git a/.npmignore b/.npmignore index c2713c4..74ece37 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +1,19 @@ +# credentials and local config +.env +.env.* + +# development and CI +.github +tests +utils +examples doc + +# build artifacts build +out + +# legacy build tooling +Makefile +wscript +node-waf.bat diff --git a/README.md b/README.md index 455610b..d7163e4 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,32 @@ mdns adds multicast DNS service discovery, also known as zeroconf or bonjour to This is a fork of the `node_mdns` package with additional infrastructure changes to integrate it into Cycling '74's worfklow. +## Contributing and releasing + +### Making changes + +1. Create a branch, make your changes, bump the version in `package.json`: + ``` + npm version patch --no-git-tag-version + ``` +2. Open a PR against `master` — CI will run tests across Node 16, 20, and 22 +3. Once reviewed and merged, a maintainer cuts the release by tagging `master`: + ``` + git pull && git tag v && git push --follow-tags + ``` + +### Publishing + +Pushing a `v*.*.*` tag triggers the **Release** workflow, which requires maintainer approval and then: + +1. Builds native binaries for `darwin-arm64`, `darwin-x64`, and `linux-x64` across Node 16, 20, and 22 and uploads them to S3 +2. Publishes the package to the internal npm registry + +To install from the internal registry: +``` +npm install @cycling74/mdns +``` + ## Synopsis ```js diff --git a/lib/resolver_sequence_tasks.js b/lib/resolver_sequence_tasks.js index f017038..a6bc3e7 100644 --- a/lib/resolver_sequence_tasks.js +++ b/lib/resolver_sequence_tasks.js @@ -100,45 +100,20 @@ exports.DNSServiceGetAddrInfo = function DNSServiceGetAddrInfo(options) { } } -var _getaddrinfo; -try { - var cares = process.binding('cares_wrap'); - function getaddrinfo_complete(err, addresses, cb) { - if (addresses) { - cb(undefined, addresses); - } else if (err === 'ENOENT') { - cb(undefined, []); - } else { - cb(errnoException(err, 'getaddrinfo')); - } - } - function getaddrinfo_0_11(host, family, cb) { - var req = new cares.GetAddrInfoReqWrap() - , err = cares.getaddrinfo(req, host, family, 0, false) - ; - req.oncomplete = function oncomplete(err, addresses) { - getaddrinfo_complete(err, addresses, cb); - } - if (err) throw errnoException(err, 'getaddrinfo', host); - } - function getaddrinfo_0_10(host, family, cb) { - var wrap = cares.getaddrinfo(host, family); - if ( ! wrap) { - throw errnoException(process._errno || global.errno, 'getaddrinfo'); - } - wrap.oncomplete = function (addresses) { - getaddrinfo_complete((process._errno || global.errno), addresses, cb); +var dns = require('dns'); +function _getaddrinfo(host, family, cb) { + dns.lookup(host, { family: family, all: true }, function(err, addresses) { + if (err) { + if (err.code === 'ENOENT' || err.code === 'ENOTFOUND') { + cb(undefined, []); + } else { + cb(err); + } + return; } - } - // node 0.11+ cares.getaddrinfo function uses request object. - // use appropriate version based on node version number - if (Number(process.version.match(/^v(\d+\.\d+)/)[1]) > 0.1) { - _getaddrinfo = getaddrinfo_0_11; - } else { - _getaddrinfo = getaddrinfo_0_10; - } -} catch (ex) { - _getaddrinfo = process.binding('net').getaddrinfo; + var addrs = addresses || []; + cb(undefined, addrs.map(function(a) { return a.address; })); + }); } exports.getaddrinfo = function getaddrinfo(options) { diff --git a/package-lock.json b/package-lock.json index f67fa27..5b159f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "@cycling74/mdns", - "version": "2.7.3", + "version": "2.7.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@cycling74/mdns", - "version": "2.7.3", + "version": "2.7.4", "hasInstallScript": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "bindings": "^1.5.0", - "nan": "^2.18.0" + "nan": "^2.26.2" }, "devDependencies": { "aws-sdk": "^2.1062.0", @@ -983,9 +983,10 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.26.2.tgz", + "integrity": "sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw==", + "license": "MIT" }, "node_modules/ncp": { "version": "2.0.0", @@ -2343,9 +2344,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.26.2.tgz", + "integrity": "sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw==" }, "ncp": { "version": "2.0.0", diff --git a/package.json b/package.json index 18607f8..f6c7c21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cycling74/mdns", - "version": "2.7.3", + "version": "2.7.4", "description": "multicast DNS service discovery", "main": "./lib/mdns.js", "types": "./index.d.ts", @@ -85,7 +85,7 @@ "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "bindings": "^1.5.0", - "nan": "^2.18.0" + "nan": "^2.26.2" }, "binary": { "module_name": "dns_sd_bindings", diff --git a/tests/test_dns_sd.js b/tests/test_dns_sd.js index 0fe6708..48d5e7d 100755 --- a/tests/test_dns_sd.js +++ b/tests/test_dns_sd.js @@ -71,7 +71,7 @@ exports['DNSServiceRegister()'] = function(t) { , iface = 0 , name = 'My sh4red stuff' , type = service_type - , domain = 'somedomain' + , domain = null /* avahi rejects non-.local domains */ , host = null /* avahi throws 'bad param'*/ , port = test_port , txtRec = Buffer.from('\0') diff --git a/utils/build.sh b/utils/build.sh index 657f6d1..e8ddfa5 100644 --- a/utils/build.sh +++ b/utils/build.sh @@ -1,9 +1,7 @@ #!/usr/bin/env bash set -e -u -# test installing from source echo "building binaries for publishing"; -npm install --build-from-source; node-pre-gyp configure; node-pre-gyp build;