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
1 change: 1 addition & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
e2e/smoke
e2e/failure_propagation
7 changes: 7 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ jobs:
echo "${{ matrix.bazel }}" > .bazelversion
bazel test //...

- name: Failure propagation test (e2e)
shell: bash
working-directory: e2e/failure_propagation
run: |
echo "${{ matrix.bazel }}" > .bazelversion
bazel test //...

# ---------------------------------------------------------------------------
# Gate: single status check for branch protection.
# Runs even if upstream jobs fail (if: always()).
Expand Down
3 changes: 3 additions & 0 deletions e2e/failure_propagation/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Failure propagation test bazelrc
common --enable_bzlmod
build --incompatible_strict_action_env
20 changes: 20 additions & 0 deletions e2e/failure_propagation/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
load("@rules_odin//odin:defs.bzl", "odin_test")
load("@rules_shell//shell:sh_test.bzl", "sh_test")

# Intentionally failing odin_test — excluded from bazel test //...
# Used only as a data dep for the failure_propagation_test below.
odin_test(
name = "should_fail",
srcs = glob(["tests_fail/*.odin"]),
tags = ["manual"],
)

# Validates that the failing test binary exits non-zero.
# Proves Bazel correctly reports FAILED for odin_test targets.
sh_test(
name = "failure_propagation_test",
srcs = ["check_exit_code.sh"],
args = ["$(rlocationpath :should_fail)"],
data = [":should_fail"],
deps = ["@rules_shell//shell/runfiles"],
)
22 changes: 22 additions & 0 deletions e2e/failure_propagation/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Failure propagation test — validates odin_test exits non-zero on test failure."""

module(
name = "rules_odin_e2e_failure_propagation",
version = "0.0.0",
)

bazel_dep(name = "rules_odin", version = "0.1.0")
local_path_override(
module_name = "rules_odin",
path = "../..",
)

bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_shell", version = "0.8.0")

odin = use_extension("@rules_odin//odin:extensions.bzl", "odin")
odin.toolchain(odin_version = "dev-2026-06")
use_repo(odin, "odin_toolchains")

register_toolchains("@odin_toolchains//:all")
525 changes: 525 additions & 0 deletions e2e/failure_propagation/MODULE.bazel.lock

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions e2e/failure_propagation/check_exit_code.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Validates that odin_test exits non-zero when @(test) procedures fail.
# This proves Bazel correctly reports FAILED for odin_test targets.

# --- begin runfiles.bash initialization v3 ---
set -uo pipefail
set +e
f=bazel_tools/tools/bash/runfiles/runfiles.bash
# shellcheck disable=SC1090
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null ||
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null ||
source "$0.runfiles/$f" 2>/dev/null ||
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null ||
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null ||
{
echo >&2 "ERROR: cannot find $f"
exit 1
}
# --- end runfiles.bash initialization v3 ---

set -e

# Resolve the binary path from the rlocationpath passed as $1.
BINARY="$(rlocation "$1")"
if [[ ! -x "$BINARY" ]]; then
echo "ERROR: binary not found or not executable: $BINARY"
exit 1
fi

# Run the failing test binary and capture its exit code.
set +e
"$BINARY" >/dev/null 2>&1
EXIT_CODE=$?
set -e

# Assert non-zero exit (test failure must propagate).
if [[ "$EXIT_CODE" -eq 0 ]]; then
echo "FAIL: expected non-zero exit code from failing odin_test binary, got 0"
echo " odin_test is NOT propagating failure correctly!"
exit 1
fi

echo "PASS: odin_test correctly propagated failure (exit code $EXIT_CODE)"
10 changes: 10 additions & 0 deletions e2e/failure_propagation/tests_fail/failing_test.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package failing_test

import "core:testing"

// This test MUST fail — it validates that odin_test propagates non-zero
// exit codes to Bazel's test infrastructure.
@(test)
test_intentional_failure :: proc(t: ^testing.T) {
testing.expect_value(t, 1 + 1, 3)
}
Loading