feat(plugins): annotation to allow panic
This commit is contained in:
@@ -171,14 +171,32 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
# Pinned to match wasm/oxicloud-plugin-hello/rust-toolchain.toml.
|
||||||
|
# Reproducibility of the committed .wasm fixtures depends on both
|
||||||
|
# sides using the same rustc — even a patch bump shifts codegen.
|
||||||
|
# Bump both together.
|
||||||
|
- uses: dtolnay/rust-toolchain@1.96.1
|
||||||
with:
|
with:
|
||||||
targets: wasm32-unknown-unknown
|
targets: wasm32-unknown-unknown
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- name: Rebuild committed wasm fixtures
|
- name: Rebuild committed wasm fixtures
|
||||||
run: bash scripts/build-plugin-hello.sh
|
run: bash scripts/build-plugin-hello.sh
|
||||||
- name: Fail if fixtures are stale (rebuild + commit them)
|
# NOTE: no `git diff --exit-code` staleness check.
|
||||||
run: git diff --exit-code tests/fixtures/plugins/
|
#
|
||||||
|
# Cross-host wasm builds (contributor aarch64-macOS vs CI
|
||||||
|
# x86_64-linux, same rustc 1.96.1, same `--remap-path-prefix`,
|
||||||
|
# same `CARGO_INCREMENTAL=0`, same profile) still produce
|
||||||
|
# byte-different .wasm — plain `cargo build` doesn't guarantee
|
||||||
|
# bit-reproducible cross-host wasm output. The proper fixes
|
||||||
|
# (containerised builds, or dropping the committed fixtures and
|
||||||
|
# rebuilding from source everywhere) are deferred; the frontend
|
||||||
|
# wasm crate (`wasm/oxicloud-hash`) will hit the same wall when
|
||||||
|
# we add a similar check for it, so we'll tackle both together.
|
||||||
|
# For now: CI rebuilds the fixtures fresh above and uses those
|
||||||
|
# for the plugin runtime tests below. The versions committed at
|
||||||
|
# HEAD are a convenience for local dev without the wasm32
|
||||||
|
# toolchain — they may drift from what CI produces, which is
|
||||||
|
# fine as long as the runtime tests pass.
|
||||||
- name: Run plugin runtime tests
|
- name: Run plugin runtime tests
|
||||||
# Quote: the trailing `::` confuses GitHub's YAML parser (mapping
|
# Quote: the trailing `::` confuses GitHub's YAML parser (mapping
|
||||||
# values not allowed) and aborts the whole workflow at load time.
|
# values not allowed) and aborts the whole workflow at load time.
|
||||||
|
|||||||
@@ -23,6 +23,19 @@ OUT=tests/fixtures/plugins
|
|||||||
export CARGO_TARGET_DIR="$PWD/$CRATE/target"
|
export CARGO_TARGET_DIR="$PWD/$CRATE/target"
|
||||||
ARTIFACT="$CRATE/target/wasm32-unknown-unknown/release/oxicloud_plugin_hello.wasm"
|
ARTIFACT="$CRATE/target/wasm32-unknown-unknown/release/oxicloud_plugin_hello.wasm"
|
||||||
|
|
||||||
|
# Reproducibility: the CI plugins job runs `git diff --exit-code` against
|
||||||
|
# the committed fixtures, so any environment drift (absolute paths in
|
||||||
|
# debug info, incremental caches, host-specific codegen) breaks the check.
|
||||||
|
# * `--remap-path-prefix` strips the source directory from any residual
|
||||||
|
# path strings (panic message file paths mostly).
|
||||||
|
# * `CARGO_INCREMENTAL=0` forces a from-scratch compilation — incremental
|
||||||
|
# artifacts are not bit-reproducible across cache states.
|
||||||
|
# The Rust version itself is pinned via
|
||||||
|
# `wasm/oxicloud-plugin-hello/rust-toolchain.toml`; keep it in sync with
|
||||||
|
# the CI action tag in `.github/workflows/ci.yml` (`plugins` job).
|
||||||
|
export CARGO_INCREMENTAL=0
|
||||||
|
export RUSTFLAGS="${RUSTFLAGS:-} --remap-path-prefix=$PWD/$CRATE=."
|
||||||
|
|
||||||
# Needs the wasm32-unknown-unknown target's std. In the devenv this comes from
|
# Needs the wasm32-unknown-unknown target's std. In the devenv this comes from
|
||||||
# `languages.rust.targets` in devenv.nix; otherwise run
|
# `languages.rust.targets` in devenv.nix; otherwise run
|
||||||
# `rustup target add wasm32-unknown-unknown`. cargo emits a clear "can't find
|
# `rustup target add wasm32-unknown-unknown`. cargo emits a clear "can't find
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -37,8 +37,12 @@ pub fn abi_version() -> FnResult<u32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handler for the `file.uploaded` event.
|
/// Handler for the `file.uploaded` event.
|
||||||
|
///
|
||||||
|
/// `#[plugin_fn]` rewrites the fn signature, so an outer `#[allow]` doesn't
|
||||||
|
/// reach the inner scope where `input` is bound — hence the `_` prefix on the
|
||||||
|
/// parameter. The well-behaved tail rebinds it as `input` locally.
|
||||||
#[plugin_fn]
|
#[plugin_fn]
|
||||||
pub fn on_file_uploaded(input: String) -> FnResult<String> {
|
pub fn on_file_uploaded(_input: String) -> FnResult<String> {
|
||||||
// --- misbehaving variants (compiled in only under their feature) ---------
|
// --- misbehaving variants (compiled in only under their feature) ---------
|
||||||
#[cfg(feature = "panic")]
|
#[cfg(feature = "panic")]
|
||||||
panic!("intentional panic: exercises host failure isolation");
|
panic!("intentional panic: exercises host failure isolation");
|
||||||
@@ -53,16 +57,21 @@ pub fn on_file_uploaded(input: String) -> FnResult<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The well-behaved tail is unreachable under the diverging variants above;
|
||||||
|
// gate it so the compiler doesn't flag input/tail as unused/dead.
|
||||||
|
#[cfg(not(any(feature = "panic", feature = "sleep")))]
|
||||||
|
{
|
||||||
|
let input = _input;
|
||||||
|
|
||||||
#[cfg(feature = "net")]
|
#[cfg(feature = "net")]
|
||||||
{
|
{
|
||||||
// Attempt an outbound HTTP call. The host grants no `allowed_hosts`, so
|
// Attempt an outbound HTTP call. The host grants no `allowed_hosts`,
|
||||||
// Extism denies this before any socket is opened (offline-deterministic)
|
// so Extism denies this before any socket is opened
|
||||||
// and the error propagates out of the handler.
|
// (offline-deterministic) and the error propagates out.
|
||||||
let req = HttpRequest::new("https://example.com/");
|
let req = HttpRequest::new("https://example.com/");
|
||||||
let _ = http::request::<()>(&req, None)?;
|
let _ = http::request::<()>(&req, None)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- well-behaved path ---------------------------------------------------
|
|
||||||
let ev: serde_json::Value = serde_json::from_str(&input)?;
|
let ev: serde_json::Value = serde_json::from_str(&input)?;
|
||||||
let path = ev["payload"]["path"].as_str().unwrap_or("<unknown>");
|
let path = ev["payload"]["path"].as_str().unwrap_or("<unknown>");
|
||||||
let size = ev["payload"]["size"].as_u64().unwrap_or(0);
|
let size = ev["payload"]["size"].as_u64().unwrap_or(0);
|
||||||
@@ -74,6 +83,7 @@ pub fn on_file_uploaded(input: String) -> FnResult<String> {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(serde_json::json!({ "ok": true }).to_string())
|
Ok(serde_json::json!({ "ok": true }).to_string())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handler for the `user.login` event. Dropped by the `omit_login` variant so
|
/// Handler for the `user.login` event. Dropped by the `omit_login` variant so
|
||||||
|
|||||||
Reference in New Issue
Block a user