Fetch and verify WebAssembly modules from OCI registries for the JVM.
<build>
<plugins>
<plugin>
<groupId>io.roastedroot</groupId>
<artifactId>inlay-maven-plugin</artifactId>
<version>${inlay.version}</version>
<executions>
<execution>
<goals><goal>fetch</goal></goals>
<configuration>
<modules>
<module>
<imageRef>ghcr.io/roastedroot/sqlite4j-wasm:3.51.0</imageRef>
<outputFile>${project.build.directory}/wasm/libsqlite3.wasm</outputFile>
</module>
</modules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>run.endive</groupId>
<artifactId>endive-compiler-maven-plugin</artifactId>
<version>${endive.version}</version>
<executions>
<execution>
<goals><goal>compile</goal></goals>
<configuration>
<wasmFile>${project.build.directory}/wasm/libsqlite3.wasm</wasmFile>
<name>com.example.SqliteModule</name>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>See examples/basic/.
Fetched artifacts are cached in ~/.cache/inlay/ (or $XDG_CACHE_HOME/inlay/), keyed by OCI digest. Survives mvn clean.
| Flag | Behavior |
|---|---|
| (default) | Cache hit → no network |
-Dinlay.update |
Re-resolves digest, updates lock file |
-Dinlay.noCache |
Always pulls from registry |
-Dinlay.skip |
Skips fetch entirely |
inlay:fetch writes wkg.lock using the wkg format (Rust wasm-pkg-common types compiled to wasm). Commit it for reproducible builds.
If the registry digest changes but the lock hasn't been updated, the build fails.
mvn io.roastedroot:inlay-maven-plugin:fetch -Dinlay.updateWhen iterating on a wasm module locally, you can avoid re-fetching from the registry:
Option A — outputFile outside target/: set outputFile to a path that mvn clean won't delete. Once the lock entry exists and the file is on disk, the plugin skips fetching:
<module>
<imageRef>ghcr.io/roastedroot/my-module-wasm:1.0.0</imageRef>
<outputFile>${project.basedir}/src/main/resources/wasm/my-module.wasm</outputFile>
</module>Rebuild your wasm locally and overwrite that file — the plugin will not touch it.
Option B — skip the fetch entirely:
mvn compile -Dinlay.skipUseful when you manage the wasm file yourself and don't need the plugin at all during local builds.
Resolved in order:
- Maven
settings.xml<server>entries keyed by registry hostname - Docker/Podman credential stores (
~/.docker/config.json)
For local dev: oras login ghcr.io or docker login ghcr.io. For CI:
<server>
<id>ghcr.io</id>
<username>${env.GHCR_USER}</username>
<password>${env.GHCR_TOKEN}</password>
</server>Use wkg-style names instead of full OCI refs. Namespaces resolve via ~/.config/wasm-pkg/config.toml:
<module>
<packageRef>roastedroot:sqlite4j-wasm@3.51.0</packageRef>
</module>Builtins: wasi:* → wasi.dev, ba:* → bytecodealliance.org.
Verification runs inline after fetch — no separate step. Configure on each module:
<module>
<imageRef>ghcr.io/roastedroot/sqlite4j-wasm:3.51.0</imageRef>
<outputFile>${project.build.directory}/wasm/libsqlite3.wasm</outputFile>
<sigstoreIssuer>https://token.actions.githubusercontent.com</sigstoreIssuer>
<sigstoreIdentity>https://github.com/roastedroot/*</sigstoreIdentity>
</module>Uses sigstore-java keyless verification. Expects a .sigstore.json bundle alongside the artifact.
Requires oras CLI and optionally cosign. Packages appear at https://github.com/orgs/<org>/packages — set visibility to public after first push.
echo $GHCR_TOKEN | oras login ghcr.io -u $GHCR_USER --password-stdin
oras push ghcr.io/roastedroot/sqlite4j-wasm:3.51.0 \
libsqlite3.wasm:application/wasm
cosign sign --yes ghcr.io/roastedroot/sqlite4j-wasm:3.51.0Use the reusable workflow included in this repo:
name: Publish Wasm
on:
push:
paths: ['wasm-build/**']
branches: [main]
permissions:
contents: read
packages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./wasm-build/build.sh
publish:
needs: build
uses: roastedroot/inlay/.github/workflows/wasm-publish.yml@main
with:
wasm-file: wasm-build/output/my-module.wasm
image-ref: ghcr.io/roastedroot/my-module-wasm
version: '1.0.0'jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: 'maven'
- run: mvn verifyNo wasm build step, no Docker, no Rust. inlay:fetch pulls from GHCR during generate-sources.
Requires JDK 17+ and Rust with wasm32-wasip1 target. Docker for integration tests.
cd wkg-wasm && make build
mvn install # unit tests
mvn verify # unit + integration tests (Docker required)See CONTRIBUTING.md for architecture and development details.