Publish to GitHub Packages (Bun Compatible) #26
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: Publish to Bun Registry | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version to publish (semantic version)' | |
| required: true | |
| type: string | |
| dry_run: | |
| description: 'Run in dry-run mode only' | |
| required: false | |
| type: boolean | |
| default: true | |
| tag: | |
| description: 'Bun tag (latest, beta, alpha, etc.)' | |
| required: false | |
| type: string | |
| default: 'latest' | |
| push: | |
| tags: | |
| - 'bun-v*' | |
| release: | |
| types: [published] | |
| permissions: | |
| contents: write | |
| packages: write | |
| id-token: write | |
| jobs: | |
| validate: | |
| name: Validate Package for Bun | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: terraphim_ai_nodejs | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Check package.json validity | |
| run: | | |
| bun -e "const pkg = require('./package.json'); console.log('Package name:', pkg.name); console.log('Version:', pkg.version);" | |
| - name: Validate Bun compatibility | |
| run: | | |
| # Test that the package works correctly with Bun | |
| bun -e " | |
| const pkg = require('./package.json'); | |
| console.log('Package loaded successfully with Bun'); | |
| console.log('Bun metadata:', pkg.bun); | |
| " | |
| - name: Validate version format | |
| run: | | |
| if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == refs/tags/* ]]; then | |
| VERSION=$(echo "${{ github.ref }}" | sed 's/refs\/tags\/bun-v//') | |
| if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Invalid version format: $VERSION" | |
| exit 1 | |
| fi | |
| echo "Version to publish: $VERSION" | |
| fi | |
| build: | |
| name: Build Multi-Platform Binaries for Bun | |
| runs-on: ${{ matrix.settings.host }} | |
| needs: validate | |
| defaults: | |
| run: | |
| working-directory: terraphim_ai_nodejs | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: macos-latest | |
| target: x86_64-apple-darwin | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| - host: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| - host: ubuntu-latest | |
| target: aarch64-unknown-linux-gnu | |
| use_docker: true | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| if: ${{ !matrix.settings.use_docker }} | |
| with: | |
| node-version: '20' | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| if: ${{ !matrix.settings.use_docker }} | |
| with: | |
| toolchain: stable | |
| targets: ${{ matrix.settings.target }} | |
| - name: Cache Cargo dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| .cargo-cache | |
| target/ | |
| key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }} | |
| - name: Install dependencies | |
| if: ${{ !matrix.settings.use_docker }} | |
| run: yarn install --frozen-lockfile | |
| - name: Build custom Docker image for aarch64 | |
| if: ${{ matrix.settings.use_docker }} | |
| working-directory: ${{ github.workspace }} | |
| run: | | |
| docker build -t terraphim-napi-aarch64:latest -f docker/Dockerfile.napi-aarch64 . | |
| - name: Build in docker | |
| if: ${{ matrix.settings.use_docker }} | |
| working-directory: ${{ github.workspace }} | |
| run: | | |
| docker run --rm \ | |
| -v ${{ github.workspace }}:/build \ | |
| -w /build/terraphim_ai_nodejs \ | |
| terraphim-napi-aarch64:latest \ | |
| bash -c "yarn install --frozen-lockfile && yarn build --target ${{ matrix.settings.target }}" | |
| - name: Build | |
| run: yarn build --target ${{ matrix.settings.target }} | |
| if: ${{ !matrix.settings.use_docker }} | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: terraphim_ai_nodejs/*.node | |
| if-no-files-found: error | |
| test-bun-compatibility: | |
| name: Test Bun Compatibility | |
| runs-on: ${{ matrix.settings.os }} | |
| needs: build | |
| # Tests are advisory - don't block publish on test failures | |
| continue-on-error: true | |
| defaults: | |
| run: | |
| working-directory: terraphim_ai_nodejs | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| bun: | |
| - 'latest' | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: ${{ matrix.bun }} | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: terraphim_ai_nodejs | |
| - name: Test package functionality with Bun | |
| run: | | |
| # Create Bun-specific test | |
| cat > test-bun-functionality.js << 'EOF' | |
| import * as pkg from './index.js'; | |
| console.log('Testing package functionality with Bun v' + process.versions.bun); | |
| console.log('Available functions:', Object.keys(pkg)); | |
| // Test autocomplete functionality | |
| if (typeof pkg.buildAutocompleteIndexFromJson === 'function') { | |
| console.log('buildAutocompleteIndexFromJson available'); | |
| const thesaurus = { | |
| name: "Test", | |
| data: { | |
| "machine learning": { | |
| id: 1, | |
| nterm: "machine learning", | |
| url: "https://example.com/ml" | |
| } | |
| } | |
| }; | |
| const indexBytes = pkg.buildAutocompleteIndexFromJson(JSON.stringify(thesaurus)); | |
| console.log('Autocomplete index built:', indexBytes.length, 'bytes'); | |
| // Convert to Buffer for Bun compatibility | |
| const indexBuffer = Buffer.from(indexBytes); | |
| const results = pkg.autocomplete(indexBuffer, "machine", 10); | |
| console.log('Autocomplete search results:', results.length, 'items'); | |
| } | |
| // Test knowledge graph functionality | |
| if (typeof pkg.buildRoleGraphFromJson === 'function') { | |
| console.log('buildRoleGraphFromJson available'); | |
| const thesaurus = { | |
| name: "Test", | |
| data: { | |
| "machine learning": { | |
| id: 1, | |
| nterm: "machine learning", | |
| url: "https://example.com/ml" | |
| } | |
| } | |
| }; | |
| const graphBytes = pkg.buildRoleGraphFromJson("Test Role", JSON.stringify(thesaurus)); | |
| console.log('Role graph built:', graphBytes.length, 'bytes'); | |
| // Convert to Buffer for Bun compatibility | |
| const graphBuffer = Buffer.from(graphBytes); | |
| const stats = pkg.getGraphStats(graphBuffer); | |
| console.log('Graph stats loaded:', stats); | |
| } | |
| console.log('All functionality tests passed with Bun!'); | |
| EOF | |
| bun test-bun-functionality.js | |
| - name: Test performance with Bun | |
| run: | | |
| # Performance benchmark | |
| cat > benchmark-bun.js << 'EOF' | |
| import * as pkg from './index.js'; | |
| import { performance } from 'perf_hooks'; | |
| const thesaurus = { | |
| name: "Performance Test", | |
| data: { | |
| "machine learning": { id: 1, nterm: "machine learning", url: "https://example.com/ml" }, | |
| "deep learning": { id: 2, nterm: "deep learning", url: "https://example.com/dl" }, | |
| "neural networks": { id: 3, nterm: "neural networks", url: "https://example.com/nn" } | |
| } | |
| }; | |
| // Benchmark autocomplete | |
| const start = performance.now(); | |
| const indexBytes = pkg.buildAutocompleteIndexFromJson(JSON.stringify(thesaurus)); | |
| const buildTime = performance.now() - start; | |
| // Convert to Buffer for Bun compatibility | |
| const indexBuffer = Buffer.from(indexBytes); | |
| const searchStart = performance.now(); | |
| const results = pkg.autocomplete(indexBuffer, "machine", 10); | |
| const searchTime = performance.now() - searchStart; | |
| console.log('Performance Metrics (Bun):'); | |
| console.log(' - Index building:', buildTime.toFixed(2), 'ms'); | |
| console.log(' - Search time:', searchTime.toFixed(2), 'ms'); | |
| console.log(' - Results found:', results.length); | |
| console.log(' - Index size:', indexBytes.length, 'bytes'); | |
| EOF | |
| bun benchmark-bun.js | |
| create-universal-macos-bun: | |
| name: Create Universal macOS Binary for Bun | |
| runs-on: macos-latest | |
| needs: build | |
| # Universal binary is optional - don't block on failure | |
| continue-on-error: true | |
| defaults: | |
| run: | |
| working-directory: terraphim_ai_nodejs | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Download macOS x64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-x86_64-apple-darwin | |
| path: ${{ github.workspace }}/artifacts | |
| - name: Download macOS arm64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-aarch64-apple-darwin | |
| path: ${{ github.workspace }}/artifacts | |
| - name: Create universal binary | |
| working-directory: ${{ github.workspace }}/artifacts | |
| run: | | |
| echo "Files in artifacts directory:" | |
| ls -la | |
| # Find the actual .node files | |
| X64_NODE=$(find . -name "*.darwin-x64.node" -o -name "*x86_64-apple-darwin.node" | head -1) | |
| ARM64_NODE=$(find . -name "*.darwin-arm64.node" -o -name "*aarch64-apple-darwin.node" | head -1) | |
| echo "x64 node: $X64_NODE" | |
| echo "arm64 node: $ARM64_NODE" | |
| if [ -n "$X64_NODE" ] && [ -n "$ARM64_NODE" ]; then | |
| lipo -create "$X64_NODE" "$ARM64_NODE" -output terraphim_ai_nodejs.darwin-universal.node | |
| ls -la *.node | |
| else | |
| echo "Could not find both architecture binaries" | |
| exit 1 | |
| fi | |
| - name: Upload universal binary | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: bindings-universal-apple-darwin | |
| path: ${{ github.workspace }}/artifacts/terraphim_ai_nodejs.darwin-universal.node | |
| if-no-files-found: error | |
| publish-to-bun: | |
| name: Publish to Bun Registry | |
| runs-on: [self-hosted, Linux] | |
| needs: build | |
| # Run after builds complete (tests and universal are optional) | |
| if: always() && needs.build.result == 'success' | |
| environment: production | |
| defaults: | |
| run: | |
| working-directory: terraphim_ai_nodejs | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Get publish token | |
| id: token | |
| run: | | |
| # Use NPM_TOKEN from GitHub secrets (works for both npm and Bun) | |
| TOKEN="${{ secrets.NPM_TOKEN }}" | |
| if [[ -z "$TOKEN" ]]; then | |
| echo "No NPM_TOKEN available for publishing" | |
| exit 1 | |
| fi | |
| echo "token=$TOKEN" >> $GITHUB_OUTPUT | |
| echo "Publish token configured" | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ${{ github.workspace }}/artifacts | |
| - name: Install dependencies | |
| run: yarn install --frozen-lockfile | |
| - name: Prepare package for Bun publishing | |
| run: | | |
| # Copy all built binaries to package directory | |
| find ${{ github.workspace }}/artifacts -name "*.node" -exec cp {} . \; | |
| # List what we have | |
| echo "Built binaries for Bun:" | |
| ls -la *.node || echo "No .node files found" | |
| # Update package.json version if provided (skip npm scripts) | |
| if [[ "${{ inputs.version }}" != "" ]]; then | |
| echo "Updating version to ${{ inputs.version }}" | |
| npm version ${{ inputs.version }} --no-git-tag-version --ignore-scripts | |
| fi | |
| - name: Configure package managers | |
| run: | | |
| # Configure npm (primary registry) | |
| echo "//registry.npmjs.org/:_authToken=${{ steps.token.outputs.token }}" > ~/.npmrc | |
| npm config set provenance true | |
| # Configure Bun registry (if different token available) | |
| if [[ "${{ secrets.BUN_TOKEN }}" != "" && "${{ secrets.BUN_TOKEN }}" != "${{ steps.token.outputs.token }}" ]]; then | |
| echo "//registry.npmjs.org/:_authToken=${{ secrets.BUN_TOKEN }}" > ~/.bunfig.toml | |
| echo "[install.scopes]\n\"@terraphim\" = \"https://registry.npmjs.org/\"" >> ~/.bunfig.toml | |
| fi | |
| # Show current package info | |
| echo "Package information:" | |
| npm pack --dry-run | head -20 | |
| - name: Determine publishing strategy | |
| id: strategy | |
| run: | | |
| VERSION_TYPE="patch" | |
| REGISTRY="npm" | |
| NPM_TAG="latest" | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| if [[ "${{ inputs.version }}" != "" ]]; then | |
| VERSION_TYPE="manual" | |
| NPM_TAG="${{ inputs.tag }}" | |
| fi | |
| elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == refs/tags/* ]]; then | |
| VERSION_TAG=$(echo "${{ github.ref }}" | sed 's/refs\/tags\/bun-v//') | |
| if [[ "$VERSION_TAG" =~ -beta$ ]]; then | |
| NPM_TAG="beta" | |
| elif [[ "$VERSION_TAG" =~ -alpha$ ]]; then | |
| NPM_TAG="alpha" | |
| elif [[ "$VERSION_TAG" =~ -rc ]]; then | |
| NPM_TAG="rc" | |
| else | |
| NPM_TAG="latest" | |
| fi | |
| elif [[ "${{ github.event_name }}" == "release" ]]; then | |
| NPM_TAG="latest" | |
| fi | |
| echo "version_type=$VERSION_TYPE" >> $GITHUB_OUTPUT | |
| echo "npm_tag=$NPM_TAG" >> $GITHUB_OUTPUT | |
| echo "registry=$REGISTRY" >> $GITHUB_OUTPUT | |
| echo "π― Publishing strategy: $VERSION_TYPE -> $NPM_TAG ($REGISTRY)" | |
| - name: Publish to npm (works with Bun) | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| if [[ "${{ inputs.dry_run }}" == "true" ]]; then | |
| echo "Dry run mode - checking package only" | |
| npm publish --dry-run --access public --tag ${{ steps.strategy.outputs.npm_tag }} --provenance --ignore-scripts | |
| else | |
| echo "Publishing @terraphim/autocomplete to npm (Bun-compatible)" | |
| echo "Tag: ${{ steps.strategy.outputs.npm_tag }}" | |
| # Publish with provenance for OIDC trusted publishing | |
| # --ignore-scripts skips napi prepublish which tries to create GitHub releases | |
| npm publish --access public --tag ${{ steps.strategy.outputs.npm_tag }} --provenance --ignore-scripts | |
| echo "Package published successfully! (Bun users can install with: bun add @terraphim/autocomplete)" | |
| fi | |
| - name: Verify package for Bun users | |
| if: inputs.dry_run != 'true' | |
| run: | | |
| echo "π Verifying package for Bun users..." | |
| # Wait a moment for npm registry to update | |
| sleep 30 | |
| # Check if package is available | |
| PACKAGE_NAME="@terraphim/autocomplete" | |
| PACKAGE_VERSION=$(node -p "require('./package.json').version") | |
| echo "Checking: $PACKAGE_NAME@$PACKAGE_VERSION" | |
| npm view $PACKAGE_NAME@$PACKAGE_VERSION || echo "β οΈ Package not immediately visible (may take a few minutes)" | |
| echo "π Package verification completed for Bun users" | |
| # Test Bun installation | |
| echo "π§ͺ Testing Bun installation..." | |
| bunx pkg install $PACKAGE_NAME@$PACKAGE_VERSION --dry-run || echo "β οΈ Dry run failed (package may not be ready yet)" | |
| - name: Create Bun-specific GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/') && inputs.dry_run != 'true' | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ github.ref }} | |
| release_name: "@terraphim/autocomplete ${{ github.ref_name }} (Bun Optimized)" | |
| body: | | |
| ## Node.js Package Release (Bun Compatible) | |
| **Package**: `@terraphim/autocomplete` | |
| **Version**: ${{ steps.strategy.outputs.version_type }} | |
| **Tag**: ${{ steps.strategy.outputs.npm_tag }} | |
| **Runtime**: Bun Optimized | |
| ### π Installation Options | |
| **With Bun (Recommended):** | |
| ```bash | |
| bun add @terraphim/autocomplete@${{ steps.strategy.outputs.npm_tag }} | |
| ``` | |
| **With npm:** | |
| ```bash | |
| npm install @terraphim/autocomplete@${{ steps.strategy.outputs.npm_tag }} | |
| ``` | |
| **With yarn:** | |
| ```bash | |
| yarn add @terraphim/autocomplete@${{ steps.strategy.outputs.npm_tag }} | |
| ``` | |
| ### β‘ Bun Performance Benefits | |
| - **π Faster Installation**: Bun's native package manager | |
| - **π¦ Optimized Dependencies**: Better dependency resolution | |
| - **π§ͺ Native Testing**: Built-in test runner | |
| - **β‘ Hot Reloading**: Faster development cycles | |
| ### β¨ Features | |
| - **Autocomplete**: Fast prefix search with scoring | |
| - **Knowledge Graph**: Semantic connectivity analysis | |
| - **Native Performance**: Rust backend with NAPI bindings | |
| - **Cross-Platform**: Linux, macOS, Windows support | |
| - **TypeScript**: Auto-generated type definitions | |
| ### π Performance | |
| - **Autocomplete Index**: ~749 bytes | |
| - **Knowledge Graph**: ~856 bytes | |
| - **Native Library**: ~10MB (optimized for production) | |
| ### π Bun-Specific Features | |
| - **Native Module Loading**: Optimized for Bun's runtime | |
| - **Fast Test Execution**: Bun's test runner integration | |
| - **Enhanced Dependency Resolution**: Faster and more accurate | |
| ### π Links | |
| - [npm package](https://www.npmjs.com/package/@terraphim/autocomplete) | |
| - [Bun documentation](https://bun.sh/docs) | |
| - [Package Documentation](https://github.com/terraphim/terraphim-ai/tree/main/terraphim_ai_nodejs) | |
| --- | |
| π€ Generated on: $(date) | |
| π’ Bun-optimized with love from Terraphim AI | |
| draft: false | |
| prerelease: ${{ steps.strategy.outputs.npm_tag != 'latest' }} | |
| - name: Notify on success | |
| if: inputs.dry_run != 'true' | |
| run: | | |
| echo "π Bun publishing workflow completed successfully!" | |
| echo "π¦ Package: @terraphim/autocomplete" | |
| echo "π·οΈ Tag: ${{ steps.strategy.outputs.npm_tag }}" | |
| echo "π’ Runtime: Bun-optimized" | |
| echo "π Version: $(node -p "require('./package.json').version")" |