Add all target and optimize Actions pipelines

This commit is contained in:
Peter Zandbergen 2026-06-21 11:18:36 +02:00
parent b8cf7bf684
commit ab60199ec9
9 changed files with 138 additions and 30 deletions

4
.env
View File

@ -1,2 +1,2 @@
BUILD_TARGET=jre # native, jre
RUN_MODE=normal # native, normal
BUILD_TARGET=native # all, jre, native
RUN_MODE=json-rpc-native # normal, json-rpc, native, json-rpc-native

View File

@ -83,10 +83,13 @@ jobs:
df -h
echo "Start CI build"
docker run --privileged --rm tonistiigi/binfmt --install all
podman manifest create build-all
podman build --format docker --layers --target all --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-all .
podman manifest push localhost/build-all docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${EPOCHSECONDS}-ci
podman manifest create build-jre
podman build --format docker --target jre --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-jre .
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${EPOCHSECONDS}-ci
podman build --format docker --layers --target jre --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-jre .
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${EPOCHSECONDS}-ci-jre
podman manifest create build-native
podman build --format docker --target native --platform linux/amd64,linux/arm64 --manifest localhost/build-native .
podman build --format docker --layers --target native --platform linux/amd64,linux/arm64 --manifest localhost/build-native .
podman manifest push localhost/build-native docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${EPOCHSECONDS}-ci-native

View File

@ -86,11 +86,15 @@ jobs:
run: |
echo "Start dev build"
docker run --privileged --rm tonistiigi/binfmt --install all
podman manifest create build-all
podman build --format docker --layers --target all --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-all .
podman manifest push localhost/build-all docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}-dev
podman manifest push localhost/build-all docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest-dev
podman manifest create build-jre
podman build --format docker --target jre --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-jre .
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}-dev
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest-dev
podman build --format docker --layers --target jre --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-jre .
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}-dev-jre
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest-dev-jre
podman manifest create build-native
podman build --format docker --target native --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64 --manifest localhost/build-native .
podman build --format docker --layers --target native --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64 --manifest localhost/build-native .
podman manifest push localhost/build-native docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}-dev-native
podman manifest push localhost/build-native docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest-dev-native

View File

@ -86,11 +86,15 @@ jobs:
run: |
echo "Start productive build"
docker run --privileged --rm tonistiigi/binfmt --install all
podman manifest create build-all
podman build --format docker --layers --target all --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-all .
podman manifest push localhost/build-all docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}
podman manifest push localhost/build-all docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest
podman manifest create build-jre
podman build --format docker --target jre --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-jre .
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest
podman build --format docker --layers --target jre --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64,linux/arm/v7 --manifest localhost/build-jre .
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}-jre
podman manifest push localhost/build-jre docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest-jre
podman manifest create build-native
podman build --format docker --target native --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64 --manifest localhost/build-native .
podman build --format docker --layers --target native --build-arg BUILD_VERSION_ARG=${VERSION} --platform linux/amd64,linux/arm64 --manifest localhost/build-native .
podman manifest push localhost/build-native docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:${VERSION}-native
podman manifest push localhost/build-native docker://${IMAGE_REGISTRY}/${IMAGE_REPO}:latest-native

View File

@ -16,7 +16,7 @@ Go-based REST API wrapping [signal-cli](https://github.com/AsamK/signal-cli) for
- `scripts/jsonrpc2-helper.go` — daemon manager for json-rpc mode
- `plugin_loader.go` — Go plugin system using Lua scripts (v1/v2 plugin API)
- `plugins/` — example Lua plugins and persistence plugin
- `Dockerfile` — multi-stage build with two release targets: `jre` and `native`
- `Dockerfile` — multi-stage build with three release targets: `all`, `jre`, and `native`
- `entrypoint.sh` — container entrypoint; validates MODE against available binaries, handles UID/GID, chown, supervisor for json-rpc mode
## Build & Run
@ -36,8 +36,9 @@ Go-based REST API wrapping [signal-cli](https://github.com/AsamK/signal-cli) for
```
- **Build specific variant (Docker):**
```bash
docker build --target jre . # JRE variant (normal + json-rpc)
docker build --target native . # native variant (native + json-rpc-native)
docker build --target all . # all-in-one (all four modes)
docker build --target jre . # JRE variant (normal + json-rpc)
docker build --target native . # native variant (native + json-rpc-native)
```
- **No linter or typecheck config exists** — standard Go tooling only (e.g., `go vet`).
@ -54,13 +55,16 @@ The receive V1 schemas require an extra step (`add_v1_receive_schemas.go`); see
## Image Variants
The Dockerfile produces two release targets from a shared `base` stage:
The Dockerfile produces three release targets from a shared `base` stage:
| Target | Tag suffix | Contains | Modes | Platforms |
|---|---|---|---|---|
| `jre` | `latest`, `X.Y.Z` | headless JRE + signal-cli Java dist | `normal`, `json-rpc` | amd64, arm64, arm/v7 |
| `all` | `latest`, `X.Y.Z` | headless JRE + signal-cli Java dist + signal-cli-native | `normal`, `json-rpc`, `native`, `json-rpc-native` | amd64, arm64, arm/v7 |
| `jre` | `latest-jre`, `X.Y.Z-jre` | headless JRE + signal-cli Java dist | `normal`, `json-rpc` | amd64, arm64, arm/v7 |
| `native` | `latest-native`, `X.Y.Z-native` | signal-cli-native only (no JRE) | `native`, `json-rpc-native` | amd64, arm64 |
The `all` target is the backwards-compatible default — it contains both runtimes so all four modes work, matching the original monolithic image.
The `entrypoint.sh` validates that the requested `MODE` matches binaries available in the running image variant and exits with a clear error if mismatched.
The JRE variant uses `openjdk-25-jre-headless` (not the full `openjdk-25-jre`) to avoid ~280 MB of GUI libraries that a CLI tool never uses.
@ -84,5 +88,5 @@ The JRE variant uses `openjdk-25-jre-headless` (not the full `openjdk-25-jre`) t
- Multi-arch builds: the `jre` target covers `linux/amd64`, `linux/arm64`, `linux/arm/v7`; the `native` target covers `linux/amd64`, `linux/arm64` only (no armv7 native binary).
- `AUTO_RECEIVE_SCHEDULE` and `SIGNAL_CLI_CMD_TIMEOUT` cause a fatal error in json-rpc mode.
- `RECEIVE_WEBHOOK_URL` is only valid in json-rpc mode; fatal in other modes.
- CI uses Podman for multi-arch builds, not Docker Buildx. Each CI/release workflow builds both `jre` and `native` targets.
- Release versions are published via `publish.sh` triggering GitHub Actions (dev vs stable tags, with `-native` suffix for the native variant).
- CI uses Podman for multi-arch builds, not Docker Buildx. Each CI/release workflow builds all three targets (`all`, `jre`, `native`).
- Release versions are published via `publish.sh` triggering GitHub Actions (dev vs stable tags, with `-jre` and `-native` suffixes for those variants; `all` variant gets the plain version/latest tags).

View File

@ -196,6 +196,19 @@ COPY --from=buildcontainer /opt/signal-cli-${SIGNAL_CLI_VERSION} /opt/signal-cli
RUN ln -s /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli /usr/bin/signal-cli \
&& mkdir -p /home/.local/share/signal-cli
# ---- All-in-one variant: MODE=normal, json-rpc, native, json-rpc-native ----
# Includes headless JRE + signal-cli Java dist + signal-cli-native.
# Supports: linux/amd64, linux/arm64, linux/arm/v7
# (arm/v7 gets JRE modes only — signal-cli-native is a dummy on arm/v7)
FROM jre AS all
ARG SIGNAL_CLI_VERSION
COPY --from=buildcontainer /tmp/signal-cli-native /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native
RUN ln -s /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native /usr/bin/signal-cli-native
# ---- Native variant: MODE=native, json-rpc-native ----
# Includes signal-cli-native only. No JRE, no Java dist.
# Supports: linux/amd64, linux/arm64 (no arm/v7 — GraalVM doesn't produce 32-bit binaries)

View File

@ -19,13 +19,16 @@ No user benefits from both the JRE and the native binary at the same time — ea
Additionally, the JRE pulls in ~280 MB of GUI libraries (LLVM, Mesa, GTK, icon themes) that signal-cli never uses. It is a headless CLI tool.
## Proposed Solution: Two Image Variants
## Proposed Solution: Three Image Variants
| Variant | Tag pattern | Contains | Modes | Est. size |
|---|---|---|---|---|
| **JRE** | `latest`, `X.Y.Z` | Headless JRE + signal-cli Java dist | `normal`, `json-rpc` | **~660 MB** |
| **all** | `latest`, `X.Y.Z` | Headles JRE and native | `normal`, `json-rpc`, `native`, `json-rpc-native` | **1.3 GB** |
| **JRE** | `latest-jre`, `X.Y.Z-jre` | Headless JRE + signal-cli Java dist | `normal`, `json-rpc` | **~660 MB** |
| **Native** | `latest-native`, `X.Y.Z-native` | signal-cli-native only (no JRE) | `native`, `json-rpc-native` | **~615 MB** |
We keep the **all** variant in to avoid breaking changes.
For `arm/v7`, only the JRE variant is published (GraalVM doesn't produce a native binary for 32-bit ARM).
### Why the native variant (615 MB) isn't smaller than JRE (660 MB)

View File

@ -1,26 +1,36 @@
services:
# JRE variant (default) -- use with MODE=normal or MODE=json-rpc
# All-in-one variant -- supports all modes: normal, json-rpc, native, json-rpc-native
# This is the backwards-compatible default (same as the original image).
signal-cli-rest-api:
# image: bbernhard/signal-cli-rest-api:latest
# image: bbernhard/signal-cli-rest-api:latest
build:
context: "."
dockerfile: Dockerfile
target: ${BUILD_TARGET}
environment:
- MODE=${RUN_MODE} #supported modes: normal, json-rpc
- MODE=${RUN_MODE} #supported modes: normal, json-rpc, native, json-rpc-native
#- AUTO_RECEIVE_SCHEDULE=0 22 * * * #enable this parameter on demand (see description below)
ports:
- "8080:8080" #map docker port 8080 to host port 8080.
volumes:
- "./signal-cli-config:/home/.local/share/signal-cli" #map "signal-cli-config" folder on host system into docker container. the folder contains the password and cryptographic keys when a new number is registered
# Native variant -- use with MODE=native or MODE=json-rpc-native
# Uncomment to use the native variant (smaller image, no Java runtime)
# signal-cli-rest-api-native:
# image: bbernhard/signal-cli-rest-api:latest-native
# JRE-only variant -- lighter, use with MODE=normal or MODE=json-rpc
# signal-cli-rest-api-jre:
# image: bbernhard/signal-cli-rest-api:latest-jre
# environment:
# - MODE=native #supported modes: native, json-rpc-native
# - MODE=normal
# ports:
# - "8080:8080"
# volumes:
# - "./signal-cli-config:/home/.local/share/signal-cli"
# Native-only variant -- lightest, use with MODE=native or MODE=json-rpc-native
# signal-cli-rest-api-native:
# image: bbernhard/signal-cli-rest-api:latest-native
# environment:
# - MODE=native
# ports:
# - "8080:8080"
# volumes:
# - "./signal-cli-config:/home/.local/share/signal-cli"

67
test-builds.sh Normal file
View File

@ -0,0 +1,67 @@
#!/usr/bin/env bash
WDIR=$(dirname $(readlink -f $0))
function test_run() {
local target=$1
local run_mode=$2
# Create the .env file
# Build and run all
# Create the .env file
cat <<EOF > $WDIR/.env
BUILD_TARGET=${target} # all, jre, native
RUN_MODE=${run_mode} # normal, json-rpc, native, json-rpc-native
EOF
docker compose \
--project-directory $WDIR \
up \
--build --abort-on-container-exit --exit-code-from signal-cli-rest-api &
compose_pid=$!
}
function test_wait() {
local target=$1
local run_mode=$2
local timeout=$3
local start_time=$(date +%s)
for i in $(seq 1 30); do
if curl -sf http://localhost:8080/v1/health >/dev/null 2>&1; then
echo "Health check passed"
echo Killing $compose_pid
kill -9 $compose_pid 2>/dev/null
wait $compose_pid 2>/dev/null
docker compose down
if [ $? -ne 0 ]; then
echo "ERROR: docker compose down failed for ${target} ${run_mode}"
exit 1
fi
return 0
fi
sleep 2
done
echo "ERROR: docker compose build failed for ${target} ${run_mode}"
}
function test_run_and_wait() {
local target=$1
local run_mode=$2
test_run $target $run_mode
test_wait $target $run_mode
}
# Try to run all three build targets and wait for them to finish
# normal, json-rpc, native, json-rpc-native
test_run_and_wait "all" "normal"
test_run_and_wait "all" "json-rpc"
test_run_and_wait "all" "native"
test_run_and_wait "all" "json-rpc-native"
test_run_and_wait "jre" "normal"
test_run_and_wait "jre" "json-rpc"
test_run_and_wait "native" "native"
test_run_and_wait "native" "json-rpc-native"