diff --git a/.github/actions/test-npm-install/action.yml b/.github/actions/test-npm-install/action.yml new file mode 100644 index 0000000..9eb4cd5 --- /dev/null +++ b/.github/actions/test-npm-install/action.yml @@ -0,0 +1,122 @@ +name: 'Test npm install' +description: 'Install and verify hookdeck-cli npm package' + +inputs: + version: + description: 'Version to install (e.g., @beta, @latest, or specific version)' + required: true + platform: + description: 'Platform being tested (darwin, linux, win32)' + required: true + +runs: + using: 'composite' + steps: + - name: Wait for npm registry propagation + shell: bash + run: | + VERSION="${{ inputs.version }}" + + # If testing a specific version (not a tag), poll until available + if [[ "$VERSION" =~ ^[0-9] ]]; then + echo "Waiting for version $VERSION to be available on npm..." + MAX_ATTEMPTS=30 + ATTEMPT=0 + + while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do + if npm view "hookdeck-cli@$VERSION" version > /dev/null 2>&1; then + echo "✓ Version $VERSION is now available on npm" + break + fi + + ATTEMPT=$((ATTEMPT + 1)) + echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Version not yet available, waiting 10 seconds..." + sleep 10 + done + + if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then + echo "✗ Version $VERSION not available after $MAX_ATTEMPTS attempts" + exit 1 + fi + else + echo "Testing with npm tag: $VERSION (no polling needed)" + fi + + - name: Install hookdeck-cli + shell: bash + run: | + VERSION="${{ inputs.version }}" + echo "Installing hookdeck-cli${VERSION}..." + npm install -g "hookdeck-cli${VERSION}" + + - name: Verify installation + shell: bash + run: | + echo "Checking hookdeck binary location..." + which hookdeck || (echo "hookdeck not in PATH" && exit 1) + + echo "Checking hookdeck version..." + hookdeck --version + + - name: Test wrapper script + shell: bash + run: | + echo "Testing wrapper script execution..." + hookdeck --help > /dev/null + echo "✓ Wrapper script works" + + - name: Verify package structure + shell: bash + run: | + HOOKDECK_PATH=$(which hookdeck) + HOOKDECK_DIR=$(dirname "$HOOKDECK_PATH") + PACKAGE_DIR=$(dirname "$HOOKDECK_DIR") + + echo "Package directory: $PACKAGE_DIR" + + echo "Checking for wrapper script..." + if [ -f "$PACKAGE_DIR/bin/hookdeck.js" ]; then + echo "✓ Wrapper script found" + else + echo "✗ Wrapper script not found" + exit 1 + fi + + echo "Checking for binaries directory..." + if [ -d "$PACKAGE_DIR/binaries" ]; then + echo "✓ Binaries directory found" + echo "Binaries included:" + ls -la "$PACKAGE_DIR/binaries" || true + else + echo "✗ Binaries directory not found" + exit 1 + fi + + # Check platform-specific binary + PLATFORM="${{ inputs.platform }}" + case "$PLATFORM" in + darwin) + if [ -f "$PACKAGE_DIR/binaries/darwin-amd64/hookdeck" ] || [ -f "$PACKAGE_DIR/binaries/darwin-arm64/hookdeck" ]; then + echo "✓ macOS binary found" + else + echo "✗ macOS binary not found" + exit 1 + fi + ;; + linux) + if [ -f "$PACKAGE_DIR/binaries/linux-amd64/hookdeck" ]; then + echo "✓ Linux binary found" + else + echo "✗ Linux binary not found" + exit 1 + fi + ;; + win32) + if [ -f "$PACKAGE_DIR/binaries/win32-amd64/hookdeck.exe" ]; then + echo "✓ Windows binary found" + else + echo "✗ Windows binary not found" + exit 1 + fi + ;; + esac diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 70df7d7..97e3d09 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -135,6 +135,24 @@ jobs: - run: npm ci + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24.9 + + - name: Install Windows cross-compilation tools + run: | + sudo apt-get update + sudo apt-get install -y gcc-mingw-w64-x86-64 + + - name: Build npm binaries with GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + version: v2.10.2 + args: build -f .goreleaser/npm.yml --clean --skip validate + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Determine npm tag for pre-releases id: npm_tag run: | diff --git a/.github/workflows/test-npm-build.yml b/.github/workflows/test-npm-build.yml new file mode 100644 index 0000000..9f5bee8 --- /dev/null +++ b/.github/workflows/test-npm-build.yml @@ -0,0 +1,40 @@ +name: test-npm-build + +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + test-npm-build: + runs-on: ubuntu-latest + steps: + - name: Code checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24.9 + + - name: Install Windows cross-compilation tools + run: | + sudo apt-get update + sudo apt-get install -y gcc-mingw-w64-x86-64 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.x" + + - name: Install GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + version: v2.10.2 + install-only: true + + - name: Run npm build tests + run: | + chmod +x test-scripts/test-npm-build.sh + ./test-scripts/test-npm-build.sh diff --git a/.github/workflows/test-npm-install.yml b/.github/workflows/test-npm-install.yml new file mode 100644 index 0000000..99d8132 --- /dev/null +++ b/.github/workflows/test-npm-install.yml @@ -0,0 +1,128 @@ +name: test-npm-install + +on: + # Trigger after release workflow completes successfully + # This will trigger for releases from ANY branch (main, feature branches, etc.) + workflow_run: + workflows: ["release"] + types: + - completed + # Manual trigger for testing + workflow_dispatch: + inputs: + npm_version: + description: "npm version to test (e.g., @beta, @latest, or specific version like 1.6.1-beta.1)" + required: false + default: "@beta" + type: string + +jobs: + determine-version: + runs-on: ubuntu-latest + # Always run, but only extract version if triggered by release workflow + if: always() + outputs: + version: ${{ steps.extract.outputs.version }} + npm_tag: ${{ steps.extract.outputs.npm_tag }} + steps: + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.x" + registry-url: "https://registry.npmjs.org" + + - name: Extract version from tag + id: extract + run: | + # For manual dispatch, skip version extraction (will use input instead) + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "Manual dispatch - version will be provided via input" + echo "version=" >> $GITHUB_OUTPUT + echo "npm_tag=" >> $GITHUB_OUTPUT + exit 0 + fi + + # For workflow_run, check if release workflow succeeded + if [ "${{ github.event.workflow_run.conclusion }}" != "success" ] || [ "${{ github.event.workflow_run.event }}" != "push" ]; then + echo "Release workflow did not succeed or was not a tag push, skipping" + echo "version=" >> $GITHUB_OUTPUT + echo "npm_tag=" >> $GITHUB_OUTPUT + exit 0 + fi + + # Try to extract tag from workflow_run head_branch (for tag pushes, this should be refs/tags/v*) + TAG_REF="${{ github.event.workflow_run.head_branch }}" + + # If head_branch contains a tag ref, extract it + if [[ "$TAG_REF" == refs/tags/v* ]]; then + TAG_VERSION=${TAG_REF#refs/tags/v} + echo "Extracted version from tag ref: $TAG_VERSION" + else + # Fallback: Query npm for the latest version in the beta tag + echo "Warning: Could not extract tag from head_branch: $TAG_REF" + echo "Attempting to determine version from npm registry..." + + # Check beta tag first (most common for feature branch releases) + BETA_VERSION=$(npm view hookdeck-cli@beta version 2>/dev/null || echo "") + if [ -n "$BETA_VERSION" ]; then + TAG_VERSION="$BETA_VERSION" + echo "Using latest beta version: $TAG_VERSION" + else + # Fall back to latest + TAG_VERSION=$(npm view hookdeck-cli@latest version 2>/dev/null || echo "") + echo "Using latest version: $TAG_VERSION" + fi + fi + + echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT + + # Determine npm tag + NPM_TAG="latest" + if [[ "$TAG_VERSION" == *-* ]]; then + NPM_TAG=$(echo "$TAG_VERSION" | cut -d'-' -f2 | cut -d'.' -f1) + fi + echo "npm_tag=$NPM_TAG" >> $GITHUB_OUTPUT + echo "Final: version=$TAG_VERSION, npm tag=$NPM_TAG" + + test-npm-install: + needs: [determine-version] + # Run if: manual dispatch OR (workflow_run trigger AND determine-version has version output) + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && needs.determine-version.outputs.version != '') + strategy: + matrix: + include: + - os: macos-latest + platform: darwin + - os: ubuntu-latest + platform: linux + - os: windows-latest + platform: win32 + runs-on: ${{ matrix.os }} + steps: + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.x" + registry-url: "https://registry.npmjs.org" + + - name: Determine version to test + id: version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + VERSION="${{ github.event.inputs.npm_version || '@beta' }}" + else + VERSION="${{ needs.determine-version.outputs.version }}" + NPM_TAG="${{ needs.determine-version.outputs.npm_tag }}" + # Use npm tag if it's a pre-release + if [ "$NPM_TAG" != "latest" ]; then + VERSION="@${NPM_TAG}" + fi + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Testing version: $VERSION" + + - name: Test npm install + uses: ./.github/actions/test-npm-install + with: + version: ${{ steps.version.outputs.version }} + platform: ${{ matrix.platform }} diff --git a/.gitignore b/.gitignore index 5b0d4d2..0487757 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ completions/ dist/ -bin/ +bin/* +!bin/hookdeck.js +binaries/ coverage.txt /hookdeck /hookdeck-darwin diff --git a/.goreleaser/npm.yml b/.goreleaser/npm.yml new file mode 100644 index 0000000..7215b06 --- /dev/null +++ b/.goreleaser/npm.yml @@ -0,0 +1,101 @@ +version: 2 +env: + - GO111MODULE=on +before: + hooks: + - go mod download + - go generate ./... +project_name: hookdeck +builds: + # Darwin builds + - id: npm-darwin-amd64 + binary: hookdeck + main: ./main.go + goos: [darwin] + goarch: [amd64] + env: + - CGO_ENABLED=1 + ldflags: + - -s -w -X github.com/hookdeck/hookdeck-cli/pkg/version.Version={{.Version}} + hooks: + post: + - mkdir -p binaries/darwin-amd64 + - cp "{{ .Path }}" binaries/darwin-amd64/hookdeck + - chmod +x binaries/darwin-amd64/hookdeck + + - id: npm-darwin-arm64 + binary: hookdeck + main: ./main.go + goos: [darwin] + goarch: [arm64] + ldflags: + - -s -w -X github.com/hookdeck/hookdeck-cli/pkg/version.Version={{.Version}} + hooks: + post: + - mkdir -p binaries/darwin-arm64 + - cp "{{ .Path }}" binaries/darwin-arm64/hookdeck + - chmod +x binaries/darwin-arm64/hookdeck + + # Linux builds + - id: npm-linux-amd64 + binary: hookdeck + main: ./main.go + goos: [linux] + goarch: [amd64] + env: + - CGO_ENABLED=0 + ldflags: + - -s -w -X github.com/hookdeck/hookdeck-cli/pkg/version.Version={{.Version}} + hooks: + post: + - mkdir -p binaries/linux-amd64 + - cp "{{ .Path }}" binaries/linux-amd64/hookdeck + - chmod +x binaries/linux-amd64/hookdeck + + - id: npm-linux-arm64 + binary: hookdeck + main: ./main.go + goos: [linux] + goarch: [arm64] + env: + - CGO_ENABLED=0 + ldflags: + - -s -w -X github.com/hookdeck/hookdeck-cli/pkg/version.Version={{.Version}} + hooks: + post: + - mkdir -p binaries/linux-arm64 + - cp "{{ .Path }}" binaries/linux-arm64/hookdeck + - chmod +x binaries/linux-arm64/hookdeck + + # Windows builds + - id: npm-windows-amd64 + binary: hookdeck + main: ./main.go + goos: [windows] + goarch: [amd64] + env: + - CGO_ENABLED=1 + - CC=x86_64-w64-mingw32-gcc + - CXX=x86_64-w64-mingw32-g++ + ldflags: + - -s -w -X github.com/hookdeck/hookdeck-cli/pkg/version.Version={{.Version}} + hooks: + post: + - mkdir -p binaries/win32-amd64 + - cp "{{ .Path }}" binaries/win32-amd64/hookdeck.exe + + - id: npm-windows-386 + binary: hookdeck + main: ./main.go + goos: [windows] + goarch: [386] + env: + - CGO_ENABLED=1 + - CC=x86_64-w64-mingw32-gcc + - CXX=x86_64-w64-mingw32-g++ + ldflags: + - -s -w -X github.com/hookdeck/hookdeck-cli/pkg/version.Version={{.Version}} + hooks: + post: + - mkdir -p binaries/win32-386 + - cp "{{ .Path }}" binaries/win32-386/hookdeck.exe diff --git a/README.md b/README.md index a89558a..940885f 100644 --- a/README.md +++ b/README.md @@ -1011,6 +1011,46 @@ Then run the locally generated `hookdeck-cli` binary: ./hookdeck-cli ``` +### Testing the npm package build + +To test the npm package build process locally (including the wrapper script), you can use the automated test script: + +```sh +# Run the automated test script (recommended) +./test-scripts/test-npm-build.sh +``` + +The test script will: +- Build all 6 platform binaries using GoReleaser +- Verify the binaries directory structure +- Test the wrapper script on your current platform +- Verify npm pack includes all required files + +**Manual testing (if you prefer step-by-step):** + +```sh +# Install GoReleaser (if not already installed) +# Option 1: Using Homebrew (recommended on macOS) +brew install goreleaser + +# Option 2: Download binary from GitHub releases +# Visit https://github.com/goreleaser/goreleaser/releases/latest + +# Build all platform binaries for npm +goreleaser build -f .goreleaser/npm.yml --snapshot --clean + +# Verify binaries directory structure +ls -R binaries/ + +# Test the wrapper script on your platform +node bin/hookdeck.js --version + +# Test npm package creation (dry-run) +npm pack --dry-run +``` + +This will create the `binaries/` directory with all 6 platform binaries, allowing you to test the wrapper script locally before publishing. + ## Testing ### Running Acceptance Tests @@ -1045,6 +1085,36 @@ In CI environments, set the `HOOKDECK_CLI_TESTING_API_KEY` environment variable For detailed testing documentation and troubleshooting, see [`test/acceptance/README.md`](test/acceptance/README.md). +### Testing npm package and wrapper script + +The npm package includes a wrapper script (`bin/hookdeck.js`) that detects the platform and executes the correct binary. + +**Quick test (using automated script):** + +```sh +./test-scripts/test-npm-build.sh +``` + +**Manual testing:** + +```sh +# Ensure GoReleaser is installed (see "Testing the npm package build" section above) + +# Build all platform binaries +goreleaser build -f .goreleaser/npm.yml --snapshot --clean + +# Test wrapper script on current platform +node bin/hookdeck.js version + +# Verify wrapper script can find binary +node bin/hookdeck.js --help + +# Test npm pack includes all files +npm pack --dry-run | grep -E "(bin/hookdeck.js|binaries/)" +``` + +**Note:** The wrapper script expects binaries in `binaries/{platform}-{arch}/hookdeck[.exe]`. When building locally, ensure all platforms are built or the wrapper will fail for missing platforms. + ### Testing against a local API When testing against a non-production Hookdeck API, you can use the @@ -1067,63 +1137,11 @@ docker run --rm -it \ ## Releasing -This section describes the branching strategy and release process for the Hookdeck CLI. - -### Branching Strategy - -The project uses two primary branches: - -- **`main`** - The stable, production-ready branch. All production releases are created from this branch. -- **`next`** - The beta/pre-release branch. All new features are merged here first for testing before being promoted to `main`. - -### Beta Releases - -Beta releases allow you to publish pre-release versions for testing without blocking the `main` branch or affecting stable releases. - -**Process:** - -1. Ensure all desired features are merged into the `next` branch -2. Pull the latest changes locally: - ```sh - git checkout next - git pull origin next - ``` -3. Create and push a beta tag with a pre-release identifier: - ```sh - git tag v1.2.3-beta.0 - git push origin v1.2.3-beta.0 - ``` -4. The GitHub Actions workflow will automatically: - - Build binaries for all platforms (macOS, Linux, Windows) - - Create a GitHub pre-release (marked as "Pre-release") - - Publish to NPM with the `beta` tag - - Create beta packages: - - Homebrew: `hookdeck-beta` formula - - Scoop: `hookdeck-beta` package - - Docker: Tagged with the version (e.g., `v1.2.3-beta.0`), but not `latest` - -**Installing beta releases:** - -```sh -# NPM -npm install hookdeck-cli@beta -g - -# Homebrew -brew install hookdeck/hookdeck/hookdeck-beta - -# To force the symlink update and overwrite all conflicting files: -# brew link --overwrite hookdeck-beta - -# Scoop -scoop install hookdeck-beta - -# Docker -docker run hookdeck/hookdeck-cli:v1.2.3-beta.0 version -``` +This section describes the release process for the Hookdeck CLI. ## Release Process -The release workflow supports tagging from ANY branch - it automatically detects which branch contains the tag. +The release workflow supports tagging from **ANY branch** - it automatically detects which branch contains the tag. This means you can create beta releases directly from feature branches for testing before merging to `main`. ### Stable Release (Preferred Method: GitHub UI) @@ -1154,6 +1172,8 @@ git push origin v1.3.0 ### Pre-release from Main (General Beta Testing) +For general beta testing of features that have been merged to `main`: + **Preferred Method: GitHub UI** 1. Ensure `main` branch is in the desired state 2. Go to the [GitHub Releases page](https://github.com/hookdeck/hookdeck-cli/releases) @@ -1171,6 +1191,25 @@ git tag v1.3.0-beta.1 git push origin v1.3.0-beta.1 ``` +**Installing beta releases:** + +```sh +# NPM +npm install hookdeck-cli@beta -g + +# Homebrew +brew install hookdeck/hookdeck/hookdeck-beta + +# To force the symlink update and overwrite all conflicting files: +# brew link --overwrite hookdeck-beta + +# Scoop +scoop install hookdeck-beta + +# Docker +docker run hookdeck/hookdeck-cli:v1.3.0-beta.1 version +``` + ### Pre-release from Feature Branch (Feature-Specific Testing) For testing a specific feature in isolation before merging to main: @@ -1194,6 +1233,25 @@ git push origin v1.3.0-beta.1 # Then create release notes on GitHub Releases page ``` +**Installing beta releases:** + +```sh +# NPM +npm install hookdeck-cli@beta -g + +# Homebrew +brew install hookdeck/hookdeck/hookdeck-beta + +# To force the symlink update and overwrite all conflicting files: +# brew link --overwrite hookdeck-beta + +# Scoop +scoop install hookdeck-beta + +# Docker +docker run hookdeck/hookdeck-cli:v1.3.0-beta.1 version +``` + **Note:** Only stable releases (without pre-release identifiers like `-beta`, `-alpha`) will update the `latest` tags across all distribution channels. ## Repository Setup diff --git a/bin/hookdeck.js b/bin/hookdeck.js new file mode 100755 index 0000000..5d0a978 --- /dev/null +++ b/bin/hookdeck.js @@ -0,0 +1,37 @@ +#!/usr/bin/env node +const { execFileSync } = require('child_process'); +const { existsSync } = require('fs'); +const path = require('path'); + +const platform = process.platform; // 'darwin', 'linux', 'win32' +const arch = process.arch; // 'x64', 'arm64', 'ia32' + +// Map Node.js arch to Go arch naming +const archMap = { + 'x64': 'amd64', + 'arm64': 'arm64', + 'ia32': '386' +}; +const goArch = archMap[arch] || arch; + +// Determine binary directory name and executable name +const binaryDir = `${platform}-${goArch}`; +const binaryName = platform === 'win32' ? 'hookdeck.exe' : 'hookdeck'; + +// Path to the binary relative to this script +const binaryPath = path.join(__dirname, '..', 'binaries', binaryDir, binaryName); + +if (!existsSync(binaryPath)) { + console.error(`Error: Unsupported platform: ${platform}-${arch}`); + console.error(`Expected binary at: ${binaryPath}`); + console.error(`Please report this issue at https://github.com/hookdeck/hookdeck-cli/issues`); + process.exit(1); +} + +try { + execFileSync(binaryPath, process.argv.slice(2), { stdio: 'inherit' }); +} catch (error) { + // execFileSync will exit with the same code as the binary + // If there's an error executing, exit with code 1 + process.exit(error.status || 1); +} diff --git a/package-lock.json b/package-lock.json index c4814ec..e198cbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,309 +1,16 @@ { "name": "hookdeck-cli", - "version": "1.0.3", + "version": "1.6.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "hookdeck-cli", - "version": "1.0.3", - "hasInstallScript": true, + "version": "1.6.0", "license": "Apache-2.0", - "dependencies": { - "go-npm-next": "^1.1.0" - }, "bin": { - "hookdeck": "bin/hookdeck" + "hookdeck": "bin/hookdeck.js" } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/go-npm-next": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/go-npm-next/-/go-npm-next-1.1.0.tgz", - "integrity": "sha512-u9duzjbQXqm7kzx+VMYgg+Ijat/vChqV/zww4o47X2AsY9OegVcFURLsRaGC/Ip0YyINQvktZAYVOjsKEj92lw==", - "license": "Apache-2.0", - "dependencies": { - "mkdirp": "^3.0.1", - "node-fetch": "^2.7.0", - "tar": "^6.2.1" - }, - "bin": { - "go-npm": "dist/index.js" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - } - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "go-npm-next": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/go-npm-next/-/go-npm-next-1.1.0.tgz", - "integrity": "sha512-u9duzjbQXqm7kzx+VMYgg+Ijat/vChqV/zww4o47X2AsY9OegVcFURLsRaGC/Ip0YyINQvktZAYVOjsKEj92lw==", - "requires": { - "mkdirp": "^3.0.1", - "node-fetch": "^2.7.0", - "tar": "^6.2.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==" - }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index 87559a0..f163663 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hookdeck-cli", - "version": "1.6.0", + "version": "1.6.1-beta.1", "description": "Hookdeck CLI", "repository": { "type": "git", @@ -16,19 +16,12 @@ }, "homepage": "https://github.com/hookdeck/hookdeck-cli#readme", "bin": { - "hookdeck": "./bin/hookdeck" + "hookdeck": "./bin/hookdeck.js" }, - "files": [], - "scripts": { - "postinstall": "go-npm install", - "preuninstall": "go-npm uninstall" - }, - "goBinary": { - "name": "hookdeck", - "path": "./bin", - "url": "https://github.com/hookdeck/hookdeck-cli/releases/download/v{{version}}/hookdeck_{{version}}_{{platform}}_{{arch}}.tar.gz" - }, - "dependencies": { - "go-npm-next": "^1.1.0" - } + "files": [ + "bin/", + "binaries/" + ], + "scripts": {}, + "dependencies": {} } \ No newline at end of file diff --git a/test-scripts/test-npm-build.sh b/test-scripts/test-npm-build.sh new file mode 100755 index 0000000..25b3a9c --- /dev/null +++ b/test-scripts/test-npm-build.sh @@ -0,0 +1,72 @@ +#!/bin/bash +set -e + +echo "Testing npm package build process..." + +# Check if GoReleaser is installed +if ! command -v goreleaser &> /dev/null; then + echo "Error: goreleaser not found." + echo "Install options:" + echo " - macOS: brew install goreleaser" + echo " - Linux/Windows: Download from https://github.com/goreleaser/goreleaser/releases/latest" + echo " - Or try: go install github.com/goreleaser/goreleaser@latest" + exit 1 +fi + +# Clean previous builds +rm -rf binaries/ dist/ + +# Build all platforms +echo "Building all platform binaries..." +goreleaser build -f .goreleaser/npm.yml --snapshot --clean + +# Verify binaries directory structure +echo "Verifying binaries directory structure..." +expected_dirs=( + "binaries/darwin-amd64" + "binaries/darwin-arm64" + "binaries/linux-amd64" + "binaries/linux-arm64" + "binaries/win32-amd64" + "binaries/win32-386" +) + +for dir in "${expected_dirs[@]}"; do + if [ ! -d "$dir" ]; then + echo "Error: Missing directory: $dir" + exit 1 + fi +done + +# Verify binaries exist +echo "Verifying binaries exist..." +if [ ! -f "binaries/darwin-amd64/hookdeck" ]; then + echo "Error: Missing binary: binaries/darwin-amd64/hookdeck" + exit 1 +fi +if [ ! -f "binaries/win32-amd64/hookdeck.exe" ]; then + echo "Error: Missing binary: binaries/win32-amd64/hookdeck.exe" + exit 1 +fi + +# Test wrapper script on current platform +echo "Testing wrapper script on current platform..." +if node bin/hookdeck.js --version > /dev/null 2>&1; then + echo "✓ Wrapper script works on $(uname -s)-$(uname -m)" +else + echo "⚠ Warning: Wrapper script test skipped (binary may not exist for this platform)" +fi + +# Test npm pack +echo "Testing npm pack..." +npm pack --dry-run > /tmp/npm-pack-output.txt 2>&1 +if grep -q "bin/hookdeck.js" /tmp/npm-pack-output.txt && grep -q "binaries/" /tmp/npm-pack-output.txt; then + echo "✓ npm pack includes wrapper script and binaries" +else + echo "Error: npm pack missing required files" + cat /tmp/npm-pack-output.txt + exit 1 +fi + +echo "" +echo "✓ All npm build tests passed!"