Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions .github/workflows/prebuild.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Prebuild

on:
push:
tags:
- 'v*'
workflow_dispatch:

jobs:
prebuild:
strategy:
matrix:
include:
# Linux x64
- os: ubuntu-latest
arch: x64

# Linux ARM64
- os: ubuntu-latest
arch: arm64

# macOS x64
- os: macos-latest
arch: x64

# macOS ARM64
- os: macos-latest
arch: arm64

# Windows x64
- os: windows-latest
arch: x64

# Windows x86
- os: windows-latest
arch: ia32

runs-on: ${{ matrix.os }}

name: Prebuild ${{ matrix.os }} - ${{ matrix.arch }}

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
architecture: ${{ matrix.arch }}

- name: Install ALSA headers (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libasound2-dev

- name: Setup ARM64 cross-compilation (Linux ARM64)
if: runner.os == 'Linux' && matrix.arch == 'arm64'
run: |
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
sudo apt-get install -y libasound2-dev:arm64

- name: Install dependencies
run: npm install --ignore-scripts

- name: Prebuild (Linux x64)
if: runner.os == 'Linux' && matrix.arch == 'x64'
run: prebuildify --napi --strip

- name: Prebuild (Linux ARM64)
if: runner.os == 'Linux' && matrix.arch == 'arm64'
run: |
export CC=aarch64-linux-gnu-gcc
export CXX=aarch64-linux-gnu-g++
export npm_config_arch=arm64
prebuildify --napi --strip --arch arm64

- name: Prebuild (macOS)
if: runner.os == 'macOS'
run: prebuildify --napi --strip

- name: Prebuild (Windows)
if: runner.os == 'Windows'
run: prebuildify --napi --strip --arch ${{ matrix.arch }}

- name: Upload prebuilds
uses: actions/upload-artifact@v4
with:
name: prebuilds-${{ matrix.os }}-${{ matrix.arch }}
path: prebuilds/
retention-days: 7

release:
needs: prebuild
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Download all prebuilds
uses: actions/download-artifact@v4
with:
path: prebuilds-artifacts

- name: Consolidate prebuilds
run: |
mkdir -p prebuilds
# Copy maintaining the directory structure that prebuild-install expects
# Each artifact contains: prebuilds/[platform-arch]/node.napi.node
cp -r prebuilds-artifacts/*/prebuilds/* prebuilds/ 2>/dev/null || true
# If the above fails, try flat structure
for dir in prebuilds-artifacts/*/; do
if [ -d "$dir/prebuilds" ]; then
cp -r "$dir/prebuilds/"* prebuilds/
fi
done
echo "Prebuild directory structure:"
ls -R prebuilds/

- name: Create tarball with prebuilds
run: |
npm install --ignore-scripts
npm pack
mv speaker-*.tgz speaker-${{ github.ref_name }}.tgz
echo "Tarball contents:"
tar -tzf speaker-${{ github.ref_name }}.tgz | grep -E 'prebuilds|package.json' | head -20

- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: speaker-${{ github.ref_name }}.tgz
generate_release_notes: true
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/node_modules/
/package-lock.json
/yarn.lock
/prebuilds/

# dev files
/?.js
Expand Down
5 changes: 5 additions & 0 deletions .prebuildrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"strip": true,
"tag-prefix": "v"
}

154 changes: 154 additions & 0 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Publishing Guide

This guide explains how to publish a new version of `node-speaker` with prebuilt binaries using GitHub Releases.

## Prerequisites

1. **GitHub Access**: You must have push access to the repository and permissions to create releases
2. **GitHub Token**: The default `GITHUB_TOKEN` is automatically provided by GitHub Actions

## Publishing Process

### 1. Prepare the Release

1. Update the version in `package.json`:
```bash
npm version patch # or minor, or major
```

2. Update `History.md` with the changes in this release

3. Commit the changes:
```bash
git add package.json package-lock.json History.md
git commit -m "Prepare for vX.Y.Z release"
```

### 2. Create and Push Tag

The prebuild workflow is triggered when you push a tag starting with `v`:

```bash
git tag v0.5.6 # Use your actual version number
git push origin master
git push origin v0.5.6
```

### 3. Monitor GitHub Actions

1. Go to the [Actions tab](https://github.com/SlvCtrlPlus/node-speaker/actions) on GitHub
2. Wait for the "Prebuild" workflow to complete
3. The workflow will:
- Build N-API binaries for all supported platforms (6 builds total)
- Each binary works across all Node.js 18+ versions thanks to N-API
- Upload the binaries as artifacts
- Create a GitHub Release with:
- Complete package tarball with all prebuilds
- Individual `.node` binaries for each platform
- Auto-generated release notes

### 4. Verify Publication

1. Check that the release was created:
- Go to [Releases](https://github.com/SlvCtrlPlus/node-speaker/releases)
- Verify the new version is listed
- Check that all prebuilt binaries are attached

2. Test installation from GitHub:
```bash
# Install from GitHub release
npm install https://github.com/SlvCtrlPlus/node-speaker/releases/download/v0.5.6/speaker-v0.5.6.tgz

# Or install from git tag
npm install github:SlvCtrlPlus/node-speaker#v0.5.6
```

## Manual Prebuild (Testing)

To test the prebuild process locally before publishing:

### Single Platform

Build for your current platform:

```bash
npm run prebuild
```

This creates binaries in the `prebuilds/` directory.

### All Platforms (Cross-compilation)

Build for all platforms using Docker:

```bash
npm run prebuild-all
```

Note: This requires Docker and can take significant time.

### Test Local Prebuild

After creating local prebuilds, test that they install correctly:

```bash
# In another directory
npm install /path/to/node-speaker
```

The installation should use the prebuilt binary instead of compiling.

## Troubleshooting

### Build Failures

If the GitHub Actions build fails:

1. Check the build logs in the Actions tab
2. Common issues:
- Missing dependencies on specific platforms
- Node version compatibility
- Architecture-specific compilation issues

### GitHub Release Failures

If creating the GitHub Release fails:

1. Verify repository has "Read and write permissions" for workflows:
- Go to Settings → Actions → General → Workflow permissions
- Select "Read and write permissions"
2. Check that the tag was pushed correctly
3. Ensure no release already exists for that tag

### Prebuilds Not Found During Installation

If users report compilation from source when prebuilds should exist:

1. Verify prebuilds exist in the GitHub Release assets
2. Check that the platform/Node version is supported
3. Ensure users are installing from the release tarball, not directly from git
4. For git installations, prebuilds must be committed or users need to build from source

## Security

- The `GITHUB_TOKEN` is automatically provided by GitHub Actions
- No manual token configuration needed for GitHub Releases
- Limit repository write access to trusted maintainers
- Review workflow permissions regularly

## Optional: Publishing to npm

If you later decide to also publish to npm, you can:

1. Add `NPM_TOKEN` to GitHub Actions secrets
2. Uncomment the npm publish step in `.github/workflows/prebuild.yml`
3. Follow the standard npm publishing process

## Support

For issues with the publishing process:

1. Check existing GitHub Issues
2. Review the [RELEASE-CHECKLIST.md](RELEASE-CHECKLIST.md)
3. Contact the package maintainers

18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,30 @@ these days.

## Installation

### From npm

Simply compile and install `node-speaker` using `npm`:

```sh
npm install speaker
```

### From GitHub Releases (with prebuilt binaries)

Install a specific release from GitHub:

```sh
npm install https://github.com/YOUR_USERNAME/node-speaker/releases/download/v0.5.6/speaker-v0.5.6.tgz
```

Or install from a git tag:

```sh
npm install github:YOUR_USERNAME/node-speaker#v0.5.6
```

### Platform Requirements

On Debian/Ubuntu, the [ALSA][alsa] backend is selected by default, so be sure
to have the `alsa.h` header file in place:

Expand Down
17 changes: 13 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
{
"name": "speaker",
"version": "0.5.5",
"version": "0.1.0",
"license": "(MIT AND LGPL-2.1-only)",
"description": "Output PCM audio data to the speakers",
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://tootallnate.net)",
"repository": "TooTallNate/node-speaker",
"repository": "github:SlvCtrlPlus/node-speaker",
"binary": {
"napi_versions": [3]
},
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"test": "standard && node-gyp rebuild --mpg123-backend=dummy && mocha --reporter spec"
"test": "standard && node-gyp rebuild --mpg123-backend=dummy && mocha --reporter spec",
"install": "prebuild-install || node-gyp rebuild",
"prebuild": "prebuildify --napi --strip",
"prebuild-all": "prebuildify-cross --napi --strip"
},
"dependencies": {
"bindings": "^1.3.0",
"buffer-alloc": "^1.1.0",
"debug": "^4.0.0"
"debug": "^4.0.0",
"prebuild-install": "^7.1.2"
},
"devDependencies": {
"@types/node": "^18.0.0",
"mocha": "^11.7.5",
"prebuildify": "^6.0.1",
"prebuildify-cross": "^5.1.1",
"standard": "^17.1.2"
},
"engines": {
Expand Down