From 591b26f7128e9595291714a868c69058b9ad586f Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 18 Sep 2026 02:02:21 +0200 Subject: [PATCH 1/4] Ten migration-critical modules become mesh-buildable (issue 060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit keycloak, mailu, minio, mongodb, mssql, nextcloud, portainer, redis, umami and verdaccio get the Dockerfile + build section the eight buildable modules already had; their runtime containers name the artifact instead of a placeholder digest. One convention, settled (060's open question, informed by 061): the runtime container runs serve mode with every serve-time entrypoint in MESH_TOOL_MODULES — tools serve, events flow, and a provider's provisioner reconciles in the same process with the broker connected. postgres, gitea and lavinmq are retrofitted from args-run provisioners, which served no tools and emitted lifecycle events nowhere. route-proxy is deferred: its build context is the mesh-controller repository, a cross-repo shape the build section cannot yet express. --- modules/gitea/Dockerfile | 2 +- modules/gitea/module.json | 4 ---- modules/keycloak/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/keycloak/module.json | 27 ++++++++++++++++++++++--- modules/lavinmq/Dockerfile | 2 +- modules/lavinmq/module.json | 6 +----- modules/mailu/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/mailu/module.json | 27 ++++++++++++++++++++++--- modules/minio/Dockerfile | 32 ++++++++++++++++++++++++++++++ modules/minio/module.json | 27 ++++++++++++++++++++++--- modules/mongodb/Dockerfile | 37 +++++++++++++++++++++++++++++++++++ modules/mongodb/module.json | 27 ++++++++++++++++++++++--- modules/mssql/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/mssql/module.json | 27 ++++++++++++++++++++++--- modules/nextcloud/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/nextcloud/module.json | 27 ++++++++++++++++++++++--- modules/portainer/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/portainer/module.json | 25 +++++++++++++++++++++-- modules/postgres/Dockerfile | 2 +- modules/postgres/module.json | 6 +----- modules/redis/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/redis/module.json | 27 ++++++++++++++++++++++--- modules/umami/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/umami/module.json | 27 ++++++++++++++++++++++--- modules/verdaccio/Dockerfile | 30 ++++++++++++++++++++++++++++ modules/verdaccio/module.json | 27 ++++++++++++++++++++++--- 26 files changed, 553 insertions(+), 46 deletions(-) create mode 100644 modules/keycloak/Dockerfile create mode 100644 modules/mailu/Dockerfile create mode 100644 modules/minio/Dockerfile create mode 100644 modules/mongodb/Dockerfile create mode 100644 modules/mssql/Dockerfile create mode 100644 modules/nextcloud/Dockerfile create mode 100644 modules/portainer/Dockerfile create mode 100644 modules/redis/Dockerfile create mode 100644 modules/umami/Dockerfile create mode 100644 modules/verdaccio/Dockerfile diff --git a/modules/gitea/Dockerfile b/modules/gitea/Dockerfile index b0ac565..0c0eabf 100644 --- a/modules/gitea/Dockerfile +++ b/modules/gitea/Dockerfile @@ -34,4 +34,4 @@ COPY --from=build /app/modules/gitea/dist /app/modules/gitea/dist # separate entrypoints because they are loaded by different things. The provisioner is the third, # and is not listed here — the declaration names it in the container's `args`, because it is what # this module's own container runs. One image, because they are one module and share a client. -ENV MESH_TOOL_MODULES=/app/modules/gitea/dist/index.js,/app/modules/gitea/dist/tools/index.js +ENV MESH_TOOL_MODULES=/app/modules/gitea/dist/index.js,/app/modules/gitea/dist/tools/index.js,/app/modules/gitea/dist/provisioner/index.js diff --git a/modules/gitea/module.json b/modules/gitea/module.json index 54a9b46..31e7ade 100644 --- a/modules/gitea/module.json +++ b/modules/gitea/module.json @@ -167,10 +167,6 @@ "MESH_RECEIVES": "/var/lib/gitea/grants/mesh.json" }, "artifact": "runtime", - "args": [ - "run", - "/app/modules/gitea/dist/provisioner/index.js" - ], "restart-on": [ "runtime-config" ] diff --git a/modules/keycloak/Dockerfile b/modules/keycloak/Dockerfile new file mode 100644 index 0000000..c30eeba --- /dev/null +++ b/modules/keycloak/Dockerfile @@ -0,0 +1,30 @@ +# keycloak's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/keycloak +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/keycloak/dist /app/modules/keycloak/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/keycloak/dist/index.js,/app/modules/keycloak/dist/tools/index.js diff --git a/modules/keycloak/module.json b/modules/keycloak/module.json index fb11901..b14a087 100644 --- a/modules/keycloak/module.json +++ b/modules/keycloak/module.json @@ -110,7 +110,6 @@ "id": "runtime", "type": "container", "name": "mesh-keycloak", - "image": "mesh-runtime-keycloak@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/keycloak/broker:/run/secrets/broker:ro", @@ -123,7 +122,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/lavinmq/Dockerfile b/modules/lavinmq/Dockerfile index 2c022d9..dfbd207 100644 --- a/modules/lavinmq/Dockerfile +++ b/modules/lavinmq/Dockerfile @@ -38,4 +38,4 @@ COPY --from=build /app/modules/lavinmq/dist /app/modules/lavinmq/dist # provisioner are not listed here — the declaration names each in its container's `args`, because # they are what this module's own containers run. One image, because they are one module and share # a client. -ENV MESH_TOOL_MODULES=/app/modules/lavinmq/dist/index.js,/app/modules/lavinmq/dist/tools/index.js +ENV MESH_TOOL_MODULES=/app/modules/lavinmq/dist/index.js,/app/modules/lavinmq/dist/tools/index.js,/app/modules/lavinmq/dist/provisioner/index.js diff --git a/modules/lavinmq/module.json b/modules/lavinmq/module.json index 2a4b36e..a2afd95 100644 --- a/modules/lavinmq/module.json +++ b/modules/lavinmq/module.json @@ -107,11 +107,7 @@ "MESH_PROVISION_LAVINMQ": "http://127.0.0.1:15672", "MESH_PROVISION_ADMIN_USER": "guest", "MESH_LAVINMQ_ADMIN_PASSWORD": "guest" - }, - "args": [ - "run", - "/app/modules/lavinmq/dist/provisioner/index.js" - ] + } } ], "build": { diff --git a/modules/mailu/Dockerfile b/modules/mailu/Dockerfile new file mode 100644 index 0000000..b4c8a17 --- /dev/null +++ b/modules/mailu/Dockerfile @@ -0,0 +1,30 @@ +# mailu's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/mailu +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/mailu/dist /app/modules/mailu/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/mailu/dist/index.js,/app/modules/mailu/dist/tools/index.js diff --git a/modules/mailu/module.json b/modules/mailu/module.json index c7fea17..79a9c60 100644 --- a/modules/mailu/module.json +++ b/modules/mailu/module.json @@ -382,7 +382,6 @@ "id": "runtime", "type": "container", "name": "mesh-mailu", - "image": "mesh-runtime-mailu@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "mailu", "volumes": [ "/var/lib/mesh/mailu/broker:/run/secrets/broker:ro", @@ -399,7 +398,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/minio/Dockerfile b/modules/minio/Dockerfile new file mode 100644 index 0000000..016bb77 --- /dev/null +++ b/modules/minio/Dockerfile @@ -0,0 +1,32 @@ +# minio's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/minio +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts provisioner/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +# minio's client drives `mc` — copied from the official image, as the workstation build did. +COPY --from=minio/mc:latest /usr/bin/mc /usr/bin/mc +COPY --from=build /app/modules/minio/dist /app/modules/minio/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/minio/dist/tools/index.js,/app/modules/minio/dist/provisioner/index.js diff --git a/modules/minio/module.json b/modules/minio/module.json index 185ff6a..457d7a0 100644 --- a/modules/minio/module.json +++ b/modules/minio/module.json @@ -102,7 +102,6 @@ "id": "runtime", "type": "container", "name": "mesh-minio", - "image": "mesh-runtime-minio@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "minio", "volumes": [ "/var/lib/mesh/minio/broker:/run/secrets/broker:ro", @@ -115,7 +114,29 @@ "MESH_MINIO_ROOT_PASSWORD_FILE": "/run/secrets/root", "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_RECEIVES": "/var/lib/minio/grants/mesh.json" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/mongodb/Dockerfile b/modules/mongodb/Dockerfile new file mode 100644 index 0000000..05f3aef --- /dev/null +++ b/modules/mongodb/Dockerfile @@ -0,0 +1,37 @@ +# mongodb's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/mongodb +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts provisioner/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +# mongodb's client shells out to `mongosh`, installed from MongoDB's own apt repo so its shared +# libraries come with it — copying the bare binary out of the mongo image leaves it unable to load. +RUN apt-get update && apt-get install -y --no-install-recommends gnupg curl ca-certificates \ + && curl -fsSL https://pgp.mongodb.com/server-7.0.asc | gpg --dearmor -o /usr/share/keyrings/mongodb.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/mongodb.gpg] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main" > /etc/apt/sources.list.d/mongodb.list \ + && apt-get update && apt-get install -y --no-install-recommends mongodb-mongosh \ + && rm -rf /var/lib/apt/lists/* +COPY --from=build /app/modules/mongodb/dist /app/modules/mongodb/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/mongodb/dist/index.js,/app/modules/mongodb/dist/tools/index.js,/app/modules/mongodb/dist/provisioner/index.js diff --git a/modules/mongodb/module.json b/modules/mongodb/module.json index 6f7479e..bcd49f4 100644 --- a/modules/mongodb/module.json +++ b/modules/mongodb/module.json @@ -101,7 +101,6 @@ "id": "runtime", "type": "container", "name": "mesh-mongodb", - "image": "mesh-runtime-mongodb@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "mongodb", "volumes": [ "/var/lib/mesh/mongodb/broker:/run/secrets/broker:ro", @@ -113,7 +112,29 @@ "MESH_PROVISION_PASSWORD_FILE": "/run/secrets/root", "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_RECEIVES": "/var/lib/mongodb/grants/mesh.json" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/mssql/Dockerfile b/modules/mssql/Dockerfile new file mode 100644 index 0000000..20e878e --- /dev/null +++ b/modules/mssql/Dockerfile @@ -0,0 +1,30 @@ +# mssql's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/mssql +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts provisioner/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/mssql/dist /app/modules/mssql/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/mssql/dist/index.js,/app/modules/mssql/dist/tools/index.js,/app/modules/mssql/dist/provisioner/index.js diff --git a/modules/mssql/module.json b/modules/mssql/module.json index 87d4708..cb516bc 100644 --- a/modules/mssql/module.json +++ b/modules/mssql/module.json @@ -97,7 +97,6 @@ "id": "runtime", "type": "container", "name": "mesh-mssql", - "image": "mesh-runtime-mssql@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "mssql", "volumes": [ "/var/lib/mesh/mssql/broker:/run/secrets/broker:ro", @@ -109,7 +108,29 @@ "MESH_PROVISION_PASSWORD_FILE": "/run/secrets/sa", "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_RECEIVES": "/var/lib/mssql/grants/mesh.json" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/nextcloud/Dockerfile b/modules/nextcloud/Dockerfile new file mode 100644 index 0000000..5a6e5a8 --- /dev/null +++ b/modules/nextcloud/Dockerfile @@ -0,0 +1,30 @@ +# nextcloud's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/nextcloud +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/nextcloud/dist /app/modules/nextcloud/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/nextcloud/dist/index.js,/app/modules/nextcloud/dist/tools/index.js diff --git a/modules/nextcloud/module.json b/modules/nextcloud/module.json index 8feaf75..ec67ae6 100644 --- a/modules/nextcloud/module.json +++ b/modules/nextcloud/module.json @@ -101,7 +101,6 @@ "id": "runtime", "type": "container", "name": "mesh-nextcloud", - "image": "mesh-runtime-nextcloud@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/nextcloud/broker:/run/secrets/broker:ro", @@ -115,7 +114,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/portainer/Dockerfile b/modules/portainer/Dockerfile new file mode 100644 index 0000000..17820ac --- /dev/null +++ b/modules/portainer/Dockerfile @@ -0,0 +1,30 @@ +# portainer's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/portainer +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/portainer/dist /app/modules/portainer/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/portainer/dist/tools/index.js diff --git a/modules/portainer/module.json b/modules/portainer/module.json index f088bce..cb36c93 100644 --- a/modules/portainer/module.json +++ b/modules/portainer/module.json @@ -51,7 +51,6 @@ "id": "runtime", "type": "container", "name": "mesh-portainer", - "image": "mesh-runtime-portainer@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/portainer/broker:/run/secrets/broker:ro", @@ -64,10 +63,32 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "own-secrets": { "broker": "/var/lib/mesh/portainer/broker" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/postgres/Dockerfile b/modules/postgres/Dockerfile index c8a2e36..818ada5 100644 --- a/modules/postgres/Dockerfile +++ b/modules/postgres/Dockerfile @@ -38,4 +38,4 @@ COPY --from=build /app/modules/postgres/dist /app/modules/postgres/dist # separate entrypoints because they are loaded by different things. The provisioner is the third, # and is not listed here — the declaration names it in the container's `args`, because it is what # this module's own container runs. One image, because they are one module and share a client. -ENV MESH_TOOL_MODULES=/app/modules/postgres/dist/index.js,/app/modules/postgres/dist/tools/index.js +ENV MESH_TOOL_MODULES=/app/modules/postgres/dist/index.js,/app/modules/postgres/dist/tools/index.js,/app/modules/postgres/dist/provisioner/index.js diff --git a/modules/postgres/module.json b/modules/postgres/module.json index 6d27b72..4841894 100644 --- a/modules/postgres/module.json +++ b/modules/postgres/module.json @@ -98,11 +98,7 @@ "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_RECEIVES": "/var/lib/postgres/grants/mesh.json" }, - "artifact": "runtime", - "args": [ - "run", - "/app/modules/postgres/dist/provisioner/index.js" - ] + "artifact": "runtime" } ], "build": { diff --git a/modules/redis/Dockerfile b/modules/redis/Dockerfile new file mode 100644 index 0000000..2338a69 --- /dev/null +++ b/modules/redis/Dockerfile @@ -0,0 +1,30 @@ +# redis's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/redis +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts provisioner/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/redis/dist /app/modules/redis/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/redis/dist/index.js,/app/modules/redis/dist/tools/index.js,/app/modules/redis/dist/provisioner/index.js diff --git a/modules/redis/module.json b/modules/redis/module.json index f50859d..22d2960 100644 --- a/modules/redis/module.json +++ b/modules/redis/module.json @@ -101,7 +101,6 @@ "id": "runtime", "type": "container", "name": "mesh-redis", - "image": "mesh-runtime-redis@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "redis", "volumes": [ "/var/lib/mesh/redis/broker:/run/secrets/broker:ro", @@ -113,7 +112,29 @@ "MESH_RECEIVES": "/var/lib/redis-module/grants/mesh.json", "MESH_PROVISION_REDIS": "redis:6379", "MESH_PROVISION_PASSWORD_FILE": "/run/secrets/default" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/umami/Dockerfile b/modules/umami/Dockerfile new file mode 100644 index 0000000..2cf6a83 --- /dev/null +++ b/modules/umami/Dockerfile @@ -0,0 +1,30 @@ +# umami's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/umami +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts provisioner/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/umami/dist /app/modules/umami/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/umami/dist/tools/index.js,/app/modules/umami/dist/provisioner/index.js diff --git a/modules/umami/module.json b/modules/umami/module.json index 761baa0..b7991e3 100644 --- a/modules/umami/module.json +++ b/modules/umami/module.json @@ -107,7 +107,6 @@ "id": "runtime", "type": "container", "name": "mesh-umami", - "image": "mesh-runtime-umami@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "umami", "volumes": [ "/var/lib/mesh/umami/broker:/run/secrets/broker:ro", @@ -121,7 +120,29 @@ }, "env-file": [ "/var/lib/umami/provisioner.env" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/verdaccio/Dockerfile b/modules/verdaccio/Dockerfile new file mode 100644 index 0000000..ee4fec8 --- /dev/null +++ b/modules/verdaccio/Dockerfile @@ -0,0 +1,30 @@ +# verdaccio's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own +# node_modules — the module is compiled against exactly the sdk it will run against. The compiler +# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image +# resolved away. +WORKDIR /app/modules/verdaccio +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/verdaccio/dist /app/modules/verdaccio/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. A container that instead ran only its +# provisioner (`run`) served no tools and emitted no events; a container that named no command +# ran no provisioner at all. +ENV MESH_TOOL_MODULES=/app/modules/verdaccio/dist/index.js,/app/modules/verdaccio/dist/tools/index.js diff --git a/modules/verdaccio/module.json b/modules/verdaccio/module.json index 3c52bd8..8cd1a06 100644 --- a/modules/verdaccio/module.json +++ b/modules/verdaccio/module.json @@ -72,7 +72,6 @@ "id": "runtime", "type": "container", "name": "mesh-verdaccio", - "image": "mesh-runtime-verdaccio@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/verdaccio/broker:/run/secrets/broker:ro", @@ -85,7 +84,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -105,5 +105,26 @@ "name": "package-registry", "scope": "mesh" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } -- 2.54.0 From e362fb951c78954155db447c6828bb9d536ecff4 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 18 Sep 2026 02:14:09 +0200 Subject: [PATCH 2/4] The rest of the catalogue becomes mesh-buildable (issue 060, batch 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 21 media/home modules, the SaaS tool modules (cloudflare-dns, confluence, gitlab, jira), model-usage, and the model-access trio get the same Dockerfile + build section as batch 1. Scheduled-only modules (anthropic-consumer, anthropic-manager, openai-consumer) deliberately declare no MESH_TOOL_MODULES — every container of theirs names its command. mosquitto's run-once bootstrap container builds from the same artifact. Modules with third-party deps (model-usage: pg; anthropic-manager: tweetnacl) install them beside their compiled code. Also fixes cloudflare-dns's package.json, unparseable since its description lost a closing quote. Deliberately still without build sections: builder and mesh-controller (the foundation builds them by its own path), distribution (provides the artifact store — building it through itself is refused by design), route-proxy (cross-repo build context, deferred), and the upstream-image-only modules, which have no code to build. --- modules/anthropic-consumer/Dockerfile | 22 ++++++++++++++++++ modules/anthropic-consumer/module.json | 31 +++++++++++++++++++++----- modules/anthropic-manager/Dockerfile | 26 +++++++++++++++++++++ modules/anthropic-manager/module.json | 27 +++++++++++++++++++--- modules/baserow/Dockerfile | 24 ++++++++++++++++++++ modules/baserow/module.json | 27 +++++++++++++++++++--- modules/bazarr/Dockerfile | 24 ++++++++++++++++++++ modules/bazarr/module.json | 25 +++++++++++++++++++-- modules/bookshelf/Dockerfile | 24 ++++++++++++++++++++ modules/bookshelf/module.json | 25 +++++++++++++++++++-- modules/cloudflare-dns/Dockerfile | 24 ++++++++++++++++++++ modules/cloudflare-dns/module.json | 27 +++++++++++++++++++--- modules/cloudflare-dns/package.json | 2 +- modules/confluence/Dockerfile | 24 ++++++++++++++++++++ modules/confluence/module.json | 27 +++++++++++++++++++--- modules/gitlab/Dockerfile | 24 ++++++++++++++++++++ modules/gitlab/module.json | 27 +++++++++++++++++++--- modules/grafana/Dockerfile | 24 ++++++++++++++++++++ modules/grafana/module.json | 25 +++++++++++++++++++-- modules/home-assistant/Dockerfile | 24 ++++++++++++++++++++ modules/home-assistant/module.json | 25 +++++++++++++++++++-- modules/icecast/Dockerfile | 24 ++++++++++++++++++++ modules/icecast/module.json | 27 +++++++++++++++++++--- modules/influxdb/Dockerfile | 24 ++++++++++++++++++++ modules/influxdb/module.json | 27 +++++++++++++++++++--- modules/jackett/Dockerfile | 24 ++++++++++++++++++++ modules/jackett/module.json | 25 +++++++++++++++++++-- modules/jira/Dockerfile | 24 ++++++++++++++++++++ modules/jira/module.json | 27 +++++++++++++++++++--- modules/letta/Dockerfile | 24 ++++++++++++++++++++ modules/letta/module.json | 27 +++++++++++++++++++--- modules/lidarr/Dockerfile | 24 ++++++++++++++++++++ modules/lidarr/module.json | 25 +++++++++++++++++++-- modules/model-usage/Dockerfile | 28 +++++++++++++++++++++++ modules/model-usage/module.json | 27 +++++++++++++++++++--- modules/mosquitto/Dockerfile | 28 +++++++++++++++++++++++ modules/mosquitto/module.json | 31 +++++++++++++++++++++----- modules/nodered/Dockerfile | 24 ++++++++++++++++++++ modules/nodered/module.json | 25 +++++++++++++++++++-- modules/nzbget/Dockerfile | 24 ++++++++++++++++++++ modules/nzbget/module.json | 27 +++++++++++++++++++--- modules/ombi/Dockerfile | 24 ++++++++++++++++++++ modules/ombi/module.json | 25 +++++++++++++++++++-- modules/openai-consumer/Dockerfile | 22 ++++++++++++++++++ modules/openai-consumer/module.json | 27 +++++++++++++++++++--- modules/plex/Dockerfile | 24 ++++++++++++++++++++ modules/plex/module.json | 27 +++++++++++++++++++--- modules/qbittorrent/Dockerfile | 24 ++++++++++++++++++++ modules/qbittorrent/module.json | 27 +++++++++++++++++++--- modules/radarr/Dockerfile | 24 ++++++++++++++++++++ modules/radarr/module.json | 25 +++++++++++++++++++-- modules/searxng/Dockerfile | 24 ++++++++++++++++++++ modules/searxng/module.json | 25 +++++++++++++++++++-- modules/sonarr/Dockerfile | 24 ++++++++++++++++++++ modules/sonarr/module.json | 25 +++++++++++++++++++-- modules/tautulli/Dockerfile | 24 ++++++++++++++++++++ modules/tautulli/module.json | 25 +++++++++++++++++++-- modules/unifi/Dockerfile | 24 ++++++++++++++++++++ modules/unifi/module.json | 29 ++++++++++++++++++++---- 59 files changed, 1392 insertions(+), 81 deletions(-) create mode 100644 modules/anthropic-consumer/Dockerfile create mode 100644 modules/anthropic-manager/Dockerfile create mode 100644 modules/baserow/Dockerfile create mode 100644 modules/bazarr/Dockerfile create mode 100644 modules/bookshelf/Dockerfile create mode 100644 modules/cloudflare-dns/Dockerfile create mode 100644 modules/confluence/Dockerfile create mode 100644 modules/gitlab/Dockerfile create mode 100644 modules/grafana/Dockerfile create mode 100644 modules/home-assistant/Dockerfile create mode 100644 modules/icecast/Dockerfile create mode 100644 modules/influxdb/Dockerfile create mode 100644 modules/jackett/Dockerfile create mode 100644 modules/jira/Dockerfile create mode 100644 modules/letta/Dockerfile create mode 100644 modules/lidarr/Dockerfile create mode 100644 modules/model-usage/Dockerfile create mode 100644 modules/mosquitto/Dockerfile create mode 100644 modules/nodered/Dockerfile create mode 100644 modules/nzbget/Dockerfile create mode 100644 modules/ombi/Dockerfile create mode 100644 modules/openai-consumer/Dockerfile create mode 100644 modules/plex/Dockerfile create mode 100644 modules/qbittorrent/Dockerfile create mode 100644 modules/radarr/Dockerfile create mode 100644 modules/searxng/Dockerfile create mode 100644 modules/sonarr/Dockerfile create mode 100644 modules/tautulli/Dockerfile create mode 100644 modules/unifi/Dockerfile diff --git a/modules/anthropic-consumer/Dockerfile b/modules/anthropic-consumer/Dockerfile new file mode 100644 index 0000000..8445007 --- /dev/null +++ b/modules/anthropic-consumer/Dockerfile @@ -0,0 +1,22 @@ +# anthropic-consumer's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/anthropic-consumer +COPY . . +RUN node /app/node_modules/typescript/bin/tsc apply/index.ts usage/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/anthropic-consumer/dist /app/modules/anthropic-consumer/dist +# No serve-time entrypoints: every container of this module names its command (`run` on a +# schedule), so nothing here serves — deliberately no MESH_TOOL_MODULES. diff --git a/modules/anthropic-consumer/module.json b/modules/anthropic-consumer/module.json index b6cc60d..981199d 100644 --- a/modules/anthropic-consumer/module.json +++ b/modules/anthropic-consumer/module.json @@ -49,7 +49,6 @@ "id": "apply", "type": "container", "name": "mesh-anthropic-consumer-apply", - "image": "mesh-runtime-anthropic-consumer@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "schedule": "*/5 * * * *", "args": [ @@ -64,13 +63,13 @@ "MESH_MODEL_ACCESS_BIND_FILE": "/run/state/model.json", "MESH_CLAUDE_CREDENTIALS_FILE": "/run/state/claude/.credentials.json", "MESH_CLAUDE_IDENTITY_FILE": "/run/state/claude/.claude.json" - } + }, + "artifact": "runtime" }, { "id": "usage", "type": "container", "name": "mesh-anthropic-consumer-usage", - "image": "mesh-runtime-anthropic-consumer@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "schedule": "*/5 * * * *", "args": [ @@ -86,7 +85,29 @@ "MESH_CLAUDE_PROJECTS_DIR": "/run/state/claude/projects", "MESH_ANTHROPIC_USAGE_OUT": "/run/state/out/session-usage.json", "MESH_TOOLS_MAIN": "/app/dist/main.js" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/anthropic-manager/Dockerfile b/modules/anthropic-manager/Dockerfile new file mode 100644 index 0000000..7f96fd0 --- /dev/null +++ b/modules/anthropic-manager/Dockerfile @@ -0,0 +1,26 @@ +# anthropic-manager's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/anthropic-manager +COPY . . +# This module's own third-party dependencies, installed beside its compiled code so Node +# resolves them from the module and falls back to the shared tree for everything common. +RUN npm install --omit=dev --no-save --no-package-lock --ignore-scripts "tweetnacl@^1.0.3" "tweetnacl-sealedbox-js@^1.2.0" +RUN node /app/node_modules/typescript/bin/tsc client.ts adopt/index.ts refresh/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/anthropic-manager/dist /app/modules/anthropic-manager/dist +COPY --from=build /app/modules/anthropic-manager/node_modules /app/modules/anthropic-manager/node_modules +# No serve-time entrypoints: every container of this module names its command (`run` on a +# schedule), so nothing here serves — deliberately no MESH_TOOL_MODULES. diff --git a/modules/anthropic-manager/module.json b/modules/anthropic-manager/module.json index b0f9d55..dc50d7f 100644 --- a/modules/anthropic-manager/module.json +++ b/modules/anthropic-manager/module.json @@ -37,7 +37,6 @@ "id": "refresh", "type": "container", "name": "mesh-anthropic-manager-refresh", - "image": "mesh-runtime-anthropic-manager@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "schedule": "*/5 * * * *", "args": [ @@ -57,7 +56,29 @@ "MESH_ANTHROPIC_GRANT_OUT": "/run/state/out/grant.json", "MESH_ANTHROPIC_USAGE_OUT": "/run/state/out/usage.json", "MESH_TOOLS_MAIN": "/app/dist/main.js" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/baserow/Dockerfile b/modules/baserow/Dockerfile new file mode 100644 index 0000000..e60fe27 --- /dev/null +++ b/modules/baserow/Dockerfile @@ -0,0 +1,24 @@ +# baserow's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/baserow +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/baserow/dist /app/modules/baserow/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/baserow/dist/tools/index.js diff --git a/modules/baserow/module.json b/modules/baserow/module.json index 3302e44..e004c57 100644 --- a/modules/baserow/module.json +++ b/modules/baserow/module.json @@ -99,7 +99,6 @@ "id": "runtime", "type": "container", "name": "mesh-baserow", - "image": "mesh-runtime-baserow@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "baserow", "volumes": [ "/var/lib/mesh/baserow/broker:/run/secrets/broker:ro", @@ -112,7 +111,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/bazarr/Dockerfile b/modules/bazarr/Dockerfile new file mode 100644 index 0000000..8e9844a --- /dev/null +++ b/modules/bazarr/Dockerfile @@ -0,0 +1,24 @@ +# bazarr's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/bazarr +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/bazarr/dist /app/modules/bazarr/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/bazarr/dist/index.js,/app/modules/bazarr/dist/tools/index.js diff --git a/modules/bazarr/module.json b/modules/bazarr/module.json index c116eac..fb95070 100644 --- a/modules/bazarr/module.json +++ b/modules/bazarr/module.json @@ -84,7 +84,6 @@ "id": "runtime", "type": "container", "name": "mesh-bazarr", - "image": "mesh-runtime-bazarr@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/bazarr/broker:/run/secrets/broker:ro", @@ -101,7 +100,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -115,5 +115,26 @@ }, "binds": { "route": "/var/lib/mesh/bazarr/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/bookshelf/Dockerfile b/modules/bookshelf/Dockerfile new file mode 100644 index 0000000..2b0f05f --- /dev/null +++ b/modules/bookshelf/Dockerfile @@ -0,0 +1,24 @@ +# bookshelf's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/bookshelf +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/bookshelf/dist /app/modules/bookshelf/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/bookshelf/dist/index.js,/app/modules/bookshelf/dist/tools/index.js diff --git a/modules/bookshelf/module.json b/modules/bookshelf/module.json index f47112d..9361d77 100644 --- a/modules/bookshelf/module.json +++ b/modules/bookshelf/module.json @@ -68,7 +68,6 @@ "id": "runtime", "type": "container", "name": "mesh-bookshelf", - "image": "mesh-runtime-bookshelf@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/bookshelf/broker:/run/secrets/broker:ro", @@ -78,7 +77,8 @@ "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_BOOKSHELF_URL": "http://127.0.0.1:8787", "MESH_BOOKSHELF_CONFIG_DIR": "/var/lib/bookshelf/config" - } + }, + "artifact": "runtime" } ], "requires": [ @@ -92,5 +92,26 @@ }, "binds": { "route": "/var/lib/mesh/bookshelf/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/cloudflare-dns/Dockerfile b/modules/cloudflare-dns/Dockerfile new file mode 100644 index 0000000..c838705 --- /dev/null +++ b/modules/cloudflare-dns/Dockerfile @@ -0,0 +1,24 @@ +# cloudflare-dns's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/cloudflare-dns +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts provisioner/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/cloudflare-dns/dist /app/modules/cloudflare-dns/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/cloudflare-dns/dist/tools/index.js,/app/modules/cloudflare-dns/dist/provisioner/index.js diff --git a/modules/cloudflare-dns/module.json b/modules/cloudflare-dns/module.json index 51908e8..5a52670 100644 --- a/modules/cloudflare-dns/module.json +++ b/modules/cloudflare-dns/module.json @@ -56,7 +56,6 @@ "id": "runtime", "type": "container", "name": "mesh-cloudflare-dns", - "image": "mesh-runtime-cloudflare-dns@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/cloudflare-dns/config.json:/run/config/config.json:ro", @@ -69,10 +68,32 @@ "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_CLOUDFLARE_CONFIG_FILE": "/run/config/config.json", "MESH_RECEIVES": "/var/lib/cloudflare-dns/grants/mesh.json" - } + }, + "artifact": "runtime" } ], "capabilities": [ "container-runtime" - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/cloudflare-dns/package.json b/modules/cloudflare-dns/package.json index a032b8e..0c5bbd5 100644 --- a/modules/cloudflare-dns/package.json +++ b/modules/cloudflare-dns/package.json @@ -1,7 +1,7 @@ { "name": "@novox/module-cloudflare-dns", "version": "0.1.0", - "description": "cloudflare-dns — a public-dns provider (ADR 0044): registers public names at Cloudflare. + "description": "cloudflare-dns — a public-dns provider (ADR 0044): registers public names at Cloudflare.", "type": "module", "private": true, "dependencies": { diff --git a/modules/confluence/Dockerfile b/modules/confluence/Dockerfile new file mode 100644 index 0000000..f2e075a --- /dev/null +++ b/modules/confluence/Dockerfile @@ -0,0 +1,24 @@ +# confluence's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/confluence +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/confluence/dist /app/modules/confluence/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/confluence/dist/tools/index.js diff --git a/modules/confluence/module.json b/modules/confluence/module.json index 8355df3..b28168b 100644 --- a/modules/confluence/module.json +++ b/modules/confluence/module.json @@ -31,7 +31,6 @@ "id": "runtime", "type": "container", "name": "mesh-runtime-confluence", - "image": "mesh-runtime-confluence@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/confluence/config.json:/run/config/config.json:ro", @@ -42,10 +41,32 @@ "MESH_CONFLUENCE_TOKEN_FILE": "/run/secrets/token", "MESH_CONFLUENCE_CONFIG_FILE": "/run/config/config.json", "MESH_BROKER_FILE": "/run/secrets/broker" - } + }, + "artifact": "runtime" } ], "capabilities": [ "container-runtime" - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/gitlab/Dockerfile b/modules/gitlab/Dockerfile new file mode 100644 index 0000000..4a27d6c --- /dev/null +++ b/modules/gitlab/Dockerfile @@ -0,0 +1,24 @@ +# gitlab's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/gitlab +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/gitlab/dist /app/modules/gitlab/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/gitlab/dist/tools/index.js diff --git a/modules/gitlab/module.json b/modules/gitlab/module.json index c580600..b082001 100644 --- a/modules/gitlab/module.json +++ b/modules/gitlab/module.json @@ -30,7 +30,6 @@ "id": "runtime", "type": "container", "name": "mesh-runtime-gitlab", - "image": "mesh-runtime-gitlab@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/gitlab/config.json:/run/config/config.json:ro", @@ -41,10 +40,32 @@ "MESH_GITLAB_TOKEN_FILE": "/run/secrets/token", "MESH_GITLAB_CONFIG_FILE": "/run/config/config.json", "MESH_BROKER_FILE": "/run/secrets/broker" - } + }, + "artifact": "runtime" } ], "capabilities": [ "container-runtime" - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/grafana/Dockerfile b/modules/grafana/Dockerfile new file mode 100644 index 0000000..9ff34c1 --- /dev/null +++ b/modules/grafana/Dockerfile @@ -0,0 +1,24 @@ +# grafana's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/grafana +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/grafana/dist /app/modules/grafana/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/grafana/dist/index.js,/app/modules/grafana/dist/tools/index.js diff --git a/modules/grafana/module.json b/modules/grafana/module.json index 60318dd..5e35aff 100644 --- a/modules/grafana/module.json +++ b/modules/grafana/module.json @@ -73,7 +73,6 @@ "id": "runtime", "type": "container", "name": "mesh-grafana", - "image": "mesh-runtime-grafana@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/grafana/broker:/run/secrets/broker:ro", @@ -86,7 +85,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -100,5 +100,26 @@ }, "binds": { "route": "/var/lib/mesh/grafana/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/home-assistant/Dockerfile b/modules/home-assistant/Dockerfile new file mode 100644 index 0000000..b3cced2 --- /dev/null +++ b/modules/home-assistant/Dockerfile @@ -0,0 +1,24 @@ +# home-assistant's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/home-assistant +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/home-assistant/dist /app/modules/home-assistant/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/home-assistant/dist/index.js,/app/modules/home-assistant/dist/tools/index.js diff --git a/modules/home-assistant/module.json b/modules/home-assistant/module.json index d528dd7..4b8bcb9 100644 --- a/modules/home-assistant/module.json +++ b/modules/home-assistant/module.json @@ -59,7 +59,6 @@ "id": "runtime", "type": "container", "name": "mesh-home-assistant", - "image": "mesh-runtime-home-assistant@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/home-assistant/broker:/run/secrets/broker:ro", @@ -76,7 +75,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -90,5 +90,26 @@ }, "binds": { "route": "/var/lib/mesh/home-assistant/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/icecast/Dockerfile b/modules/icecast/Dockerfile new file mode 100644 index 0000000..cdc8b00 --- /dev/null +++ b/modules/icecast/Dockerfile @@ -0,0 +1,24 @@ +# icecast's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/icecast +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/icecast/dist /app/modules/icecast/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/icecast/dist/index.js,/app/modules/icecast/dist/tools/index.js diff --git a/modules/icecast/module.json b/modules/icecast/module.json index 6d49425..ec765ec 100644 --- a/modules/icecast/module.json +++ b/modules/icecast/module.json @@ -66,7 +66,6 @@ "id": "runtime", "type": "container", "name": "mesh-icecast", - "image": "mesh-runtime-icecast@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/icecast/broker:/run/secrets/broker:ro", @@ -79,7 +78,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/influxdb/Dockerfile b/modules/influxdb/Dockerfile new file mode 100644 index 0000000..341d8ce --- /dev/null +++ b/modules/influxdb/Dockerfile @@ -0,0 +1,24 @@ +# influxdb's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/influxdb +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/influxdb/dist /app/modules/influxdb/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/influxdb/dist/tools/index.js diff --git a/modules/influxdb/module.json b/modules/influxdb/module.json index 62c31dc..b51328a 100644 --- a/modules/influxdb/module.json +++ b/modules/influxdb/module.json @@ -79,7 +79,6 @@ "id": "runtime", "type": "container", "name": "mesh-influxdb", - "image": "mesh-runtime-influxdb@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/influxdb/broker:/run/secrets/broker:ro", @@ -94,7 +93,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/jackett/Dockerfile b/modules/jackett/Dockerfile new file mode 100644 index 0000000..50911de --- /dev/null +++ b/modules/jackett/Dockerfile @@ -0,0 +1,24 @@ +# jackett's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/jackett +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/jackett/dist /app/modules/jackett/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/jackett/dist/tools/index.js diff --git a/modules/jackett/module.json b/modules/jackett/module.json index d5f681e..a2a5d06 100644 --- a/modules/jackett/module.json +++ b/modules/jackett/module.json @@ -55,7 +55,6 @@ "id": "runtime", "type": "container", "name": "mesh-jackett", - "image": "mesh-runtime-jackett@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/jackett/broker:/run/secrets/broker:ro", @@ -70,7 +69,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "own-secrets": { @@ -87,5 +87,26 @@ }, "binds": { "route": "/var/lib/mesh/jackett/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/jira/Dockerfile b/modules/jira/Dockerfile new file mode 100644 index 0000000..0d9cabb --- /dev/null +++ b/modules/jira/Dockerfile @@ -0,0 +1,24 @@ +# jira's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/jira +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/jira/dist /app/modules/jira/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/jira/dist/tools/index.js diff --git a/modules/jira/module.json b/modules/jira/module.json index 42bbdc1..62e6e64 100644 --- a/modules/jira/module.json +++ b/modules/jira/module.json @@ -30,7 +30,6 @@ "id": "runtime", "type": "container", "name": "mesh-runtime-jira", - "image": "mesh-runtime-jira@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/jira/config.json:/run/config/config.json:ro", @@ -41,10 +40,32 @@ "MESH_JIRA_TOKEN_FILE": "/run/secrets/token", "MESH_JIRA_CONFIG_FILE": "/run/config/config.json", "MESH_BROKER_FILE": "/run/secrets/broker" - } + }, + "artifact": "runtime" } ], "capabilities": [ "container-runtime" - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/letta/Dockerfile b/modules/letta/Dockerfile new file mode 100644 index 0000000..cd28e15 --- /dev/null +++ b/modules/letta/Dockerfile @@ -0,0 +1,24 @@ +# letta's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/letta +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/letta/dist /app/modules/letta/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/letta/dist/tools/index.js diff --git a/modules/letta/module.json b/modules/letta/module.json index 5774538..cdb419e 100644 --- a/modules/letta/module.json +++ b/modules/letta/module.json @@ -87,7 +87,6 @@ "id": "runtime", "type": "container", "name": "mesh-letta", - "image": "mesh-runtime-letta@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "letta", "volumes": [ "/var/lib/mesh/letta/broker:/run/secrets/broker:ro", @@ -103,7 +102,29 @@ ], "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/lidarr/Dockerfile b/modules/lidarr/Dockerfile new file mode 100644 index 0000000..83c0375 --- /dev/null +++ b/modules/lidarr/Dockerfile @@ -0,0 +1,24 @@ +# lidarr's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/lidarr +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/lidarr/dist /app/modules/lidarr/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/lidarr/dist/index.js,/app/modules/lidarr/dist/tools/index.js diff --git a/modules/lidarr/module.json b/modules/lidarr/module.json index 1533966..ebb2b0b 100644 --- a/modules/lidarr/module.json +++ b/modules/lidarr/module.json @@ -67,7 +67,6 @@ "id": "runtime", "type": "container", "name": "mesh-lidarr", - "image": "mesh-runtime-lidarr@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/lidarr/broker:/run/secrets/broker:ro", @@ -77,7 +76,8 @@ "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_LIDARR_URL": "http://127.0.0.1:8686", "MESH_LIDARR_CONFIG_DIR": "/var/lib/lidarr/config" - } + }, + "artifact": "runtime" } ], "requires": [ @@ -91,5 +91,26 @@ }, "binds": { "route": "/var/lib/mesh/lidarr/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/model-usage/Dockerfile b/modules/model-usage/Dockerfile new file mode 100644 index 0000000..b6da6be --- /dev/null +++ b/modules/model-usage/Dockerfile @@ -0,0 +1,28 @@ +# model-usage's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/model-usage +COPY . . +# This module's own third-party dependencies, installed beside its compiled code so Node +# resolves them from the module and falls back to the shared tree for everything common. +RUN npm install --omit=dev --no-save --no-package-lock --ignore-scripts "pg@^8" +RUN node /app/node_modules/typescript/bin/tsc index.ts tools/index.ts pg.d.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/model-usage/dist /app/modules/model-usage/dist +COPY --from=build /app/modules/model-usage/node_modules /app/modules/model-usage/node_modules +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/model-usage/dist/index.js,/app/modules/model-usage/dist/tools/index.js diff --git a/modules/model-usage/module.json b/modules/model-usage/module.json index d9cdba6..75d9553 100644 --- a/modules/model-usage/module.json +++ b/modules/model-usage/module.json @@ -49,7 +49,6 @@ "id": "runtime", "type": "container", "name": "mesh-model-usage", - "image": "mesh-runtime-model-usage@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/model-usage/broker:/run/secrets/broker:ro", @@ -60,7 +59,29 @@ }, "env-file": [ "/var/lib/model-usage/db.env" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/mosquitto/Dockerfile b/modules/mosquitto/Dockerfile new file mode 100644 index 0000000..cdd07b1 --- /dev/null +++ b/modules/mosquitto/Dockerfile @@ -0,0 +1,28 @@ +# mosquitto's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/mosquitto +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts provisioner/index.ts bootstrap/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +# mosquitto's client and bootstrap drive `mosquitto_ctrl`; the apt package carries it with its +# shared libraries — the musl binary from the eclipse image would not load on this glibc base. +RUN apt-get update && apt-get install -y --no-install-recommends mosquitto \ + && rm -rf /var/lib/apt/lists/* +COPY --from=build /app/modules/mosquitto/dist /app/modules/mosquitto/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/mosquitto/dist/index.js,/app/modules/mosquitto/dist/tools/index.js,/app/modules/mosquitto/dist/provisioner/index.js diff --git a/modules/mosquitto/module.json b/modules/mosquitto/module.json index 2a9cbae..774231f 100644 --- a/modules/mosquitto/module.json +++ b/modules/mosquitto/module.json @@ -89,7 +89,6 @@ "id": "bootstrap", "type": "container", "name": "mosquitto-bootstrap", - "image": "mesh-runtime-mosquitto@sha256:0000000000000000000000000000000000000000000000000000000000000000", "run-once": true, "volumes": [ "/services/mosquitto/data:/mosquitto/data", @@ -104,7 +103,8 @@ "args": [ "run", "/app/modules/mosquitto/dist/bootstrap/index.js" - ] + ], + "artifact": "runtime" }, { "id": "server", @@ -125,7 +125,6 @@ "id": "runtime", "type": "container", "name": "mesh-mosquitto", - "image": "mesh-runtime-mosquitto@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "mosquitto", "volumes": [ "/var/lib/mesh/mosquitto/broker:/run/secrets/broker:ro", @@ -138,7 +137,29 @@ "MESH_PROVISION_MQTT": "mosquitto:1883", "MESH_PROVISION_ADMIN_USER": "mesh-admin", "MESH_PROVISION_PASSWORD_FILE": "/run/secrets/admin" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/nodered/Dockerfile b/modules/nodered/Dockerfile new file mode 100644 index 0000000..afa2f8c --- /dev/null +++ b/modules/nodered/Dockerfile @@ -0,0 +1,24 @@ +# nodered's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/nodered +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/nodered/dist /app/modules/nodered/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/nodered/dist/tools/index.js diff --git a/modules/nodered/module.json b/modules/nodered/module.json index bc3d95e..73217b4 100644 --- a/modules/nodered/module.json +++ b/modules/nodered/module.json @@ -59,7 +59,6 @@ "id": "runtime", "type": "container", "name": "mesh-nodered", - "image": "mesh-runtime-nodered@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/nodered/broker:/run/secrets/broker:ro", @@ -72,7 +71,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -86,5 +86,26 @@ }, "binds": { "route": "/var/lib/mesh/nodered/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/nzbget/Dockerfile b/modules/nzbget/Dockerfile new file mode 100644 index 0000000..338f493 --- /dev/null +++ b/modules/nzbget/Dockerfile @@ -0,0 +1,24 @@ +# nzbget's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/nzbget +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/nzbget/dist /app/modules/nzbget/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/nzbget/dist/index.js,/app/modules/nzbget/dist/tools/index.js diff --git a/modules/nzbget/module.json b/modules/nzbget/module.json index 42b9cdf..94f0f87 100644 --- a/modules/nzbget/module.json +++ b/modules/nzbget/module.json @@ -71,7 +71,6 @@ "id": "runtime", "type": "container", "name": "mesh-nzbget", - "image": "mesh-runtime-nzbget@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/nzbget/broker:/run/secrets/broker:ro", @@ -88,7 +87,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/ombi/Dockerfile b/modules/ombi/Dockerfile new file mode 100644 index 0000000..fb96f72 --- /dev/null +++ b/modules/ombi/Dockerfile @@ -0,0 +1,24 @@ +# ombi's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/ombi +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/ombi/dist /app/modules/ombi/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/ombi/dist/index.js,/app/modules/ombi/dist/tools/index.js diff --git a/modules/ombi/module.json b/modules/ombi/module.json index 97cff4b..27536d7 100644 --- a/modules/ombi/module.json +++ b/modules/ombi/module.json @@ -63,7 +63,6 @@ "id": "runtime", "type": "container", "name": "mesh-ombi", - "image": "mesh-runtime-ombi@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/ombi/broker:/run/secrets/broker:ro", @@ -80,7 +79,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -94,5 +94,26 @@ }, "binds": { "route": "/var/lib/mesh/ombi/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/openai-consumer/Dockerfile b/modules/openai-consumer/Dockerfile new file mode 100644 index 0000000..ff58bd2 --- /dev/null +++ b/modules/openai-consumer/Dockerfile @@ -0,0 +1,22 @@ +# openai-consumer's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/openai-consumer +COPY . . +RUN node /app/node_modules/typescript/bin/tsc apply/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/openai-consumer/dist /app/modules/openai-consumer/dist +# No serve-time entrypoints: every container of this module names its command (`run` on a +# schedule), so nothing here serves — deliberately no MESH_TOOL_MODULES. diff --git a/modules/openai-consumer/module.json b/modules/openai-consumer/module.json index 9c2b8d9..fef8822 100644 --- a/modules/openai-consumer/module.json +++ b/modules/openai-consumer/module.json @@ -31,7 +31,6 @@ "id": "apply", "type": "container", "name": "mesh-openai-consumer-apply", - "image": "mesh-runtime-openai-consumer@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "schedule": "*/5 * * * *", "args": [ @@ -46,7 +45,29 @@ "MESH_MODEL_ACCESS_BIND_FILE": "/run/state/model.json", "MESH_OPENAI_ENV_FILE": "/run/state/config/openai.env", "MESH_OPENAI_CREDENTIALS_FILE": "/run/state/config/auth.json" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/plex/Dockerfile b/modules/plex/Dockerfile new file mode 100644 index 0000000..31f7958 --- /dev/null +++ b/modules/plex/Dockerfile @@ -0,0 +1,24 @@ +# plex's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/plex +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/plex/dist /app/modules/plex/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/plex/dist/index.js,/app/modules/plex/dist/tools/index.js diff --git a/modules/plex/module.json b/modules/plex/module.json index c184c18..b5c56f0 100644 --- a/modules/plex/module.json +++ b/modules/plex/module.json @@ -92,7 +92,6 @@ "id": "runtime", "type": "container", "name": "mesh-plex", - "image": "mesh-runtime-plex@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/plex/broker:/run/secrets/broker:ro", @@ -104,7 +103,29 @@ "MESH_PLEX_URL": "http://127.0.0.1:32400", "MESH_PLEX_TOKEN_FILE": "/run/secrets/token", "MESH_PLEX_DATA_DIR": "/var/lib/plex" - } + }, + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/qbittorrent/Dockerfile b/modules/qbittorrent/Dockerfile new file mode 100644 index 0000000..91832e0 --- /dev/null +++ b/modules/qbittorrent/Dockerfile @@ -0,0 +1,24 @@ +# qbittorrent's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/qbittorrent +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/qbittorrent/dist /app/modules/qbittorrent/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/qbittorrent/dist/index.js,/app/modules/qbittorrent/dist/tools/index.js diff --git a/modules/qbittorrent/module.json b/modules/qbittorrent/module.json index f14a496..1820649 100644 --- a/modules/qbittorrent/module.json +++ b/modules/qbittorrent/module.json @@ -72,7 +72,6 @@ "id": "runtime", "type": "container", "name": "mesh-qbittorrent", - "image": "mesh-runtime-qbittorrent@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/qbittorrent/broker:/run/secrets/broker:ro", @@ -89,7 +88,29 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } - ] + ], + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] + } } diff --git a/modules/radarr/Dockerfile b/modules/radarr/Dockerfile new file mode 100644 index 0000000..4a04bde --- /dev/null +++ b/modules/radarr/Dockerfile @@ -0,0 +1,24 @@ +# radarr's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/radarr +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/radarr/dist /app/modules/radarr/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/radarr/dist/index.js,/app/modules/radarr/dist/tools/index.js diff --git a/modules/radarr/module.json b/modules/radarr/module.json index db77f89..4b39284 100644 --- a/modules/radarr/module.json +++ b/modules/radarr/module.json @@ -67,7 +67,6 @@ "id": "runtime", "type": "container", "name": "mesh-radarr", - "image": "mesh-runtime-radarr@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/radarr/broker:/run/secrets/broker:ro", @@ -77,7 +76,8 @@ "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_RADARR_URL": "http://127.0.0.1:7878", "MESH_RADARR_CONFIG_DIR": "/var/lib/radarr/config" - } + }, + "artifact": "runtime" } ], "requires": [ @@ -91,5 +91,26 @@ }, "binds": { "route": "/var/lib/mesh/radarr/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/searxng/Dockerfile b/modules/searxng/Dockerfile new file mode 100644 index 0000000..12e7f29 --- /dev/null +++ b/modules/searxng/Dockerfile @@ -0,0 +1,24 @@ +# searxng's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/searxng +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/searxng/dist /app/modules/searxng/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/searxng/dist/tools/index.js diff --git a/modules/searxng/module.json b/modules/searxng/module.json index 881b37b..60a0951 100644 --- a/modules/searxng/module.json +++ b/modules/searxng/module.json @@ -84,7 +84,6 @@ "id": "runtime", "type": "container", "name": "mesh-searxng", - "image": "mesh-runtime-searxng@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/searxng/broker:/run/secrets/broker:ro", @@ -97,7 +96,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -111,5 +111,26 @@ }, "binds": { "route": "/var/lib/searxng-module/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/sonarr/Dockerfile b/modules/sonarr/Dockerfile new file mode 100644 index 0000000..9dcd59f --- /dev/null +++ b/modules/sonarr/Dockerfile @@ -0,0 +1,24 @@ +# sonarr's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/sonarr +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/sonarr/dist /app/modules/sonarr/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/sonarr/dist/index.js,/app/modules/sonarr/dist/tools/index.js diff --git a/modules/sonarr/module.json b/modules/sonarr/module.json index b203111..32ecce9 100644 --- a/modules/sonarr/module.json +++ b/modules/sonarr/module.json @@ -72,7 +72,6 @@ "id": "runtime", "type": "container", "name": "mesh-sonarr", - "image": "mesh-runtime-sonarr@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/sonarr/broker:/run/secrets/broker:ro", @@ -82,7 +81,8 @@ "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_SONARR_URL": "http://127.0.0.1:8989", "MESH_SONARR_CONFIG_DIR": "/var/lib/sonarr/config" - } + }, + "artifact": "runtime" } ], "requires": [ @@ -96,5 +96,26 @@ }, "binds": { "route": "/var/lib/mesh/sonarr/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/tautulli/Dockerfile b/modules/tautulli/Dockerfile new file mode 100644 index 0000000..13f4e9a --- /dev/null +++ b/modules/tautulli/Dockerfile @@ -0,0 +1,24 @@ +# tautulli's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/tautulli +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts index.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/tautulli/dist /app/modules/tautulli/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/tautulli/dist/index.js,/app/modules/tautulli/dist/tools/index.js diff --git a/modules/tautulli/module.json b/modules/tautulli/module.json index 478ff6f..8752c70 100644 --- a/modules/tautulli/module.json +++ b/modules/tautulli/module.json @@ -61,7 +61,6 @@ "id": "runtime", "type": "container", "name": "mesh-tautulli", - "image": "mesh-runtime-tautulli@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/tautulli/broker:/run/secrets/broker:ro", @@ -76,7 +75,8 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "requires": [ @@ -90,5 +90,26 @@ }, "binds": { "route": "/var/lib/mesh/tautulli/route.json" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } diff --git a/modules/unifi/Dockerfile b/modules/unifi/Dockerfile new file mode 100644 index 0000000..cea9f20 --- /dev/null +++ b/modules/unifi/Dockerfile @@ -0,0 +1,24 @@ +# unifi's runtime: the tool runtime, carrying this module's compiled code. +# +# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in +# the base images, published like any other artifact — which is what makes this buildable by the +# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that +# happens to have the siblings. +# +# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the +# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. +ARG BUILD_BASE +ARG RUNTIME_BASE + +FROM ${BUILD_BASE} AS build +WORKDIR /app/modules/unifi +COPY . . +RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts \ + --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist + +FROM ${RUNTIME_BASE} +COPY --from=build /app/modules/unifi/dist /app/modules/unifi/dist +# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a +# provider's provisioner runs its reconcile loop in the same process, with the broker connected — +# the convention novox/hq issues 060/061 settled. +ENV MESH_TOOL_MODULES=/app/modules/unifi/dist/tools/index.js diff --git a/modules/unifi/module.json b/modules/unifi/module.json index 5bc5a5f..a2b1573 100644 --- a/modules/unifi/module.json +++ b/modules/unifi/module.json @@ -15,7 +15,7 @@ "port": 8080, "protocol": "tcp", "from": "mesh", - "why": "device inform — how APs and switches check in and are adopted" + "why": "device inform \u2014 how APs and switches check in and are adopted" }, { "port": 3478, @@ -27,7 +27,7 @@ "port": 10001, "protocol": "udp", "from": "mesh", - "why": "device discovery — the controller finds unadopted devices on the network" + "why": "device discovery \u2014 the controller finds unadopted devices on the network" }, { "port": 1902, @@ -113,7 +113,6 @@ "id": "runtime", "type": "container", "name": "mesh-unifi", - "image": "mesh-runtime-unifi@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/unifi/broker:/run/secrets/broker:ro", @@ -126,10 +125,32 @@ }, "restart-on": [ "runtime-config" - ] + ], + "artifact": "runtime" } ], "own-secrets": { "broker": "/var/lib/mesh/unifi/broker" + }, + "build": { + "on": [ + { + "arg": "BUILD_BASE", + "module": "mesh-tools", + "artifact": "build" + }, + { + "arg": "RUNTIME_BASE", + "module": "mesh-tools", + "artifact": "runtime" + } + ], + "artifacts": [ + { + "name": "runtime", + "kind": "image", + "from": "Dockerfile" + } + ] } } -- 2.54.0 From b8d390cbae8941f6c2546384d40ebbf55d51cf0f Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 18 Sep 2026 02:48:09 +0200 Subject: [PATCH 3/4] Defer model-usage and anthropic-manager from the buildable set (issue 060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both carry third-party runtime deps (pg; tweetnacl + sealedbox) that their Dockerfile installs with npm — which 404s in a mesh build, whose npm points at the mesh's own registry, not public npm. The workstation build script got away with it by installing on a host with public npm. Delivering a module's third-party deps into a mesh build is an open question (how: publish to the mesh registry, or proxy); until it is answered these two stay on the placeholder path they were already on. The other 37 modules build from their own directory with no external fetch. --- modules/anthropic-manager/Dockerfile | 26 ------------------------- modules/anthropic-manager/module.json | 27 +++----------------------- modules/model-usage/Dockerfile | 28 --------------------------- modules/model-usage/module.json | 27 +++----------------------- 4 files changed, 6 insertions(+), 102 deletions(-) delete mode 100644 modules/anthropic-manager/Dockerfile delete mode 100644 modules/model-usage/Dockerfile diff --git a/modules/anthropic-manager/Dockerfile b/modules/anthropic-manager/Dockerfile deleted file mode 100644 index 7f96fd0..0000000 --- a/modules/anthropic-manager/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# anthropic-manager's runtime: the tool runtime, carrying this module's compiled code. -# -# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in -# the base images, published like any other artifact — which is what makes this buildable by the -# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that -# happens to have the siblings. -# -# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the -# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. -ARG BUILD_BASE -ARG RUNTIME_BASE - -FROM ${BUILD_BASE} AS build -WORKDIR /app/modules/anthropic-manager -COPY . . -# This module's own third-party dependencies, installed beside its compiled code so Node -# resolves them from the module and falls back to the shared tree for everything common. -RUN npm install --omit=dev --no-save --no-package-lock --ignore-scripts "tweetnacl@^1.0.3" "tweetnacl-sealedbox-js@^1.2.0" -RUN node /app/node_modules/typescript/bin/tsc client.ts adopt/index.ts refresh/index.ts \ - --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist - -FROM ${RUNTIME_BASE} -COPY --from=build /app/modules/anthropic-manager/dist /app/modules/anthropic-manager/dist -COPY --from=build /app/modules/anthropic-manager/node_modules /app/modules/anthropic-manager/node_modules -# No serve-time entrypoints: every container of this module names its command (`run` on a -# schedule), so nothing here serves — deliberately no MESH_TOOL_MODULES. diff --git a/modules/anthropic-manager/module.json b/modules/anthropic-manager/module.json index dc50d7f..b0f9d55 100644 --- a/modules/anthropic-manager/module.json +++ b/modules/anthropic-manager/module.json @@ -37,6 +37,7 @@ "id": "refresh", "type": "container", "name": "mesh-anthropic-manager-refresh", + "image": "mesh-runtime-anthropic-manager@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "schedule": "*/5 * * * *", "args": [ @@ -56,29 +57,7 @@ "MESH_ANTHROPIC_GRANT_OUT": "/run/state/out/grant.json", "MESH_ANTHROPIC_USAGE_OUT": "/run/state/out/usage.json", "MESH_TOOLS_MAIN": "/app/dist/main.js" - }, - "artifact": "runtime" + } } - ], - "build": { - "on": [ - { - "arg": "BUILD_BASE", - "module": "mesh-tools", - "artifact": "build" - }, - { - "arg": "RUNTIME_BASE", - "module": "mesh-tools", - "artifact": "runtime" - } - ], - "artifacts": [ - { - "name": "runtime", - "kind": "image", - "from": "Dockerfile" - } - ] - } + ] } diff --git a/modules/model-usage/Dockerfile b/modules/model-usage/Dockerfile deleted file mode 100644 index b6da6be..0000000 --- a/modules/model-usage/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -# model-usage's runtime: the tool runtime, carrying this module's compiled code. -# -# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in -# the base images, published like any other artifact — which is what makes this buildable by the -# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that -# happens to have the siblings. -# -# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the -# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. -ARG BUILD_BASE -ARG RUNTIME_BASE - -FROM ${BUILD_BASE} AS build -WORKDIR /app/modules/model-usage -COPY . . -# This module's own third-party dependencies, installed beside its compiled code so Node -# resolves them from the module and falls back to the shared tree for everything common. -RUN npm install --omit=dev --no-save --no-package-lock --ignore-scripts "pg@^8" -RUN node /app/node_modules/typescript/bin/tsc index.ts tools/index.ts pg.d.ts \ - --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist - -FROM ${RUNTIME_BASE} -COPY --from=build /app/modules/model-usage/dist /app/modules/model-usage/dist -COPY --from=build /app/modules/model-usage/node_modules /app/modules/model-usage/node_modules -# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a -# provider's provisioner runs its reconcile loop in the same process, with the broker connected — -# the convention novox/hq issues 060/061 settled. -ENV MESH_TOOL_MODULES=/app/modules/model-usage/dist/index.js,/app/modules/model-usage/dist/tools/index.js diff --git a/modules/model-usage/module.json b/modules/model-usage/module.json index 75d9553..d9cdba6 100644 --- a/modules/model-usage/module.json +++ b/modules/model-usage/module.json @@ -49,6 +49,7 @@ "id": "runtime", "type": "container", "name": "mesh-model-usage", + "image": "mesh-runtime-model-usage@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "host", "volumes": [ "/var/lib/mesh/model-usage/broker:/run/secrets/broker:ro", @@ -59,29 +60,7 @@ }, "env-file": [ "/var/lib/model-usage/db.env" - ], - "artifact": "runtime" + ] } - ], - "build": { - "on": [ - { - "arg": "BUILD_BASE", - "module": "mesh-tools", - "artifact": "build" - }, - { - "arg": "RUNTIME_BASE", - "module": "mesh-tools", - "artifact": "runtime" - } - ], - "artifacts": [ - { - "name": "runtime", - "kind": "image", - "from": "Dockerfile" - } - ] - } + ] } -- 2.54.0 From 965c58fe44f7070a5fdffcf37befc63ea8d7e8fa Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 18 Sep 2026 02:51:09 +0200 Subject: [PATCH 4/4] Defer minio from the buildable set too (issue 060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit minio's runtime copies the `mc` client from minio/mc:latest — a Docker Hub pull the mesh build environment cannot make (its docker reaches the mesh registry, not public Hub), the same isolation that blocks npm deps. apt-based installs (mongodb's mongosh, mosquitto) build fine because the build has real internet for apt; only npm and Docker Hub are redirected. Delivering an external binary or image layer into a mesh build is the same open question as the npm deps — deferred with them. --- modules/minio/Dockerfile | 32 -------------------------------- modules/minio/module.json | 27 +++------------------------ 2 files changed, 3 insertions(+), 56 deletions(-) delete mode 100644 modules/minio/Dockerfile diff --git a/modules/minio/Dockerfile b/modules/minio/Dockerfile deleted file mode 100644 index 016bb77..0000000 --- a/modules/minio/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -# minio's runtime: the tool runtime, carrying this module's compiled code. -# -# **Built from this module's own directory and nothing else.** The sdk and the tool runtime are in -# the base images, published like any other artifact — which is what makes this buildable by the -# mesh from a repository and a path (novox/hq ADR 0069) rather than only on a workstation that -# happens to have the siblings. -# -# Two bases, named rather than pinned (novox/hq issue 044): the image this is COMPILED in and the -# image it RUNS in — the second must not carry a compiler. Declared in module.json's `build.on`. -ARG BUILD_BASE -ARG RUNTIME_BASE - -FROM ${BUILD_BASE} AS build -# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own -# node_modules — the module is compiled against exactly the sdk it will run against. The compiler -# is invoked by its real path: node_modules/.bin entries are launcher symlinks the base image -# resolved away. -WORKDIR /app/modules/minio -COPY . . -RUN node /app/node_modules/typescript/bin/tsc client.ts tools/index.ts provisioner/index.ts \ - --module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist - -FROM ${RUNTIME_BASE} -# minio's client drives `mc` — copied from the official image, as the workstation build did. -COPY --from=minio/mc:latest /usr/bin/mc /usr/bin/mc -COPY --from=build /app/modules/minio/dist /app/modules/minio/dist -# Every serve-time entrypoint, loaded by the runtime in serve mode: tools and events serve, and a -# provider's provisioner runs its reconcile loop in the same process, with the broker connected — -# the convention novox/hq issues 060/061 settled. A container that instead ran only its -# provisioner (`run`) served no tools and emitted no events; a container that named no command -# ran no provisioner at all. -ENV MESH_TOOL_MODULES=/app/modules/minio/dist/tools/index.js,/app/modules/minio/dist/provisioner/index.js diff --git a/modules/minio/module.json b/modules/minio/module.json index 457d7a0..185ff6a 100644 --- a/modules/minio/module.json +++ b/modules/minio/module.json @@ -102,6 +102,7 @@ "id": "runtime", "type": "container", "name": "mesh-minio", + "image": "mesh-runtime-minio@sha256:0000000000000000000000000000000000000000000000000000000000000000", "network": "minio", "volumes": [ "/var/lib/mesh/minio/broker:/run/secrets/broker:ro", @@ -114,29 +115,7 @@ "MESH_MINIO_ROOT_PASSWORD_FILE": "/run/secrets/root", "MESH_BROKER_FILE": "/run/secrets/broker", "MESH_RECEIVES": "/var/lib/minio/grants/mesh.json" - }, - "artifact": "runtime" + } } - ], - "build": { - "on": [ - { - "arg": "BUILD_BASE", - "module": "mesh-tools", - "artifact": "build" - }, - { - "arg": "RUNTIME_BASE", - "module": "mesh-tools", - "artifact": "runtime" - } - ], - "artifacts": [ - { - "name": "runtime", - "kind": "image", - "from": "Dockerfile" - } - ] - } + ] } -- 2.54.0