Files
mesh-catalog/modules/mesh-build-image
jschoubben 071c6885d9
mesh/delivery merged: source.main moved to novox/mesh-catalog@61563abf2f93
mesh/delivery-group group fix/fetch-reads-all merged: every member is merged
mesh/check checking 071c6885d923 on 8393e2962193
The mesh's forge accounts all read every repository, and a build's fetch says the forge's own words
mesh-catalog #495 gave read on every repository to the tools' account alone. The build modules
fetch over ssh as nox-builder (the forge-account provider's builders account, ADR 0466 §3), so
ace's and g14's fetch of jschoubben/car-hunter and jschoubben/snake still failed; the machines'
agents (nox-agent, ADR 0410 §1) could not read them either.

- gitea: readall.ts grants every account of one list, meshAccounts in tools-account.ts (mesh-tools,
  nox-builder, nox-agent; a Go test holds the two Go names to internal/forgeaccount's constants),
  on the same start pass, forge events and tools. gitea_unreadable_repos answers per account and
  names the accounts the forge does not hold yet; gitea_grant_read takes accounts as well as
  repositories. An absent account is asked nothing; the start pass runs again ten minutes apart
  until every account was there once.
- mesh-build-go, mesh-build-node, mesh-build-image: pin mesh-sdk ff81bdf8 (fix/fetch-reads-all),
  whose forgekey.Said keeps git's words past the bare "error:" line: the mirror's line said only
  "git -C: error:". Their own git reasons (ls-files, ls-remote, rev-parse, repack) go through it too.
2026-10-26 15:27:38 +01:00
..

mesh-build-image — the image build module

Design 47, release R4c-9 (novox/hq ADR 0487, ADR 0466 §1, ADR 0469; issue 1703). The module that builds a module's image artifact from the Dockerfile in the module's own directory, on a build machine, as an account of its own (runs-as, no login shell, home at mode 0700). It serves every module's image, whatever the base, so it is not a build module for one module. It claims no seat: it is assigned to the build machines and runs dark until the builder uses it.

Rootless

The tool is buildah, which the buildah module installs and provides as rootless-image-build with the machine's reach: a machine without it refuses this module at assignment, naming buildah. The build runs as the module's own account in a user namespace (--isolation oci), with buildah's image store and runtime state in /var/lib/mesh-build-image-store (outside the home), no mount of the host, no container runtime socket, no registry credential and an environment built from scratch.

The account's subordinate user and group ranges are not declared anywhere: the node-engine makes every user account with useradd, which allocates them. The module's health reads /etc/subuid and /etc/subgid and is unhealthy without a range for the account, without buildah, or when a user namespace cannot be made.

The Dockerfile's steps may use the network (ADR 0487 §6); nothing a step can read holds a key.

Steps

  • build_image_fetch fetches a commit over SSH into a workspace (a base commit makes the merge preview, as the other build modules' fetch). Long: answers a step id and ends on its key in steps.
  • build_image_build builds one image artifact: buildah bud with the Dockerfile of the module's directory as file and context, --target, and the images build.on pins as --build-arg. Answers the image's digest. With publish: true (a merged trunk commit only) the module's own process then pushes it to the registry under <module>/<artifact>:<tag of its own> (the first 12 hex digits of the digest unless the call gives one), waiting out a registry held still, and the key carries the digest the registry serves and the reference pinned by it. Without publish (a pull request) nothing is pushed.
  • build_image_copy copies an upstream artifact (module, artifact, from) registry to registry into the artifact store over the registry API, the whole index and every blob, by the digest the manifest pins (ADR 0498 §4), and verifies the store serves that digest. Answers the digest and the reference <registry>/<module>/<artifact>@sha256:<digest>. A from without a digest fails not pinned:. It needs no workspace and no buildah.
  • It refuses, naming why, an image whose build context is a whole repository (context) or whose build.on names another module's artifact (unsupportedImage in build.go): those forms belong to the images build-agent builds until it is removed at R4g.
  • build_image_release {workspace} removes a workspace at once (no guard, no floor; one already gone is no error, one a running step holds is refused); its caller calls it once its last step answered. A failed fetch removes its own workspace, and one no caller released is removed two hours after its last use (ADR 0509).
  • A fetch and a build are refused, refused: <node> has N GiB free under the floor of 20 GiB (on <dir>), and the health is unhealthy with that text, while the work directory's or the image store's filesystem has less than 20 GiB free (issue 1839). A copy writes nothing to the disk and is not refused.
  • build_image_step, build_image_steps, build_image_status and build_image_health read.

The registry's address is placed into <home>/registry as ${seat:mesh-artifact-store:reach} (host:port): the provisioner's client fills a moved module's placement, and the artifact store has not moved, so a ${bound:artifact-store:...} is refused at composition (issue 1703).