ci: self-contained secs_server image for secs4j interop
The harness previously bound the source tree into a compose service and built inside it. That breaks under docker-in-docker (gitea-act, GitHub Actions runners with /var/run/docker.sock mounted) because bind-mount sources resolve against the *host* daemon's filesystem, not the runner container's. Now Dockerfile.server bakes a Release secs_server into its own image, and secs4j_validate.sh wires server and harness together on a dedicated bridge — no volumes needed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
build/
|
build/
|
||||||
|
build-*/
|
||||||
.git/
|
.git/
|
||||||
.gitignore
|
.gitignore
|
||||||
*.md
|
*.md
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Self-contained secs_server image for the secs4j interop harness.
|
||||||
|
#
|
||||||
|
# The dev-time `server` compose service bind-mounts the source tree
|
||||||
|
# read-write at /app and lets the in-container `builder` step compile
|
||||||
|
# there. That works on a developer laptop but breaks under docker-
|
||||||
|
# in-docker (gitea-act / GitHub Actions runners with a mounted
|
||||||
|
# /var/run/docker.sock): the bind-mount source resolves against the
|
||||||
|
# *host* daemon's filesystem, not the runner container's, so /app
|
||||||
|
# mounts empty and the build / launch silently fails.
|
||||||
|
#
|
||||||
|
# This image bakes the source + Release binary in at build time so
|
||||||
|
# `docker run` of it needs no volumes at all — same pattern already
|
||||||
|
# used by interop/secs4j/Dockerfile for the Java harness.
|
||||||
|
FROM ubuntu:24.04 AS build
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential cmake ninja-build \
|
||||||
|
libasio-dev libyaml-cpp-dev \
|
||||||
|
python3 python3-yaml \
|
||||||
|
git ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . /src
|
||||||
|
RUN cmake -S /src -B /src/build -G Ninja -DCMAKE_BUILD_TYPE=Release \
|
||||||
|
&& cmake --build /src/build --target secs_server
|
||||||
|
|
||||||
|
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libyaml-cpp0.8 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# WORKDIR must be the directory holding `data/` because secs_server's
|
||||||
|
# default --config / --state-table paths are relative ("data/...").
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /src/build/secs_server /usr/local/bin/secs_server
|
||||||
|
COPY data /app/data
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
ENTRYPOINT ["/usr/local/bin/secs_server"]
|
||||||
|
CMD ["--port", "5000", "--device", "0"]
|
||||||
+39
-23
@@ -1,9 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Orchestrate the secs4java8 interop harness against our C++ server.
|
# Orchestrate the secs4java8 interop harness against our C++ server.
|
||||||
#
|
#
|
||||||
# Boots secs_server on the docker bridge, then runs the Java harness
|
# Builds a self-contained C++ server image (interop/Dockerfile.server)
|
||||||
# in its own container against it. Wired into CI via a separate
|
# and the Java harness image (interop/secs4j/Dockerfile), spins both
|
||||||
# job (see .gitea/workflows/ci.yml).
|
# up on a dedicated docker network, and runs the harness against the
|
||||||
|
# server. No bind mounts — important under docker-in-docker (gitea-
|
||||||
|
# act / GitHub Actions runners with a mounted /var/run/docker.sock),
|
||||||
|
# where bind-mount sources don't resolve against the daemon's host
|
||||||
|
# filesystem. Wired into CI via .gitea/workflows/ci.yml.
|
||||||
#
|
#
|
||||||
# Usage: bash interop/secs4j_validate.sh
|
# Usage: bash interop/secs4j_validate.sh
|
||||||
# Exit codes:
|
# Exit codes:
|
||||||
@@ -12,35 +16,47 @@
|
|||||||
# 2 — script / orchestration error
|
# 2 — script / orchestration error
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
PORT=${PORT:-5099}
|
|
||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
# Ensure the secs4j-interop image is built (idempotent). The image
|
NET=secs4j-interop-net
|
||||||
# COPYs Secs4jHostHarness.java in and compiles it at build time, so
|
SERVER_NAME=secs4j-interop-server
|
||||||
# no bind mount is needed at run time — important because docker-
|
|
||||||
# in-docker (CI runners with a mounted /var/run/docker.sock) can't
|
|
||||||
# bind-mount paths from the container's filesystem to the daemon's.
|
|
||||||
echo "ensuring secs4j-interop image is built..."
|
|
||||||
docker build -t secsgem-secs4j-interop -f interop/secs4j/Dockerfile interop/secs4j \
|
|
||||||
>/dev/null 2>&1
|
|
||||||
|
|
||||||
# Start the C++ server in background on the compose bridge network so
|
cleanup() {
|
||||||
# the secs4j container can DNS-resolve it.
|
docker rm -f "$SERVER_NAME" >/dev/null 2>&1 || true
|
||||||
echo "starting secs_server (compose)..."
|
docker network rm "$NET" >/dev/null 2>&1 || true
|
||||||
docker compose up -d server >/dev/null 2>&1
|
}
|
||||||
trap 'docker compose stop server >/dev/null 2>&1 || true' EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Build both images (idempotent — docker reuses layers). Errors are
|
||||||
|
# NOT swallowed: an early failure here is the most informative signal
|
||||||
|
# we get when something breaks in CI.
|
||||||
|
echo "building secs_server image..."
|
||||||
|
docker build -t secsgem-secs4j-server -f interop/Dockerfile.server .
|
||||||
|
|
||||||
|
echo "building secs4j harness image..."
|
||||||
|
docker build -t secsgem-secs4j-interop -f interop/secs4j/Dockerfile interop/secs4j
|
||||||
|
|
||||||
|
# Fresh network each run so we don't collide with a leftover from a
|
||||||
|
# previous failed invocation.
|
||||||
|
docker network rm "$NET" >/dev/null 2>&1 || true
|
||||||
|
docker network create "$NET" >/dev/null
|
||||||
|
|
||||||
|
echo "starting secs_server..."
|
||||||
|
# --name doubles as the DNS hostname on the user-defined network, so
|
||||||
|
# the harness reaches it as "secs4j-interop-server:5000".
|
||||||
|
docker run -d --rm \
|
||||||
|
--name "$SERVER_NAME" \
|
||||||
|
--network "$NET" \
|
||||||
|
secsgem-secs4j-server >/dev/null
|
||||||
|
|
||||||
# Give the server a moment to bind.
|
# Give the server a moment to bind.
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
# Run the harness on the same compose network as the server, against
|
|
||||||
# the compose-defined hostname "server" on port 5000 (the demo
|
|
||||||
# server's default).
|
|
||||||
echo "running Secs4jHostHarness..."
|
echo "running Secs4jHostHarness..."
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
--network secs-gem_secs \
|
--network "$NET" \
|
||||||
secsgem-secs4j-interop \
|
secsgem-secs4j-interop \
|
||||||
java -cp /opt/secs4java8/Export.jar:/work Secs4jHostHarness server 5000
|
java -cp /opt/secs4java8/Export.jar:/work Secs4jHostHarness \
|
||||||
|
"$SERVER_NAME" 5000
|
||||||
|
|
||||||
# trap handles teardown.
|
# trap handles teardown.
|
||||||
|
|||||||
Reference in New Issue
Block a user