feat(plugins): annotation to allow panic
This commit is contained in:
@@ -171,14 +171,32 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- 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:
|
||||
targets: wasm32-unknown-unknown
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Rebuild committed wasm fixtures
|
||||
run: bash scripts/build-plugin-hello.sh
|
||||
- name: Fail if fixtures are stale (rebuild + commit them)
|
||||
run: git diff --exit-code tests/fixtures/plugins/
|
||||
# NOTE: no `git diff --exit-code` staleness check.
|
||||
#
|
||||
# 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
|
||||
# Quote: the trailing `::` confuses GitHub's YAML parser (mapping
|
||||
# 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"
|
||||
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
|
||||
# `languages.rust.targets` in devenv.nix; otherwise run
|
||||
# `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.
|
||||
///
|
||||
/// `#[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]
|
||||
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) ---------
|
||||
#[cfg(feature = "panic")]
|
||||
panic!("intentional panic: exercises host failure isolation");
|
||||
@@ -53,27 +57,33 @@ pub fn on_file_uploaded(input: String) -> FnResult<String> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
// 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")))]
|
||||
{
|
||||
// Attempt an outbound HTTP call. The host grants no `allowed_hosts`, so
|
||||
// Extism denies this before any socket is opened (offline-deterministic)
|
||||
// and the error propagates out of the handler.
|
||||
let req = HttpRequest::new("https://example.com/");
|
||||
let _ = http::request::<()>(&req, None)?;
|
||||
}
|
||||
let input = _input;
|
||||
|
||||
// --- well-behaved path ---------------------------------------------------
|
||||
let ev: serde_json::Value = serde_json::from_str(&input)?;
|
||||
let path = ev["payload"]["path"].as_str().unwrap_or("<unknown>");
|
||||
let size = ev["payload"]["size"].as_u64().unwrap_or(0);
|
||||
#[cfg(feature = "net")]
|
||||
{
|
||||
// Attempt an outbound HTTP call. The host grants no `allowed_hosts`,
|
||||
// so Extism denies this before any socket is opened
|
||||
// (offline-deterministic) and the error propagates out.
|
||||
let req = HttpRequest::new("https://example.com/");
|
||||
let _ = http::request::<()>(&req, None)?;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
log(
|
||||
"info".to_string(),
|
||||
format!("hello plugin saw upload: {path} ({size} bytes)"),
|
||||
)?;
|
||||
let ev: serde_json::Value = serde_json::from_str(&input)?;
|
||||
let path = ev["payload"]["path"].as_str().unwrap_or("<unknown>");
|
||||
let size = ev["payload"]["size"].as_u64().unwrap_or(0);
|
||||
|
||||
unsafe {
|
||||
log(
|
||||
"info".to_string(),
|
||||
format!("hello plugin saw upload: {path} ({size} bytes)"),
|
||||
)?;
|
||||
}
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user