Some checks failed
repo hygiene / hygiene (push) Has been cancelled
p2p-intel / engine (push) Has been cancelled
p2p-intel / notifications (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (push) Has been cancelled
The previous commit refused to write these two, on the grounds that code no compiler has ever seen is not an implementation -- it is plausible-looking text that would sit in the same crate as tested code and be read as equally finished. That reasoning holds. The premise behind it did not. `cargo check` needs the *target's standard library*, not a linker or a platform SDK. `rustup target add x86_64-pc-windows-msvc aarch64-apple-darwin` puts the real `windows` and `objc2` crates -- genuine WinRT metadata, genuine Objective-C class definitions -- in front of the type checker on a Linux host. So both backends are now written and both compile against the frameworks they call. Compile-checking earned its place immediately. The Windows backend was written against `ToastNotificationManager::CreateToastNotifier(&HSTRING)`, which does not exist: the AUMID overload is `CreateToastNotifierWithId`. Nothing short of a compiler holding the real metadata would have caught that, and it would have shipped looking entirely correct. Because a cfg-gated module can silently compile to nothing -- leaving a green check that proves only that the module was skipped -- each backend was verified to be genuinely reachable by injecting a type error and confirming the target build failed. Both macOS and Windows were checked this way, then restored. Two platform decisions worth recording. macOS uses NSUserNotification, not UNUserNotificationCenter, and that is a deliberate downgrade to a deprecated API. `UNUserNotificationCenter.current()` raises an Objective-C exception when the process has no bundle identifier; that unwinds through Rust frames and aborts. A plain `cargo run` host has no bundle, so the modern API would crash the caller instead of reporting unavailable -- which is worse than deprecated. The nil check on `defaultUserNotificationCenter` is there for the same reason: msg_send on nil returns zero rather than crashing, so every later call would silently do nothing, which is precisely the failure this crate exists to remove. Windows requires the host to supply an AppUserModelID, because a library cannot invent one. It comes from an MSIX manifest or a Start Menu shortcut, and a fabricated id produces a notifier that constructs happily and then fails at Show. `set_app_user_model_id` is therefore public, a no-op off Windows so portable hosts call it unconditionally, and `is_available()` is false with a reason naming exactly what is missing until it is called. Toast payloads are XML, so text is escaped -- the same bug class as the Telegram MarkdownV2 escaping p2p-intel needed before it dropped Telegram, and a merchant nickname containing `&` is not hypothetical. The support table now has two columns, "compiles" and "executed", because they are different claims. All four backends compile; only Linux has posted a notification. iOS remains unavailable by design: it needs UN* with a bundle and an entitlement, which is an app-packaging concern rather than something this crate can satisfy. Off Windows the module defines no entry points at all rather than stubs. Clippy was right to call them dead: sys/mod.rs dispatches elsewhere, so they existed only to satisfy a symmetry nothing needs. CI gains a step that clippies all four cross-targets with -D warnings, so a cfg-gated backend cannot rot unnoticed -- which is exactly how the CreateToastNotifier mistake would have survived. 51 tests, clippy clean on five targets, p2p-intel still at 225.
183 lines
7 KiB
YAML
183 lines
7 KiB
YAML
name: p2p-intel
|
|
|
|
# p2p-intel is a nested workspace (crates/apps/p2p-intel/Cargo.toml), so the
|
|
# root workspace jobs never touch it. Without this file the crate would have
|
|
# no gate at all.
|
|
#
|
|
# Measured when this job was added:
|
|
# total 97.03% of lines (floor 90)
|
|
# 223 tests, 0 failures
|
|
#
|
|
# The coverage script installs the toolchain from rust-toolchain.toml into
|
|
# its own temporary directory and deletes it on exit, so there is no
|
|
# toolchain step in the `coverage` job.
|
|
#
|
|
# Two jobs, for the same reason spreadsheet.yml has two: the engine half is
|
|
# pure Rust and finishes in about a minute, while the Makepad half has to
|
|
# build the Linux windowing backend to link. A single job would hide an
|
|
# engine regression behind a slow GPU-stack build.
|
|
|
|
on:
|
|
push:
|
|
paths:
|
|
- 'crates/apps/p2p-intel/**'
|
|
- 'crates/robius-notification/**'
|
|
- 'crates/apps/nigig-mpesa/src/pages/exchange/**'
|
|
- 'crates/apps/nigig-pay/src/payments_frame/pages/mpesa/exchange/**'
|
|
- 'tools/test-p2p-coverage.sh'
|
|
- 'tools/test-p2p-app-smoke.sh'
|
|
- 'tools/makepad-native-libs.sh'
|
|
- 'rust-toolchain.toml'
|
|
- '.forgejo/workflows/p2p-intel.yml'
|
|
pull_request:
|
|
paths:
|
|
- 'crates/apps/p2p-intel/**'
|
|
- 'crates/robius-notification/**'
|
|
- 'crates/apps/nigig-mpesa/src/pages/exchange/**'
|
|
- 'crates/apps/nigig-pay/src/payments_frame/pages/mpesa/exchange/**'
|
|
- 'tools/test-p2p-coverage.sh'
|
|
- 'tools/test-p2p-app-smoke.sh'
|
|
- 'tools/makepad-native-libs.sh'
|
|
- 'rust-toolchain.toml'
|
|
- '.forgejo/workflows/p2p-intel.yml'
|
|
|
|
jobs:
|
|
engine:
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Test, lint and format the engine crates
|
|
working-directory: crates/apps/p2p-intel
|
|
run: |
|
|
set -Eeuo pipefail
|
|
cargo fmt --all -- --check
|
|
cargo clippy --workspace --all-targets -- -D warnings
|
|
cargo test --workspace
|
|
|
|
- name: Keep the dependency tree lean and the suite hermetic
|
|
working-directory: crates/apps/p2p-intel
|
|
run: |
|
|
set -Eeuo pipefail
|
|
# Two properties, one check.
|
|
#
|
|
# No HTTP client: networking goes through Makepad's Cx::http_request,
|
|
# so a reqwest/tokio/rustls here would mean someone reintroduced a
|
|
# second networking stack -- and CI would start depending on Binance
|
|
# being reachable.
|
|
#
|
|
# No serde: the stack deserialises with makepad_micro_serde. serde
|
|
# and serde_derive are a proc-macro build this crate does not need,
|
|
# and `toml` drags them back in through the back door.
|
|
tree="$(cargo tree --workspace -e normal 2>/dev/null)"
|
|
for forbidden in reqwest tokio rustls hyper serde_json serde_derive '^serde ' '^toml '; do
|
|
if printf '%s' "$tree" | sed 's/^[^a-zA-Z]*//' | grep -qE "$forbidden"; then
|
|
echo "forbidden dependency matched /$forbidden/ in the default graph" >&2
|
|
printf '%s' "$tree" | sed 's/^[^a-zA-Z]*//' | grep -E "$forbidden" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "ok: no HTTP client and no serde in the default build"
|
|
|
|
notifications:
|
|
# robius-notification's Linux backend speaks D-Bus by hand, so its tests
|
|
# need a real daemon. ROBIUS_NOTIFICATION_REQUIRE_DBUS makes the suite
|
|
# fail rather than skip if one is missing -- without it the integration
|
|
# tests could stop running and the build would stay green.
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install dbus
|
|
run: sudo apt-get install -y -qq dbus
|
|
|
|
- name: Test the notification crate
|
|
env:
|
|
ROBIUS_NOTIFICATION_REQUIRE_DBUS: '1'
|
|
run: |
|
|
set -Eeuo pipefail
|
|
cargo fmt -p robius-notification -- --check
|
|
cargo clippy -p robius-notification --all-targets -- -D warnings
|
|
cargo test -p robius-notification
|
|
|
|
- name: Type-check every platform backend
|
|
# A cfg-gated backend that nothing compiles rots silently: the
|
|
# Windows one was written against CreateToastNotifier(&HSTRING),
|
|
# which does not exist, and only a compiler holding the real WinRT
|
|
# metadata said so. `cargo check` needs the target's std, not an SDK,
|
|
# so all four are verifiable from Linux.
|
|
run: |
|
|
set -Eeuo pipefail
|
|
for t in aarch64-linux-android aarch64-apple-darwin aarch64-apple-ios x86_64-pc-windows-msvc; do
|
|
rustup target add "$t"
|
|
cargo clippy -p robius-notification --target "$t" -- -D warnings
|
|
done
|
|
|
|
coverage:
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Enforce the coverage floors
|
|
run: ./tools/test-p2p-coverage.sh
|
|
|
|
makepad-app:
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install the Makepad native libraries and a virtual display
|
|
run: |
|
|
set -Eeuo pipefail
|
|
sudo bash tools/makepad-native-libs.sh --install
|
|
sudo apt-get install -y -qq xvfb
|
|
|
|
- name: Build and lint the desktop app
|
|
working-directory: crates/apps/p2p-intel
|
|
env:
|
|
# naga is memory-hungry; a parallel build is OOM-killed on a small
|
|
# runner, which presents as a SIGKILL with no error message.
|
|
CARGO_BUILD_JOBS: '1'
|
|
run: |
|
|
set -Eeuo pipefail
|
|
cargo clippy -p p2p-makepad --features ui --all-targets -- -D warnings
|
|
cargo test -p p2p-makepad --features ui
|
|
|
|
- name: Start the app under a virtual display
|
|
# `script_mod!` is parsed at *runtime*, so a malformed widget tree
|
|
# compiles perfectly and then logs an error and renders nothing.
|
|
# cargo build cannot catch that; this can, and did — it found
|
|
# `Row = <View>`, which is not valid in this fork's script language.
|
|
env:
|
|
CARGO_BUILD_JOBS: '1'
|
|
run: ./tools/test-p2p-app-smoke.sh
|
|
|
|
exchange-tab:
|
|
# The spread panel is consumed by nigig-mpesa and nigig-pay, whose
|
|
# exchange pages are byte-identical. A change to p2p-analyzer that breaks
|
|
# either is a change that ships broken, so both are built here.
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install the Makepad native libraries
|
|
run: sudo bash tools/makepad-native-libs.sh --install
|
|
|
|
- name: Build the apps that embed the exchange tab
|
|
env:
|
|
CARGO_BUILD_JOBS: '1'
|
|
run: |
|
|
set -Eeuo pipefail
|
|
cargo check -p nigig-mpesa -p nigig-pay
|
|
|
|
- name: The two exchange pages must stay identical
|
|
run: |
|
|
set -Eeuo pipefail
|
|
a=crates/apps/nigig-mpesa/src/pages/exchange/mod.rs
|
|
b=crates/apps/nigig-pay/src/payments_frame/pages/mpesa/exchange/mod.rs
|
|
if ! diff -q "$a" "$b" >/dev/null; then
|
|
echo "the two exchange pages have drifted apart:" >&2
|
|
diff "$a" "$b" >&2
|
|
exit 1
|
|
fi
|
|
echo "ok: both apps carry the same exchange page"
|