A Rust backend that discovers Android projects under configured roots, builds one on request, and serves the APK over pinned TLS on a WireGuard interface; an Android client that lists what is buildable, watches a build, and installs the result. Enrolment carries the token and the CA, so the phone trusts exactly the machine that issued it and nothing else. `AGENTS.md` is the working guide and `README.md` the configuration reference. The shared tunnel-and-TLS code lives in `vendor/wg-app-link`, which ai-app uses too. History before this point was squashed away, and a stale `config.json` went with it: nothing had read that file since the config moved to RON outside the checkout, and what it still held was one machine's absolute paths and the names of projects on it.
86 lines
4.4 KiB
Markdown
86 lines
4.4 KiB
Markdown
# Test projects
|
|
|
|
Small fake projects for exercising Dev Updater against something other than
|
|
Dev Updater. They are apps in the sense the server cares about -- a path
|
|
with a declaration and a build that produces an APK -- and nothing else.
|
|
|
|
The point of having them is control. Dev Updater's job is installing *other*
|
|
projects' builds, so trying it out needs something to install, and a real
|
|
project only ever does what it happens to do: it builds, or it doesn't, and
|
|
you cannot ask it to fail on the third component, produce two variants, or
|
|
run a service that writes a coloured log. These can be asked for any of
|
|
that.
|
|
|
|
## Why they are not picked up automatically
|
|
|
|
`scan_roots` in `server/src/discover.rs` descends two levels below each
|
|
configured repo root, **and stops at any directory carrying a
|
|
`.dev-updater.ron`** -- a declaration says "this directory is the project",
|
|
so what is underneath is that project's own layout rather than more projects
|
|
to offer. This checkout carries one at its root, so with `/home/bob/repos`
|
|
as a root the scan considers `dev-updater` itself and descends no further.
|
|
Nothing in here is ever suggested.
|
|
|
|
To work with them, add `.../dev-updater/test-projects` as a repo root of its
|
|
own from the app's settings; each directory below is then a suggestion. Or
|
|
type one project's path into the Add screen, which is the escape hatch for
|
|
anything the scan does not reach.
|
|
|
|
## The `app/` directory each one builds into
|
|
|
|
`find_apks` matches APKs up to **two** directories below a project root, and
|
|
it is run against the *project* path, not a component's `cwd`. A test
|
|
project building into `test-projects/<name>/build/outputs/apk/` would
|
|
therefore also be found from the repository root -- offered as a build of
|
|
Dev Updater itself, and, being the newest, served as the default. Somebody
|
|
pressing Update on the Dev Updater card would get a stub app.
|
|
|
|
One more level down (`test-projects/<name>/app/build/outputs/apk/`) is out of
|
|
reach from the root while staying within reach from the test project, which
|
|
is why `lib/build-apk.sh` writes there. It is also what a real Gradle project
|
|
looks like, so nothing about it reads as a workaround. Check it after
|
|
changing any of this:
|
|
|
|
```sh
|
|
cd <repo root> && for p in build/outputs/apk/*/*.apk */build/outputs/apk/*/*.apk \
|
|
*/*/build/outputs/apk/*/*.apk; do [ -f "$p" ] && echo "$p"; done
|
|
```
|
|
|
|
Only `app/androidApp/build/outputs/apk/debug/androidApp-debug.apk` should
|
|
appear.
|
|
|
|
## What is here
|
|
|
|
| project | what it is for |
|
|
|---|---|
|
|
| `hello-app` | The plain case: one APK, one variant. Declares **no** `resources:`, so Uninstall has to show its data and config toggles disabled and say why. |
|
|
| `two-variants` | Builds `debug` and `release`, so the phone gets a variant picker and `resolve_apk` has something to fall back from. |
|
|
| `breakable` | `touch breakable/break-the-build` and its next build fails, in colour, on stderr. `rm` it and it stops. |
|
|
| `service-and-app` | A `Server` beside an `Apk`: two components building at once, the whole service contract, a runtime log that is not this server's own, and a `resources:` declaration giving Uninstall real paths. |
|
|
|
|
All four are unaccepted when first added, so each is also a run through the
|
|
acceptance gate.
|
|
|
|
## The apps themselves
|
|
|
|
One screen showing the app's label, its package, and when the installed copy
|
|
landed -- `lib/StubActivity.java`, shared by all of them, because what
|
|
differs between these projects is what Dev Updater has to do with them, not
|
|
what the app is. The install time is `PackageInfo.lastUpdateTime`, which is
|
|
the exact value the freshness check compares an APK's mtime against, so the
|
|
screen shows what the card is reasoning about.
|
|
|
|
They are built by `lib/build-apk.sh` -- aapt2, javac, d8, apksigner, about
|
|
two seconds -- rather than by Gradle. A Gradle daemon is around a gigabyte
|
|
resident and four of these would be four daemons, which is how this machine
|
|
ran itself out of memory on 2026-08-30; and a fixture you wait forty seconds
|
|
for stops getting used. The cost is that the script is a small build system,
|
|
which is why it is one file and should stay one: a test project that needs
|
|
more than a screen with its own name on it wants a real project.
|
|
|
|
The signing key is generated once at
|
|
`$XDG_DATA_HOME/dev-updater/test-projects/debug.keystore`, outside the
|
|
repository -- the checkout is a mount shared with the host, and a stable key
|
|
is what lets a rebuild install over the copy already on a device. Delete it
|
|
to produce a signature-mismatch install failure on purpose.
|