From c65d47085cd26e8abfc459b19fe1c6e1db7b137e Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Sat, 6 Jun 2026 07:12:34 -0700 Subject: [PATCH 1/9] docs: update AGENTS.md with user preferences and workspace facts build: add dynamic debug and release presets for Linux in CMakePresets.json docs: add crash issue documentation for troubleshooting protobuf linkage build: include codegen feature for gRPC in vcpkg.json --- AGENTS.md | 17 ++++++++++ CMakePresets.json | 48 ++++++++++++++++++++++++++++ docs/crash issue.txt | 76 ++++++++++++++++++++++++++++++++++++++++++++ vcpkg.json | 5 ++- 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 docs/crash issue.txt diff --git a/AGENTS.md b/AGENTS.md index 53aaad8e..cc09585a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -283,3 +283,20 @@ See `.github/copilot-instructions.md` for: - Tool and automation protocols - Dynamic workflow orchestration - URL translation for raw GitHub content + +--- + +## Learned User Preferences + +- Keep OdbDesign local test env vars in `~/.bashrc` (`ODB_TEST_DATA_DIR`, `ODB_TEST_ENVIRONMENT_VARIABLE`) for routine `ctest` runs on this machine. +- Revert incompatible vcpkg baseline bumps (rather than carrying overlay patches) when `grpc` is pinned and the new baseline breaks the build. + +## Learned Workspace Facts + +- Release-only SIGABRT on `GET /filemodels//matrix/matrix` comes from dual static protobuf descriptor pools in `libOdbDesign.so` and `OdbDesignServer`; use `linux-dynamic-debug` / `linux-dynamic-release` presets (`VCPKG_TARGET_TRIPLET=x64-linux-dynamic`) for a single shared protobuf runtime. +- Target `grpc` in `vcpkg.json` must include feature `codegen` so fresh triplet installs export `gRPC::grpc++_reflection` (host-only codegen is insufficient). +- Keep vcpkg baseline at `d1ff36c6520ee43f1a656c03cd6425c2974a449e` while `grpc` is pinned to `1.71.0#3`; baseline `059d760472984042e1b4db0d40efd935a1adcbc9` pulls newer Abseil and breaks gRPC compile (`glob.cc`: `std::any_of`). +- Local test fixtures live in sibling repo `OdbDesignTestData`: set `ODB_TEST_DATA_DIR=/home/nam20485/src/github/nam20485/OdbDesignTestData/TEST_DATA`; design `.tgz` archives at `TEST_DATA/` root, small file-reader fixtures under `TEST_DATA/FILES/`. +- Also set `ODB_TEST_ENVIRONMENT_VARIABLE=ODB_TEST_ENVIRONMENT_VARIABLE_EXISTS` for CrossPlatform env tests; these vars are not baked into CMake presets. +- `OdbDesignServer` loads designs via `--designs-dir`, not `ODB_TEST_DATA_DIR`. +- `CommandLineArgs` treats tokens starting with `/` as flags, so absolute paths after `--designs-dir` parse as boolean `true`; use relative paths (e.g. from `/home/nam20485/src/github/nam20485`: `OdbDesignTestData/TEST_DATA`). diff --git a/CMakePresets.json b/CMakePresets.json index d2505c3c..ed1de6f2 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -133,6 +133,24 @@ "CMAKE_BUILD_TYPE": "Release" } }, + { + "name": "linux-dynamic-debug", + "displayName": "Linux Dynamic Debug", + "inherits": "linux-base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "VCPKG_TARGET_TRIPLET": "x64-linux-dynamic" + } + }, + { + "name": "linux-dynamic-release", + "displayName": "Linux Dynamic Release", + "inherits": "linux-base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "VCPKG_TARGET_TRIPLET": "x64-linux-dynamic" + } + }, { "name": "linux-mingw-w64-debug", "displayName": "Linux MinGW-w64 Debug", @@ -268,6 +286,24 @@ "configuration": "Release", "description": "Build Linux Release" }, + { + "name": "linux-dynamic-debug", + "displayName": "Linux Dynamic Debug", + "configurePreset": "linux-dynamic-debug", + "inherits": "linux-base", + "cleanFirst": false, + "configuration": "Debug", + "description": "Build Linux Dynamic Debug (shared protobuf/gRPC)" + }, + { + "name": "linux-dynamic-release", + "displayName": "Linux Dynamic Release", + "configurePreset": "linux-dynamic-release", + "inherits": "linux-base", + "cleanFirst": false, + "configuration": "Release", + "description": "Build Linux Dynamic Release (shared protobuf/gRPC)" + }, { "name": "linux-mingw-w64-base", "hidden": true, @@ -366,6 +402,18 @@ "configurePreset": "linux-release", "inherits": "linux-base" }, + { + "name": "linux-dynamic-debug", + "displayName": "Test Linux Dynamic Debug", + "configurePreset": "linux-dynamic-debug", + "inherits": "linux-base" + }, + { + "name": "linux-dynamic-release", + "displayName": "Test Linux Dynamic Release", + "configurePreset": "linux-dynamic-release", + "inherits": "linux-base" + }, { "name": "linux-mingw-w64-base", "hidden": true, diff --git a/docs/crash issue.txt b/docs/crash issue.txt new file mode 100644 index 00000000..f3350006 --- /dev/null +++ b/docs/crash issue.txt @@ -0,0 +1,76 @@ +any idea what happened here? cleitn establishes connectin and then when I try to load a design this happens (in debug build it works perfectly no errors) + + +```[06/03/26 01:09:28.532 FileArchive.cpp :401 INFO] Parsing misc/attrlist file complete + [06/03/26 01:09:28.532 FileArchive.cpp :96 INFO] Successfully parsed. (0.573s) + [06/03/26 01:09:28.532 DesignCache.cpp :89 INFO] Loaded from file + gRPC server thread started on port 50051 + Crow REST server starting on 0.0.0.0:8888 (http-trace=false) + Loaded gRPC config from: /home/nam20485/src/github/nam20485/OdbDesign/out/build/linux-release/OdbDesignServer/config.json + gRPC max message sizes: receive=250MB (262144000 bytes), send=250MB (262144000 bytes) + gRPC compression enabled (gzip) + gRPC thread pool: max_threads=8, min_pollers=1 + gRPC keepalive: time=30s, timeout=10s, permit_without_calls=true + gRPC server listening on 0.0.0.0:50051 + [interactive] Type 'q' then Enter to quit gracefully... + (2026-06-03 08:09:28) [INFO ] Crow/master server is running at http://0.0.0.0:8888 using 20 threads + (2026-06-03 08:09:28) [INFO ] Call `app.loglevel(crow::LogLevel::Warning)` to hide Info level logs. + (2026-06-03 08:09:59) [INFO ] Request: 127.0.0.1:41190 0x55d244e0c810 HTTP/1.1 GET /designs + (2026-06-03 08:09:59) [INFO ] Response: 0x55d244e0c810 /designs 200 0 + (2026-06-03 08:10:11) [INFO ] Request: 127.0.0.1:37666 0x7f20e8000c30 HTTP/1.1 GET /filemodels/sample_design/steps + (2026-06-03 08:10:11) [INFO ] Response: 0x7f20e8000c30 /filemodels/sample_design/steps 200 0 + (2026-06-03 08:10:11) [INFO ] Request: 127.0.0.1:37666 0x7f20e8000c30 HTTP/1.1 GET /filemodels/sample_design/steps/step/layers + (2026-06-03 08:10:11) [INFO ] Response: 0x7f20e8000c30 /filemodels/sample_design/steps/step/layers 200 0 + (2026-06-03 08:10:11) [INFO ] Request: 127.0.0.1:37666 0x7f20e8000c30 HTTP/1.1 GET /filemodels/sample_design/matrix/matrix + WARNING: All log messages before absl::InitializeLog() is called are written to STDERR + F0000 00:00:1780474211.295713 524736 generated_message_reflection.cc:3668] Check failed: file != nullptr + *** Check failure stack trace: *** + + Process finished with exit code 134 (interrupted by signal 6:SIGABRT)``` + + + + + There's the smoking gun. protobuf::libprotobuf is a STATIC library (libprotobuf.a). Here's the full picture: + +OdbDesign (shared lib, libOdbDesign.so) links protobuf::libprotobuf (static .a) — so protobuf runtime code gets baked into the .so +OdbDesignServer (executable) also links protobuf::libprotobuf (via gRPC dependencies) — so a second copy of the protobuf runtime gets baked into the exe +At runtime, there are two separate descriptor pools, two GeneratedDatabase instances, etc. +The .pb.cc files for matrixfile, design, etc. register their descriptors into the libOdbDesign.so copy of the descriptor pool +When service.pb.cc (in the exe) tries to resolve its dependencies (design.proto, featuresfile.proto, symbolname.proto), it looks them up in the exe's descriptor pool — where they were never registered +In debug builds, the linker may not strip unused symbols or the initialization order may differ, or the debug versions of protobuf may behave differently — which is why it works in debug but not release +Here's what I recommend: + +Root Cause: Dual Static Protobuf Linkage +You have protobuf::libprotobuf as a static library (libprotobuf.a) being linked into both: + +libOdbDesign.so (shared library) +OdbDesignServer (executable, via gRPC) +This creates two independent copies of the protobuf runtime, each with its own DescriptorPool::generated_pool(). The .pb.cc files in OdbDesignLib register descriptors (like matrixfile.proto) in the .so's pool, while service.pb.cc in the exe registers into the exe's pool. When the exe's protobuf runtime tries to look up matrixfile's file descriptor (triggered by MessageToJsonString via to_json()), it finds nullptr because that descriptor was registered in the other pool. + +Fixes (pick one) +Option 1 (Recommended): Build protobuf as a shared library +In your + +vcpkg.json +, add a feature or triplet override to build protobuf dynamically. Create or modify the vcpkg triplet to use dynamic linkage for protobuf: + +json +// vcpkg.json - add: +"overrides": [ + { "name": "protobuf", "version": "..." } +], +"features": { ... } +Or better — create a custom triplet (e.g., x64-linux-dynamic.cmake): + +cmake +set(VCPKG_TARGET_TRIPLET x64-linux) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE dynamic) +Option 2: Move protobuf linkage to OdbDesignLib only +Since OdbDesignServer depends on OdbDesign which is PUBLICly linking protobuf::libprotobuf, the server is already getting protobuf. The problem is that gRPC also pulls in protobuf statically. You could try making the protobuf link PRIVATE in the server and relying on the .so's copy, but with a static protobuf this is fragile. + +Option 3 (Quick workaround): Force single protobuf instance via linker flags +Add -Wl,-Bsymbolic to the shared library or use --whole-archive when linking protobuf into the shared library, and exclude it from the exe. This is fragile but can work. + +Want me to investigate your vcpkg configuration and implement one of these fixes? Option 1 (shared protobuf) is the cleanest and most reliable. \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index d843bd44..e8d4cfe6 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,7 +11,10 @@ ] }, { - "name": "grpc" + "name": "grpc", + "features": [ + "codegen" + ] } ], "overrides": [ From bfad87ea7bc432e8eeee61f74d19f7a220e98915 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Sat, 6 Jun 2026 07:13:18 -0700 Subject: [PATCH 2/9] add files to ignore --- .dockerignore | 32 +++++++++++++++++++++++++------- .gitignore | 4 ++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/.dockerignore b/.dockerignore index 93d47c42..15c5b137 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,17 +1,35 @@ +# Ignore build artifacts and large directories out/ +cmake-build-*/ +build/ +log.txt +designs/ +new_designs/ + +# Ignore IDE files .vs/ -.github/ +.idea/ + +# Ignore Git-related files .git/ .gitignore .gitattributes -Dockerfile* + +# Ignore GitHub-related files +.github/ + +# Ignore Docker-related files (except Dockerfile itself) docker-compose.yml *.code-workspace + +# Ignore vcpkg artifacts vcpkg_installed/ + +# Ignore SSL certificates ssl/ -out/ -cmake-build-*/ -build/ -.idea/ + +# Ignore testing artifacts Testing/ -*.code-workspace + +# Ignore other Docker files +Dockerfile* diff --git a/.gitignore b/.gitignore index 2f23ca22..74d32908 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,7 @@ gpg_keys/ #Ignore insiders AI rules .github\instructions\codacy.instructions.md /new_designs/ +.cursor/hooks/state/continual-learning.json +.cursor/hooks/state/continual-learning-index.json +.qwen/settings.json +.qwen/settings.json.orig From 1a9fde4462a045e7143aa40973c8150e7301465e Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Sat, 6 Jun 2026 07:14:14 -0700 Subject: [PATCH 3/9] chore: update Dockerfiles to use Debian 13 and add health checks --- Dockerfile | 21 ++++++++++++++++++--- Dockerfile.prebuilt | 20 +++++++++++++++++++- compose.local.yml | 37 +++++++++++++++++++++++++++++++++++++ compose.yml | 20 +++++++++++++++++--- 4 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 compose.local.yml diff --git a/Dockerfile b/Dockerfile index 45e5a1ce..32d08b15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Debian 13 (Trixie) slim - amd64 # Version: 13.3-slim (trixie-slim) # Reduces vulnerabilities: 2 HIGH, 1 MEDIUM, 4 LOW vs Debian 12 -FROM --platform=$BUILDPLATFORM debian@sha256:346fa035ca82052ce8ec3ddb9df460b255507acdeb1dc880a8b6930e778a553c AS build +FROM --platform=$BUILDPLATFORM debian@sha256:ed8750007edb5cb6c6e69d930d3fe3f1af60e759f05de5362be014d498d5f25f AS build ARG OWNER=nam20485 ARG GITHUB_TOKEN="PASSWORD" @@ -75,7 +75,7 @@ RUN cmake --build --preset linux-release # Debian 13 (Trixie) slim - amd64 # Version: 13.3-slim (trixie-slim) # Reduces vulnerabilities: 2 HIGH, 1 MEDIUM, 4 LOW vs Debian 12 -FROM --platform=$TARGETPLATFORM debian@sha256:346fa035ca82052ce8ec3ddb9df460b255507acdeb1dc880a8b6930e778a553c AS run +FROM --platform=$TARGETPLATFORM debian@sha256:ed8750007edb5cb6c6e69d930d3fe3f1af60e759f05de5362be014d498d5f25f AS run # ARG ODBDESIGN_SERVER_REQUEST_USERNAME="" # ARG ODBDESIGN_SERVER_REQUEST_PASSWORD="" LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ @@ -88,7 +88,11 @@ LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ EXPOSE 8888 50051 -# install dependencies (7z command) +# # Docker health check using existing HTTP endpoint +# HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ +# CMD curl -f http://localhost:8888/healthz/live || exit 1 + +# install dependencies (curl for healthcheck, 7z for archive extraction) RUN apt-get update && \ apt-get install -y -q --no-install-recommends \ curl \ @@ -99,6 +103,17 @@ RUN apt-get update && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +# --- gRPC health check (easy to disable: comment out the two blocks below) --- +# Download grpc_health_probe binary +ARG GRPC_HEALTH_PROBE_VERSION=v0.4.24 +RUN curl -sL -o /bin/grpc_health_probe \ + https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# gRPC-specific healthcheck (comment out to disable, re-enable HTTP-only HEALTHCHECK above) +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD /bin/grpc_health_probe -addr=localhost:50051 || exit 1 + # test 7z install RUN 7z -h diff --git a/Dockerfile.prebuilt b/Dockerfile.prebuilt index 69e264a7..122f9385 100644 --- a/Dockerfile.prebuilt +++ b/Dockerfile.prebuilt @@ -2,7 +2,10 @@ # This Dockerfile is used by the Docker Publish workflow to create images from # artifacts built by the CMake Multi-Platform workflow, avoiding a full rebuild. -FROM debian:bookworm-slim@sha256:74a21da88cf4b2e8fde34558376153c5cd80b00ca81da2e659387e76524edc73 AS run +# Debian 13 (Trixie) slim - amd64 +# Version: 13.3-slim (trixie-slim) +# Reduces vulnerabilities: 2 HIGH, 1 MEDIUM, 4 LOW vs Debian 12 +FROM debian@sha256:ed8750007edb5cb6c6e69d930d3fe3f1af60e759f05de5362be014d498d5f25f AS run LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ org.opencontainers.image.authors=https://github.com/nam20485 \ @@ -15,6 +18,10 @@ LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ EXPOSE 8888 EXPOSE 50051 +# Docker health check using existing HTTP endpoint +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:8888/healthz/live || exit 1 + # install runtime dependencies only RUN apt-get update && \ apt-get install -y -q --no-install-recommends \ @@ -26,6 +33,17 @@ RUN apt-get update && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +# --- gRPC health check (easy to disable: comment out the two blocks below) --- +# Download grpc_health_probe binary +RUN GRPC_HEALTH_PROBE_VERSION=v0.4.24 && \ + curl -sL -o /bin/grpc_health_probe \ + https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# gRPC-specific healthcheck (comment out to disable, re-enable HTTP-only HEALTHCHECK above) +# HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ +# CMD /bin/grpc_health_probe -addr=localhost:50051 || exit 1 + # test 7z install RUN 7z -h diff --git a/compose.local.yml b/compose.local.yml new file mode 100644 index 00000000..3e784e6d --- /dev/null +++ b/compose.local.yml @@ -0,0 +1,37 @@ +name: odbdesign-local + +services: + + ### use local image built from Dockerfile + server: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./compose-designs:/OdbDesign/designs + ports: + - 8888:8888 + - 50051:50051 + environment: + - ODBDESIGN_SERVER_REQUEST_USERNAME + - ODBDESIGN_SERVER_REQUEST_PASSWORD + healthcheck: + # Default: HTTP check (works out of the box) + # test: ["CMD", "curl", "-f", "http://localhost:8888/healthz/live"] + # interval: 30s + # timeout: 3s + # retries: 3 + # start_period: 10s + # gRPC check (uncomment to enable during gRPC troubleshooting; requires grpc_health_probe in image) + test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s + + swagger-ui: + image: ghcr.io/nam20485/odbdesignserver-swaggerui:nam20485-latest + depends_on: + - server + ports: + - 8080:8080 diff --git a/compose.yml b/compose.yml index 01aa4a64..519ab9d6 100644 --- a/compose.yml +++ b/compose.yml @@ -3,8 +3,8 @@ name: odbdesign services: ### use remote image build from github container registry - server: - image: ghcr.io/nam20485/odbdesign:nam20485-latest + server: + image: ghcr.io/nam20485/odbdesign:nam20485-latest volumes: - ./compose-designs:/OdbDesign/designs ports: @@ -13,6 +13,13 @@ services: environment: - ODBDESIGN_SERVER_REQUEST_USERNAME - ODBDESIGN_SERVER_REQUEST_PASSWORD + healthcheck: + # Default: HTTP check (works out of the box) + test: ["CMD", "curl", "-f", "http://localhost:8888/healthz/live"] + interval: 30s + timeout: 3s + retries: 3 + start_period: 10s ### use local image built from Dockerfile # server: @@ -26,7 +33,14 @@ services: # - 50051:50051 # environment: # - ODBDESIGN_SERVER_REQUEST_USERNAME - # - ODBDESIGN_SERVER_REQUEST_PASSWORD + # - ODBDESIGN_SERVER_REQUEST_PASSWORD + # healthcheck: + # # Default: HTTP check (works out of the box) + # test: ["CMD", "curl", "-f", "http://localhost:8888/healthz/live"] + # interval: 30s + # timeout: 3s + # retries: 3 + # start_period: 10s swagger-ui: image: ghcr.io/nam20485/odbdesignserver-swaggerui:nam20485-latest From 551de145629bfb457402c727ee2cc34a19e06de7 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Sat, 6 Jun 2026 07:42:39 -0700 Subject: [PATCH 4/9] feat: add health checks and create non-root user in Dockerfiles --- Dockerfile | 39 +++++++++++++++++++++++---------------- Dockerfile.prebuilt | 25 +++++++++++++++++-------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Dockerfile b/Dockerfile index 32d08b15..95ed9b9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -88,9 +88,9 @@ LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ EXPOSE 8888 50051 -# # Docker health check using existing HTTP endpoint -# HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ -# CMD curl -f http://localhost:8888/healthz/live || exit 1 +# Docker health check using existing HTTP endpoint +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:8888/healthz/live || exit 1 # install dependencies (curl for healthcheck, 7z for archive extraction) RUN apt-get update && \ @@ -103,21 +103,25 @@ RUN apt-get update && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -# --- gRPC health check (easy to disable: comment out the two blocks below) --- -# Download grpc_health_probe binary -ARG GRPC_HEALTH_PROBE_VERSION=v0.4.24 -RUN curl -sL -o /bin/grpc_health_probe \ - https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ - chmod +x /bin/grpc_health_probe +# # --- gRPC health check (easy to disable: comment out the two blocks below) --- +# # Download grpc_health_probe binary +# ARG GRPC_HEALTH_PROBE_VERSION=v0.4.24 +# RUN curl -sL -o /bin/grpc_health_probe \ +# https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ +# chmod +x /bin/grpc_health_probe -# gRPC-specific healthcheck (comment out to disable, re-enable HTTP-only HEALTHCHECK above) -HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD /bin/grpc_health_probe -addr=localhost:50051 || exit 1 +# # gRPC-specific healthcheck (comment out to disable, re-enable HTTP-only HEALTHCHECK above) +# HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ +# CMD /bin/grpc_health_probe -addr=localhost:50051 || exit 1 # test 7z install RUN 7z -h -RUN mkdir --parents /OdbDesign/bin +# create non-root user +RUN groupadd --gid 10001 odbdesign && \ + useradd --uid 10001 --gid odbdesign --create-home --shell /usr/sbin/nologin odbdesign + +RUN mkdir --parents /OdbDesign/bin /OdbDesign/templates /OdbDesign/designs WORKDIR /OdbDesign # copy binaries @@ -129,11 +133,15 @@ COPY --from=build /src/OdbDesign/out/build/linux-release/OdbDesignTests/OdbDesig # COPY --from=build /src/OdbDesign/out/build/linux-release/OdbDesignApp/OdbDesignApp ./bin/ # COPY --from=build /src/OdbDesign/out/build/linux-release/OdbDesignApp/*.so ./bin/ - # copy templates directory -RUN mkdir -p ./templates COPY --from=build /src/OdbDesign/OdbDesignServer/templates/* ./templates +# set ownership to non-root user +RUN chmod +x ./bin/OdbDesignServer && \ + chown --recursive odbdesign:odbdesign /OdbDesign + +USER odbdesign + # create designs directory # required to be volume mounted! #RUN mkdir ./designs @@ -142,5 +150,4 @@ COPY --from=build /src/OdbDesign/OdbDesignServer/templates/* ./templates ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/OdbDesign/bin # ENV ODBDESIGN_SERVER_REQUEST_USERNAME=${ODBDESIGN_SERVER_REQUEST_USERNAME} # ENV ODBDESIGN_SERVER_REQUEST_PASSWORD=${ODBDESIGN_SERVER_REQUEST_PASSWORD} -RUN chmod +x ./bin/OdbDesignServer ENTRYPOINT [ "./bin/OdbDesignServer", "--designs-dir", "./designs", "--templates-dir", "./templates" ] diff --git a/Dockerfile.prebuilt b/Dockerfile.prebuilt index 122f9385..91aed9c3 100644 --- a/Dockerfile.prebuilt +++ b/Dockerfile.prebuilt @@ -33,12 +33,12 @@ RUN apt-get update && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -# --- gRPC health check (easy to disable: comment out the two blocks below) --- -# Download grpc_health_probe binary -RUN GRPC_HEALTH_PROBE_VERSION=v0.4.24 && \ - curl -sL -o /bin/grpc_health_probe \ - https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ - chmod +x /bin/grpc_health_probe +# # --- gRPC health check (easy to disable: comment out the two blocks below) --- +# # Download grpc_health_probe binary +# RUN GRPC_HEALTH_PROBE_VERSION=v0.4.24 && \ +# curl -sL -o /bin/grpc_health_probe \ +# https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ +# chmod +x /bin/grpc_health_probe # gRPC-specific healthcheck (comment out to disable, re-enable HTTP-only HEALTHCHECK above) # HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ @@ -47,7 +47,11 @@ RUN GRPC_HEALTH_PROBE_VERSION=v0.4.24 && \ # test 7z install RUN 7z -h -RUN mkdir --parents /OdbDesign/bin +# create non-root user +RUN groupadd --gid 10001 odbdesign && \ + useradd --uid 10001 --gid odbdesign --create-home --shell /usr/sbin/nologin odbdesign + +RUN mkdir --parents /OdbDesign/bin /OdbDesign/templates /OdbDesign/designs WORKDIR /OdbDesign # copy pre-built binaries from artifacts (extracted from zip in workflow) @@ -57,7 +61,12 @@ COPY ./artifacts/OdbDesignServer ./bin/ # copy templates directory from source COPY ./OdbDesignServer/templates/* ./templates/ +# set ownership to non-root user +RUN chmod +x ./bin/OdbDesignServer && \ + chown --recursive odbdesign:odbdesign /OdbDesign + +USER odbdesign + # run ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/OdbDesign/bin -RUN chmod +x ./bin/OdbDesignServer ENTRYPOINT [ "./bin/OdbDesignServer", "--designs-dir", "./designs", "--templates-dir", "./templates" ] From 02fd0aea65d7d664316d9746496e34a355cb0f36 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Sat, 6 Jun 2026 08:05:10 -0700 Subject: [PATCH 5/9] chore: update Dockerfiles to use consistent Debian 13 image digest --- Dockerfile | 5 +++-- Dockerfile.prebuilt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 95ed9b9a..46567e58 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Debian 13 (Trixie) slim - amd64 # Version: 13.3-slim (trixie-slim) # Reduces vulnerabilities: 2 HIGH, 1 MEDIUM, 4 LOW vs Debian 12 -FROM --platform=$BUILDPLATFORM debian@sha256:ed8750007edb5cb6c6e69d930d3fe3f1af60e759f05de5362be014d498d5f25f AS build +FROM --platform=$BUILDPLATFORM debian@sha256:b6e2a152f22a40ff69d92cb397223c906017e1391a73c952b588e51af8883bf8 AS build ARG OWNER=nam20485 ARG GITHUB_TOKEN="PASSWORD" @@ -75,7 +75,8 @@ RUN cmake --build --preset linux-release # Debian 13 (Trixie) slim - amd64 # Version: 13.3-slim (trixie-slim) # Reduces vulnerabilities: 2 HIGH, 1 MEDIUM, 4 LOW vs Debian 12 -FROM --platform=$TARGETPLATFORM debian@sha256:ed8750007edb5cb6c6e69d930d3fe3f1af60e759f05de5362be014d498d5f25f AS run +# FROM --platform=$TARGETPLATFORM debian@sha256:b6e2a152f22a40ff69d92cb397223c906017e1391a73c952b588e51af8883bf8 AS run +FROM debian@sha256:b6e2a152f22a40ff69d92cb397223c906017e1391a73c952b588e51af8883bf8 AS run # ARG ODBDESIGN_SERVER_REQUEST_USERNAME="" # ARG ODBDESIGN_SERVER_REQUEST_PASSWORD="" LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ diff --git a/Dockerfile.prebuilt b/Dockerfile.prebuilt index 91aed9c3..e8bf05c3 100644 --- a/Dockerfile.prebuilt +++ b/Dockerfile.prebuilt @@ -5,7 +5,7 @@ # Debian 13 (Trixie) slim - amd64 # Version: 13.3-slim (trixie-slim) # Reduces vulnerabilities: 2 HIGH, 1 MEDIUM, 4 LOW vs Debian 12 -FROM debian@sha256:ed8750007edb5cb6c6e69d930d3fe3f1af60e759f05de5362be014d498d5f25f AS run +FROM debian@sha256:b6e2a152f22a40ff69d92cb397223c906017e1391a73c952b588e51af8883bf8 AS run LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign \ org.opencontainers.image.authors=https://github.com/nam20485 \ From f6e354688bc910e7566d1379728143eafac2c8bb Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Thu, 11 Jun 2026 19:53:33 -0700 Subject: [PATCH 6/9] Add symlink for compile_commands.json Creates symlink from build/ to source root so clangd, Zed, and VS Code can locate the compilation database automatically. --- .gitignore | 1 + CMakeLists.txt | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index 74d32908..36047d03 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.vs /out +/compile_commands.json /cmake-build-debug build/ /vcpkg_installed diff --git a/CMakeLists.txt b/CMakeLists.txt index f7fa5145..48a5d41c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,16 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) # See: https://docs.sonarsource.com/sonarqube-for-ide/vs-code/getting-started/running-an-analysis/#generate-a-compilation-database set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +# symlink compile_commands.json to project root so IDEs (clangd, Zed, VS Code) +# can find it without manual configuration +if(EXISTS "${CMAKE_BINARY_DIR}/compile_commands.json") + file(CREATE_LINK + "${CMAKE_BINARY_DIR}/compile_commands.json" + "${CMAKE_SOURCE_DIR}/compile_commands.json" + SYMBOLIC COPY_ON_ERROR + ) +endif() + # only use ccache locally, i.e. not in CI # nm, looks like we re-en-disabled it. Apparently it can speed up CI builds too. (Not sure how since its first one-off single build everytime, but maybe it can cache within a single build run) #if (NOT DEFINED ENV{CI}) From 9c18c992850d9d1d0af363b30eb9f2ce67c8088a Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Thu, 11 Jun 2026 19:53:50 -0700 Subject: [PATCH 7/9] Add Zed debug configuration for OdbDesignServer --- .zed/debug.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .zed/debug.json diff --git a/.zed/debug.json b/.zed/debug.json new file mode 100644 index 00000000..7398bde1 --- /dev/null +++ b/.zed/debug.json @@ -0,0 +1,17 @@ +// Project-local debug tasks +// +// For more documentation on how to configure debug tasks, +// see: https://zed.dev/docs/debugger +[ + { + "label": "Debug native binary", + "build": { + "command": "cmake", + "args": ["--build", "--preset", "linux-debug"], + "cwd": "$ZED_WORKTREE_ROOT", + }, + "program": "$ZED_WORKTREE_ROOT/out/build/linux-debug/OdbDesignServer/OdbDesignServer", + "request": "launch", + "adapter": "CodeLLDB", + }, +] From 475b6afe03984e7be33cf55361315867b73b2f9a Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Thu, 11 Jun 2026 19:57:06 -0700 Subject: [PATCH 8/9] Add Zed tasks for CMake build, test workflows --- .zed/tasks.json | 175 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 .zed/tasks.json diff --git a/.zed/tasks.json b/.zed/tasks.json new file mode 100644 index 00000000..e2cf5180 --- /dev/null +++ b/.zed/tasks.json @@ -0,0 +1,175 @@ +[ + // ── Configure ────────────────────────────────────────────────────────── + { + "label": "CMake: Configure (Linux Debug)", + "command": "cmake --preset linux-debug", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Configure (Linux Release)", + "command": "cmake --preset linux-release", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Configure (Linux Dynamic Debug)", + "command": "cmake --preset linux-dynamic-debug", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Configure (Linux Dynamic Release)", + "command": "cmake --preset linux-dynamic-release", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + + // ── Build ─────────────────────────────────────────────────────────────── + { + "label": "CMake: Build (Linux Debug)", + "command": "cmake --build --preset linux-debug", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Build (Linux Release)", + "command": "cmake --build --preset linux-release", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Build (Linux Dynamic Debug)", + "command": "cmake --build --preset linux-dynamic-debug", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Build (Linux Dynamic Release)", + "command": "cmake --build --preset linux-dynamic-release", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + + // ── Test ───────────────────────────────────────────────────────────────── + { + "label": "CMake: Test (Linux Debug)", + "command": "ctest --preset linux-debug --output-on-failure", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never" + }, + { + "label": "CMake: Test (Linux Release)", + "command": "ctest --preset linux-release --output-on-failure", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never" + }, + { + "label": "CMake: Test (Linux Dynamic Debug)", + "command": "ctest --preset linux-dynamic-debug --output-on-failure", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never" + }, + { + "label": "CMake: Test (Linux Dynamic Release)", + "command": "ctest --preset linux-dynamic-release --output-on-failure", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never" + }, + + // ── Clean ──────────────────────────────────────────────────────────────── + { + "label": "CMake: Clean Build (Linux Debug)", + "command": "cmake --build --preset linux-debug --target clean", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Clean Build (Linux Release)", + "command": "cmake --build --preset linux-release --target clean", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + + // ── Full pipeline: Configure + Build ───────────────────────────────────── + { + "label": "CMake: Configure & Build (Linux Debug)", + "command": "cmake --preset linux-debug && cmake --build --preset linux-debug", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + { + "label": "CMake: Configure & Build (Linux Release)", + "command": "cmake --preset linux-release && cmake --build --preset linux-release", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "on_success" + }, + + // ── Full pipeline: Build + Test ────────────────────────────────────────── + { + "label": "CMake: Build & Test (Linux Debug)", + "command": "cmake --build --preset linux-debug && ctest --preset linux-debug --output-on-failure", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never" + }, + { + "label": "CMake: Build & Test (Linux Release)", + "command": "cmake --build --preset linux-release && ctest --preset linux-release --output-on-failure", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": false, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never" + } +] From 2fb098935454e2e322d6570a95d597f4a724b626 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Thu, 11 Jun 2026 20:03:14 -0700 Subject: [PATCH 9/9] Add debug and run configurations for OdbDesign apps in Zed --- .zed/debug.json | 24 +++++++++++++++- .zed/tasks.json | 76 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/.zed/debug.json b/.zed/debug.json index 7398bde1..a5e2566f 100644 --- a/.zed/debug.json +++ b/.zed/debug.json @@ -4,7 +4,7 @@ // see: https://zed.dev/docs/debugger [ { - "label": "Debug native binary", + "label": "Debug OdbDesignServer", "build": { "command": "cmake", "args": ["--build", "--preset", "linux-debug"], @@ -14,4 +14,26 @@ "request": "launch", "adapter": "CodeLLDB", }, + { + "label": "Debug OdbDesignApp", + "build": { + "command": "cmake", + "args": ["--build", "--preset", "linux-debug"], + "cwd": "$ZED_WORKTREE_ROOT", + }, + "program": "$ZED_WORKTREE_ROOT/out/build/linux-debug/OdbDesignApp/OdbDesignApp", + "request": "launch", + "adapter": "CodeLLDB", + }, + { + "label": "Debug OdbDesignTests", + "build": { + "command": "cmake", + "args": ["--build", "--preset", "linux-debug"], + "cwd": "$ZED_WORKTREE_ROOT", + }, + "program": "$ZED_WORKTREE_ROOT/out/build/linux-debug/OdbDesignTests/OdbDesignTests", + "request": "launch", + "adapter": "CodeLLDB", + }, ] diff --git a/.zed/tasks.json b/.zed/tasks.json index e2cf5180..db542b2f 100644 --- a/.zed/tasks.json +++ b/.zed/tasks.json @@ -7,7 +7,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Configure (Linux Release)", @@ -16,7 +16,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Configure (Linux Dynamic Debug)", @@ -25,7 +25,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Configure (Linux Dynamic Release)", @@ -34,7 +34,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, // ── Build ─────────────────────────────────────────────────────────────── @@ -45,7 +45,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Build (Linux Release)", @@ -54,7 +54,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Build (Linux Dynamic Debug)", @@ -63,7 +63,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Build (Linux Dynamic Release)", @@ -72,7 +72,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, // ── Test ───────────────────────────────────────────────────────────────── @@ -83,7 +83,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "never" + "hide": "never", }, { "label": "CMake: Test (Linux Release)", @@ -92,7 +92,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "never" + "hide": "never", }, { "label": "CMake: Test (Linux Dynamic Debug)", @@ -101,7 +101,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "never" + "hide": "never", }, { "label": "CMake: Test (Linux Dynamic Release)", @@ -110,7 +110,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "never" + "hide": "never", }, // ── Clean ──────────────────────────────────────────────────────────────── @@ -121,7 +121,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Clean Build (Linux Release)", @@ -130,7 +130,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, // ── Full pipeline: Configure + Build ───────────────────────────────────── @@ -141,7 +141,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, { "label": "CMake: Configure & Build (Linux Release)", @@ -150,7 +150,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "on_success" + "hide": "on_success", }, // ── Full pipeline: Build + Test ────────────────────────────────────────── @@ -161,7 +161,7 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "never" + "hide": "never", }, { "label": "CMake: Build & Test (Linux Release)", @@ -170,6 +170,44 @@ "use_new_terminal": false, "allow_concurrent_runs": false, "reveal": "always", - "hide": "never" - } + "hide": "never", + }, + + // ── Run (start without debugging) ──────────────────────────────────────── + { + "label": "Run: OdbDesignServer (Debug)", + "command": "$ZED_WORKTREE_ROOT/out/build/linux-debug/OdbDesignServer/OdbDesignServer", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": true, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never", + }, + { + "label": "Run: OdbDesignApp (Debug)", + "command": "$ZED_WORKTREE_ROOT/out/build/linux-debug/OdbDesignApp/OdbDesignApp", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": true, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never", + }, + { + "label": "Run: OdbDesignServer (Release)", + "command": "$ZED_WORKTREE_ROOT/out/build/linux-release/OdbDesignServer/OdbDesignServer", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": true, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never", + }, + { + "label": "Run: OdbDesignApp (Release)", + "command": "$ZED_WORKTREE_ROOT/out/build/linux-release/OdbDesignApp/OdbDesignApp", + "cwd": "$ZED_WORKTREE_ROOT", + "use_new_terminal": true, + "allow_concurrent_runs": false, + "reveal": "always", + "hide": "never", + }, ]