-
Notifications
You must be signed in to change notification settings - Fork 0
Item Types
Every item in a manifest carries a type, and the type decides what BootstrapMate does
with the downloaded payload. There are three: package, rootscript and userscript.
This page covers what each does, which fields matter for it, how success is judged, and the
traps in each.
The values are matched exactly and are case-sensitive. Anything else logs
Unknown item type: <type>, shows "Unknown type" in the dialog, and fails the item.
| Field | package |
rootscript |
userscript |
|---|---|---|---|
file, hash, url, type
|
Yes | Yes | Yes |
name |
Yes | Yes | Yes |
retries, retrywait
|
Yes | Yes | Yes |
skipIf |
Yes | Yes | Yes |
packageid, version
|
Yes | No effect | No effect |
expectedTeamID, allowUnsigned
|
Yes | No effect | No effect |
donotwait |
No effect | Yes | Yes |
followRedirects |
Accepted, no effect | Accepted, no effect | Accepted, no effect |
An Apple installer package, installed at the system root.
The sequence is: check whether it is already installed, download, verify the signature,
install. The already-installed check only happens when both packageid and version
are set — BootstrapMate reads pkgutil --pkg-info-plist <packageid> and skips the item if
the receipt's version is greater than or equal to version. A skip here counts as a
success and is reported in the dialog as already installed.
Installation is /usr/sbin/installer -pkg <file> -target /. Success is installer
exiting 0 — nothing else is checked. A package that installs cleanly but does nothing
useful is a success as far as BootstrapMate is concerned.
Before installer runs, the package's signature is checked with
pkgutil --check-signature. An untrusted or missing signature refuses the install unless
allowUnsigned is set, and an expectedTeamID mismatch refuses it unconditionally. See
Security and Package Verification.
Gotchas:
-
-target /is the only target. There is no way to install to a volume or a custom location, andfileis the download destination, not an install destination. - Distribution packages that would normally prompt, require a choices file, or refuse headless install will fail here, because there is no interactive installer.
-
donotwaitdoes nothing for packages. Every package install is waited on, with no timeout. - Downloads are read fully into memory before being written to
file, so a very large package is fully resident in RAM during the transfer.
An executable file run as root.
BootstrapMate downloads it, sets its permissions to 0755, and runs it directly — the file
at file is the executable, so it needs a working shebang. There is no interpreter
argument and no way to pass arguments to the script. The environment inherits the daemon's,
with PATH set to /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin, and the working
directory is set to the script's own directory.
Success is exit code 0. Any non-zero exit fails the item. Standard output is logged at
INFO and standard error at WARN, each line prefixed [OUTPUT] <script name>: , which is
how you find out what a script actually did.
Scripts are not signature-checked. The SHA-256 hash is the only integrity control on
a script, which makes the manifest's own transport the thing you have to trust.
rootscript is also the only type preflight will use, and there its exit code means
something different — see Stages.
Same schema fields as rootscript, and intended for per-user work in the userland stage.
A userscript runs as root, not as the logged-in user. It is executed through exactly
the same code path as a rootscript: same permissions, same environment, same root daemon
context. The code that would run a script as the console user via launchctl asuser exists
but is never called. The only real difference between the two types today is the label, and
that --userscript mode runs userland items of this type and nothing else.
Write these scripts accordingly. Anything that relies on being the user — defaults write
without an explicit path, ~ expansion, per-user launchd domains, the user's keychain —
will act on root, not on the person logging in. If you need to touch the console user's
environment, look the user up inside the script and target them explicitly.
Success and output handling are identical to rootscript: exit 0 is success, output is
captured to the log.
With donotwait: true the script is launched and BootstrapMate continues immediately. The
item is marked successful the moment the process starts; its exit code is never read, and
its output is not captured to the log — a fire-and-forget script that fails leaves no
trace in the run. The working directory is not set for these launches either.
This is the mechanism behind the handoff: because the daemon plist sets
AbandonProcessGroup, a donotwait child keeps running after BootstrapMate exits and its
LaunchDaemon is booted out. See Handoff to Munki.