Skip to content

Commit 1c60761

Browse files
Merge pull request #129 from godaddy/use-go-warmup-library
Add Bun runtime support via Go warmup library
2 parents 8f7eeac + 41d9891 commit 1c60761

File tree

8 files changed

+301
-10
lines changed

8 files changed

+301
-10
lines changed

.asherah-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ASHERAH_VERSION=v0.4.33
1+
ASHERAH_VERSION=v0.4.36

.github/workflows/test.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@ jobs:
3030
options: --ulimit core=-1 --ulimit memlock=-1:-1
3131
steps:
3232
- uses: actions/checkout@v4
33+
- name: Install Bun
34+
run: |
35+
curl -fsSL https://bun.sh/install | bash
36+
export PATH="$HOME/.bun/bin:$PATH"
37+
echo "PATH=$HOME/.bun/bin:$PATH" >> $GITHUB_ENV
38+
bun --version
3339
- name: Install npm packages
3440
run: npm install
35-
- name: Unit Test
41+
- name: Unit Test (includes Bun test via posttest)
3642
run: npm test
3743
- name: Initialize RDBMS based metastore
3844
run: |

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
"test:mocha-debug": "lldb -o run -- node node_modules/mocha/bin/mocha --inspect-brk",
1717
"test:mocha": "mocha",
1818
"test": "nyc npm run test:mocha",
19+
"test:bun": "bun test/bun-test.js",
1920
"debug": "nyc npm run test:mocha-debug",
20-
"posttest": "npm run lint",
21+
"posttest": "npm run lint && npm run test:bun",
2122
"lint": "eslint src/**.ts --fix",
2223
"update": "npx npm-check-updates --target latest -u -x mocha && npm i && npm audit fix"
2324
},

scripts/download-libraries.sh

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ function download_file {
7171
function verify_checksums {
7272
local archive=$1
7373
local header=$2
74-
local sums=$3
74+
local warmup=$3
75+
local sums=$4
7576

7677
# Determine the available SHA hashing utility
7778
if command -v sha256sum &> /dev/null; then
@@ -90,9 +91,9 @@ function verify_checksums {
9091
fi
9192

9293
# Filter the relevant checksums and verify they are not empty
93-
checksums=$(grep -e "${archive}" -e "${header}" "${sums}")
94+
checksums=$(grep -e "${archive}" -e "${header}" -e "${warmup}" "${sums}")
9495
if [[ -z "$checksums" ]]; then
95-
echo "Error: No matching checksums found for ${archive} or ${header} in ${sums}." >&2
96+
echo "Error: No matching checksums found for ${archive}, ${header}, or ${warmup} in ${sums}." >&2
9697
return 1
9798
fi
9899

@@ -144,11 +145,13 @@ function detect_os_and_cpu {
144145
#echo "Using Asherah libraries for Linux x86_64"
145146
ARCHIVE="libasherah-x64.a"
146147
HEADER="libasherah-x64-archive.h"
148+
WARMUP="go-warmup-linux-x64.so"
147149
SUMS="SHA256SUMS"
148150
elif [[ ${MACHINE} == 'aarch64' ]]; then
149151
#echo "Using Asherah libraries for Linux aarch64"
150152
ARCHIVE="libasherah-arm64.a"
151153
HEADER="libasherah-arm64-archive.h"
154+
WARMUP="go-warmup-linux-arm64.so"
152155
SUMS="SHA256SUMS"
153156
else
154157
#echo "Unsupported CPU architecture: ${MACHINE}" >&2
@@ -159,11 +162,13 @@ function detect_os_and_cpu {
159162
#echo "Using Asherah libraries for MacOS x86_64"
160163
ARCHIVE="libasherah-darwin-x64.a"
161164
HEADER="libasherah-darwin-x64-archive.h"
165+
WARMUP="go-warmup-darwin-x64.dylib"
162166
SUMS="SHA256SUMS-darwin"
163167
elif [[ ${MACHINE} == 'arm64' ]]; then
164168
#echo "Using Asherah libraries for MacOS arm64"
165169
ARCHIVE="libasherah-darwin-arm64.a"
166170
HEADER="libasherah-darwin-arm64-archive.h"
171+
WARMUP="go-warmup-darwin-arm64.dylib"
167172
SUMS="SHA256SUMS-darwin"
168173
else
169174
echo "Unsupported CPU architecture: ${MACHINE}" >&2
@@ -174,7 +179,7 @@ function detect_os_and_cpu {
174179
exit 1
175180
fi
176181

177-
echo "${ARCHIVE}" "${HEADER}" "${SUMS}" # Return value
182+
echo "${ARCHIVE}" "${HEADER}" "${WARMUP}" "${SUMS}" # Return value
178183
}
179184

180185
# Parse script arguments
@@ -216,18 +221,20 @@ function main {
216221
no_cache=$(parse_args "$@")
217222

218223
# Detect OS and CPU architecture
219-
read -r archive header sums < <(detect_os_and_cpu)
224+
read -r archive header warmup sums < <(detect_os_and_cpu)
220225
echo "Archive: $archive"
221226
echo "Header: $header"
227+
echo "Warmup: $warmup"
222228
echo "Sums: $sums"
223229
echo "Version: $ASHERAH_VERSION"
224230

225231
# Interpolate the URLs
226232
url_prefix="https://github.com/godaddy/asherah-cobhan/releases/download/${ASHERAH_VERSION}"
227-
file_names=("${archive}" "${header}" "${sums}")
233+
file_names=("${archive}" "${header}" "${warmup}" "${sums}")
228234
file_urls=(
229235
"${url_prefix}/${archive}"
230236
"${url_prefix}/${header}"
237+
"${url_prefix}/${warmup}"
231238
"${url_prefix}/${sums}"
232239
)
233240

@@ -249,7 +256,7 @@ function main {
249256
done
250257

251258
# Verify checksums and copy files
252-
if verify_checksums "${archive}" "${header}" "${sums}"; then
259+
if verify_checksums "${archive}" "${header}" "${warmup}" "${sums}"; then
253260
copy_files "${archive}" "${header}"
254261
checksums_verified=true
255262
else

scripts/runs-on-emulated.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
#!/bin/bash
22
cd /build || exit 1
3+
4+
# Install Bun for multi-arch testing
5+
echo "Installing Bun..."
6+
curl -fsSL https://bun.sh/install | bash
7+
export PATH="$HOME/.bun/bin:$PATH"
8+
bun --version
9+
10+
# Run npm install and tests
311
npm install
412
npm run test

src/index.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* asherah-node - Entry point with runtime compatibility support
3+
*
4+
* This module automatically handles runtime compatibility by detecting
5+
* JavaScript runtimes that need Go initialization and loading the warmup
6+
* library if available.
7+
*/
8+
9+
const path = require('path');
10+
11+
// Auto-detect and handle Bun runtime compatibility
12+
if (typeof Bun !== 'undefined') {
13+
try {
14+
const { dlopen, FFIType } = require('bun:ffi');
15+
const fs = require('fs');
16+
17+
// Determine platform-specific library name
18+
const platform = process.platform;
19+
const arch = process.arch;
20+
let libName;
21+
22+
if (platform === 'darwin') {
23+
if (arch === 'x64') {
24+
libName = 'go-warmup-darwin-x64.dylib';
25+
} else if (arch === 'arm64') {
26+
libName = 'go-warmup-darwin-arm64.dylib';
27+
} else {
28+
throw new Error(`Unsupported architecture for Darwin: ${arch}. Only x64 and arm64 are supported.`);
29+
}
30+
} else if (platform === 'linux') {
31+
if (arch === 'x64') {
32+
libName = 'go-warmup-linux-x64.so';
33+
} else if (arch === 'arm64') {
34+
libName = 'go-warmup-linux-arm64.so';
35+
} else {
36+
throw new Error(`Unsupported architecture for Linux: ${arch}. Only x64 and arm64 are supported.`);
37+
}
38+
} else {
39+
throw new Error(`Unsupported platform: ${platform}. Only darwin and linux are supported.`);
40+
}
41+
42+
// Load Go warmup library to initialize Go runtime for compatibility
43+
const libPath = path.join(__dirname, '..', 'lib', libName);
44+
45+
// Check if library exists
46+
if (!fs.existsSync(libPath)) {
47+
throw new Error(
48+
`asherah-node: Go warmup library not found at ${libPath}. ` +
49+
`Please ensure you have the latest asherah-cobhan release with warmup library support.`
50+
);
51+
}
52+
53+
const lib = dlopen(libPath, {
54+
Warmup: { returns: FFIType.int, args: [] }
55+
});
56+
57+
// Initialize Go runtime
58+
lib.symbols.Warmup();
59+
60+
// Optional: Log success in verbose mode
61+
if (process.env.ASHERAH_VERBOSE) {
62+
console.log('✅ asherah-node: Go runtime initialized for compatibility');
63+
}
64+
65+
} catch (error) {
66+
// Re-throw the error - initialization is required for Bun
67+
throw new Error(`asherah-node: Failed to initialize Go runtime for Bun: ${error.message}`);
68+
}
69+
}
70+
71+
// Load the native asherah module
72+
module.exports = require(path.join(__dirname, '..', 'build', 'Release', 'asherah.node'));

test/bun-test.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env bun
2+
3+
/**
4+
* Simple Bun test runner for CI/CD integration
5+
*
6+
* This script runs the Bun compatibility test and exits with
7+
* appropriate status codes for CI/CD pipelines.
8+
*
9+
* Usage: bun test/bun-test.js
10+
*/
11+
12+
const asherah = require('../src/index');
13+
14+
console.log('=== Bun Compatibility Test ===');
15+
console.log(`Runtime: ${typeof Bun !== 'undefined' ? 'Bun' : 'Not Bun'}`);
16+
console.log(`Platform: ${process.platform} ${process.arch}`);
17+
console.log('');
18+
19+
const config = {
20+
KMS: 'static',
21+
Metastore: 'memory',
22+
ServiceName: 'bun-test',
23+
ProductID: 'bun-test',
24+
Verbose: false,
25+
EnableSessionCaching: false,
26+
ExpireAfter: 60,
27+
CheckInterval: 1
28+
};
29+
30+
let success = true;
31+
32+
try {
33+
// Test 1: Setup
34+
console.log('1. Testing setup...');
35+
asherah.setup(config);
36+
console.log(' ✅ Setup successful');
37+
38+
// Test 2: Encrypt
39+
console.log('2. Testing encryption...');
40+
const partitionId = 'bun-test-' + Date.now();
41+
const testData = 'Bun runtime test: Hello from Bun! 🚀';
42+
const encrypted = asherah.encrypt(partitionId, Buffer.from(testData, 'utf8'));
43+
44+
if (!encrypted || encrypted.length === 0) {
45+
throw new Error('Encryption failed - no data returned');
46+
}
47+
console.log(` ✅ Encrypted ${testData.length} bytes -> ${encrypted.length} chars`);
48+
49+
// Test 3: Decrypt
50+
console.log('3. Testing decryption...');
51+
const decrypted = asherah.decrypt(partitionId, encrypted);
52+
53+
if (!decrypted) {
54+
throw new Error('Decryption failed - no data returned');
55+
}
56+
57+
const decryptedText = decrypted.toString('utf8');
58+
if (decryptedText !== testData) {
59+
throw new Error(`Decryption mismatch: expected "${testData}", got "${decryptedText}"`);
60+
}
61+
console.log(' ✅ Decrypted successfully, data matches');
62+
63+
// Test 4: Multiple cycles
64+
console.log('4. Testing multiple encrypt/decrypt cycles...');
65+
for (let i = 0; i < 5; i++) {
66+
const data = `Test cycle ${i}: ${Math.random()}`;
67+
const enc = asherah.encrypt(partitionId, Buffer.from(data, 'utf8'));
68+
const dec = asherah.decrypt(partitionId, enc);
69+
if (dec.toString('utf8') !== data) {
70+
throw new Error(`Cycle ${i} failed: data mismatch`);
71+
}
72+
}
73+
console.log(' ✅ 5 cycles completed successfully');
74+
75+
// Test 5: Shutdown
76+
console.log('5. Testing shutdown...');
77+
asherah.shutdown();
78+
console.log(' ✅ Shutdown successful');
79+
80+
console.log('');
81+
console.log('🎉 All tests PASSED!');
82+
console.log('Bun compatibility confirmed ✅');
83+
84+
} catch (error) {
85+
console.error('');
86+
console.error('❌ Test FAILED:');
87+
console.error(error.message);
88+
if (error.stack) {
89+
console.error('\nStack trace:');
90+
console.error(error.stack);
91+
}
92+
success = false;
93+
}
94+
95+
// Exit with appropriate code
96+
process.exit(success ? 0 : 1);

0 commit comments

Comments
 (0)