From ea9f86f75a287425dfc1aa9b2124b9c892ec7672 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Fri, 12 May 2023 14:59:38 +0100 Subject: [PATCH 01/18] feat: ARM64 Linux/MacOS Pact Ruby Standalone --- .cirrus.yml | 57 +++++---- script/lib/download-standalone.sh | 10 +- src/pact-standalone.spec.ts | 192 ++++++++++++------------------ standalone/install.ts | 29 +++-- 4 files changed, 141 insertions(+), 147 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index a9a02372..843b7d0c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -8,22 +8,17 @@ BUILD_TEST_TASK_TEMPLATE: &BUILD_TEST_TASK_TEMPLATE - node --version - script/ci/build-and-test.sh -# These are probably expected to fail in the post install script -# until we are packing v2.0.0 of pact-ruby-standalone that supports -# arm64 linux - as per https://github.com/pact-foundation/pact-js-core/issues/416 -# Error: Error while locating pact binary: Cannot find binary for platform 'linux' with architecture 'arm64'. -# linux_arm64_task: -# skip: "changesInclude('.github/**')" -# env: -# matrix: -# - IMAGE: node:16-slim -# - IMAGE: node:18-slim -# - IMAGE: node:20-slim -# arm_container: -# image: $IMAGE -# install_script: -# - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip -# << : *BUILD_TEST_TASK_TEMPLATE +linux_arm64_task: + env: + matrix: + - IMAGE: node:16-slim + - IMAGE: node:18-slim + - IMAGE: node:20-slim + arm_container: + image: $IMAGE + install_script: + - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip + << : *BUILD_TEST_TASK_TEMPLATE linux_amd64_task: env: @@ -37,8 +32,7 @@ linux_amd64_task: - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip << : *BUILD_TEST_TASK_TEMPLATE - -mac_task: +mac_arm64_task: macos_instance: image: ghcr.io/cirruslabs/macos-ventura-base:latest env: @@ -49,10 +43,31 @@ mac_task: - NODE_VERSION: 16 - NODE_VERSION: 18 - NODE_VERSION: 20 - install_script: # we need to install rosetta as v1.x of pact-ruby-standalone doesn't support arm64 - - softwareupdate --install-rosetta --agree-to-license + install_script: - brew install nvm - source $(brew --prefix nvm)/nvm.sh - nvm install $NODE_VERSION - nvm use $NODE_VERSION - << : *BUILD_TEST_TASK_TEMPLATE \ No newline at end of file + << : *BUILD_TEST_TASK_TEMPLATE + +mac_rosetta_task: + macos_instance: + image: ghcr.io/cirruslabs/macos-ventura-base:latest + env: + NVS_HOME: ${HOME}/.nvs + PATH: ${NVS_HOME}:${PATH} + matrix: + - NODE_VERSION: 16 + - NODE_VERSION: 18 + - NODE_VERSION: 20 + install nvs_script: | + git clone https://github.com/jasongin/nvs "$NVS_HOME" + . "$NVS_HOME/nvs.sh" install + install_rosetta_script: softwareupdate --install-rosetta --agree-to-license + install_x64_script: | + . "$NVS_HOME/nvs.sh" + nvs add $NODE_VERSION/x64 + nvs use $NODE_VERSION/x64 + file $(which node) | grep -e 'x64' + node --version + << : *BUILD_TEST_TASK_TEMPLATE diff --git a/script/lib/download-standalone.sh b/script/lib/download-standalone.sh index aa81df37..0c8ee251 100755 --- a/script/lib/download-standalone.sh +++ b/script/lib/download-standalone.sh @@ -1,4 +1,6 @@ #!/bin/bash -eu +set -e +set -u LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running . "${LIB_DIR}/robust-bash.sh" . "${LIB_DIR}/download-file.sh" @@ -7,7 +9,7 @@ require_binary curl require_binary unzip require_env_var STANDALONE_VERSION -BASEURL=https://github.com/pact-foundation/pact-ruby-standalone/releases/download +BASEURL=https://github.com/you54f/pact-ruby-standalone/releases/download STANDALONE_DIR="${LIB_DIR}/../../standalone" function download_standalone { @@ -45,11 +47,13 @@ if [[ $(find "${STANDALONE_DIR}" -name "*${STANDALONE_VERSION}") ]]; then exit 0 fi -download_standalone "pact-${STANDALONE_VERSION}-win32.zip" "win32-${STANDALONE_VERSION}.zip" +download_standalone "pact-${STANDALONE_VERSION}-windows-x86_64.zip" "windows-x64-${STANDALONE_VERSION}.zip" if [ -z "${ONLY_DOWNLOAD_PACT_FOR_WINDOWS:-}" ]; then - download_standalone "pact-${STANDALONE_VERSION}-osx.tar.gz" "darwin-${STANDALONE_VERSION}.tar.gz" + download_standalone "pact-${STANDALONE_VERSION}-osx-x86_64.tar.gz" "darwin-x64-${STANDALONE_VERSION}.tar.gz" + download_standalone "pact-${STANDALONE_VERSION}-osx-arm64.tar.gz" "darwin-arm64-${STANDALONE_VERSION}.tar.gz" download_standalone "pact-${STANDALONE_VERSION}-linux-x86_64.tar.gz" "linux-x64-${STANDALONE_VERSION}.tar.gz" + download_standalone "pact-${STANDALONE_VERSION}-linux-arm64.tar.gz" "linux-arm64-${STANDALONE_VERSION}.tar.gz" fi # Write readme in the ffi folder diff --git a/src/pact-standalone.spec.ts b/src/pact-standalone.spec.ts index 4d46437f..64ce6b97 100644 --- a/src/pact-standalone.spec.ts +++ b/src/pact-standalone.spec.ts @@ -38,122 +38,82 @@ describe('Pact Standalone', function forMocha() { describe('Check if OS specific files are there', () => { if (!process.env['ONLY_DOWNLOAD_PACT_FOR_WINDOWS']) { - describe('OSX', () => { - beforeEach(() => { - pact = standalone('darwin'); - }); - - it('broker relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.brokerPath))).to.be - .true; - }); - - it('broker full path', () => { - expect(fs.existsSync(pact.brokerFullPath)).to.be.true; - }); - - it('mock service relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.mockServicePath))).to - .be.true; - }); - - it('mock service full path', () => { - expect(fs.existsSync(pact.mockServiceFullPath)).to.be.true; - }); - - it('stub relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.stubPath))).to.be - .true; - }); - - it('stub full path', () => { - expect(fs.existsSync(pact.stubFullPath)).to.be.true; - }); - - it('provider verifier relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.verifierPath))).to.be - .true; - }); - - it('provider verifier full path', () => { - expect(fs.existsSync(pact.verifierFullPath)).to.be.true; - }); - - it('pact relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.pactPath))).to.be - .true; - }); - - it('pact full path', () => { - expect(fs.existsSync(pact.pactFullPath)).to.be.true; - }); - it('pactflow relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.pactflowPath))).to.be - .true; - }); - - it('pactflow full path', () => { - expect(fs.existsSync(pact.pactflowFullPath)).to.be.true; - }); - }); - - describe('Linux X64', () => { - beforeEach(() => { - pact = standalone('linux', 'x64'); - }); - - it('broker relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.brokerPath))).to.be - .true; - }); - - it('broker full path', () => { - expect(fs.existsSync(pact.brokerFullPath)).to.be.true; - }); - - it('mock service relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.mockServicePath))).to - .be.true; - }); - - it('mock service full path', () => { - expect(fs.existsSync(pact.mockServiceFullPath)).to.be.true; - }); - - it('stub relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.stubPath))).to.be - .true; - }); - - it('stub full path', () => { - expect(fs.existsSync(pact.stubFullPath)).to.be.true; - }); - - it('provider verifier relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.verifierPath))).to.be - .true; - }); - - it('provider verifier full path', () => { - expect(fs.existsSync(pact.verifierFullPath)).to.be.true; - }); - - it('pact relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.pactPath))).to.be - .true; - }); - - it('pact full path', () => { - expect(fs.existsSync(pact.pactFullPath)).to.be.true; - }); - - it('pactflow relative path', () => { - expect(fs.existsSync(path.resolve(basePath, pact.pactflowPath))).to.be - .true; - }); - - it('pactflow full path', () => { - expect(fs.existsSync(pact.pactflowFullPath)).to.be.true; + const binaries = [ + { + platform: 'darwin', + arch: 'x64', + }, + { + platform: 'darwin', + arch: 'arm64', + }, + { + platform: 'linux', + arch: 'x64', + }, + { + platform: 'linux', + arch: 'arm64', + }, + ]; + binaries.forEach((binary) => { + describe(`Testing binary for ${binary.arch} ${binary.platform}`, () => { + beforeEach(() => { + pact = standalone(binary.platform, binary.arch); + }); + + it('broker relative path', () => { + expect(fs.existsSync(path.resolve(basePath, pact.brokerPath))).to.be + .true; + }); + + it('broker full path', () => { + expect(fs.existsSync(pact.brokerFullPath)).to.be.true; + }); + + it('mock service relative path', () => { + expect(fs.existsSync(path.resolve(basePath, pact.mockServicePath))) + .to.be.true; + }); + + it('mock service full path', () => { + expect(fs.existsSync(pact.mockServiceFullPath)).to.be.true; + }); + + it('stub relative path', () => { + expect(fs.existsSync(path.resolve(basePath, pact.stubPath))).to.be + .true; + }); + + it('stub full path', () => { + expect(fs.existsSync(pact.stubFullPath)).to.be.true; + }); + + it('provider verifier relative path', () => { + expect(fs.existsSync(path.resolve(basePath, pact.verifierPath))).to + .be.true; + }); + + it('provider verifier full path', () => { + expect(fs.existsSync(pact.verifierFullPath)).to.be.true; + }); + + it('pact relative path', () => { + expect(fs.existsSync(path.resolve(basePath, pact.pactPath))).to.be + .true; + }); + + it('pact full path', () => { + expect(fs.existsSync(pact.pactFullPath)).to.be.true; + }); + it('pactflow relative path', () => { + expect(fs.existsSync(path.resolve(basePath, pact.pactflowPath))).to + .be.true; + }); + + it('pactflow full path', () => { + expect(fs.existsSync(pact.pactflowFullPath)).to.be.true; + }); }); }); } diff --git a/standalone/install.ts b/standalone/install.ts index 0ff4d95f..5f13eb88 100644 --- a/standalone/install.ts +++ b/standalone/install.ts @@ -1,7 +1,7 @@ import chalk = require('chalk'); // Get latest version from https://github.com/pact-foundation/pact-ruby-standalone/releases -export const PACT_STANDALONE_VERSION = '1.92.0'; +export const PACT_STANDALONE_VERSION = '2.2.1'; function makeError(msg: string): Error { return new Error(chalk.red(`Error while locating pact binary: ${msg}`)); @@ -14,15 +14,23 @@ export function createConfig(): Config { binaries: [ { platform: 'win32', - binary: `pact-${PACT_STANDALONE_VERSION}-win32.zip`, - binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-win32.zip${CHECKSUM_SUFFIX}`, - folderName: `win32-${PACT_STANDALONE_VERSION}`, + binary: `pact-${PACT_STANDALONE_VERSION}-windows-x86_64.zip`, + binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-windows-x86_64.zip${CHECKSUM_SUFFIX}`, + folderName: `windows-x64-${PACT_STANDALONE_VERSION}`, }, { platform: 'darwin', - binary: `pact-${PACT_STANDALONE_VERSION}-osx.tar.gz`, - binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-osx.tar.gz${CHECKSUM_SUFFIX}`, - folderName: `darwin-${PACT_STANDALONE_VERSION}`, + arch: 'x64', + binary: `pact-${PACT_STANDALONE_VERSION}-osx-x86_64.tar.gz`, + binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-osx-x86_64.tar.gz${CHECKSUM_SUFFIX}`, + folderName: `darwin-x64-${PACT_STANDALONE_VERSION}`, + }, + { + platform: 'darwin', + arch: 'arm64', + binary: `pact-${PACT_STANDALONE_VERSION}-osx-arm64.tar.gz`, + binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-osx-arm64.tar.gz${CHECKSUM_SUFFIX}`, + folderName: `darwin-arm64-${PACT_STANDALONE_VERSION}`, }, { platform: 'linux', @@ -31,6 +39,13 @@ export function createConfig(): Config { binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-linux-x86_64.tar.gz${CHECKSUM_SUFFIX}`, folderName: `linux-x64-${PACT_STANDALONE_VERSION}`, }, + { + platform: 'linux', + arch: 'arm64', + binary: `pact-${PACT_STANDALONE_VERSION}-linux-arm64.tar.gz`, + binaryChecksum: `pact-${PACT_STANDALONE_VERSION}-linux-arm64.tar.gz${CHECKSUM_SUFFIX}`, + folderName: `linux-arm64-${PACT_STANDALONE_VERSION}`, + }, ], }; } From 6960d8e3bc0899a29415d944176fd69d37a8b8dd Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Thu, 18 May 2023 21:55:23 +0100 Subject: [PATCH 02/18] test: pact-2.0.1 pact-ruby-standalone --- script/lib/download-standalone.sh | 2 +- standalone/install.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/download-standalone.sh b/script/lib/download-standalone.sh index 0c8ee251..2012e1ae 100755 --- a/script/lib/download-standalone.sh +++ b/script/lib/download-standalone.sh @@ -9,7 +9,7 @@ require_binary curl require_binary unzip require_env_var STANDALONE_VERSION -BASEURL=https://github.com/you54f/pact-ruby-standalone/releases/download +BASEURL=https://github.com/pact-foundation/pact-ruby-standalone/releases/download STANDALONE_DIR="${LIB_DIR}/../../standalone" function download_standalone { diff --git a/standalone/install.ts b/standalone/install.ts index 5f13eb88..a7712640 100644 --- a/standalone/install.ts +++ b/standalone/install.ts @@ -1,7 +1,7 @@ import chalk = require('chalk'); // Get latest version from https://github.com/pact-foundation/pact-ruby-standalone/releases -export const PACT_STANDALONE_VERSION = '2.2.1'; +export const PACT_STANDALONE_VERSION = '2.0.1'; function makeError(msg: string): Error { return new Error(chalk.red(`Error while locating pact binary: ${msg}`)); From 6bfac100e04909055b88f39da90bf01d6305e176 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Thu, 18 May 2023 23:33:33 +0100 Subject: [PATCH 03/18] chore(ci): add libyaml-dev to node-slim images --- .cirrus.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 843b7d0c..ce6ca892 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -17,7 +17,7 @@ linux_arm64_task: arm_container: image: $IMAGE install_script: - - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip + - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip libyaml-dev << : *BUILD_TEST_TASK_TEMPLATE linux_amd64_task: @@ -29,7 +29,7 @@ linux_amd64_task: container: image: $IMAGE install_script: - - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip + - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip libyaml-dev << : *BUILD_TEST_TASK_TEMPLATE mac_arm64_task: From 6a38cf7cf2738e43e84586446fcaa8022d9e2431 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Tue, 30 May 2023 13:28:47 +0100 Subject: [PATCH 04/18] Feat: Prebuild pact_ffi pact.node - This change pre-builds the pact node bindings with prebuildify Supported node versions are node LTS versions 16, 18, 20. Supported Platforms + Arches are now * Linux ARM64/X64 * MacOS ARM64/X64 * Windows X64 For the Pact FFI. This change additional includes the Pact-Ruby-Standalone updated to v2.x This brings is support for * Linux/MacOS ARM64 for the pact cli and api ## Requirements Users are no longer required to * Install a node-gyp build chain - Not limited to - Python - MSVS for Windows * Ensure `--ignore-scripts` is not set to true - This is because pact-js-core and the npm package pact-core will now come batteries included, which means the ffi and standalone come packaged in the npm package. This increases size, however all files have to be downloaded currently even if all are not used, so we might as well do this once for the user, rather than every user needing to, and possibly struggling due to various build system reasons related to node-gyp. --- .cirrus.yml | 102 ++++++--------- .github/workflows/build-and-test.yml | 102 +++++++++++++-- .github/workflows/publish.yml | 30 ++--- .gitignore | 44 ++++--- .npmignore | 12 ++ CHANGELOG.md | 28 ++++ DEVELOPER.md | 91 ++++++++++++- README.md | 30 ++++- binding.gyp | 67 +++++----- download-checksums.js | 1 - ffi/README.md | 3 - package-lock.json | 82 ++++-------- package.json | 14 +- script/ci/build-and-test.sh | 21 ++- script/ci/check-release-libs.sh | 110 ++++++++++++++++ script/ci/clean.sh | 10 ++ script/ci/download-standalone-and-test.sh | 9 ++ script/ci/lib/publish.sh | 12 +- script/ci/prebuild.sh | 89 +++++++++++++ script/ci/release.sh | 130 ++++++++++++++----- script/ci/unpack-and-test.sh | 13 ++ script/download-standalone.sh | 5 + script/lib/download-ffi.sh | 4 + script/lib/download-standalone.sh | 6 +- src/ffi/index.ts | 148 +++++++++++++++++++++- src/ffi/node-gyp-build.ts | 1 + standalone/install.ts | 2 +- test/consumer.integration.spec.ts | 9 +- 28 files changed, 911 insertions(+), 264 deletions(-) delete mode 100644 download-checksums.js delete mode 100644 ffi/README.md create mode 100755 script/ci/check-release-libs.sh create mode 100755 script/ci/clean.sh create mode 100755 script/ci/download-standalone-and-test.sh create mode 100755 script/ci/prebuild.sh create mode 100755 script/ci/unpack-and-test.sh create mode 100755 script/download-standalone.sh create mode 100644 src/ffi/node-gyp-build.ts diff --git a/.cirrus.yml b/.cirrus.yml index 843b7d0c..bae88b48 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,73 +1,49 @@ -env: - PACT_BROKER_FEATURES: publish_pacts_using_old_api -BUILD_TEST_TASK_TEMPLATE: &BUILD_TEST_TASK_TEMPLATE - arch_check_script: - - uname -am - test_script: - - node --version - - script/ci/build-and-test.sh +INSTALL_GH_CLI: &INSTALL_GH_CLI + install_gh_cli_script: | + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ + && chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ + && apt update \ + && apt install gh -y -linux_arm64_task: +RELEASE: &RELEASE + release_script: ./script/ci/release.sh env: - matrix: - - IMAGE: node:16-slim - - IMAGE: node:18-slim - - IMAGE: node:20-slim - arm_container: - image: $IMAGE - install_script: - - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip - << : *BUILD_TEST_TASK_TEMPLATE + GITHUB_TOKEN: ENCRYPTED[636f316600928de28b5c36027cc39d9796bc0d0eca2a181368f255ad61540f13bb38cdce09b6428774f315bbf45e0ada] + GH_PRE_RELEASE_UPLOAD: true -linux_amd64_task: - env: - matrix: - - IMAGE: node:16-slim - - IMAGE: node:18-slim - - IMAGE: node:20-slim - container: - image: $IMAGE - install_script: - - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip - << : *BUILD_TEST_TASK_TEMPLATE +PREBUILD_AND_TEST: &PREBUILD_AND_TEST + prebuild_script: NODE_VERSION=20 script/ci/prebuild.sh + <<: *RELEASE + test_20_script: NODE_VERSION=20 script/ci/build-and-test.sh && script/ci/clean.sh + test_18_script: NODE_VERSION=18 script/ci/build-and-test.sh && script/ci/clean.sh + test_16_script: NODE_VERSION=16 script/ci/build-and-test.sh && script/ci/clean.sh -mac_arm64_task: - macos_instance: - image: ghcr.io/cirruslabs/macos-ventura-base:latest +linux_arm_task: env: - PACT_BROKER_FEATURES: publish_pacts_using_old_api - NVS_HOME: ${HOME}/.nvs - PATH: ${NVS_HOME}:${PATH} - matrix: - - NODE_VERSION: 16 - - NODE_VERSION: 18 - - NODE_VERSION: 20 - install_script: - - brew install nvm - - source $(brew --prefix nvm)/nvm.sh - - nvm install $NODE_VERSION - - nvm use $NODE_VERSION - << : *BUILD_TEST_TASK_TEMPLATE + SET_NVM: "true" + arm_container: + # container: + image: node:20-slim + cirrus_setup_script: chmod +x script/**/* && chmod +x script/** + setup_script: apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip libyaml-dev git + dry_run_check_script: npx --yes commit-and-tag-version --dry-run && git remote -v + pre_req_script: curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.3/install.sh | bash + <<: *INSTALL_GH_CLI + <<: *PREBUILD_AND_TEST + artifacts: + path: prebuilds/*.tar.gz -mac_rosetta_task: +macos_arm_task: macos_instance: image: ghcr.io/cirruslabs/macos-ventura-base:latest env: - NVS_HOME: ${HOME}/.nvs - PATH: ${NVS_HOME}:${PATH} - matrix: - - NODE_VERSION: 16 - - NODE_VERSION: 18 - - NODE_VERSION: 20 - install nvs_script: | - git clone https://github.com/jasongin/nvs "$NVS_HOME" - . "$NVS_HOME/nvs.sh" install - install_rosetta_script: softwareupdate --install-rosetta --agree-to-license - install_x64_script: | - . "$NVS_HOME/nvs.sh" - nvs add $NODE_VERSION/x64 - nvs use $NODE_VERSION/x64 - file $(which node) | grep -e 'x64' - node --version - << : *BUILD_TEST_TASK_TEMPLATE + SET_NVM: "true" + cirrus_setup_script: chmod +x script/**/* && chmod +x script/** + dry_run_check_script: | + npx --yes commit-and-tag-version --dry-run && git remote -v + pre_req_script: brew install nvm + <<: *PREBUILD_AND_TEST + artifacts: + path: prebuilds/*.tar.gz \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 6110a456..d06713ce 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,7 +7,18 @@ on: workflow_dispatch: jobs: - build-and-test-osx: + + create_pre_release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: GH_CREATE_PRE_RELEASE=true ./script/ci/release.sh + if: github.ref == 'refs/heads/master' && env.ACT != 'true' && runner.os == 'Linux' + env: + GITHUB_TOKEN: ${{ github.token }} + + prebuild: + needs: [ create_pre_release ] runs-on: ${{ matrix.os }} defaults: run: @@ -15,23 +26,88 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16,18,20] + node-version: [20] os: [macos-latest,ubuntu-latest,windows-latest] + env: + NODE_VERSION: ${{ matrix.node-version }} + steps: - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node-version }} + + + - name: Use Node.js ${{ env.NODE_VERSION }} uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} - - run: script/ci/build-and-test.sh - if: runner.os != 'Windows' + node-version: ${{ env.NODE_VERSION }} + + - if: runner.os == 'Windows' + run: echo "ONLY_DOWNLOAD_PACT_FOR_WINDOWS=true" >> $GITHUB_ENV + + - run: ./script/ci/prebuild.sh + + - name: Upload prebuild for ${{ runner.os }}-${{ runner.arch }} + uses: actions/upload-artifact@v3 + with: + path: prebuilds/*.tar.gz + + - run: GH_PRE_RELEASE_UPLOAD=true ./script/ci/release.sh + if: github.ref == 'refs/heads/master' && env.ACT != 'true' env: - NODE_VERSION: ${{ matrix.node-version }} - PACT_BROKER_FEATURES: publish_pacts_using_old_api - - run: script/ci/build-and-test.sh - if: runner.os == 'Windows' + GITHUB_TOKEN: ${{ github.token }} + + test: + runs-on: ${{ matrix.os }} + needs: [prebuild] + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + node-version: [16,18,20] + os: [macos-latest,ubuntu-latest,windows-latest] + + env: + NODE_VERSION: ${{ matrix.node-version }} + + steps: + - uses: actions/checkout@v3 + + - name: Download prebuilds + uses: actions/download-artifact@v3 + + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - if: runner.os == 'Windows' + run: echo "ONLY_DOWNLOAD_PACT_FOR_WINDOWS=true" >> $GITHUB_ENV + - run: ./script/ci/unpack-and-test.sh + + release_dry_run: + runs-on: ubuntu-latest + needs: [ create_pre_release, prebuild ] + if: github.ref == 'refs/heads/master' + + env: + NODE_VERSION: 20 + + steps: + - uses: actions/checkout@v3 + + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + registry-url: 'https://registry.npmjs.org' + + - name: "release - dry run: ${{ env.DRY_RUN }}" + id: publish + run: script/ci/release.sh env: - NODE_VERSION: ${{ matrix.node-version }} - PACT_BROKER_FEATURES: publish_pacts_using_old_api - ONLY_DOWNLOAD_PACT_FOR_WINDOWS: true + GITHUB_TOKEN: ${{ github.token }} + DRY_RUN: true + + - run: echo "New Release will be v${{ steps.publish.outputs.version }}" \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4566cb2a..a471d862 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,26 +9,22 @@ on: jobs: release: runs-on: ubuntu-latest + + env: + NODE_VERSION: 20 + steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v3 with: - node-version: 16 + node-version: ${{ env.NODE_VERSION }} registry-url: 'https://registry.npmjs.org' - - id: publish - run: script/ci/release.sh env: NODE_AUTH_TOKEN: ${{secrets.NPM_AUTOMATION_TOKEN}} - - name: Create Release - id: create_release - uses: actions/create-release@v1 + - name: "release" + id: publish + run: script/ci/release.sh env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: v${{ steps.publish.outputs.version }} - release_name: Release v${{ steps.publish.outputs.version }} - body: ${{steps.publish.outputs.notes}} - draft: false - prerelease: false + GITHUB_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 1b5ddb5d..b1a0ef08 100644 --- a/.gitignore +++ b/.gitignore @@ -19,8 +19,7 @@ coverage # node-waf configuration .lock-wscript -# Compiled binary addons (http://nodejs.org/api/addons.html) -build + # Redis database dump dump.rdb @@ -44,8 +43,11 @@ src/**/**.d.ts test/**/**.d.ts bin/**/**.d.ts **/*.d.ts -*.js -!test.js +src/**/**.js +test/**/**.js +bin/**/**.js +# *.js +# !test.js *.js.map @@ -53,12 +55,26 @@ bin/**/**.d.ts ts-node-* # pact standalone binaries -standalone/* -!standalone/__fixtures__/.keep -!standalone/*.ts +# standalone/* +standalone/darwin* +standalone/linux* +standalone/windows* standalone/*.d.ts -ffi/* -!ffi/README.md +standalone/*.js +standalone/*.checksum +standalone/*.gz +standalone/README.md +# FFI native bindings +*.so +*.dll* +pact.h +pact-cpp.h +ffi/README.md +*.dylib +# Compiled binary addons (http://nodejs.org/api/addons.html) +build +# Precompiled binary addons +prebuilds # Folders created during testing log @@ -66,13 +82,3 @@ reports tmp .tmp test/__testoutput__ - -# jest config -!jest.config.js - -# mocha config -!.mocharc.js -!ts-node.js - -# jest mocks -!__mocks__ diff --git a/.npmignore b/.npmignore index b65f4840..aa54c8e6 100644 --- a/.npmignore +++ b/.npmignore @@ -79,3 +79,15 @@ test # release scripts script + +## these arent needed in the final bundle +binding.gyp +native + +.cirrus +.gitattributes +DEVELOPER.md +RELEASING.md +test.js +tsconfig.build.json +tsconfig.json \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7509255a..ad209474 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,34 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## 13.19.0 (2023-05-27) + + +### Features + +* Improved error messaging on path lookups ([b3c80be](https://github.com/pact-foundation/pact-js-core/commit/b3c80be68882cdbbc0801f01e3d0ea1493dccb5e)) + +## 13.18.2 (2023-05-27) + + +### Fixes and Improvements + +* node-gyp-build for resolution only ([fceb1cf](https://github.com/pact-foundation/pact-js-core/commit/fceb1cf2cd091b0858f73b6184398df392aa061a)) + +## 13.18.1 (2023-05-27) + + +### Fixes and Improvements + +* ensure ffi not npm ignored ([8092c22](https://github.com/pact-foundation/pact-js-core/commit/8092c22b3a9a8714e85908d16dd0fa531613cb7e)) + +## 13.18.0 (2023-05-27) + + +### Features + +* Prebuild pact_ffi pact.node + publish in npm pkg - (win-32|linux|darwin)-x64 (linux|darwin)-arm64 ([2cd224d](https://github.com/pact-foundation/pact-js-core/commit/2cd224dbbb49b06ab98f4e1e05d38aa45b497d16)) + ## [13.13.8](https://github.com/pact-foundation/pact-js-core/compare/v13.13.7...v13.13.8) (2023-04-24) diff --git a/DEVELOPER.md b/DEVELOPER.md index 280479e7..17008731 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -11,4 +11,93 @@ npm test _notes_ - As a developer, you need to run `bash script/download-libs.sh` to download the FFI libraries prior to running `npm install` / `npm ci` as the libraries will be expected to be there, and you won't have any `node_modules` installed yet. -For end users, the `ffi` folder is populated, as part of the npm publishing step. \ No newline at end of file +For end users, the `ffi` folder is populated, as part of the npm publishing step. + +### Linux x86_64 Task + +#### Pre Reqs + +1. x86_64 Machine + 1. ARM64 Mac - If you have Rosetta (MacOS) + +### CI Locally + +1. Docker/Podman +2. Act + +```sh +act --container-architecture linux/amd64 -W .github/workflows/build-and-test.yml --artifact-server-path tmp +``` + +### MacOS x86_64 Task + +#### Pre Reqs + +1. Arm64 Mac with Rosetta + 1. install notes for rosetta + 2. prefix commands with `arch -x86_64` +2. x86_64 Mac + +### CI Locally + +1. Arm64 Mac with Rosetta +2. x86_64 Mac +3. Cirrus-Cli +4. Parallels + +```sh +to be added +``` + +### MacOS ARM64 Task + +#### Pre Reqs + +1. Arm64 Mac + +### CI Locally + +1. Arm64 Mac +2. Cirrus-Cli +3. Tart.run + + +```sh +cirrus run --output github-actions macos_arm --artifacts-dir tmp +``` + +#### Notes + +Change `arm_container` to container + +### Linux ARM64 Task + +#### Pre Reqs + +1. Arm64 Machine + +### CI Locally + +1. Arm64 Machine +2. Docker / Podman +3. Cirrus-Cli + 1. Fork that supports running `container` tasks as `aarch64` + + +```sh +saffus run --output github-actions linux_arm --artifacts-dir tmp +``` + +#### Notes + +Change `arm_container` to container + + + +#### Publishing Assets + +`cirrus run --output github-actions macos_arm --artifacts-dir tmp --environment GITHUB_TOKEN=$GITHUB_TOKEN --environment CIRRUS_RELEASE=test --environment CIRRUS_REPO_FULL_NAME=pact-foundation/pact-js-core;` + +Change `arm_container` to container + +`saffus run --output github-actions linux_arm --artifacts-dir tmp --environment GITHUB_TOKEN=$GITHUB_TOKEN --environment CIRRUS_RELEASE=test --environment CIRRUS_REPO_FULL_NAME=pact-foundation/pact-js-core;` \ No newline at end of file diff --git a/README.md b/README.md index 80ce41ad..db7cf649 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,34 @@ ![Build and test](https://github.com/pact-foundation/pact-js-core/workflows/Build%20and%20test/badge.svg) [![Known Vulnerabilities](https://snyk.io/test/github/pact-foundation/pact-js-core/badge.svg?targetFile=package.json)](https://snyk.io/test/github/pact-foundation/pact-js-core?targetFile=package.json) +[![GitHub release](https://img.shields.io/github/release/pact-foundation/pact-js-core)](https://github.com/pact-foundation/pact-js-core) [![npm](https://img.shields.io/npm/v/@pact-foundation/pact-core.svg)](https://www.npmjs.com/package/@pact-foundation/pact-core) [![license](https://img.shields.io/github/license/pact-foundation/pact-js-core.svg)](https://github.com/pact-foundation/pact-js-core/blob/master/LICENSE) -[![dependencies](https://img.shields.io/david/pact-foundation/pact-js-core.svg)](https://www.npmjs.com/package/@pact-foundation/pact-core) [![slack](http://slack.pact.io/badge.svg)](http://slack.pact.io) + +[![Npm package license](https://badgen.net/npm/license/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) +[![Npm package version](https://badgen.net/npm/v/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) +[![Minimum node.js version](https://badgen.net/npm/node/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) + +[![Npm package total downloads](https://badgen.net/npm/dt/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) + +[![Npm package yearly downloads](https://badgen.net/npm/dy/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) +[![Npm package monthly downloads](https://badgen.net/npm/dm/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) +[![Npm package daily downloads](https://badgen.net/npm/dd/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) + +[![Npm package dependents](https://badgen.net/npm/dependents/@pact-foundation/pact-core)](https://npmjs.com/package/@pact-foundation/pact-core) + +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/pact-foundation/pact-js-core/graphs/commit-activity) + +[![Build and test](https://github.com/pact-foundation/pact-js-core/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/pact-foundation/pact-js-core/actions/workflows/build-and-test.yml) +[![Publish and release](https://github.com/pact-foundation/pact-js-core/actions/workflows/publish.yml/badge.svg)](https://github.com/pact-foundation/pact-js-core/actions/workflows/publish.yml) + +[![Linux](https://svgshare.com/i/Zhy.svg)](https://svgshare.com/i/Zhy.svg) +[![macOS](https://svgshare.com/i/ZjP.svg)](https://svgshare.com/i/ZjP.svg) +[![Windows](https://svgshare.com/i/ZhY.svg)](https://svgshare.com/i/ZhY.svg) + + # Pact-JS Core A wrapper for the [Pact](http://pact.io) [CLI Tools](https://github.com/pact-foundation/pact-ruby-standalone). @@ -42,6 +65,11 @@ A wrapper for the [Pact](http://pact.io) [CLI Tools](https://github.com/pact-fou - [Create Message Pacts](#create-message-pacts) - [Example](#example) - [CLI Tools](#cli-tools) + - [Windows Issues](#windows-issues) + - [Enable Long Paths](#enable-long-paths) + - [Contributing](#contributing) + - [Testing](#testing) + - [Questions?](#questions) diff --git a/binding.gyp b/binding.gyp index 80b6ad26..bb0c7998 100644 --- a/binding.gyp +++ b/binding.gyp @@ -28,7 +28,11 @@ "VCCLCompilerTool": { "ExceptionHandling": 1 } - } + }, + "copies":[{ + "files": [ "<(module_root_dir)/ffi/pact_ffi.dll"], + "destination": "<(PRODUCT_DIR)" + }], } ], [ @@ -47,7 +51,11 @@ "-L<(module_root_dir)/ffi", "-Wl,-rpath,@loader_path" ] - } + }, + "copies":[{ + "files": [ "<(module_root_dir)/ffi/libpact_ffi.dylib"], + "destination": "<(PRODUCT_DIR)" + }], } ], [ @@ -63,10 +71,14 @@ "link_settings": { "libraries": [ "-lpact_ffi", - "-L<(module_root_dir)/ffi/osxaarch64", - "-Wl,-rpath,@loader_path/osxaarch64" + "-L<(module_root_dir)/ffi", + "-Wl,-rpath,@loader_path" ] - } + }, + "copies":[{ + "files": [ "<(module_root_dir)/ffi/osxaarch64/libpact_ffi.dylib"], + "destination": "<(PRODUCT_DIR)" + }], } ], [ @@ -78,7 +90,11 @@ "-L<(module_root_dir)/ffi", "-Wl,-rpath,'$$ORIGIN'" ] - } + }, + "copies":[{ + "files": [ "<(module_root_dir)/ffi/libpact_ffi.so"], + "destination": "<(PRODUCT_DIR)" + }], } ], [ @@ -88,9 +104,13 @@ "libraries": [ "-lpact_ffi", "-L<(module_root_dir)/ffi/linuxaarch64", - "-Wl,-rpath,'$$ORIGIN'/linuxaarch64" + "-Wl,-rpath,'$$ORIGIN'" ] - } + }, + "copies":[{ + "files": [ "<(module_root_dir)/ffi/linuxaarch64/libpact_ffi.so"], + "destination": "<(PRODUCT_DIR)" + }], } ] ], @@ -105,39 +125,10 @@ "NAPI_CPP_EXCEPTIONS" ] }, - # Copy the shared libraries into the build/Release folder for distribution - { - "target_name": "copy_release_artifacts", - "dependencies": ["pact"], - "type": "none", - "copies": [ - { - # must use module_root_dir here, because it uses proper windows paths - "files": [ - "<(module_root_dir)/ffi/libpact_ffi.dylib", - "<(module_root_dir)/ffi/libpact_ffi.so", - "<(module_root_dir)/ffi/pact_ffi.dll", - ], - "destination": "<(PRODUCT_DIR)" - }, - { - "files": [ - "<(module_root_dir)/ffi/osxaarch64/libpact_ffi.dylib", - ], - "destination": "<(PRODUCT_DIR)/osxaarch64" - }, - { - "files": [ - "<(module_root_dir)/ffi/linuxaarch64/libpact_ffi.so", - ], - "destination": "<(PRODUCT_DIR)/linuxaarch64" - } - ] - }, # Need to set the library install name to enable the rpath settings to work on OSX { "target_name": "set_osx_install_name", - "dependencies": ["pact", "copy_release_artifacts"], + "dependencies": ["pact"], "type": "none", "target_conditions":[ [ diff --git a/download-checksums.js b/download-checksums.js deleted file mode 100644 index 8a7e98c0..00000000 --- a/download-checksums.js +++ /dev/null @@ -1 +0,0 @@ -require('./standalone/install').downloadChecksums(); diff --git a/ffi/README.md b/ffi/README.md deleted file mode 100644 index f1ec21b9..00000000 --- a/ffi/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# FFI binaries - -This folder is automatically populated during build by /script/download-ffi.sh diff --git a/package-lock.json b/package-lock.json index 36a79f45..3470d44e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pact-foundation/pact-core", - "version": "13.13.8", + "version": "13.19.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@pact-foundation/pact-core", - "version": "13.13.8", + "version": "13.19.0", "cpu": [ "x64", "ia32", @@ -20,13 +20,12 @@ "win32" ], "dependencies": { - "bindings": "^1.5.0", "chalk": "4.1.2", "check-types": "7.3.0", "cross-spawn": "7.0.3", "mkdirp": "1.0.0", "needle": "^3.2.0", - "node-addon-api": "^4.2.0", + "node-gyp-build": "^4.6.0", "pino": "^8.7.0", "pino-pretty": "^9.1.1", "promise-timeout": "1.3.0", @@ -50,7 +49,6 @@ "@snyk/protect": "^1.1118.0", "@tsconfig/node14": "^1.0.3", "@types/basic-auth": "^1.1.2", - "@types/bindings": "^1.5.1", "@types/chai": "4.1.2", "@types/chai-as-promised": "7.1.0", "@types/check-types": "^7.3.2", @@ -92,6 +90,7 @@ "form-data": "^4.0.0", "grpc-promise": "^1.4.0", "mocha": "^9.1.3", + "node-addon-api": "^6.1.0", "nodemon": "^2.0.4", "prettier": "^2.3.0", "protobufjs": "^6.11.2", @@ -609,15 +608,6 @@ "@types/node": "*" } }, - "node_modules/@types/bindings": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/bindings/-/bindings-1.5.1.tgz", - "integrity": "sha512-8HzueDeoxGXdsJ0Ep7TOXHGN+woRTWa1bAds30r5we7PCC3P5zrSTRknePLn/KYAubgQv5t/1zkonnStHLCWOg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -1456,14 +1446,6 @@ "node": ">=8" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -3648,11 +3630,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -5616,9 +5593,20 @@ } }, "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "dev": true + }, + "node_modules/node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } }, "node_modules/nodemon": { "version": "2.0.20", @@ -8082,15 +8070,6 @@ "@types/node": "*" } }, - "@types/bindings": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/bindings/-/bindings-1.5.1.tgz", - "integrity": "sha512-8HzueDeoxGXdsJ0Ep7TOXHGN+woRTWa1bAds30r5we7PCC3P5zrSTRknePLn/KYAubgQv5t/1zkonnStHLCWOg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -8740,14 +8719,6 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -10409,11 +10380,6 @@ "flat-cache": "^3.0.4" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -11866,9 +11832,15 @@ } }, "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "dev": true + }, + "node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==" }, "nodemon": { "version": "2.0.20", diff --git a/package.json b/package.json index a0161b33..046383cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pact-foundation/pact-core", - "version": "13.13.8", + "version": "13.19.0", "description": "Core of @pact-foundation/pact. You almost certainly don't want to depend on this directly.", "main": "src/index.js", "homepage": "https://github.com/pact-foundation/pact-js-core#readme", @@ -52,13 +52,12 @@ "access": "public" }, "dependencies": { - "bindings": "^1.5.0", "chalk": "4.1.2", "check-types": "7.3.0", "cross-spawn": "7.0.3", "mkdirp": "1.0.0", "needle": "^3.2.0", - "node-addon-api": "^4.2.0", + "node-gyp-build": "^4.6.0", "pino": "^8.7.0", "pino-pretty": "^9.1.1", "promise-timeout": "1.3.0", @@ -73,7 +72,6 @@ "@snyk/protect": "^1.1118.0", "@tsconfig/node14": "^1.0.3", "@types/basic-auth": "^1.1.2", - "@types/bindings": "^1.5.1", "@types/chai": "4.1.2", "@types/chai-as-promised": "7.1.0", "@types/check-types": "^7.3.2", @@ -115,6 +113,7 @@ "form-data": "^4.0.0", "grpc-promise": "^1.4.0", "mocha": "^9.1.3", + "node-addon-api": "^6.1.0", "nodemon": "^2.0.4", "prettier": "^2.3.0", "protobufjs": "^6.11.2", @@ -126,7 +125,9 @@ "clean": "rimraf '{src,test,bin,standalone}/**/*.{js,map,d.ts}' 'package.zip' '.tmp' 'tmp'", "lint": "eslint . --ext .ts --config .eslintrc", "lint:fix": "npm run lint -- --fix", - "prebuild": "npm run clean && bash script/download-libs.sh", + "prebuild": "npm run clean", + "download-libs": "npm run clean && bash script/download-libs.sh", + "clean-libs": "rimraf standalone/*.{js,map,d.ts} standalone/{windows**,linux**,darwin**} 'ffi'", "build": "tsc --project tsconfig.build.json", "prerelease": "npm run snyk-protect", "release": "commit-and-tag-version", @@ -135,8 +136,7 @@ "format:base": "prettier --parser typescript", "format:check": "npm run format:base -- --list-different \"{src,standalone,bin,test}/**/*.{ts,tsx}\"", "format:fix": "npm run format:base -- --write \"{src,standalone,bin,test}/**/*.{ts,tsx}\"", - "postinstall": "npm run native", - "native": "node-gyp rebuild -v" + "install": "echo welcome to Pact-JS - This post install script supresses node-gyp rebuild as it is not required for this package" }, "prettier": "@pact-foundation/pact-js-prettier-config", "commit-and-tag-version": { diff --git a/script/ci/build-and-test.sh b/script/ci/build-and-test.sh index 7d5e330c..abc3c01b 100755 --- a/script/ci/build-and-test.sh +++ b/script/ci/build-and-test.sh @@ -5,10 +5,25 @@ set -u SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running . "$SCRIPT_DIR"/../lib/robust-bash.sh -bash script/download-libs.sh -npm ci +if [[ ${SET_NVM:-} == 'true' && "$(uname -s)" == 'Darwin' ]]; then + NVM_DIR=${NVM_DIR:-"$HOME/.nvm"} + . $(brew --prefix nvm)/nvm.sh # Load nvm + nvm install $NODE_VERSION + nvm use $NODE_VERSION +elif [[ ${SET_NVM:-} == 'true' && "$(uname -s)" == 'Linux' ]]; then + NVM_DIR=${NVM_DIR:-"$HOME/.nvm"} + . $NVM_DIR/nvm.sh # Load nvm + nvm install $NODE_VERSION + nvm use $NODE_VERSION +fi + +node --version +npm --version + +npm ci --ignore-scripts npm run format:check npm run lint npm run build -npm run test \ No newline at end of file +npm run test +ls -1 \ No newline at end of file diff --git a/script/ci/check-release-libs.sh b/script/ci/check-release-libs.sh new file mode 100755 index 00000000..14a5cdb8 --- /dev/null +++ b/script/ci/check-release-libs.sh @@ -0,0 +1,110 @@ +#!/bin/bash -eu + +# Usage: ./check-release-libs.sh [OPTIONS] +# +# This script checks the release assets of a GitHub repository. +# +# Options: +# -r, --repo The GitHub repository to check (default: pact-foundation/pact-js-core) +# -t, --tag The release tag to check (default: TAG) +# -l, --list-assets List the remote release assets +# -f, --fetch-assets Fetch the remote release assets (will clean local assets) +# -c, --clean-assets Clean the local release assets +# +# Example: +# ./check-release-libs.sh -r myorg/myrepo -t v1.0.0 -l +# +# This will list the remote release assets of the myorg/myrepo repository for the v1.0.0 tag. + +# Parse command line arguments +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -r|--repo) + REPO="$2" + shift # past argument + shift # past value + ;; + -t|--tag) + TAG="$2" + shift # past argument + shift # past value + ;; + -l|--list-assets) + LIST_ASSETS=true + shift # past argument + ;; + -f|--fetch-assets) + FETCH_ASSETS=true + shift # past argument + ;; + -c|--clean-assets) + CLEAN_ASSETS=true + shift # past argument + ;; + *) # unknown option + echo "Unknown option: $1" + exit 1 + ;; +esac +done + +# Set default values for REPO and TAG if not provided +REPO=${REPO:-pact-foundation/pact-js-core} +TAG=${NEXT_TAG:-${TAG:-latest}} + +echo "Checking release assets" + +if [[ "${CLEAN_ASSETS:-}" = true || "${FETCH_ASSETS:-}" = true ]]; then + echo "Cleaning local release assets" + rm -rf *.tar.gz + rm -rf prebuilds +fi + +if [[ "$TAG" == "" ]]; then + echo "Please provide a release TAG to check" + exit 1 +else + GH_TAG_OPTION="$TAG" + if [[ "$TAG" == "latest" ]]; then + GH_TAG_OPTION='' + fi + + if [[ "${LIST_ASSETS:-}" = true || "${FETCH_ASSETS:-}" = true ]]; then + echo "Listing remote release assets for ${REPO} ${GH_TAG_OPTION}" + gh release view --repo "${REPO}" $GH_TAG_OPTION --json assets | jq '.assets[].name' + fi + + if [ "${FETCH_ASSETS:-}" = true ]; then + echo "Fetching release assets" + gh release download --repo "${REPO}" $GH_TAG_OPTION + fi + +fi + +ERRORS=() +ls *.gz +ls *.gz | xargs -n1 tar -xzf +rm *.tar.gz +ls -1 prebuilds/** + +[[ -f prebuilds/darwin-arm64/libpact_ffi.dylib ]] || ERRORS='prebuilds/darwin-arm64/libpact_ffi.dylib' +[[ -f prebuilds/darwin-arm64/node.napi.node ]] || ERRORS='prebuilds/darwin-arm64/node.napi.node' +[[ -f prebuilds/darwin-x64/libpact_ffi.dylib ]] || ERRORS='prebuilds/darwin-x64/libpact_ffi.dylib' +[[ -f prebuilds/darwin-x64/node.napi.node ]] || ERRORS='prebuilds/darwin-x64/node.napi.node' +[[ -f prebuilds/linux-arm64/libpact_ffi.so ]] || ERRORS='prebuilds/linux-arm64/libpact_ffi.so' +[[ -f prebuilds/linux-arm64/node.napi.node ]] || ERRORS='prebuilds/linux-arm64/node.napi.node' +[[ -f prebuilds/linux-x64/libpact_ffi.so ]] || ERRORS='prebuilds/linux-x64/libpact_ffi.so' +[[ -f prebuilds/linux-x64/node.napi.node ]] || ERRORS='prebuilds/linux-x64/node.napi.node' +[[ -f prebuilds/win32-x64/pact_ffi.dll ]] || ERRORS='prebuilds/win32-x64/pact_ffi.dll' +[[ -f prebuilds/win32-x64/node.napi.node ]] || ERRORS='prebuilds/win32-x64/node.napi.node' + +if [ ! -z "${ERRORS:-}" ]; then + echo "The following files are missing from the release:" + echo $ERRORS + exit 1 +else + echo "All release files are present" +fi \ No newline at end of file diff --git a/script/ci/clean.sh b/script/ci/clean.sh new file mode 100755 index 00000000..e14d1c1a --- /dev/null +++ b/script/ci/clean.sh @@ -0,0 +1,10 @@ +#!/bin/bash -eu +set -e # This needs to be here for windows bash, which doesn't read the #! line above +set -u + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running +. "$SCRIPT_DIR"/../lib/robust-bash.sh + +npm run clean +rm -rf node_modules +ls \ No newline at end of file diff --git a/script/ci/download-standalone-and-test.sh b/script/ci/download-standalone-and-test.sh new file mode 100755 index 00000000..65639d43 --- /dev/null +++ b/script/ci/download-standalone-and-test.sh @@ -0,0 +1,9 @@ +#!/bin/bash -eu +set -e # This needs to be here for windows bash, which doesn't read the #! line above +set -u + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running +. "$SCRIPT_DIR"/../lib/robust-bash.sh + +./script/download-standalone.sh +./script/ci/build-and-test.sh \ No newline at end of file diff --git a/script/ci/lib/publish.sh b/script/ci/lib/publish.sh index 83ae513b..28a3b687 100755 --- a/script/ci/lib/publish.sh +++ b/script/ci/lib/publish.sh @@ -8,12 +8,16 @@ require_binary npm VERSION="$("$SCRIPT_DIR/get-version.sh")" -echo "--> Preparing npmrc file" -"$SCRIPT_DIR"/create_npmrc_file.sh - echo "--> Releasing version ${VERSION}" echo "--> Releasing artifacts" echo " Publishing pact-core@${VERSION}..." -npm publish --access public --tag latest +if [[ ${DRY_RUN:-} == 'true' ]]; then + echo "publishing in dry run mode" + npm publish --access-public --dry-run + else + echo "--> Preparing npmrc file" + "$SCRIPT_DIR"/create_npmrc_file.sh + npm publish --access public --tag latest +fi echo " done!" diff --git a/script/ci/prebuild.sh b/script/ci/prebuild.sh new file mode 100755 index 00000000..21b354f4 --- /dev/null +++ b/script/ci/prebuild.sh @@ -0,0 +1,89 @@ +# !/bin/bash -eu +set -e # This needs to be here for windows bash, which doesn't read the #! line above +set -u + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running +. "$SCRIPT_DIR"/../lib/robust-bash.sh + +if [[ ${SET_NVM:-} == 'true' && "$(uname -s)" == 'Darwin' ]]; then + NVM_DIR=${NVM_DIR:-"$HOME/.nvm"} + . $(brew --prefix nvm)/nvm.sh # Load nvm + nvm install $NODE_VERSION + nvm use $NODE_VERSION +elif [[ ${SET_NVM:-} == 'true' && "$(uname -s)" == 'Linux' ]]; then + NVM_DIR=${NVM_DIR:-"$HOME/.nvm"} + . $NVM_DIR/nvm.sh # Load nvm + nvm install $NODE_VERSION + nvm use $NODE_VERSION +fi + +## normalise OS and ARCH names +OS=$(uname -s | tr '[:upper:]' '[:lower:]') +ARCH=$(uname -m | tr '[:upper:]' '[:lower:]') +case $OS in + "windows"* | "mingw64"*) + OS=win32 + ;; +esac +node --version +npm --version +echo "OS: $OS" +echo "ARCH: $ARCH" +PREBUILDIFY_VERSION=5.0.1 + +./script/download-libs.sh +npm ci --ignore-scripts +npx --yes prebuildify@${PREBUILDIFY_VERSION} --napi +ls prebuilds/**/* +case $OS in + darwin) + case $ARCH in + arm64) + tar -czf prebuilds/darwin-arm64.tar.gz prebuilds/darwin-arm64 + ;; + x86_64) + tar -czf prebuilds/darwin-x64.tar.gz prebuilds/darwin-x64 + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; + esac + ;; + linux) + echo "Linux" + case $ARCH in + aarch64) + echo "aarch64" + tar -czf prebuilds/linux-arm64.tar.gz prebuilds/linux-arm64 + ;; + x86_64) + tar -czf prebuilds/linux-x64.tar.gz prebuilds/linux-x64 + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; + esac + ;; + win32) + case $ARCH in + arm64) + tar -czf prebuilds/win32-arm64.tar.gz prebuilds/win32-arm64 + ;; + x86_64) + tar -czf prebuilds/win32-x64.tar.gz prebuilds/win32-x64 + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; + esac + ;; + *) + echo "Unsupported OS: $OS" + exit 1 + ;; +esac +ls +rm -rf ffi build \ No newline at end of file diff --git a/script/ci/release.sh b/script/ci/release.sh index 51a8c281..cf8b0c9f 100755 --- a/script/ci/release.sh +++ b/script/ci/release.sh @@ -1,48 +1,116 @@ #!/bin/bash -eu -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running +SCRIPT_DIR="$( + cd "$(dirname "${BASH_SOURCE[0]}")" + pwd +)" # Figure out where the script is running . "$SCRIPT_DIR"/../lib/robust-bash.sh -require_env_var CI "This script must be run from CI. If you are running locally, note that it stamps your repo git settings." -require_env_var GITHUB_ACTOR -require_env_var NODE_AUTH_TOKEN +if [[ ${DRY_RUN:-} == 'true' && ${CI:-"false"} == "false" ]]; then + echo "running in dry run mode and not in CI" +else + require_env_var CI "This script must be run from CI. If you are running locally, note that it stamps your repo git settings." + if [[ ${GITHUB_ACTIONS:-} == 'true' ]]; then + require_env_var GITHUB_ACTOR + # Setup git for github actions + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git config user.name "${GITHUB_ACTOR}" + fi +fi +REPO=${REPO:-pact-foundation/pact-js-core} +# It's easier to read the release notes +# from the standard version tool before it runs +RELEASE_NOTES="$(npx -y commit-and-tag-version --dry-run | awk 'BEGIN { flag=0 } /^---$/ { if (flag == 0) { flag=1 } else { flag=2 }; next } flag == 1')" +echo "$RELEASE_NOTES" +NEXT_VERSION=$(npx -y commit-and-tag-version --dry-run | grep 'tagging release' | grep -E -o "([0-9\.]+(-[a-z\.0-9]+)?)") +NEXT_TAG="v${NEXT_VERSION}" +GIT_SHA=$(git rev-parse HEAD) +GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) -if [ ! -z "${ONLY_DOWNLOAD_PACT_FOR_WINDOWS:-}" ]; then - error "The environment variable ONLY_DOWNLOAD_PACT_FOR_WINDOWS is set" - echo " - you cannot run a release with this variable set" - echo " as only the windows binaries would be included" - echo "*** STOPPING RELEASE PROCESS ***" - exit 1 +if [ "${GH_CREATE_PRE_RELEASE:-}" = true ]; then + echo "Creating pre-release ${NEXT_TAG}" + if gh release view ${NEXT_TAG} --repo ${REPO}; then + echo "${NEXT_TAG} exists, checking if pre-release" + if gh release view ${NEXT_TAG} --repo ${REPO} --json isPrerelease | jq -e '.isPrerelease == false' >/dev/null; then + echo "${NEXT_TAG} exists, and is not a pre-release, exiting" + exit 1 + elif gh release view ${NEXT_TAG} --repo ${REPO} --json isPrerelease | jq -e '.isPrerelease == true' >/dev/null; then + echo "${NEXT_TAG} exists, and is a pre-release, updating" + gh release edit ${NEXT_TAG} --prerelease --draft --repo ${REPO} --title "Release ${NEXT_TAG}" --notes "${RELEASE_NOTES}" --target ${GIT_SHA} + exit 0 + fi + else + echo "doesnt exist, lets create" + gh release create ${NEXT_TAG} --prerelease --draft --repo ${REPO} --title "Release ${NEXT_TAG}" --notes "${RELEASE_NOTES}" --target ${GIT_SHA} + exit 0 + fi + echo "echo shouldnt get here" + exit 0 +elif [ "${GH_PRE_RELEASE_UPLOAD:-}" = true ]; then + + echo "Uploading pre-release ${NEXT_TAG}" + echo "get latest Draft pre-release" + if [[ ${CIRRUS_CI:-} == 'true' && ${CIRRUS_BRANCH:-} != 'master' ]]; then + echo "Not on master in CIRRUS_CI, skipping pre-release upload" + exit 0 + fi + if [[ ${CIRRUS_CI:-} == 'true' ]]; then + LATEST_DRAFT_PRERELEASE=$(gh release list --limit 1 --repo $REPO | grep Draft | awk '{print $2}') + NEXT_TAG=${LATEST_DRAFT_PRERELEASE} + fi + gh release upload ${NEXT_TAG} prebuilds/*.tar.gz --repo ${REPO} --clobber + exit 0 fi -# Setup git for github actions -git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" -git config user.name "${GITHUB_ACTOR}" +if [[ ${CI:-} == 'true' ]]; then + require_env_var NODE_AUTH_TOKEN +fi -# It's easier to read the release notes -# from the standard version tool before it runs -RELEASE_NOTES="$(npx standard-version --dry-run | awk 'BEGIN { flag=0 } /^---$/ { if (flag == 0) { flag=1 } else { flag=2 }; next } flag == 1')" -# Don't release if there are no changes -if [ "$(echo "$RELEASE_NOTES" | wc -l)" -eq 1 ] ; then +if [[ ${RUNNER_OS:-} == 'Windows' ]]; then + ONLY_DOWNLOAD_PACT_FOR_WINDOWS=true +fi + +if [ ! -z "${ONLY_DOWNLOAD_PACT_FOR_WINDOWS:-}" ]; then + error "The environment variable ONLY_DOWNLOAD_PACT_FOR_WINDOWS is set" + echo " - you cannot run a release with this variable set" + echo " as only the windows binaries would be included" + echo "*** STOPPING RELEASE PROCESS ***" + exit 1 +fi + +FETCH_ASSETS=true ./script/ci/check-release-libs.sh --fetch-assets -t "${NEXT_TAG}" +"$SCRIPT_DIR"/download-standalone-and-test.sh + +if [[ ${DRY_RUN:-} == 'true' ]]; then + VERSION=$NEXT_VERSION + TAG=$NEXT_TAG +else + # Don't release if there are no changes + if [ "$(echo "$RELEASE_NOTES" | wc -l)" -eq 1 ]; then error "This release would have no release notes. Does it include changes?" echo " - You must have at least one fix / feat commit to generate release notes" echo "*** STOPPING RELEASE PROCESS ***" exit 1 + fi + # This is github actions' method for emitting multi-line values + RELEASE_NOTES="${RELEASE_NOTES//'%'/'%25'}" + RELEASE_NOTES="${RELEASE_NOTES//$'\n'/'%0A'}" + RELEASE_NOTES="${RELEASE_NOTES//$'\r'/'%0D'}" + echo "notes=$RELEASE_NOTES" >> $GITHUB_OUTPUT + npm run release + # Emit version to next step + VERSION="$("$SCRIPT_DIR/lib/get-version.sh")" + TAG="v${VERSION}" + echo "version=$VERSION" >> $GITHUB_OUTPUT fi -# This is github actions' method for emitting multi-line values -RELEASE_NOTES="${RELEASE_NOTES//'%'/'%25'}" -RELEASE_NOTES="${RELEASE_NOTES//$'\n'/'%0A'}" -RELEASE_NOTES="${RELEASE_NOTES//$'\r'/'%0D'}" -echo "::set-output name=notes::$RELEASE_NOTES" - -"$SCRIPT_DIR"/build-and-test.sh -npm run release - -# Emit version to next step -VERSION="$("$SCRIPT_DIR/lib/get-version.sh")" -echo "::set-output name=version::$VERSION" "$SCRIPT_DIR"/lib/publish.sh # Push the new commit back to the repo. -git push --follow-tags +# and update GH pre-release to released +if [[ ${DRY_RUN:-} == 'true' ]]; then + echo "not pushing tags as in dry run mode" +else + git push --follow-tags + gh release edit ${TAG} --title "Release ${TAG}" --repo ${REPO} --notes "${RELEASE_NOTES}" --draft=false --prerelease=false --target ${GIT_SHA} +fi \ No newline at end of file diff --git a/script/ci/unpack-and-test.sh b/script/ci/unpack-and-test.sh new file mode 100755 index 00000000..1f7fdd1b --- /dev/null +++ b/script/ci/unpack-and-test.sh @@ -0,0 +1,13 @@ +#!/bin/bash -eu +set -e # This needs to be here for windows bash, which doesn't read the #! line above +set -u + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running +. "$SCRIPT_DIR"/../lib/robust-bash.sh + +ls -1 +ls -1 artifact +mkdir -p prebuilds +mv artifact*/*.tar.gz . || echo "no mac prebuilds" +ls *.gz |xargs -n1 tar -xzf +./script/ci/download-standalone-and-test.sh \ No newline at end of file diff --git a/script/download-standalone.sh b/script/download-standalone.sh new file mode 100755 index 00000000..44dff19b --- /dev/null +++ b/script/download-standalone.sh @@ -0,0 +1,5 @@ +#!/bin/bash -eu +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)" # Figure out where the script is running + +. "${SCRIPT_DIR}/lib/export-binary-versions.sh" +"${SCRIPT_DIR}/lib/download-standalone.sh" \ No newline at end of file diff --git a/script/lib/download-ffi.sh b/script/lib/download-ffi.sh index b0b37461..c5559acf 100755 --- a/script/lib/download-ffi.sh +++ b/script/lib/download-ffi.sh @@ -55,6 +55,10 @@ function download_ffi { gunzip "$DOWNLOAD_LOCATION" } +if [[ ${RUNNER_OS:-} == 'Windows' ]]; then + ONLY_DOWNLOAD_PACT_FOR_WINDOWS=true +fi + if [ -z "${ONLY_DOWNLOAD_PACT_FOR_WINDOWS:-}" ]; then download_ffi "linux-x86_64.so.gz" "lib" "libpact_ffi.so.gz" download_ffi "linux-aarch64.so.gz" "lib" "linuxaarch64/libpact_ffi.so.gz" diff --git a/script/lib/download-standalone.sh b/script/lib/download-standalone.sh index 0c8ee251..00daf45b 100755 --- a/script/lib/download-standalone.sh +++ b/script/lib/download-standalone.sh @@ -9,7 +9,7 @@ require_binary curl require_binary unzip require_env_var STANDALONE_VERSION -BASEURL=https://github.com/you54f/pact-ruby-standalone/releases/download +BASEURL=https://github.com/pact-foundation/pact-ruby-standalone/releases/download STANDALONE_DIR="${LIB_DIR}/../../standalone" function download_standalone { @@ -49,6 +49,10 @@ fi download_standalone "pact-${STANDALONE_VERSION}-windows-x86_64.zip" "windows-x64-${STANDALONE_VERSION}.zip" +if [[ ${RUNNER_OS:-} == 'Windows' ]]; then + ONLY_DOWNLOAD_PACT_FOR_WINDOWS=true +fi + if [ -z "${ONLY_DOWNLOAD_PACT_FOR_WINDOWS:-}" ]; then download_standalone "pact-${STANDALONE_VERSION}-osx-x86_64.tar.gz" "darwin-x64-${STANDALONE_VERSION}.tar.gz" download_standalone "pact-${STANDALONE_VERSION}-osx-arm64.tar.gz" "darwin-arm64-${STANDALONE_VERSION}.tar.gz" diff --git a/src/ffi/index.ts b/src/ffi/index.ts index 82074441..4588f5cf 100644 --- a/src/ffi/index.ts +++ b/src/ffi/index.ts @@ -1,19 +1,159 @@ -import bindings = require('bindings'); +import path from 'node:path'; +import bindings = require('node-gyp-build'); import logger, { DEFAULT_LOG_LEVEL } from '../logger'; import { LogLevel } from '../logger/types'; import { Ffi } from './types'; -const ffiLib: Ffi = bindings('pact.node'); - export const PACT_FFI_VERSION = '0.4.0'; +// supported prebuilds +// darwin-arm64 +// darwin-x64 +// linux-arm64 +// linux-x64 +// win32-x64 + +const supportedPlatforms = [ + 'darwin-arm64', + 'darwin-x64', + 'linux-arm64', + 'linux-x64', + 'win32-x64', +]; +const platform = `${process.platform}-${process.arch}`; + +const supportedPlatformsMessage = [ + 'Supported platforms are: ', + ` - ${supportedPlatforms.join('\n - ')}`, +].join('\n'); +const detectedMessage = `We detected your platform as: \n\n - ${platform}\n`; +logger.info(detectedMessage); +if ( + !supportedPlatforms.includes(platform) && + process.env['UNSUPPORTED_PLATFORM'] !== platform +) { + logger.warn(supportedPlatformsMessage); + logger.warn(detectedMessage); + logger.error(`Unsupported platform: ${platform}`); + throw new Error( + `Unsupported platform: ${platform}, set $UNSUPPORTED_PLATFORM to ${platform} to override this check` + ); +} + +if (process.env['UNSUPPORTED_PLATFORM'] !== platform) { + logger.warn( + `You have set the environment variable UNSUPPORTED_PLATFORM to ${process.env['UNSUPPORTED_PLATFORM']}, this will override the detected platform of ${platform}` + ); +} + +const loadPathMessage = (bindingsPath: string) => + `: loading native module from: \n\n - ${path.join( + bindingsPath, + 'prebuilds', + platform + )} ${ + process.env['PACT_NAPI_NODE_LOCATION'] + ? `\n - source: PACT_NAPI_NODE_LOCATION \n - You must have a supported prebuild for your platform at this location in the path ${path.join( + process.env['PACT_NAPI_NODE_LOCATION'], + 'prebuilds', + platform + )}` + : `\n source: ${path.join( + bindingsPath, + 'prebuilds', + platform + )} \n\n - You can override via PACT_NAPI_NODE_LOCATION\n` + }`; + +const bindingsResolver = (bindingsPath: string | undefined) => + bindings(bindingsPath); + +const bindingPaths = [ + path.resolve( + process.env['PACT_NAPI_NODE_LOCATION']?.toString() ?? path.resolve(), + path.resolve(__dirname, '..', '..') + ), +]; +let ffiLib: Ffi; +let loadPath: string | undefined; +try { + bindingPaths.forEach((bindingPath) => { + try { + loadPath = bindingPath; + logger.info( + `Attempting to find pact native module ${loadPathMessage(bindingPath)}` + ); + ffiLib = bindingsResolver(bindingPath); + if (ffiLib) { + throw new Error('Native module not found'); + } + } catch (error) { + logger.warn(`Failed to load native module from ${bindingPath}: ${error}`); + } + }); +} catch (error) { + logger.debug(supportedPlatformsMessage); + logger.debug(detectedMessage); + logger.debug(`Failed ${loadPathMessage}`); + logger.error(`Failed to load native module: ${error}`); + throw new Error( + 'Native module not found - check the logs for more details and set PACT_LOG_LEVEL=debug for more details' + ); +} + let ffi: typeof ffiLib; let ffiLogLevel: LogLevel; const initialiseFfi = (logLevel: LogLevel): typeof ffi => { logger.debug(`Initalising native core at log level '${logLevel}'`); ffiLogLevel = logLevel; - ffiLib.pactffiInitWithLogLevel(logLevel); + try { + ffiLib.pactffiInitWithLogLevel(logLevel); + } catch (error) { + logger.debug(supportedPlatformsMessage); + logger.debug(detectedMessage); + logger.error( + `Failed to initialise native module for ${platform}: ${error}` + ); + logger.error( + `We looked for a supported build in this location ${path.join( + loadPath ?? path.resolve(), + 'prebuilds', + platform + )}` + ); + logger.error(`Tip: check there this a prebuild for ${platform}`); + logger.error( + `Tip: check the prebuild exists at the path: ${path.join( + loadPath ?? path.resolve(), + 'prebuilds', + platform + )}` + ); + logger.error( + `Wrong Path?: set the load path with $PACT_NAPI_NODE_LOCATION ensuring that ${path.join( + '$PACT_NODE_NAPI_LOCATION', + 'prebuilds', + platform + )} exists` + ); + logger.error( + ` - Note: You dont need to include the prebuilds${platform} part of the path, just the parent directory` + ); + logger.error( + ` - Let us know: - We can add more supported path lookups easily, chat to us on slack or raise an issue on github` + ); + logger.error( + `Pro Tip: build your own prebuild, and set $UNSUPPORTED_PLATFORM to ${platform}` + ); + logger.error(`Pro Tip: see DEVELOPER.md in pact-js-core for more details`); + logger.error( + ` - Let us know: - We can add look to build more supported platforms, chat to us on slack or raise an issue on github` + ); + throw new Error( + 'Native module not found - check the logs for more details and set PACT_LOG_LEVEL=debug for more details' + ); + } return ffiLib; }; diff --git a/src/ffi/node-gyp-build.ts b/src/ffi/node-gyp-build.ts new file mode 100644 index 00000000..e06eb4ef --- /dev/null +++ b/src/ffi/node-gyp-build.ts @@ -0,0 +1 @@ +declare module 'node-gyp-build'; diff --git a/standalone/install.ts b/standalone/install.ts index 5f13eb88..a7712640 100644 --- a/standalone/install.ts +++ b/standalone/install.ts @@ -1,7 +1,7 @@ import chalk = require('chalk'); // Get latest version from https://github.com/pact-foundation/pact-ruby-standalone/releases -export const PACT_STANDALONE_VERSION = '2.2.1'; +export const PACT_STANDALONE_VERSION = '2.0.1'; function makeError(msg: string): Error { return new Error(chalk.red(`Error while locating pact binary: ${msg}`)); diff --git a/test/consumer.integration.spec.ts b/test/consumer.integration.spec.ts index f41dedb3..3edc3fff 100644 --- a/test/consumer.integration.spec.ts +++ b/test/consumer.integration.spec.ts @@ -23,10 +23,15 @@ const HOST = '127.0.0.1'; const isWin = process.platform === 'win32'; const isLinux = process.platform === 'linux'; const isDarwinArm64 = process.platform === 'darwin' && process.arch === 'arm64'; +const isDarwinX64 = process.platform === 'darwin' && process.arch === 'x64'; const isLinuxArm64 = process.platform === 'linux' && process.arch === 'arm64'; const isCirrusCi = process.env['CIRRUS_CI'] === 'true'; const usesOctetStream = - isLinuxArm64 || isWin || isDarwinArm64 || (isCirrusCi && isLinux); + isLinuxArm64 || + isWin || + isDarwinArm64 || + (isCirrusCi && isLinux) || + (isCirrusCi && isDarwinX64); describe('FFI integration test for the HTTP Consumer API', () => { setLogLevel('trace'); @@ -39,7 +44,7 @@ describe('FFI integration test for the HTTP Consumer API', () => { value, }); - describe('with JSON data', () => { + describe.skip('with JSON data', () => { beforeEach(() => { pact = makeConsumerPact( 'foo-consumer', From 67741bddef33c487844bbea7e628b1b1346cca68 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Tue, 30 May 2023 14:02:35 +0100 Subject: [PATCH 05/18] chore: remove leftovers from testing changes --- CHANGELOG.md | 28 ---------------------------- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad209474..7509255a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,34 +2,6 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. -## 13.19.0 (2023-05-27) - - -### Features - -* Improved error messaging on path lookups ([b3c80be](https://github.com/pact-foundation/pact-js-core/commit/b3c80be68882cdbbc0801f01e3d0ea1493dccb5e)) - -## 13.18.2 (2023-05-27) - - -### Fixes and Improvements - -* node-gyp-build for resolution only ([fceb1cf](https://github.com/pact-foundation/pact-js-core/commit/fceb1cf2cd091b0858f73b6184398df392aa061a)) - -## 13.18.1 (2023-05-27) - - -### Fixes and Improvements - -* ensure ffi not npm ignored ([8092c22](https://github.com/pact-foundation/pact-js-core/commit/8092c22b3a9a8714e85908d16dd0fa531613cb7e)) - -## 13.18.0 (2023-05-27) - - -### Features - -* Prebuild pact_ffi pact.node + publish in npm pkg - (win-32|linux|darwin)-x64 (linux|darwin)-arm64 ([2cd224d](https://github.com/pact-foundation/pact-js-core/commit/2cd224dbbb49b06ab98f4e1e05d38aa45b497d16)) - ## [13.13.8](https://github.com/pact-foundation/pact-js-core/compare/v13.13.7...v13.13.8) (2023-04-24) diff --git a/package-lock.json b/package-lock.json index 3470d44e..e42dea49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pact-foundation/pact-core", - "version": "13.19.0", + "version": "13.13.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@pact-foundation/pact-core", - "version": "13.19.0", + "version": "13.13.8", "cpu": [ "x64", "ia32", diff --git a/package.json b/package.json index 046383cb..9589f574 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pact-foundation/pact-core", - "version": "13.19.0", + "version": "13.13.8", "description": "Core of @pact-foundation/pact. You almost certainly don't want to depend on this directly.", "main": "src/index.js", "homepage": "https://github.com/pact-foundation/pact-js-core#readme", From 3c68db3a2e50d25e005dbf933807ad8355299f9f Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 17:23:15 +0100 Subject: [PATCH 06/18] ci(cirrus): remove libyaml-dev --- .cirrus.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index ce6ca892..843b7d0c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -17,7 +17,7 @@ linux_arm64_task: arm_container: image: $IMAGE install_script: - - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip libyaml-dev + - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip << : *BUILD_TEST_TASK_TEMPLATE linux_amd64_task: @@ -29,7 +29,7 @@ linux_amd64_task: container: image: $IMAGE install_script: - - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip libyaml-dev + - apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip << : *BUILD_TEST_TASK_TEMPLATE mac_arm64_task: From 03da25cec30889a9ce579a7dc6da60781c122c9b Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 17:23:59 +0100 Subject: [PATCH 07/18] chore: set windows binary path --- standalone/install.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standalone/install.ts b/standalone/install.ts index c13cea63..c542c56a 100644 --- a/standalone/install.ts +++ b/standalone/install.ts @@ -10,7 +10,7 @@ function makeError(msg: string): Error { export function createConfig(): Config { return { binaries: [ - ['win32', 'x64', 'windows', 'x86_64', 'zip'], + ['win32', 'x64', 'windows', 'x64', 'zip'], ['darwin', 'arm64', 'osx', 'arm64', 'tar.gz'], ['darwin', 'x64', 'osx', 'x86_64', 'tar.gz'], ['linux', 'arm64', 'linux', 'arm64', 'tar.gz'], @@ -22,7 +22,7 @@ export function createConfig(): Config { arch, binary, binaryChecksum: `${binary}.checksum`, - folderName: `${platform}-${arch}-${PACT_STANDALONE_VERSION}`, + folderName: `${platform === 'win32' ? 'windows' : platform}-${arch}-${PACT_STANDALONE_VERSION}`, }; }), }; From c0447e5c4768647f964db4cd032db09e99bbc2bc Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 17:29:25 +0100 Subject: [PATCH 08/18] chore: linting --- standalone/install.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/standalone/install.ts b/standalone/install.ts index c542c56a..72bead95 100644 --- a/standalone/install.ts +++ b/standalone/install.ts @@ -22,7 +22,9 @@ export function createConfig(): Config { arch, binary, binaryChecksum: `${binary}.checksum`, - folderName: `${platform === 'win32' ? 'windows' : platform}-${arch}-${PACT_STANDALONE_VERSION}`, + folderName: `${ + platform === 'win32' ? 'windows' : platform + }-${arch}-${PACT_STANDALONE_VERSION}`, }; }), }; From 18a9e4dea92a063c7dea10c46261a291fa06944e Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 18:55:36 +0100 Subject: [PATCH 09/18] chore: reorder ignored binaries --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b1a0ef08..a3d54657 100644 --- a/.gitignore +++ b/.gitignore @@ -67,10 +67,10 @@ standalone/README.md # FFI native bindings *.so *.dll* +*.dylib pact.h pact-cpp.h ffi/README.md -*.dylib # Compiled binary addons (http://nodejs.org/api/addons.html) build # Precompiled binary addons From e3241c2373aafd06b8642427bca65ee15123ef85 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 18:55:47 +0100 Subject: [PATCH 10/18] chore(docs): update developer documentation --- DEVELOPER.md | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/DEVELOPER.md b/DEVELOPER.md index 17008731..45f6888f 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -1,17 +1,41 @@ # Developer documentation +Pact-Js-Core uses FFI bindings from the pact-reference project, which are prebuilt for end users, the following steps will show some of the steps required to build and test locally on your machine. + Do this and you should be 👌👌👌: ``` -bash script/download-libs.sh -npm ci +bash script/ci/prebuild.sh +npm ci --ignore-scripts +npm run build npm test ``` +_notes_ - + +As a developer, you need to run `bash script/ci/prebuild.sh` to + +- download the FFI libraries to `ffi` folder +- prebuilds the binaries and outputs to `prebuilds` +- cleans up `ffi` and `build` +- downloads the `pact-ruby-standalone` bindings to `standalone` + +For end users, the following is provided as part of the packaging and release step in CI. -_notes_ - As a developer, you need to run `bash script/download-libs.sh` to download the FFI libraries prior to running `npm install` / `npm ci` as the libraries will be expected to be there, and you won't have any `node_modules` installed yet. +- the `prebuilds` folder containing built `ffi` bindings +- the `standalone` folder containing the pact ruby standalone bindings is populated, +- the `binding.gyp` file is removed from the npm package, so `npm install` doesn't attempt to build the `ffi` buildings, that are prebuilt. -For end users, the `ffi` folder is populated, as part of the npm publishing step. +If you have a `binding.gyp` file, and have created `prebuilds` you will want to perform `npm ci` or `npm install` with `--ignore-scripts` set, to avoid building the `ffi` which is prebuilt. + +Alternatively you can run the following, which will not create a prebuild, but instead use `node-gyp` to output the built `ffi` libraries to the `build` folder. This was the previous method, which meant that end users would also perform. + +``` +bash script/download-libs.sh +npm ci +npm run build +npm test +``` ### Linux x86_64 Task @@ -81,23 +105,18 @@ Change `arm_container` to container 1. Arm64 Machine 2. Docker / Podman 3. Cirrus-Cli - 1. Fork that supports running `container` tasks as `aarch64` ```sh -saffus run --output github-actions linux_arm --artifacts-dir tmp +cirrus run --output github-actions linux_arm --artifacts-dir tmp ``` -#### Notes - -Change `arm_container` to container - - - #### Publishing Assets +MacOS ARM64 + `cirrus run --output github-actions macos_arm --artifacts-dir tmp --environment GITHUB_TOKEN=$GITHUB_TOKEN --environment CIRRUS_RELEASE=test --environment CIRRUS_REPO_FULL_NAME=pact-foundation/pact-js-core;` -Change `arm_container` to container +Linux ARM64 -`saffus run --output github-actions linux_arm --artifacts-dir tmp --environment GITHUB_TOKEN=$GITHUB_TOKEN --environment CIRRUS_RELEASE=test --environment CIRRUS_REPO_FULL_NAME=pact-foundation/pact-js-core;` \ No newline at end of file +`cirrus run --output github-actions linux_arm --artifacts-dir tmp --environment GITHUB_TOKEN=$GITHUB_TOKEN --environment CIRRUS_RELEASE=test --environment CIRRUS_REPO_FULL_NAME=pact-foundation/pact-js-core;` \ No newline at end of file From 65b5aadcfb9d9949382b420a8d91c6f6b180b25a Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 18:56:20 +0100 Subject: [PATCH 11/18] chore: remove npm install message, as binding.gyp not published --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 9589f574..6b29ab70 100644 --- a/package.json +++ b/package.json @@ -135,8 +135,7 @@ "snyk-protect": "snyk-protect", "format:base": "prettier --parser typescript", "format:check": "npm run format:base -- --list-different \"{src,standalone,bin,test}/**/*.{ts,tsx}\"", - "format:fix": "npm run format:base -- --write \"{src,standalone,bin,test}/**/*.{ts,tsx}\"", - "install": "echo welcome to Pact-JS - This post install script supresses node-gyp rebuild as it is not required for this package" + "format:fix": "npm run format:base -- --write \"{src,standalone,bin,test}/**/*.{ts,tsx}\"" }, "prettier": "@pact-foundation/pact-js-prettier-config", "commit-and-tag-version": { From 9d87c564850e00f0ff12ba08d91dd24b1c02c8e5 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 18:56:35 +0100 Subject: [PATCH 12/18] chore(test): unskip json test --- test/consumer.integration.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/consumer.integration.spec.ts b/test/consumer.integration.spec.ts index 3edc3fff..8d27a879 100644 --- a/test/consumer.integration.spec.ts +++ b/test/consumer.integration.spec.ts @@ -44,7 +44,7 @@ describe('FFI integration test for the HTTP Consumer API', () => { value, }); - describe.skip('with JSON data', () => { + describe('with JSON data', () => { beforeEach(() => { pact = makeConsumerPact( 'foo-consumer', From e7cbd906e80a305d6e0d9b025b84b4ca4390bbd1 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 18:56:52 +0100 Subject: [PATCH 13/18] chore: update pact-ruby-standalone to 2.0.2 --- standalone/install.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standalone/install.ts b/standalone/install.ts index a7712640..187e8f45 100644 --- a/standalone/install.ts +++ b/standalone/install.ts @@ -1,7 +1,7 @@ import chalk = require('chalk'); // Get latest version from https://github.com/pact-foundation/pact-ruby-standalone/releases -export const PACT_STANDALONE_VERSION = '2.0.1'; +export const PACT_STANDALONE_VERSION = '2.0.2'; function makeError(msg: string): Error { return new Error(chalk.red(`Error while locating pact binary: ${msg}`)); From 99c66e7fb8ac63b11b23f0a479a74712d006f6f8 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 18:57:18 +0100 Subject: [PATCH 14/18] chore: remove UNSUPPORTED_PLATFORM and set log levels more approp --- src/ffi/index.ts | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/src/ffi/index.ts b/src/ffi/index.ts index 4588f5cf..5ca70510 100644 --- a/src/ffi/index.ts +++ b/src/ffi/index.ts @@ -27,23 +27,12 @@ const supportedPlatformsMessage = [ ` - ${supportedPlatforms.join('\n - ')}`, ].join('\n'); const detectedMessage = `We detected your platform as: \n\n - ${platform}\n`; -logger.info(detectedMessage); -if ( - !supportedPlatforms.includes(platform) && - process.env['UNSUPPORTED_PLATFORM'] !== platform -) { +logger.debug(detectedMessage); +if (!supportedPlatforms.includes(platform)) { logger.warn(supportedPlatformsMessage); logger.warn(detectedMessage); logger.error(`Unsupported platform: ${platform}`); - throw new Error( - `Unsupported platform: ${platform}, set $UNSUPPORTED_PLATFORM to ${platform} to override this check` - ); -} - -if (process.env['UNSUPPORTED_PLATFORM'] !== platform) { - logger.warn( - `You have set the environment variable UNSUPPORTED_PLATFORM to ${process.env['UNSUPPORTED_PLATFORM']}, this will override the detected platform of ${platform}` - ); + throw new Error(`Unsupported platform: ${platform}`); } const loadPathMessage = (bindingsPath: string) => @@ -80,21 +69,23 @@ try { bindingPaths.forEach((bindingPath) => { try { loadPath = bindingPath; - logger.info( + logger.debug( `Attempting to find pact native module ${loadPathMessage(bindingPath)}` ); ffiLib = bindingsResolver(bindingPath); - if (ffiLib) { + if (!ffiLib) { throw new Error('Native module not found'); } } catch (error) { - logger.warn(`Failed to load native module from ${bindingPath}: ${error}`); + logger.error( + `Failed to load native module from ${bindingPath}: ${error}` + ); } }); } catch (error) { logger.debug(supportedPlatformsMessage); logger.debug(detectedMessage); - logger.debug(`Failed ${loadPathMessage}`); + logger.error(`Failed ${loadPathMessage}`); logger.error(`Failed to load native module: ${error}`); throw new Error( 'Native module not found - check the logs for more details and set PACT_LOG_LEVEL=debug for more details' @@ -115,46 +106,38 @@ const initialiseFfi = (logLevel: LogLevel): typeof ffi => { logger.error( `Failed to initialise native module for ${platform}: ${error}` ); - logger.error( + logger.debug( `We looked for a supported build in this location ${path.join( loadPath ?? path.resolve(), 'prebuilds', platform )}` ); - logger.error(`Tip: check there this a prebuild for ${platform}`); - logger.error( + logger.debug(`Tip: check there this a prebuild for ${platform}`); + logger.debug( `Tip: check the prebuild exists at the path: ${path.join( loadPath ?? path.resolve(), 'prebuilds', platform )}` ); - logger.error( + logger.debug( `Wrong Path?: set the load path with $PACT_NAPI_NODE_LOCATION ensuring that ${path.join( '$PACT_NODE_NAPI_LOCATION', 'prebuilds', platform )} exists` ); - logger.error( + logger.debug( ` - Note: You dont need to include the prebuilds${platform} part of the path, just the parent directory` ); - logger.error( + logger.debug( ` - Let us know: - We can add more supported path lookups easily, chat to us on slack or raise an issue on github` ); - logger.error( - `Pro Tip: build your own prebuild, and set $UNSUPPORTED_PLATFORM to ${platform}` - ); - logger.error(`Pro Tip: see DEVELOPER.md in pact-js-core for more details`); - logger.error( - ` - Let us know: - We can add look to build more supported platforms, chat to us on slack or raise an issue on github` - ); throw new Error( 'Native module not found - check the logs for more details and set PACT_LOG_LEVEL=debug for more details' ); } - return ffiLib; }; From 46137be8c1dc9bb9cd58dac01d1ab942bf2eada8 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 19:57:46 +0100 Subject: [PATCH 15/18] chore: remove dry-run check script from linux cirrus --- .cirrus.yml | 3 +-- DEVELOPER.md | 30 +----------------------------- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index bae88b48..1b7f066c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -27,8 +27,7 @@ linux_arm_task: # container: image: node:20-slim cirrus_setup_script: chmod +x script/**/* && chmod +x script/** - setup_script: apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip libyaml-dev git - dry_run_check_script: npx --yes commit-and-tag-version --dry-run && git remote -v + setup_script: apt update --yes && apt install --yes curl python3 make build-essential g++ unzip zip git pre_req_script: curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.3/install.sh | bash <<: *INSTALL_GH_CLI <<: *PREBUILD_AND_TEST diff --git a/DEVELOPER.md b/DEVELOPER.md index 45f6888f..55b54af5 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -42,7 +42,7 @@ npm test #### Pre Reqs 1. x86_64 Machine - 1. ARM64 Mac - If you have Rosetta (MacOS) + 1. ARM64 Mac - If you have Rosetta (MacOS) ### CI Locally @@ -53,34 +53,10 @@ npm test act --container-architecture linux/amd64 -W .github/workflows/build-and-test.yml --artifact-server-path tmp ``` -### MacOS x86_64 Task - -#### Pre Reqs - -1. Arm64 Mac with Rosetta - 1. install notes for rosetta - 2. prefix commands with `arch -x86_64` -2. x86_64 Mac - -### CI Locally - -1. Arm64 Mac with Rosetta -2. x86_64 Mac -3. Cirrus-Cli -4. Parallels - -```sh -to be added -``` - ### MacOS ARM64 Task #### Pre Reqs -1. Arm64 Mac - -### CI Locally - 1. Arm64 Mac 2. Cirrus-Cli 3. Tart.run @@ -90,10 +66,6 @@ to be added cirrus run --output github-actions macos_arm --artifacts-dir tmp ``` -#### Notes - -Change `arm_container` to container - ### Linux ARM64 Task #### Pre Reqs From f9fd3c435a55857521f8b82cd6c58f97fd790b26 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 20:09:04 +0100 Subject: [PATCH 16/18] chore: use fine-grained pat token for pact-js-core releases from cirrus --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 1b7f066c..c837f10c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -10,7 +10,7 @@ INSTALL_GH_CLI: &INSTALL_GH_CLI RELEASE: &RELEASE release_script: ./script/ci/release.sh env: - GITHUB_TOKEN: ENCRYPTED[636f316600928de28b5c36027cc39d9796bc0d0eca2a181368f255ad61540f13bb38cdce09b6428774f315bbf45e0ada] + GITHUB_TOKEN: ENCRYPTED[80f01174768fa2065635588baac761b8d7079ea3e06f4af861d3c5c6ada0a8fe93a19e45d33a64fccc24f94f6398593d] GH_PRE_RELEASE_UPLOAD: true PREBUILD_AND_TEST: &PREBUILD_AND_TEST From 72247702e1868286c09988764f93ac4aad68dfdb Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 21:36:05 +0100 Subject: [PATCH 17/18] feat: allow setting of LOG_LEVEL env var --- README.md | 12 +++++++++--- package.json | 2 +- src/logger/index.ts | 4 +++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index db7cf649..835d032b 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,12 @@ var pact = require("@pact-foundation/pact-core"); pact.logLevel("debug"); ``` +or you can set it via an environment variable + +``` +LOG_LEVEL=debug +``` + ### Mock Servers Mock servers are used by Pact to record interactions and create pact contracts. @@ -166,7 +172,7 @@ var server = pact.createServer({ | `port` | false | number | Port number that the server runs on, defaults to random available port | | `host` | false | string | Host on which to bind the server on, defaults to 'localhost'. Supports '0.0.0.0' to bind on all IPv4 addresses on the local machine. | | `log` | false | string | File to log output on relative to current working directory, defaults to none | -| `logLevel` | false | LogLevel (string) | Log level to pass to the pact core. One of "DEBUG", "ERROR", "WARN", "INFO" | +| `logLevel` | false | LogLevel (string) | Log level to pass to the pact core. One of "DEBUG", "ERROR", "WARN", "INFO", can be set by LOG_LEVEL env var | | `ssl` | false | boolean | Create a self-signed SSL cert to run the server over HTTPS , defaults to `false` | | `sslcert` | false | string | Path to a custom self-signed SSL cert file, 'ssl' option must be set to true to use this option, defaults to none | | `sslkey` | false | string | Path a custom key and self-signed SSL cert key file, 'ssl' option must be set to true to use this, defaults to none | @@ -295,7 +301,7 @@ pact.verifyPacts({ | `providerVersion` | false | string | Provider version, required to publish verification result to Broker. Optional otherwise. | | `enablePending` | false | boolean | Enable the [pending pacts](https://docs.pact.io/pending) feature. | | `timeout` | false | number | The duration in ms we should wait to confirm verification process was successful. Defaults to 30000. | -| `logLevel` | false | LogLevel (string) | Log level. One of "TRACE", "DEBUG", "ERROR", "WARN", "INFO" | +| `logLevel` | false | LogLevel (string) | Log level. One of "TRACE", "DEBUG", "ERROR", "WARN", "INFO", can be set by LOG_LEVEL env var | The consumer version selector looks like this: @@ -410,7 +416,7 @@ var server = pact.createStub({ | port | false | number | Port number that the server runs on, defaults to random available port | | host | false | string | Host on which to bind the server on, defaults to 'localhost'. Supports '0.0.0.0' to bind on all IPv4 addresses on the local machine. | | log | false | string | File to log output on relative to current working directory, defaults to none | -| logLevel | false | LogLevel (string) | Log level to pass to the pact core. One of "DEBUG", "ERROR", "WARN", "INFO" | +| logLevel | false | LogLevel (string) | Log level to pass to the pact core. One of "DEBUG", "ERROR", "WARN", "INFO", can be set by LOG_LEVEL env var | | ssl | false | boolean | Create a self-signed SSL cert to run the server over HTTPS , defaults to 'false' | | sslcert | false | string | Path to a custom self-signed SSL cert file, 'ssl' option must be set to true to use this option. Defaults false | to none | | sslkey | false | string | Path a custom key and self-signed SSL cert key file, 'ssl' option must be set to true to use this option false. Defaults to none | diff --git a/package.json b/package.json index 703231ac..b030805a 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "build": "tsc --project tsconfig.build.json", "prerelease": "npm run snyk-protect", "release": "commit-and-tag-version", - "test": "cross-env LOGLEVEL=debug PACT_DO_NOT_TRACK=true mocha \"{src,test,bin,standalone}/**/*.spec.ts\"", + "test": "cross-env LOG_LEVEL=debug PACT_DO_NOT_TRACK=true mocha \"{src,test,bin,standalone}/**/*.spec.ts\"", "snyk-protect": "snyk-protect", "format:base": "prettier --parser typescript", "format:check": "npm run format:base -- --list-different \"{src,standalone,bin,test}/**/*.{ts,tsx}\"", diff --git a/src/logger/index.ts b/src/logger/index.ts index 48adcd3f..d797c134 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -8,7 +8,9 @@ import { LogLevel } from './types'; const pkg = require('../../package.json'); const logContext = `pact-core@${pkg.version}`; -let currentLogLevel: LogLevel = 'info'; +let currentLogLevel: LogLevel = process.env['LOG_LEVEL'] + ? (process.env['LOG_LEVEL'] as LogLevel) + : 'info'; let logger = createLogger(currentLogLevel); export const DEFAULT_LOG_LEVEL = 'info'; From e83f04bca3f3ceafd40ae1d9e05a09b77ff05f12 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Wed, 5 Jul 2023 21:36:47 +0100 Subject: [PATCH 18/18] chore: move logic into initiliase ffi func --- src/ffi/index.ts | 117 +++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 70 deletions(-) diff --git a/src/ffi/index.ts b/src/ffi/index.ts index 5ca70510..f60e191a 100644 --- a/src/ffi/index.ts +++ b/src/ffi/index.ts @@ -41,17 +41,13 @@ const loadPathMessage = (bindingsPath: string) => 'prebuilds', platform )} ${ - process.env['PACT_NAPI_NODE_LOCATION'] - ? `\n - source: PACT_NAPI_NODE_LOCATION \n - You must have a supported prebuild for your platform at this location in the path ${path.join( - process.env['PACT_NAPI_NODE_LOCATION'], + process.env['PACT_PREBUILD_LOCATION'] + ? `\n - source: PACT_PREBUILD_LOCATION \n - You must have a supported prebuild for your platform at this location in the path ${path.join( + process.env['PACT_PREBUILD_LOCATION'], 'prebuilds', platform )}` - : `\n source: ${path.join( - bindingsPath, - 'prebuilds', - platform - )} \n\n - You can override via PACT_NAPI_NODE_LOCATION\n` + : `\n source: pact-js-core binding lookup \n\n - You can override via PACT_PREBUILD_LOCATION\n` }`; const bindingsResolver = (bindingsPath: string | undefined) => @@ -59,38 +55,37 @@ const bindingsResolver = (bindingsPath: string | undefined) => const bindingPaths = [ path.resolve( - process.env['PACT_NAPI_NODE_LOCATION']?.toString() ?? path.resolve(), - path.resolve(__dirname, '..', '..') + path.resolve(__dirname, '..', '..'), + process.env['PACT_PREBUILD_LOCATION']?.toString() ?? path.resolve() ), ]; let ffiLib: Ffi; -let loadPath: string | undefined; -try { - bindingPaths.forEach((bindingPath) => { - try { - loadPath = bindingPath; - logger.debug( - `Attempting to find pact native module ${loadPathMessage(bindingPath)}` - ); - ffiLib = bindingsResolver(bindingPath); - if (!ffiLib) { - throw new Error('Native module not found'); - } - } catch (error) { - logger.error( - `Failed to load native module from ${bindingPath}: ${error}` - ); - } - }); -} catch (error) { - logger.debug(supportedPlatformsMessage); - logger.debug(detectedMessage); - logger.error(`Failed ${loadPathMessage}`); - logger.error(`Failed to load native module: ${error}`); - throw new Error( - 'Native module not found - check the logs for more details and set PACT_LOG_LEVEL=debug for more details' + +const renderBinaryErrorMessage = (error: unknown, bindingPath: string) => { + logger.debug(`${supportedPlatformsMessage}\n${detectedMessage}`); + logger.error(`Failed to initialise native module for ${platform}: ${error}`); + logger.debug( + `{supportedPlatformsMessage}\n${detectedMessage}\n + We looked for a supported build in this location ${path.join( + bindingPath ?? path.resolve(), + 'prebuilds', + platform + )}\n + Tip: check there is a prebuild for ${platform} \n + check the prebuild exists at the path: ${path.join( + bindingPath ?? path.resolve(), + 'prebuilds', + platform + )}\n + Wrong Path?: set the load path with PACT_PREBUILD_LOCATION ensuring that ${path.join( + '$PACT_NODE_NAPI_LOCATION', + 'prebuilds', + platform + )} exists\n + - Note: You dont need to include the prebuilds/${platform} part of the path, just the parent directory\n + - Let us know: We can add more supported path lookups easily, chat to us on slack or raise an issue on github` ); -} +}; let ffi: typeof ffiLib; let ffiLogLevel: LogLevel; @@ -99,43 +94,25 @@ const initialiseFfi = (logLevel: LogLevel): typeof ffi => { logger.debug(`Initalising native core at log level '${logLevel}'`); ffiLogLevel = logLevel; try { + bindingPaths.forEach((bindingPath) => { + try { + logger.debug( + `Attempting to find pact native module ${loadPathMessage( + bindingPath + )}` + ); + ffiLib = bindingsResolver(bindingPath); + if (!ffiLib) { + throw new Error('Native module not found'); + } + } catch (error) { + renderBinaryErrorMessage(error, bindingPath); + } + }); ffiLib.pactffiInitWithLogLevel(logLevel); } catch (error) { - logger.debug(supportedPlatformsMessage); - logger.debug(detectedMessage); - logger.error( - `Failed to initialise native module for ${platform}: ${error}` - ); - logger.debug( - `We looked for a supported build in this location ${path.join( - loadPath ?? path.resolve(), - 'prebuilds', - platform - )}` - ); - logger.debug(`Tip: check there this a prebuild for ${platform}`); - logger.debug( - `Tip: check the prebuild exists at the path: ${path.join( - loadPath ?? path.resolve(), - 'prebuilds', - platform - )}` - ); - logger.debug( - `Wrong Path?: set the load path with $PACT_NAPI_NODE_LOCATION ensuring that ${path.join( - '$PACT_NODE_NAPI_LOCATION', - 'prebuilds', - platform - )} exists` - ); - logger.debug( - ` - Note: You dont need to include the prebuilds${platform} part of the path, just the parent directory` - ); - logger.debug( - ` - Let us know: - We can add more supported path lookups easily, chat to us on slack or raise an issue on github` - ); throw new Error( - 'Native module not found - check the logs for more details and set PACT_LOG_LEVEL=debug for more details' + `Failed to load native module, try setting LOG_LEVEL=debug for more info \n. ${error}` ); } return ffiLib;