fix(ci): fix three coverage workflow failures (#597)

* fix(ci): fix three coverage workflow failures

1. Migration ordering: glob `V*.sql` sorted V10 before V1 (ASCII '0' < '_').
   Use `sort -V` for correct numeric ordering.

2. Missing WASM channels: telegram_auth_integration tests need the Telegram
   WASM binary. Add wasm32-wasip2 target, cargo-component, and
   build-wasm-extensions.sh to both coverage and e2e-coverage jobs
   (matching test.yml).

3. E2E shell quoting: `cargo llvm-cov show-env` outputs shell-quoted values
   (KEY='value') but GITHUB_ENV expects unquoted KEY=value. Strip single
   quotes with sed before appending.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(ci): address PR review feedback on coverage workflow

- Migration loop: use readarray + printf | sort -V instead of $(ls)
  to avoid word-splitting on filenames
- cargo-component install: check if already installed first, don't
  mask failures with || true
- show-env quote stripping: use targeted regex to strip only wrapping
  quotes (KEY='value' -> KEY=value) instead of removing all quotes

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: skip telegram_auth_integration tests when WASM module not built

Replace panicking assert! with a require_telegram_wasm!() macro that
gracefully skips tests when the Telegram WASM binary hasn't been compiled.
This ensures the test suite passes across all configurations (with and
without wasm32-wasip2 target), while still running the tests in CI where
the WASM channels are built.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: panic in CI when telegram WASM module missing, skip locally

- require_telegram_wasm!() now checks the CI env var: panics in CI
  (so a broken WASM build step fails loudly) but skips locally
- fs::read error now includes the file path for better diagnostics

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Illia Polosukhin
2026-03-06 05:59:01 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 06c84a5c77
commit 2df9602d56
2 changed files with 55 additions and 13 deletions
+26 -5
View File
@@ -44,6 +44,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
targets: wasm32-wasip2
- uses: Swatinem/rust-cache@v2
with:
@@ -52,11 +53,21 @@ jobs:
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Install cargo-component
run: |
if ! command -v cargo-component >/dev/null 2>&1; then
cargo install cargo-component --locked
fi
- name: Build WASM channels (for integration tests)
run: ./scripts/build-wasm-extensions.sh --channels
- name: Run database migrations
if: matrix.has_postgres
run: |
set -euo pipefail
for f in migrations/V*.sql; do
readarray -t migration_files < <(printf '%s\n' migrations/V*.sql | sort -V)
for f in "${migration_files[@]}"; do
echo "Applying $f..."
psql -v ON_ERROR_STOP=1 -f "$f"
done
@@ -92,6 +103,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
targets: wasm32-wasip2
- uses: Swatinem/rust-cache@v2
with:
@@ -100,12 +112,21 @@ jobs:
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Install cargo-component
run: |
if ! command -v cargo-component >/dev/null 2>&1; then
cargo install cargo-component --locked
fi
- name: Build WASM channels
run: ./scripts/build-wasm-extensions.sh --channels
- name: Set up coverage instrumentation
run: |
# Append ALL env vars from show-env (including CARGO_ENCODED_RUSTFLAGS,
# CARGO_INCREMENTAL, LLVM_PROFILE_FILE, etc.) so the build step
# compiles an instrumented binary regardless of cargo-llvm-cov version.
cargo llvm-cov show-env >> "$GITHUB_ENV"
# show-env outputs shell-quoted values (KEY='value') but GITHUB_ENV
# expects unquoted KEY=value. Strip only the wrapping single quotes
# from KEY='value' lines without altering any internal characters.
cargo llvm-cov show-env | sed -E "s/^([A-Za-z_][A-Za-z0-9_]*)='(.*)'$/\1=\2/" >> "$GITHUB_ENV"
- name: Clean coverage workspace
run: cargo llvm-cov clean --workspace
+29 -8
View File
@@ -18,6 +18,26 @@ use ironclaw::channels::wasm::{
};
use ironclaw::pairing::PairingStore;
/// Skip the test if the Telegram WASM module hasn't been built.
/// In CI (detected via the `CI` env var), panic instead of skipping so a
/// broken WASM build step doesn't silently produce green tests.
macro_rules! require_telegram_wasm {
() => {
if !telegram_wasm_path().exists() {
let msg = format!(
"Telegram WASM module not found at {:?}. \
Build with: cd channels-src/telegram && cargo build --target wasm32-wasip2 --release",
telegram_wasm_path()
);
if std::env::var("CI").is_ok() {
panic!("{}", msg);
}
eprintln!("Skipping test: {}", msg);
return;
}
};
}
/// Path to the built Telegram WASM module
fn telegram_wasm_path() -> std::path::PathBuf {
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
@@ -34,14 +54,9 @@ fn create_test_runtime() -> Arc<WasmChannelRuntime> {
async fn load_telegram_module(
runtime: &Arc<WasmChannelRuntime>,
) -> Result<Arc<PreparedChannelModule>, Box<dyn std::error::Error>> {
let wasm_path = telegram_wasm_path();
assert!(
wasm_path.exists(),
"Telegram WASM module not found at {:?}. Build it with: cd channels-src/telegram && cargo build --target wasm32-wasip2 --release",
wasm_path
);
let wasm_bytes = std::fs::read(&wasm_path)?;
let path = telegram_wasm_path();
let wasm_bytes = std::fs::read(&path)
.map_err(|e| format!("Failed to read WASM module at {}: {}", path.display(), e))?;
let module = runtime
.prepare(
@@ -107,6 +122,7 @@ fn build_telegram_update(
#[tokio::test]
async fn test_group_message_unauthorized_user_blocked_with_allowlist() {
require_telegram_wasm!();
let runtime = create_test_runtime();
// Config: owner_id=null, dm_policy="allowlist", allow_from=["authorized_user"]
@@ -159,6 +175,7 @@ async fn test_group_message_unauthorized_user_blocked_with_allowlist() {
#[tokio::test]
async fn test_group_message_authorized_user_allowed() {
require_telegram_wasm!();
let runtime = create_test_runtime();
let config = serde_json::json!({
@@ -206,6 +223,7 @@ async fn test_group_message_authorized_user_allowed() {
#[tokio::test]
async fn test_group_message_with_owner_id_set() {
require_telegram_wasm!();
let runtime = create_test_runtime();
// Config: owner_id=123 (only this user can interact)
@@ -251,6 +269,7 @@ async fn test_group_message_with_owner_id_set() {
#[tokio::test]
async fn test_private_message_without_owner_id_with_pairing_policy() {
require_telegram_wasm!();
let runtime = create_test_runtime();
let config = serde_json::json!({
@@ -291,6 +310,7 @@ async fn test_private_message_without_owner_id_with_pairing_policy() {
#[tokio::test]
async fn test_open_dm_policy_allows_all_users() {
require_telegram_wasm!();
let runtime = create_test_runtime();
let config = serde_json::json!({
@@ -335,6 +355,7 @@ async fn test_open_dm_policy_allows_all_users() {
#[tokio::test]
async fn test_bot_mention_detection_case_insensitive() {
require_telegram_wasm!();
let runtime = create_test_runtime();
let config = serde_json::json!({