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
40 changes: 40 additions & 0 deletions .github/workflows/javy-plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Javy plugin

# The main CI runs against the pinned wasm, which predates these changes.
on:
pull_request:
branches: [ main ]
paths: ['javy-plugin/**']

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
plugin:
name: Build the plugin and test against it
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1

- name: Build javy_quickjs4j_plugin.wasm
run: make -C javy-plugin build

- name: Set up Java
uses: actions/setup-java@v6
with:
distribution: 'temurin'
java-version: '11'
cache: maven

- name: Test quickjs4j against the locally built plugin
run: mvn -B install
42 changes: 42 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:

permissions:
contents: write
packages: write

jobs:
release:
Expand Down Expand Up @@ -43,6 +44,44 @@ jobs:
- name: Compile
run: mvn --batch-mode clean install -DskipTests

- name: Install ORAS
uses: oras-project/setup-oras@v2

# Retags the digest CI tested; no Rust toolchain needed.
- name: Publish the Javy plugin wasm under the release version
run: |
set -euo pipefail
DIGEST=$(grep -oE 'sha256:[0-9a-f]{64}' wkg.lock | head -1 || true)
if [ -z "$DIGEST" ]; then
echo "::error::No digest found in wkg.lock"
exit 1
fi
echo "Retagging $DIGEST as $VERSION"
echo "${{ secrets.GITHUB_TOKEN }}" | oras login ghcr.io -u ${{ github.actor }} --password-stdin
oras tag "ghcr.io/roastedroot/quickjs4j-javy-plugin@${DIGEST}" "$VERSION"
env:
VERSION: ${{ github.event.inputs.release-version }}

# Before "Set the version", so its `git add .` picks these up.
- name: Pin the build to the released wasm
run: |
mvn versions:set-property -Dproperty=javy-plugin.version \
-DnewVersion=${{ github.event.inputs.release-version }} -DgenerateBackupPoms=false
mvn --batch-mode generate-sources -pl core -Dinlay.update

# Jars built against a mutable tag could not be rebuilt later.
- name: Verify the Javy plugin wasm tag is immutable
run: |
set -euo pipefail
v=$(mvn help:evaluate -Dexpression=javy-plugin.version -q -DforceStdout)
echo "javy-plugin.version = $v"
case "$v" in
*SNAPSHOT*)
echo "::error::Refusing to release jars built against the mutable wasm tag '$v'"
exit 1
;;
esac

- name: Setup Git
run: |
git config --global user.name "GitHub Actions"
Expand Down Expand Up @@ -70,6 +109,9 @@ jobs:
- name: Back to Snapshot
run: |
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=999-SNAPSHOT
mvn versions:set-property -Dproperty=javy-plugin.version \
-DnewVersion=999.0.0-SNAPSHOT -DgenerateBackupPoms=false
mvn --batch-mode generate-sources -pl core -Dinlay.update
git add .
git commit -m "Snapshot version update"
git push
Expand Down
94 changes: 94 additions & 0 deletions .github/workflows/wasm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Publish javy_quickjs4j_plugin.wasm

on:
push:
branches: [main]
paths: ['javy-plugin/**']
workflow_dispatch:
inputs:
version:
description: >-
Semver tag to publish, e.g. 1.2.0. Leave the default to refresh the
development snapshot. Must be valid semver: wkg.lock rejects "latest".
required: true
default: 999.0.0-SNAPSHOT

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

# Must match javy-plugin.version in the root pom.xml.
env:
WASM_VERSION: ${{ inputs.version || '999.0.0-SNAPSHOT' }}

jobs:
build-and-publish:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- name: Checkout sources
uses: actions/checkout@v7

- name: Validate version is semver
run: |
if ! echo "$WASM_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
echo "::error::'$WASM_VERSION' is not valid semver; wkg.lock would reject it"
exit 1
fi

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1

- name: Build javy_quickjs4j_plugin.wasm
run: make -C javy-plugin build

- name: Install ORAS
uses: oras-project/setup-oras@v2

- name: Login to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | oras login ghcr.io -u ${{ github.actor }} --password-stdin

# Run from the repo root so the image title is a bare filename.
- name: Push to GHCR
run: |
oras push \
--annotation "org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}" \
ghcr.io/roastedroot/quickjs4j-javy-plugin:${WASM_VERSION} \
javy_quickjs4j_plugin.wasm:application/wasm

- name: Set up Java
uses: actions/setup-java@v6
with:
distribution: 'temurin'
java-version: '11'
cache: maven

# Every publish yields a new digest, so re-pin in the same run.
- name: Re-pin wkg.lock on main
if: github.ref == 'refs/heads/main'
run: |
set -euo pipefail

# Tests first, so a broken wasm is never pinned.
mvn -B install -Dinlay.update

if git diff --quiet -- wkg.lock; then
echo "Lock already matches the published digest."
exit 0
fi

git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add wkg.lock
git commit -m "Re-pin javy_quickjs4j_plugin.wasm"
git pull --rebase origin main
git push origin HEAD:main

- name: Summary
run: |
echo "Published \`ghcr.io/roastedroot/quickjs4j-javy-plugin:$WASM_VERSION\`." \
"Open pull requests need a rebase to pick up the re-pinned lock." >> "$GITHUB_STEP_SUMMARY"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
target
.cargo
.claude
/javy_quickjs4j_plugin.wasm
18 changes: 12 additions & 6 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,22 +235,28 @@ Key points:

To build this project, you'll need:

* A Rust toolchain
* JDK 11 or newer
* Maven

Steps:
```bash
mvn clean install
```

**No Rust toolchain needed.** The [inlay](https://github.com/roastedroot/inlay) Maven plugin downloads the [Javy](https://github.com/bytecodealliance/javy) plugin wasm from `ghcr.io/roastedroot/quickjs4j-javy-plugin`, pinned by digest in `wkg.lock`.

### Working on the Javy plugin

```bash
rustup target add wasm32-wasip1 # Only needed once

cd javy-plugin
make build
cd ..

make -C javy-plugin build # writes ./javy_quickjs4j_plugin.wasm (gitignored)
mvn clean install
```

inlay skips the download when `javy_quickjs4j_plugin.wasm` already exists, so your local build wins; delete it to go back to the published one.

Pushes to `main` touching `javy-plugin/**` publish a new snapshot and re-pin `wkg.lock` ([wasm-publish.yml](.github/workflows/wasm-publish.yml)). Releases retag the pinned digest, so every release ships an immutable wasm matching its jars. To re-pin by hand: `mvn generate-sources -pl core -Dinlay.update`.

## Acknowledgements

This project stands on the shoulders of giants:
Expand Down
23 changes: 23 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@

<build>
<plugins>
<!-- Fetches the Javy plugin wasm; skipped when the file already exists. -->
<plugin>
<groupId>io.roastedroot</groupId>
<artifactId>inlay-maven-plugin</artifactId>
<executions>
<execution>
<id>fetch-javy-plugin</id>
<goals>
<goal>fetch</goal>
</goals>
<phase>initialize</phase>
<configuration>
<modules>
<module>
<imageRef>ghcr.io/roastedroot/quickjs4j-javy-plugin:${javy-plugin.version}</imageRef>
<outputFile>${project.basedir}/../javy_quickjs4j_plugin.wasm</outputFile>
</module>
</modules>
<lockFile>${project.basedir}/../wkg.lock</lockFile>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Loading
Loading