Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ jobs:
# job.
- name: Zero leak
run: ./scripts/zero-leak.sh
- name: MSRV
run: ./scripts/msrv-lint.sh

fmt:
name: rustfmt
Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ The videre and shepherd repositories build on the SDK and the runtime published
## Build, test, lint

The workspace uses Rust edition 2024.
The flake pins the toolchain to Rust 1.94.0, which matches the toolchain CI installs.
The flake pins the toolchain to Rust 1.94.0, which matches the toolchain CI installs and the `rust-version` every crate inherits.
`just msrv` proves the three have not drifted, and holds the licence to one inherited SPDX identifier.
Run `nix develop` to enter the dev shell, or run `direnv allow` once.
The dev shell supplies the toolchain, the `wasm32-wasip2` target, `cargo-nextest`, `just`, `ripgrep`, and `ast-grep`.

Expand Down
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ members = [
"modules/fixtures/slow-host",
"modules/fixtures/topic-parity",
]
resolver = "2"
# A virtual manifest has no edition, so an absent key means resolver 1.
resolver = "3"

[workspace.package]
version = "0.1.0"
edition = "2024"
license = "AGPL-3.0"
license = "AGPL-3.0-or-later"
rust-version = "1.94.0"
repository = "https://github.com/nullislabs/nexum-runtime"

# Shared dependency table. Every external dependency is hoisted here.
Expand Down Expand Up @@ -217,6 +219,7 @@ todo = "deny"
unwrap_used = "deny"
expect_used = "warn"

# Cargo forces unwind on test and bench regardless, so `#[should_panic]` works.
[profile.dev]
panic = "abort"

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ Against a compromised artifact store, supply an operator-owned manifest from out

## Licence

AGPL-3.0. See [LICENSE](LICENSE).
AGPL-3.0-or-later. See [LICENSE](LICENSE).
1 change: 1 addition & 0 deletions crates/nexum-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-cli"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

Expand Down
1 change: 1 addition & 0 deletions crates/nexum-launch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-launch"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

Expand Down
1 change: 1 addition & 0 deletions crates/nexum-module-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-module-macros"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Proc-macro glue for nexum runtime modules: #[module] emits the per-cdylib wit-bindgen, host adapter, event dispatch, and export."
Expand Down
1 change: 1 addition & 0 deletions crates/nexum-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-runtime"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

Expand Down
1 change: 1 addition & 0 deletions crates/nexum-sdk-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-sdk-test"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "In-memory host mocks for nexum module unit tests. Implements nexum_sdk::host::{ChainHost, LocalStoreHost, LoggingHost}."
Expand Down
1 change: 1 addition & 0 deletions crates/nexum-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-sdk"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Guest-side SDK for nexum runtime modules: host-neutral helpers usable by any module, independent of the CoW domain layer."
Expand Down
1 change: 1 addition & 0 deletions crates/nexum-tasks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-tasks"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Task lifecycle and graceful shutdown for the Nexum runtime"
Expand Down
1 change: 1 addition & 0 deletions crates/nexum-world/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "nexum-world"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Per-module WIT world synthesis: the core capability table, registry-driven extension rows, manifest parsing, and crate-local WIT package resolution."
Expand Down
3 changes: 2 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

inherit (pkgs) lib stdenv;

# Pinned to match CI exactly (.github/workflows/ci.yml uses "1.94").
# scripts/msrv-lint.sh holds this, Cargo.toml and the rust-setup
# action on one version.
# Develop with `nix develop` so the local toolchain matches CI/CD.
rustToolchain = pkgs.rust-bin.stable."1.94.0".default.override {
extensions = [ "rust-src" "rust-analyzer" "clippy" "rustfmt" ];
Expand Down
12 changes: 8 additions & 4 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,20 @@ content range="main..HEAD":
zero-leak:
./scripts/zero-leak.sh

msrv:
./scripts/msrv-lint.sh

# Check the workspace quickly.
check:
cargo check --target wasm32-wasip2 -p example
cargo check -p nexum-runtime
cargo check -p nexum-cli

# Run the full CI series locally before pushing. Mirrors
# .github/workflows/ci.yml one-to-one: house style, the zero-leak gate,
# rustfmt, clippy, rustdoc, the module wasms the integration tests need, and
# the workspace test suite via nextest plus the doctests, all under the
# `-D warnings` the CI workflow sets globally.
# .github/workflows/ci.yml one-to-one: house style, the zero-leak gate, the
# MSRV gate, rustfmt, clippy, rustdoc, the module wasms the integration tests
# need, and the workspace test suite via nextest plus the doctests, all under
# the `-D warnings` the CI workflow sets globally.
ci:
#!/usr/bin/env bash
set -euo pipefail
Expand All @@ -73,6 +76,7 @@ ci:
export RUSTDOCFLAGS="${RUSTDOCFLAGS:-} -D warnings"
./scripts/content-lint.sh "main..HEAD"
./scripts/zero-leak.sh
./scripts/msrv-lint.sh
cargo fmt --all --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo doc --workspace --all-features --no-deps
Expand Down
1 change: 1 addition & 0 deletions modules/example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "example"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

Expand Down
1 change: 1 addition & 0 deletions modules/examples/balance-tracker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "balance-tracker"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Example module: tracks native-token balances of a list of addresses and emits a log when one changes by more than a threshold. Demonstrates chain::request + local-store + multi-key persistence."
Expand Down
1 change: 1 addition & 0 deletions modules/examples/http-probe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "http-probe"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Example module: fetches an allowlisted URL over wasi:http on every block and verifies the off-list path is denied."
Expand Down
1 change: 1 addition & 0 deletions modules/examples/price-alert/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "price-alert"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Example module: polls a Chainlink price oracle every block and emits a Warn log when the price crosses a config-supplied threshold."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/clock-reader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "clock-reader"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Test fixture: on every event reads the WASI wall clock through std and logs it. Lets a test assert the guest observes a WasiClockOverride end to end."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/env-reader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "env-reader"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Test fixture: on every event counts the guest-visible environment variables, process arguments, and stdin bytes through std and logs all three. Lets a test assert the guest observes an empty wasi:cli/environment and an empty wasi:cli/stdin end to end."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/flaky-bomb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "flaky-bomb"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Evil-by-design fixture: traps on the first N events (via unreachable!) and succeeds afterwards. The supervisor must exercise its exponential-backoff restart policy + reset the failure counter when the module recovers."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/fuel-bomb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "fuel-bomb"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Evil-by-design fixture: on every event runs an unbounded loop to exhaust the wasmtime fuel budget. Engine must trap with OutOfFuel + mark the module dead."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/memory-bomb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "memory-bomb"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Evil-by-design fixture: on every event allocates past the 64 MiB memory cap to force a memory-growth trap. Engine must trap + mark the module dead without taking down the supervisor."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/panic-bomb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "panic-bomb"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Evil-by-design fixture: installs the nexum-sdk tracing facade in init and panics on every event. One death must leave Stderr, HostInterface, and Panic records on the run."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/slow-host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "slow-host"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Evil-by-design fixture: on_event issues a single chain::request host call that the test wires to a mock provider which parks the request far past the dispatch deadline. Proves the supervisor cuts off a blocked host call and recovers on a fresh store, which fuel and epoch metering cannot do."
Expand Down
1 change: 1 addition & 0 deletions modules/fixtures/topic-parity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "topic-parity"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

Expand Down
72 changes: 72 additions & 0 deletions scripts/msrv-lint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env bash
# Three files state the toolchain version independently and none of them is
# compiled, so any one can drift without an error: Cargo.toml, the flake pin,
# and the CI action input. The action names two components, which rustup
# resolves to the newest patch, so it is compared on major.minor.
#
# The licence rides along because cargo performs no SPDX validation at all:
# `cargo publish --dry-run` packages and compiles a member licensed
# `NOT-A-REAL-LICENCE` and exits 0.

set -euo pipefail

root=$(git rev-parse --show-toplevel)
cd "$root"

status=0
fail() {
printf ' %s\n' "$1" >&2
status=1
}

MANIFEST=Cargo.toml
FLAKE=flake.nix
ACTION=.github/actions/rust-setup/action.yml

# `|| true`: a missing key must reach the report, not die on grep's exit status.
msrv=$(grep -oE '^rust-version = "[0-9.]+"' "$MANIFEST" | sed -e 's/.*"\(.*\)"/\1/' || true)
flake=$(grep -oE 'rust-bin\.stable\."[0-9.]+"' "$FLAKE" | sed -e 's/.*"\(.*\)"/\1/' || true)
action=$(grep -oE 'toolchain: "[0-9.]+"' "$ACTION" | sed -e 's/.*"\(.*\)"/\1/' || true)

echo "msrv-lint: $MANIFEST $msrv, $FLAKE $flake, $ACTION $action"

for pair in "$MANIFEST:$msrv" "$FLAKE:$flake" "$ACTION:$action"; do
if [ -z "${pair#*:}" ]; then
fail "${pair%%:*} states no Rust version, or states it in a form this check cannot read"
fi
done

if [ "$status" -eq 0 ]; then
if [ "$msrv" != "$flake" ]; then
fail "$MANIFEST rust-version $msrv does not match the $FLAKE pin $flake"
fi
if [ "$(cut -d. -f1,2 <<<"$action")" != "$(cut -d. -f1,2 <<<"$flake")" ]; then
fail "$ACTION toolchain $action does not match the $FLAKE pin $flake"
fi
fi

# Matched by shape, not against this workspace's choice, so a licence change
# needs no edit here.
license=$(grep -oE '^license = "[^"]+"' "$MANIFEST" | sed -e 's/.*"\(.*\)"/\1/' || true)
echo "msrv-lint: $MANIFEST licence $license"
if [ -z "$license" ]; then
fail "$MANIFEST states no license on [workspace.package]"
elif [[ "$license" =~ ^(AGPL|LGPL|GPL)-[0-9]+\.[0-9]+$ ]]; then
fail "$MANIFEST license $license is deprecated in the SPDX list; write $license-only or $license-or-later"
fi

echo "msrv-lint: every member inherits rust-version and license"
while read -r member; do
[ -n "$member" ] || continue
[ "$member" = "$MANIFEST" ] && continue
for key in rust-version license; do
if ! grep -qE "^$key\.workspace = true\$" "$member"; then
fail "$member does not carry $key.workspace = true"
fi
done
done < <(git ls-files '*Cargo.toml')

if [ "$status" -eq 0 ]; then
echo "msrv-lint: ok"
fi
exit "$status"
Loading