diff --git a/.github/actions/build-adapter-provider/action.yml b/.github/actions/build-adapter-provider/action.yml new file mode 100644 index 000000000000..60b9d08a37a0 --- /dev/null +++ b/.github/actions/build-adapter-provider/action.yml @@ -0,0 +1,25 @@ +name: 'Build wasi component adapter provider' +description: 'Build the wasi-preview1-component-adapter provider using the adapter artefacts' + +inputs: + run-id: + description: 'run id of the main.yml action that produced the adapter artefacts' + required: true + +runs: + using: composite + steps: + - uses: actions/download-artifact@v4 + with: + name: bins-wasi-preview1-component-adapter + path: crates/wasi-preview1-component-adapter/provider/artefacts + github-token: ${{ github.token }} + run-id: ${{ inputs.run-id }} + + - name: Install required Rust components + shell: bash + run: rustup component add rustfmt clippy + + - name: Build and checl the adapter provider + shell: bash + run: ./ci/build-wasi-preview1-component-adapter-provider.sh diff --git a/.github/actions/fetch-run-id/action.yml b/.github/actions/fetch-run-id/action.yml new file mode 100644 index 000000000000..614f2e37c64a --- /dev/null +++ b/.github/actions/fetch-run-id/action.yml @@ -0,0 +1,18 @@ +name: 'Fetch run id for commit' +description: 'Fetch the main.yml run id for the current commit' + +runs: + using: composite + steps: + - name: Fetch run id + shell: bash + run: | + run_id=$( + gh api -H 'Accept: application/vnd.github+json' \ + /repos/${{ github.repository }}/actions/workflows/main.yml/runs\?exclude_pull_requests=true \ + | jq '.workflow_runs' \ + | jq "map(select(.head_commit.id == \"${{ github.sha }}\"))[0].id" \ + ) + echo COMMIT_RUN_ID=${run_id} >> "$GITHUB_ENV" + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 83f915183cb3..e8181b121abd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -811,6 +811,26 @@ jobs: path: target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.*.wasm + # common logic to cancel the entire run if this job fails + - run: gh run cancel ${{ github.run_id }} + if: failure() && github.event_name != 'pull_request' + env: + GH_TOKEN: ${{ github.token }} + + build-preview1-component-adapter-provider: + name: Build wasi-preview1-component-adapter-provider + needs: build-preview1-component-adapter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/actions/install-rust + - uses: ./.github/actions/build-adapter-provider + with: + run-id: ${{ github.run_id }} + + # common logic to cancel the entire run if this job fails - run: gh run cancel ${{ github.run_id }} if: failure() && github.event_name != 'pull_request' @@ -1078,6 +1098,7 @@ jobs: - determine - miri - build-preview1-component-adapter + - build-preview1-component-adapter-provider - build-wasmtime-target-wasm32 - test-min-platform-example - check_js diff --git a/.github/workflows/publish-artifacts.yml b/.github/workflows/publish-artifacts.yml index 9ef7e2bcb492..4a108ff083a4 100644 --- a/.github/workflows/publish-artifacts.yml +++ b/.github/workflows/publish-artifacts.yml @@ -14,15 +14,9 @@ jobs: if: github.repository == 'bytecodealliance/wasmtime' steps: - uses: actions/checkout@v4 + - uses: ./.github/actions/fetch-run-id - run: | - sha=${{ github.sha }} - run_id=$( - gh api -H 'Accept: application/vnd.github+json' \ - /repos/${{ github.repository }}/actions/workflows/main.yml/runs\?exclude_pull_requests=true \ - | jq '.workflow_runs' \ - | jq "map(select(.head_commit.id == \"$sha\"))[0].id" \ - ) - gh run download $run_id + gh run download ${COMMIT_RUN_ID} ls find bins-* env: diff --git a/.github/workflows/publish-to-cratesio.yml b/.github/workflows/publish-to-cratesio.yml index 23af15a85785..46d3611a3fe6 100644 --- a/.github/workflows/publish-to-cratesio.yml +++ b/.github/workflows/publish-to-cratesio.yml @@ -23,3 +23,12 @@ jobs: ./publish publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + # Manifest and publish the wasi-preview1-component-adapter-provider + - uses: ./.github/actions/fetch-run-id + - uses: ./.github/actions/build-adapter-provider + with: + run-id: ${{ env.COMMIT_RUN_ID }} + - run: cargo publish -p wasi-preview1-component-adapter-provider --allow-dirty + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/ci/build-wasi-preview1-component-adapter-provider.sh b/ci/build-wasi-preview1-component-adapter-provider.sh new file mode 100755 index 000000000000..c8c2bf4d2086 --- /dev/null +++ b/ci/build-wasi-preview1-component-adapter-provider.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -ex + +# Manifest the adapter provider into the workspace +cp crates/wasi-preview1-component-adapter/provider/Cargo.toml.in crates/wasi-preview1-component-adapter/provider/Cargo.toml +sed -i '/"crates\/wasi-preview1-component-adapter",/a\ \ "crates\/wasi-preview1-component-adapter\/provider",' Cargo.toml + +# Check the adapter provider's code formatting and style +cargo fmt -p wasi-preview1-component-adapter-provider -- --check +cargo check -p wasi-preview1-component-adapter-provider +cargo clippy -p wasi-preview1-component-adapter-provider + +# Check that publishing the adapter provider should work +cargo publish -p wasi-preview1-component-adapter-provider --dry-run --allow-dirty diff --git a/ci/build-wasi-preview1-component-adapter.sh b/ci/build-wasi-preview1-component-adapter.sh index 76dcbc1c167e..545a4e06f389 100755 --- a/ci/build-wasi-preview1-component-adapter.sh +++ b/ci/build-wasi-preview1-component-adapter.sh @@ -15,24 +15,28 @@ release="target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.wasm" $build_adapter $verify $debug +build() { + input=$1 + flavor=$2 + $verify $input + name=wasi_snapshot_preview1.$flavor.wasm + dst=$(dirname $input)/$name + wasm-tools metadata add --name "wasi_preview1_component_adapter.$flavor.adapter" $input \ + -o $dst +} + # Debug build, command $build_adapter --no-default-features --features command $verify $debug # Release build, command $build_adapter --release --no-default-features --features command -$verify $release -wasm-tools metadata add --name "wasi_preview1_component_adapter.command.adapter:${VERSION}" $release \ - -o target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.command.wasm +build $release command # Release build, default features (reactor) $build_adapter --release -$verify $release -wasm-tools metadata add --name "wasi_preview1_component_adapter.reactor.adapter:${VERSION}" $release \ - -o target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.reactor.wasm +build $release reactor # Release build, proxy $build_adapter --release --no-default-features --features proxy -$verify $release -wasm-tools metadata add --name "wasi_preview1_component_adapter.proxy.adapter:${VERSION}" $release \ - -o target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.proxy.wasm +build $release proxy diff --git a/crates/wasi-preview1-component-adapter/provider/.gitignore b/crates/wasi-preview1-component-adapter/provider/.gitignore new file mode 100644 index 000000000000..1ae47fad85cd --- /dev/null +++ b/crates/wasi-preview1-component-adapter/provider/.gitignore @@ -0,0 +1 @@ +/Cargo.toml diff --git a/crates/wasi-preview1-component-adapter/provider/Cargo.toml.in b/crates/wasi-preview1-component-adapter/provider/Cargo.toml.in new file mode 100644 index 000000000000..9f0ea47c7301 --- /dev/null +++ b/crates/wasi-preview1-component-adapter/provider/Cargo.toml.in @@ -0,0 +1,19 @@ +[package] +name = "wasi-preview1-component-adapter-provider" +version.workspace = true +authors.workspace = true +description = "Embedded wasi-preview1-component-adapter binaries" +license = "Apache-2.0 WITH LLVM-exception" +repository = "https://github.com/bytecodealliance/wasmtime" +documentation = "https://docs.rs/wasi-preview1-component-adapter-provider/" +categories = ["wasm"] +keywords = ["webassembly", "wasm"] +edition.workspace = true + +[lints] +workspace = true + +[package.metadata.docs.rs] +all-features = true + +[dependencies] diff --git a/crates/wasi-preview1-component-adapter/provider/artefacts/.gitignore b/crates/wasi-preview1-component-adapter/provider/artefacts/.gitignore new file mode 100644 index 000000000000..46be8eadbf31 --- /dev/null +++ b/crates/wasi-preview1-component-adapter/provider/artefacts/.gitignore @@ -0,0 +1,3 @@ +/wasi_snapshot_preview1.reactor.wasm +/wasi_snapshot_preview1.command.wasm +/wasi_snapshot_preview1.proxy.wasm diff --git a/crates/wasi-preview1-component-adapter/provider/src/lib.rs b/crates/wasi-preview1-component-adapter/provider/src/lib.rs new file mode 100644 index 000000000000..0783c93bdb42 --- /dev/null +++ b/crates/wasi-preview1-component-adapter/provider/src/lib.rs @@ -0,0 +1,51 @@ +//! This crate contains the binaries of three WebAssembly modules: +//! +//! - [`WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER`] +//! - [`WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER`] +//! - [`WASI_SNAPSHOT_PREVIEW1_PROXY_ADAPTER`] +//! +//! These three modules bridge the wasip1 ABI to the wasip2 ABI of the component +//! model. +//! +//! They can be given to the [`wit_component::ComponentEncoder::adapter`] +//! method, using the [`WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME`], to translate a +//! module from the historical WASM ABI to the canonical ABI. +//! +//! [`wit_component::ComponentEncoder::adapter`]: https://docs.rs/wit-component/latest/wit_component/struct.ComponentEncoder.html#method.adapter + +/// The name of the adapters in this crate, which may be provided to +/// [`wit_component::ComponentEncoder::adapter`]. +/// +/// [`wit_component::ComponentEncoder::adapter`]: https://docs.rs/wit-component/latest/wit_component/struct.ComponentEncoder.html#method.adapter +pub const WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME: &str = "wasi_snapshot_preview1"; + +/// The "reactor" adapter provides the default adaptation from preview1 to +/// preview2. +/// +/// This adapter implements the [`wasi:cli/imports`] world. +/// +/// [`wasi:cli/imports`]: https://github.com/WebAssembly/WASI/blob/01bb90d8b66cbc1d50349aaaab9ac5b143c9c98c/preview2/cli/imports.wit +pub const WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER: &[u8] = + include_bytes!("../artefacts/wasi_snapshot_preview1.reactor.wasm"); + +/// The "command" adapter extends the ["reactor" adapter] and additionally +/// exports a `run` function entrypoint. +/// +/// This adapter implements the [`wasi:cli/command`] world. +/// +/// ["reactor" adapter]: WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER +/// [`wasi:cli/command`]: https://github.com/WebAssembly/WASI/blob/01bb90d8b66cbc1d50349aaaab9ac5b143c9c98c/preview2/cli/command.wit +pub const WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER: &[u8] = + include_bytes!("../artefacts/wasi_snapshot_preview1.command.wasm"); + +/// The "proxy" adapter provides implements a HTTP proxy which is more +/// restricted than the ["reactor" adapter] adapter, as it lacks filesystem, +/// socket, environment, exit, and terminal support, but includes HTTP handlers +/// for incoming and outgoing requests. +/// +/// This adapter implements the [`wasi:http/proxy`] world. +/// +/// ["reactor" adapter]: WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER +/// [`wasi:http/proxy`]: https://github.com/WebAssembly/WASI/blob/01bb90d8b66cbc1d50349aaaab9ac5b143c9c98c/preview2/http/proxy.wit +pub const WASI_SNAPSHOT_PREVIEW1_PROXY_ADAPTER: &[u8] = + include_bytes!("../artefacts/wasi_snapshot_preview1.proxy.wasm");