werkdock: import the rootfs archive, fall back to load -i on an older werkdock
Werkdock's docker-compat branch names the verb for rootfs archives 'import' (docker import semantics) and keeps 'load -i --name' only as a compatibility path. Werkator now runs 'werkdock import ARCHIVE IMAGE' and falls back to 'load -i --name' on exactly the unknown-verb signature (exit 125, 'unknown command' on stderr), so Werkator and werkdock can be updated in either order. Any other import failure propagates as before. The image name stays untagged: it equals werkator-buildenv-<hash>:latest in werkdock's naming, and the existing store needs no re-import. PR-doc under docs/prs/ with the PR#000 placeholder. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
0f9f119687
commit
b8600bb556
@@ -475,7 +475,9 @@ The section was called `bwrap` and its binary key `bwrap.werkdock` until v1.2.0;
|
||||
`werkdock.rootfs` names the prepared root filesystem archive — a Debian-base rootfs with the build tools (JDK, git, locales, project-specific tooling) built elsewhere, since `debootstrap` is unavailable on the target.
|
||||
It is a local path or an `http(s)` URL; a URL is downloaded once into `.git/werkator/buildenv/`.
|
||||
Build the archive with `tools/build-bwrap-rootfs.sh` on any machine with Docker.
|
||||
The archive is loaded once per source as the werkdock image `werkator-buildenv-<hash>` into werkdock's store (`$WERKDOCK_HOME`, default `~/.werkdock`) — shared by every repository of this OS user; the hash derives from the source string, so a changed `rootfs` loads a fresh image and stale ones can be removed from the store.
|
||||
The archive is imported once per source as the werkdock image `werkator-buildenv-<hash>` into werkdock's store (`$WERKDOCK_HOME`, default `~/.werkdock`) — shared by every repository of this OS user; the hash derives from the source string, so a changed `rootfs` imports a fresh image and stale ones can be removed from the store.
|
||||
Werkator uses `werkdock import ARCHIVE IMAGE` (docker import semantics) and falls back to the older `werkdock load -i ARCHIVE --name IMAGE` when the installed werkdock does not know the verb yet, so Werkator and werkdock can be updated in either order.
|
||||
The image keeps its untagged name (it equals `werkator-buildenv-<hash>:latest` in werkdock's docker-style naming), so an existing store needs no re-import.
|
||||
Per-repo Gradle caches persist in `.git/werkator/buildenv/home`, bound as `/root`.
|
||||
`werkdock.env` adds environment variables inside the sandbox; the environment is otherwise cleared (docker semantics) — the server's environment does not leak in.
|
||||
Files created inside the sandbox are owned by the host user, because uid 0 maps back to the unprivileged webspace user.
|
||||
|
||||
+1
-1
@@ -342,7 +342,7 @@ tools/remote --env-file .env.mih34 port-forward start # browser tunne
|
||||
|
||||
Layout on the host: the watched repository at `$WERKATOR_PATH/werkator/`, the unpacked runtime at `$WERKATOR_PATH/.werkator/werkator/`, the werkdock binary at `$WERKATOR_PATH/.werkator/bin/werkdock`.
|
||||
That is the default, not a requirement: `WERKATOR_REPO_DIR`, `WERKATOR_INSTALL_DIR` and `WERKATOR_SANDBOX` bend it to an installation that predates the script, see [Updating an Existing Installation](#updating-an-existing-installation).
|
||||
The rootfs archive is loaded once per source into werkdock's image store (`~/.werkdock`), shared by every repository of the user.
|
||||
The rootfs archive is imported once per source into werkdock's image store (`~/.werkdock`), shared by every repository of the user.
|
||||
Fill `git.account`/`git.token` in the machine config when the origin is private, and make the user's services survive logout with `loginctl enable-linger`.
|
||||
|
||||
Updates are one command, refused while a build runs (`FORCE=1` overrides):
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
> **WARNING:** This document describes only the change applied in this PR.
|
||||
> It may already be outdated once the next PR is merged.
|
||||
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
|
||||
|
||||
## Related Links
|
||||
|
||||
- Werkdock `CHANGELOG.md` on its `docker-compat` branch — the release notes this PR adapts to: `import` replaces `load -i --name` for rootfs archives, `load` is reserved for docker/OCI image archives, image names gained docker-style tags.
|
||||
- ADR 0008 — the bwrap build runtime; `docs/configuration.md`, notes on `builds.<name>.werkdock`.
|
||||
|
||||
## The Problem
|
||||
|
||||
Werkdock moves its CLI closer to `docker run --rm`.
|
||||
For the rootfs archives Werkator uses, the verb is now `werkdock import ARCHIVE IMAGE` (docker import semantics).
|
||||
`werkdock load -i ARCHIVE --name IMAGE` still works but is a compatibility path with a note on stderr, and is announced to go away once Werkator has switched.
|
||||
Werkator ships the werkdock binary with its deployment, but nothing forces the two to be updated together: an installation may run a new Werkator against an older werkdock for a while, or the other way round.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- No switch of the existence check from `werkdock images` to `werkdock inspect`: `images` prints the bare name for untagged images on every werkdock version, the exact-line match keeps working, and `inspect` would tie Werkator to the new werkdock.
|
||||
- No tagged image name (`werkator-buildenv:<hash>`): it would re-import every build environment on the webspace and orphan the old image, for no functional gain today.
|
||||
- None of the new `run` flags (`--mount`, `--entrypoint`, `--network host`): Werkator's invocation needs none of them.
|
||||
|
||||
## The Scenarios
|
||||
|
||||
### Feature: rootfs archives are imported with werkdock's docker-shaped verb
|
||||
|
||||
#### Background
|
||||
|
||||
- The build environment is a rootfs archive named by `builds.<name>.werkdock.rootfs`.
|
||||
- Werkator creates the werkdock image `werkator-buildenv-<hash>` from it once per source.
|
||||
- Werkdock answers an unknown verb with `werkdock: unknown command "import"` and exit code 125, its code for its own errors.
|
||||
|
||||
#### Scenario#000.01: A missing image is imported with `werkdock import`
|
||||
|
||||
So that Werkator uses the verb werkdock names for rootfs archives, and the deprecated path can be removed on werkdock's side.
|
||||
|
||||
- **Given** `werkdock images` does not list the image
|
||||
- **When** a build starts
|
||||
- **Then** Werkator runs `werkdock import ARCHIVE werkator-buildenv-<hash>`
|
||||
- **and** runs no `werkdock load`.
|
||||
|
||||
##### Verified by
|
||||
|
||||
- [WerkdockBuildRunnerTest "imports the image once when werkdock does not know it yet"](../../src/test/kotlin/de/hoennig/werkator/build/WerkdockBuildRunnerTest.kt)
|
||||
- [WerkdockBuildRunnerTest "downloads a URL rootfs once before importing it"](../../src/test/kotlin/de/hoennig/werkator/build/WerkdockBuildRunnerTest.kt)
|
||||
|
||||
#### Scenario#000.02: An older werkdock without the verb still works
|
||||
|
||||
So that Werkator and werkdock can be updated in either order.
|
||||
|
||||
- **Given** the installed werkdock answers `import` with `unknown command` and exit 125
|
||||
- **When** a build starts with a missing image
|
||||
- **Then** Werkator falls back to `werkdock load -i ARCHIVE --name werkator-buildenv-<hash>`
|
||||
- **and** logs the fallback.
|
||||
|
||||
##### Verified by
|
||||
|
||||
- [WerkdockBuildRunnerTest "falls back to load -i --name on a werkdock without the import verb"](../../src/test/kotlin/de/hoennig/werkator/build/WerkdockBuildRunnerTest.kt)
|
||||
|
||||
#### Scenario#000.03: A real import failure is not masked by the fallback
|
||||
|
||||
So that a broken archive fails the build with werkdock's message, as before.
|
||||
|
||||
- **Given** `werkdock import` fails for any other reason (any other exit code, or exit 125 without `unknown command`)
|
||||
- **When** a build starts with a missing image
|
||||
- **Then** the build fails with that command's output
|
||||
- **and** no `werkdock load` runs.
|
||||
|
||||
##### Verified by
|
||||
|
||||
- [WerkdockBuildRunnerTest "propagates an import failure that is not a missing verb"](../../src/test/kotlin/de/hoennig/werkator/build/WerkdockBuildRunnerTest.kt)
|
||||
|
||||
#### Scenario#000.04: An existing image is neither imported nor loaded
|
||||
|
||||
- **Given** `werkdock images` lists the image
|
||||
- **When** a build starts
|
||||
- **Then** neither `import` nor `load` runs.
|
||||
|
||||
##### Verified by
|
||||
|
||||
- [WerkdockBuildRunnerTest "does not import an image werkdock already has"](../../src/test/kotlin/de/hoennig/werkator/build/WerkdockBuildRunnerTest.kt)
|
||||
|
||||
## The Solution
|
||||
|
||||
`WerkdockBuildRunner.ensureImage` calls the new `importImage`: `werkdock import ARCHIVE IMAGE` through the non-throwing `run`, then either returns, falls back to `load -i --name` on exactly the unknown-verb signature (exit 125 plus `unknown command` on stderr), or rethrows the import's result as a `GitCommandException` — the same exception and message the old code produced.
|
||||
The fallback is keyed on werkdock's own error signature rather than on a version string, because werkdock's version output does not yet distinguish the two builds.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- When to drop the fallback: once every installation runs a werkdock with `import`, the `load -i --name` branch and its test go, and werkdock can remove the compatibility path.
|
||||
|
||||
## Additional Changes
|
||||
|
||||
- `docs/configuration.md` and `docs/deployment.md` say "imported" where they said "loaded", and name the fallback and the reason the image name stays untagged.
|
||||
|
||||
## Prerequisite PRs
|
||||
|
||||
- Werkdock's `docker-compat` branch (repository `mi/werkdock`), which introduces `import`; without it the fallback path runs.
|
||||
|
||||
## Follow-up PRs
|
||||
|
||||
- Remove the fallback (see Open Questions).
|
||||
Reference in New Issue
Block a user