Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

inlay

Fetch and verify WebAssembly modules from OCI registries for the JVM.

Quick start

<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/.

Caching

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

Lock file

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.

Upgrading

mvn io.roastedroot:inlay-maven-plugin:fetch -Dinlay.update

Local development

When 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.skip

Useful when you manage the wasm file yourself and don't need the plugin at all during local builds.

Authentication

Resolved in order:

  1. Maven settings.xml <server> entries keyed by registry hostname
  2. 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>

Package references

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.

Signature verification

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.

Publishing wasm to OCI

Requires oras CLI and optionally cosign. Packages appear at https://github.com/orgs/<org>/packagesset 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.0

GitHub Actions — publisher

Use 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'

GitHub Actions — consumer

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 verify

No wasm build step, no Docker, no Rust. inlay:fetch pulls from GHCR during generate-sources.

Building from source

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.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages