diff options
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3b96c6 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# devtools + +Small, shared wrappers around Gradle and adb whose only job is to make a build or +test result **impossible to misread**. + +These exist because of a specific, repeated failure: concluding that something +passed or failed by reading console text, when the text was about a different +project, a stale result, or a command that never ran. Every script here reports +from exit codes and structured artifacts instead, and fails loudly rather than +defaulting to something plausible. + +Invoke by absolute path — `/workspace/devtools/bin/<script>`. Nothing needs to be +on `PATH`, which is itself one less piece of ambient state to get wrong. + +--- + +## The rule these encode + +> **Never conclude from grepped stdout. Conclude from exit codes and structured +> artifacts.** + +Corollaries, each learned the hard way: + +| Trap | What it looks like | Guard | +| --- | --- | --- | +| cwd drift | `cd x && cp y .` fails; the next line runs Gradle in the old directory and prints `BUILD SUCCESSFUL` about the wrong project | `gradle-verify` takes the project dir as an argument, resolves it absolutely, and passes `-p`. A missing dir is fatal, never a fallback. | +| Stale test results | Gradle reports `UP-TO-DATE`, runs nothing, and the XML on disk describes older code | `gradle-test` compares result mtimes against a marker written at run start and refuses stale numbers | +| Zero tests | A test source set that won't compile leaves a green build with nothing executed | `gradle-test` fails when the parsed test count is 0 | +| `cmd \| tail; echo $?` | Reports `tail`'s status, not the command's | Redirect to a file, then check `$?`. Or use `PIPESTATUS[0]`. | +| `... \| grep -q` under `pipefail` | `grep -q` exits on first match and SIGPIPEs upstream; the pipeline reports failure despite matching | Do membership tests in pure shell (`case`), not pipelines | +| `set -e` + a command that legitimately fails | `pid=$(pidof x)` aborts the whole script when the process is gone — i.e. exactly when you are trying to detect a crash | `|| true` on any substitution whose non-zero status is meaningful data | +| Discarded command output | `adb install ... >/dev/null` hides "filename doesn't end .apk"; the old build stays installed and is silently what gets tested | `android-launch-check --apk` checks the install output for `Success` | +| `monkey` as a launch check | Reports a healthy app dead and a dead app healthy; lands on whatever activity is foreground | `android-launch-check` uses `am start -W` against a resolved activity and samples the pid repeatedly | + +--- + +## Scripts + +### `gradle-verify <project-dir> <task...> [-- <gradle args>]` + +Runs Gradle against an explicitly named project. Exits with Gradle's exit code. +Prints the absolute project directory actually used, so the output is +self-describing. + +``` +/workspace/devtools/bin/gradle-verify /workspace/nav/android-app compileDebugKotlin +``` + +### `gradle-test <project-dir> [task] [--allow-stale] [-- <gradle args>]` + +Runs the test task, then reports counts parsed from the JUnit XML. Auto-detects +`testDebugUnitTest` for Android projects and `test` otherwise. + +Fails on: non-zero Gradle exit, any failure or error in the XML, **zero tests +executed**, **no XML at all**, or **results that predate this run**. + +``` +/workspace/devtools/bin/gradle-test /workspace/nav/android-app -- --rerun-tasks +``` + +`--rerun-tasks` is usually what you want when the answer matters — otherwise +Gradle may skip the task and the script will (correctly) refuse the stale +results. + +### `android-launch-check <package> [--apk <path>] [--serial <s>] [--settle <secs>]` + +Answers "does this build actually start and stay up", and shows the exception if +not. Optionally installs an APK first, verifying the install genuinely succeeded. + +Exit codes: `0` launched and stayed up · `1` crashed or died · `2` operator error +(no device, package not installed, unusable filename). + +``` +/workspace/devtools/bin/android-launch-check org.terst.feedreader \ + --apk /path/to/app-debug.apk --settle 15 +``` + +--- + +## Tests + +``` +/workspace/devtools/test/run-tests.sh +``` + +12 cases, mostly negative — each drives a script into one failure mode and +asserts it is caught. A wrapper that only ever reports PASS is worse than no +wrapper, so the negative cases are the point. |
