Skip to content

Commit d60fc46

Browse files
committed
[#17] documentation: explain the logic inversion impossibility
1 parent 4c02d5c commit d60fc46

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,3 +911,86 @@ This repository includes a presentation about Markdown Runner.
911911
912912
- [View the slides](./slides/slides.md) (github will render the source somewhat)
913913
- [Building the slides](./slides/README.md)
914+
915+
## Usage tips
916+
917+
### Limitation: interactive shell vs chunk behavior
918+
919+
Markdown-runner uses `set -e` to match tutorial step-by-step expectations, but this creates a disconnect between **script behavior** and **interactive shell behavior**:
920+
921+
**Interactive Shell** (what humans experience):
922+
923+
```bash
924+
$ oikjoij || ! echo "must show up"
925+
bash: oikjoij: command not found
926+
must show up
927+
$ echo $?
928+
1 # Command failed as expected
929+
```
930+
931+
**Script with `set -e`** (what markdown-runner does):
932+
933+
```bash
934+
#!/bin/bash
935+
set -e
936+
oikjoij || ! echo "must show up"
937+
echo "This continues executing" # ✅ Script continues, exits 0
938+
```
939+
940+
**The Disconnect:**
941+
- **Humans** typing commands see failures when they expect them
942+
- **Scripts with `set -e`** have special exemption rules for compound commands (`||`, `&&`) that mask failures
943+
- **Tutorial authors** write commands based on interactive experience, but CI runs them as scripts
944+
945+
#### The `set -e` Exemption Rules
946+
947+
From the [Bash manual](https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/): *`"This option is also smart enough to not react on failing commands that are part of conditional statements. Moreover, you can append a command with || true for those rare cases where you don’t want a failing command to trigger an immediate exit.`"*
948+
949+
This means:
950+
951+
```bash
952+
# Interactive shell: FAILS (exit 1)
953+
oikjoij || ! echo "error"
954+
955+
# Script with set -e: SUCCEEDS (exit 0)
956+
# Because oikjoij is "part of a || list"
957+
```
958+
959+
#### The Human Expectation Gap
960+
961+
**Tutorial authors think:** *"I'll write this like I would in my terminal"*
962+
963+
```bash
964+
docker --version || echo "Please install Docker first"
965+
```
966+
967+
**What they experience interactively:** Command fails appropriately when Docker is missing
968+
969+
**What happens in CI:** Script succeeds even when Docker is missing, because `set -e` doesn't apply to the `||` construct
970+
971+
#### Good vs Bad Compound Command Patterns
972+
973+
##### ❌ Problematic Pattern (works interactively, fails in CI):
974+
```bash
975+
oikjoij || ! echo "must show up"
976+
```
977+
**Problem:** Interactive shell fails (exit 1), but `set -e` script succeeds (exit 0)
978+
979+
##### ✅ Good Pattern (consistent behavior):
980+
981+
```bash
982+
minikube kubectl -- wait --for=condition=Available --timeout=2m || {
983+
echo "Wait command failed. Dumping deployment YAML:"
984+
minikube kubectl -- get deployment cert-manager-webhook -o yaml
985+
false # Explicitly fail - works same in both contexts
986+
}
987+
```
988+
989+
##### ✅ Alternative Clear Pattern:
990+
991+
```bash
992+
if ! oikjoij; then
993+
echo "oikjoij failed"
994+
exit 1 # Explicit failure - consistent everywhere
995+
fi
996+
```

0 commit comments

Comments
 (0)