Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 97 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ on:
push:
branches:
- main
- 'cursor/*'
- 'feature/*'
- 'fix/*'
- 'hotfix/*'
- 'release/*'

jobs:
Build:
CoreJava8:
runs-on: ubuntu-latest
env:
CI: true
Expand Down Expand Up @@ -64,18 +65,109 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Execute Gradle build
run: ./gradlew clean build -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs"
- name: Execute Java 8 core build
run: ./gradlew :clean :build -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs"

- name: Archive test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
name: core-java8-test-results
path: build/reports

- name: Archive libs
uses: actions/upload-artifact@v4
with:
name: libs
name: core-java8-libs
path: build/libs

ChicoryJava17:
runs-on: ubuntu-latest
env:
CI: true
steps:
- uses: actions/checkout@v4

- name: Check out blue-quickjs
uses: actions/checkout@v4
with:
repository: bluecontract/blue-quickjs
path: blue-quickjs
submodules: recursive

- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'corretto'

- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 9.8.0
run_install: false

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: 'blue-quickjs/.nvmrc'
cache: 'pnpm'
cache-dependency-path: 'blue-quickjs/pnpm-lock.yaml'

- name: Cache emsdk
uses: actions/cache@v4
with:
path: blue-quickjs/tools/emsdk
key: emsdk-${{ runner.os }}-${{ hashFiles('blue-quickjs/tools/scripts/emsdk-version.txt') }}

- name: Install blue-quickjs dependencies
run: pnpm install --frozen-lockfile
working-directory: blue-quickjs

- name: Install emsdk
run: bash tools/scripts/setup-emsdk.sh
working-directory: blue-quickjs

- name: Build blue-quickjs runtime
run: |
WASM_VARIANTS=wasm32 WASM_BUILD_TYPES=release pnpm exec nx build quickjs-wasm-build
pnpm exec nx build quickjs-wasm
pnpm exec nx build abi-manifest
pnpm exec nx build quickjs-runtime
working-directory: blue-quickjs

- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Execute full Gradle build
run: ./gradlew clean build -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs" -PblueQuickJsRoot="$GITHUB_WORKSPACE/blue-quickjs"

- name: Confirm no native runtime dependency creep
run: ./gradlew :quickjs-chicory:dependencies --configuration runtimeClasspath

- name: Verify Chicory no-Node smoke test
run: ./gradlew :quickjs-chicory:test --tests '*LambdaPackagingSmokeTest' -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs" -PblueQuickJsRoot="$GITHUB_WORKSPACE/blue-quickjs"

- name: Archive test results
uses: actions/upload-artifact@v4
if: always()
with:
name: chicory-java17-test-results
path: |
build/reports
quickjs-chicory/build/reports

- name: Archive Chicory parity and benchmark reports
uses: actions/upload-artifact@v4
if: always()
with:
name: chicory-parity-benchmark-reports
path: quickjs-chicory/build/reports/*.json

- name: Archive libs
uses: actions/upload-artifact@v4
with:
name: chicory-java17-libs
path: |
build/libs
quickjs-chicory/build/libs
14 changes: 10 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '8'
java-version: '17'
distribution: 'corretto'

- name: Set up pnpm
Expand Down Expand Up @@ -63,17 +63,21 @@ jobs:
working-directory: blue-quickjs

- name: Build blue-quickjs runtime
run: pnpm exec nx build quickjs-runtime
run: |
WASM_VARIANTS=wasm32 WASM_BUILD_TYPES=release pnpm exec nx build quickjs-wasm-build
pnpm exec nx build quickjs-wasm
pnpm exec nx build abi-manifest
pnpm exec nx build quickjs-runtime
working-directory: blue-quickjs

- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Execute Gradle build
run: ./gradlew clean build -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs"
run: ./gradlew clean build -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs" -PblueQuickJsRoot="$GITHUB_WORKSPACE/blue-quickjs"

- name: Execute Gradle publish
run: ./gradlew publish -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs"
run: ./gradlew publish -Dblue.quickjs.root="$GITHUB_WORKSPACE/blue-quickjs" -PblueQuickJsRoot="$GITHUB_WORKSPACE/blue-quickjs"

- name: Execute Gradle release
env:
Expand All @@ -92,5 +96,7 @@ jobs:
name: artifacts
path: |
build/libs
quickjs-chicory/build/libs
build/publications
quickjs-chicory/build/publications
build/jreleaser
111 changes: 110 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ dependencies {
This project targets Java 8 bytecode and depends on published artifacts:

```groovy
api "blue.language:blue-language-java:1.0.0"
api "blue.language:blue-language-java:2.0.0"
api "blue.repo:blue-repo-java:1.2.0"
```

Expand Down Expand Up @@ -412,6 +412,115 @@ cd ../blue-quickjs
pnpm nx build quickjs-runtime
```

### Experimental Chicory blue-quickjs runtime

The root `blue-contract-java` artifact remains Java 8 compatible and continues
to use `NodeQuickJsRuntime` by default. Chicory is optional and must be enabled
explicitly. The optional Java 11+ artifact is:

```groovy
dependencies {
implementation "blue.contract:blue-contract-java:1.0.0"
implementation "blue.contract:blue-contract-java-quickjs-chicory:1.0.0"
}
```

The Chicory runtime executes the canonical blue-quickjs wasm32 release artifact
on the JVM. It does not require Node, V8, Javet, JNI, native Wasmtime bindings,
or another native JavaScript runtime in the Chicory evaluation path.

Treat Chicory as an experimental AWS Lambda / JVM-only runtime because current
benchmarks show it is substantially slower than the Node bridge. The no-Node
classpath smoke and Java 11 AWS Lambda container smoke have passed, so the
remaining blocker is performance and release hardening, not basic packaging.
For the same pinned blue-quickjs artifact, Host.v1 ABI, source wrapper,
bindings, and gas limit, Chicory and `NodeQuickJsRuntime` must return identical
values/errors, `wasmGasUsed`, and `hostGasUsed`. Benchmark reports are
timing-only; gas must match exactly.

Build, publish locally, and test the optional module with a built `blue-quickjs`
checkout:

```bash
cd ../blue-quickjs
pnpm install --frozen-lockfile
bash tools/scripts/setup-emsdk.sh
WASM_VARIANTS=wasm32 WASM_BUILD_TYPES=release pnpm exec nx build quickjs-wasm-build
pnpm exec nx build quickjs-wasm
pnpm exec nx build abi-manifest
pnpm exec nx build quickjs-runtime

cd ../blue-contract-java
./gradlew :quickjs-chicory:test \
-PblueQuickJsRoot=../blue-quickjs \
-Dblue.quickjs.root=../blue-quickjs
./gradlew publishToMavenLocal -PblueQuickJsRoot=../blue-quickjs
```

The module verifies the pinned wasm artifact, `engineBuildHash`, Host.v1
manifest hash, gas version, and deterministic execution profile before
evaluation. Filesystem WASM resolution fails closed unless an expected engine
hash is supplied, and both filesystem and classpath modes require metadata with
`engineBuildHash`, `gasVersion`, `executionProfile`, and `abiManifestHash`.
Classpath-bundled WASM is self-pinned by generated metadata. For packaging,
generate classpath resources with:

```bash
./gradlew :quickjs-chicory:jar -PblueQuickJsRoot=../blue-quickjs
```

Applications can use classpath-pinned WASM resources and inject the runtime
without adding Chicory to the Java 8 core:

```java
import blue.contract.processor.BlueDocumentProcessorOptions;
import blue.contract.processor.BlueDocumentProcessors;
import blue.contract.processor.conversation.javascript.JavaScriptRuntime;
import blue.contract.processor.conversation.javascript.chicory.ChicoryBlueQuickJsRuntime;

JavaScriptRuntime runtime = ChicoryBlueQuickJsRuntime.fromClasspathDefaults();

BlueDocumentProcessors.registerWith(
blue,
BlueDocumentProcessorOptions.builder()
.javaScriptRuntime(runtime)
.build());
```

Filesystem WASM resources are also supported, but must be explicitly pinned by
engine hash and must include the same metadata fields:

```java
import blue.contract.processor.conversation.javascript.JavaScriptRuntime;
import blue.contract.processor.conversation.javascript.chicory.BlueQuickJsWasmRuntimeConfig;
import blue.contract.processor.conversation.javascript.chicory.ChicoryBlueQuickJsRuntime;
import java.nio.file.Paths;

JavaScriptRuntime runtime = new ChicoryBlueQuickJsRuntime(
BlueQuickJsWasmRuntimeConfig.builder()
.preferClasspathResources(false)
.blueQuickJsRoot(Paths.get("/opt/blue-quickjs"))
.expectedEngineBuildHash("f91091cb7feb788df340305a877a9cadb0c6f4d13aea8a7da4040b6367d178ea")
.build());
```

`NodeQuickJsRuntime` remains the compatibility fallback and parity oracle.
The generated POM for `blue-contract-java` does not depend on Chicory; users
must opt in by depending on `blue-contract-java-quickjs-chicory`.

Container/Lambda status: CI runs a no-Node classpath smoke test that evaluates
`1 + 2` through `ChicoryBlueQuickJsRuntime.fromClasspathDefaults()`, verifies gas
is charged, and checks that Node, V8, Javet, JNI, native Wasmtime, and other
native JavaScript runtime dependencies are absent from the Chicory runtime
classpath. The same smoke has also passed in Docker using the Java 11 AWS SAM
Lambda build image. A full AWS Lambda runtime/RIE invocation smoke can still be
added later if release policy requires it.

The generated `quickjs-chicory` metadata currently bridges fields that should
come from upstream blue-quickjs release metadata long term, especially
`executionProfile` and `abiManifestHash`. Java consumes and verifies those
generated fields; it must not infer gas version from documentation.

## Registration

Most applications should use the one-call facade:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ tasks.withType(JavaCompile).configureEach {
}

dependencies {
api 'blue.language:blue-language-java:1.0.0'
api 'blue.language:blue-language-java:2.0.0'
api 'blue.repo:blue-repo-java:1.2.0'

implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
Expand Down
Loading
Loading