refactor(UCBD): delegate 11 duplicate primitives to trueno canonical … #47
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: Release macOS DMG | ||
|
Check failure on line 1 in .github/workflows/release-macos.yml
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: 'Version (e.g., 1.0.1)' | ||
| required: "true" | ||
| default: '1.0.0' | ||
| env: | ||
| CARGO_TERM_COLOR: always | ||
| jobs: | ||
| build-macos: | ||
| runs-on: macos-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Install Rust | ||
| uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| targets: wasm32-unknown-unknown | ||
| - name: Install wasm-pack | ||
| run: cargo install wasm-pack | ||
| - name: Cache cargo | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/.cargo/registry | ||
| ~/.cargo/git | ||
| target | ||
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | ||
| - name: Build WASM | ||
| env: | ||
| CARGO_TARGET_DIR: target | ||
| run: | | ||
| # Build main WASM library (not demos workspace which has local deps) | ||
| wasm-pack build --target web --release --features wasm | ||
| ls -la pkg/ | ||
| - name: Build demo WASM (if possible) | ||
| continue-on-error: "true" | ||
| env: | ||
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | ||
| run: | | ||
| # Try to build demo - may fail if probar not available | ||
| cd demos/www-demo | ||
| wasm-pack build --target web --release 2>/dev/null || echo "Demo build skipped (probar dependency)" | ||
| ls -la pkg/ 2>/dev/null || true | ||
| - name: Download model | ||
| run: | | ||
| mkdir -p models | ||
| # Download from HuggingFace or existing release | ||
| curl -L -o models/whisper-tiny-fb.apr \ | ||
| "https://github.com/paiml/whisper.apr/releases/download/v1.0.0/whisper-tiny-fb.apr" \ | ||
| || echo "Model not found in releases, checking local..." | ||
| # Fallback: if model doesn't exist, skip (CI won't have 145MB model) | ||
| if [ ! -f models/whisper-tiny-fb.apr ]; then | ||
| echo "WARNING: Model file not available, DMG will not include model" | ||
| touch models/whisper-tiny-fb.apr.placeholder | ||
| fi | ||
| - name: Create App Bundle | ||
| run: | | ||
| VERSION="${{ github.event.inputs.version || github.ref_name }}" | ||
| VERSION="${VERSION#v}" # Remove 'v' prefix if present | ||
| APP_NAME="Whisper.apr" | ||
| APP_DIR="target/${APP_NAME}.app" | ||
| # Create bundle structure | ||
| mkdir -p "${APP_DIR}/Contents/MacOS" | ||
| mkdir -p "${APP_DIR}/Contents/Resources/pkg" | ||
| mkdir -p "${APP_DIR}/Contents/Resources/models" | ||
| mkdir -p "${APP_DIR}/Contents/Frameworks" | ||
| # Info.plist | ||
| cat > "${APP_DIR}/Contents/Info.plist" << PLIST | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict> | ||
| <key>CFBundleName</key> | ||
| <string>${APP_NAME}</string> | ||
| <key>CFBundleDisplayName</key> | ||
| <string>Whisper.apr</string> | ||
| <key>CFBundleIdentifier</key> | ||
| <string>com.paiml.whisper-apr</string> | ||
| <key>CFBundleVersion</key> | ||
| <string>${VERSION}</string> | ||
| <key>CFBundleShortVersionString</key> | ||
| <string>${VERSION}</string> | ||
| <key>CFBundlePackageType</key> | ||
| <string>APPL</string> | ||
| <key>CFBundleExecutable</key> | ||
| <string>whisper-apr-launcher</string> | ||
| <key>LSMinimumSystemVersion</key> | ||
| <string>10.15</string> | ||
| <key>NSHighResolutionCapable</key> | ||
| <true/> | ||
| <key>NSMicrophoneUsageDescription</key> | ||
| <string>Whisper.apr needs microphone access for speech recognition.</string> | ||
| </dict> | ||
| </plist> | ||
| PLIST | ||
| # Launcher script with COOP/COEP headers | ||
| cat > "${APP_DIR}/Contents/MacOS/whisper-apr-launcher" << 'LAUNCHER' | ||
| #!/bin/bash | ||
| RESOURCES="$(dirname "$0")/../Resources" | ||
| cd "$RESOURCES" | ||
| python3 -c " | ||
| import http.server, socketserver | ||
| class H(http.server.SimpleHTTPRequestHandler): | ||
| def end_headers(self): | ||
| self.send_header('Cross-Origin-Opener-Policy', 'same-origin') | ||
| self.send_header('Cross-Origin-Embedder-Policy', 'require-corp') | ||
| super().end_headers() | ||
| socketserver.TCPServer(('', 8765), H).serve_forever() | ||
| " & | ||
| sleep 1 | ||
| open 'http://localhost:8765/index.html' | ||
| wait | ||
| LAUNCHER | ||
| chmod +x "${APP_DIR}/Contents/MacOS/whisper-apr-launcher" | ||
| # Copy resources - use demo pkg if available, otherwise main pkg | ||
| if [ -d demos/www-demo/pkg ]; then | ||
| cp demos/www/index.html "${APP_DIR}/Contents/Resources/" | ||
| cp -r demos/www-demo/pkg/* "${APP_DIR}/Contents/Resources/pkg/" | ||
| else | ||
| # Create simple HTML that loads main WASM | ||
| cat > "${APP_DIR}/Contents/Resources/index.html" << 'HTMLEOF' | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <title>Whisper.apr</title> | ||
| <style> | ||
| body { font-family: system-ui; max-width: 800px; margin: 2rem auto; padding: 1rem; } | ||
| h1 { color: #333; } | ||
| .status { padding: 1rem; background: #f0f0f0; border-radius: 8px; } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <h1>Whisper.apr</h1> | ||
| <div class="status"> | ||
| <p>WASM Speech Recognition Engine</p> | ||
| <p>Library loaded. See console for API.</p> | ||
| </div> | ||
| <script type="module"> | ||
| import init from './pkg/whisper_apr.js'; | ||
| await init(); | ||
| console.log('Whisper.apr WASM loaded'); | ||
| </script> | ||
| </body> | ||
| </html> | ||
| HTMLEOF | ||
| cp -r pkg/* "${APP_DIR}/Contents/Resources/pkg/" | ||
| fi | ||
| cp demos/www/*.wav "${APP_DIR}/Contents/Resources/" 2>/dev/null || true | ||
| # Copy model if available | ||
| if [ -f models/whisper-tiny-fb.apr ]; then | ||
| cp models/whisper-tiny-fb.apr "${APP_DIR}/Contents/Resources/models/" | ||
| fi | ||
| # Ad-hoc sign | ||
| codesign --force --deep --sign - "${APP_DIR}" || echo "Signing skipped" | ||
| echo "App bundle created at ${APP_DIR}" | ||
| ls -la "${APP_DIR}/Contents/Resources/" | ||
| - name: Create DMG | ||
| run: | | ||
| VERSION="${{ github.event.inputs.version || github.ref_name }}" | ||
| VERSION="${VERSION#v}" | ||
| hdiutil create -volname "Whisper.apr" \ | ||
| -srcfolder "target/Whisper.apr.app" \ | ||
| -ov -format UDZO \ | ||
| "target/Whisper.apr-${VERSION}.dmg" | ||
| ls -lh target/*.dmg | ||
| - name: Upload DMG artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Whisper.apr-macos-dmg | ||
| path: target/*.dmg | ||
| - name: Upload to Release | ||
| if: startsWith(github.ref, 'refs/tags/') | ||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| files: target/*.dmg | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| # Also build native CLI for multiple platforms | ||
| build-cli: | ||
| strategy: | ||
| matrix: | ||
| include: | ||
| - os: macos-latest | ||
| target: x86_64-apple-darwin | ||
| name: whisper-apr-cli-macos-x64 | ||
| - os: macos-latest | ||
| target: aarch64-apple-darwin | ||
| name: whisper-apr-cli-macos-arm64 | ||
| - os: ubuntu-latest | ||
| target: x86_64-unknown-linux-gnu | ||
| name: whisper-apr-cli-linux-x64 | ||
| runs-on: ${{ matrix.os }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Install Rust | ||
| uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| targets: ${{ matrix.target }} | ||
| - name: Build CLI | ||
| continue-on-error: "true" | ||
| env: | ||
| CARGO_TARGET_DIR: target | ||
| run: | | ||
| cargo build --release --features cli --target ${{ matrix.target }} || exit 0 | ||
| mkdir -p dist | ||
| # Find the built binary | ||
| find target/${{ matrix.target }}/release -maxdepth 1 -type f -perm +111 -name 'whisper*' | head -1 | xargs -I{} cp {} dist/${{ matrix.name }} || true | ||
| ls -la dist/ || true | ||
| - name: Upload CLI artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ matrix.name }} | ||
| path: dist/* | ||
| - name: Upload to Release | ||
| if: startsWith(github.ref, 'refs/tags/') | ||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| files: dist/* | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||