Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
109 changes: 107 additions & 2 deletions docker-compose.docs-snapshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ services:
[
'sh',
'-c',
'node extract.cjs --directory /extract/plotly-express --output /results/plotly-express; node extract.cjs --directory /extract/ui --output /results/ui',
'node extract.cjs --directory /extract/plotly-express --output /results/plotly-express; node extract.cjs --directory /extract/ui --output /results/ui; node extract.cjs --directory /extract/tradingview-lightweight --output /results/tradingview-lightweight',
]
volumes:
- ./plugins/ui/docs:/extract/ui
- ./plugins/plotly-express/docs:/extract/plotly-express
- ./plugins/tradingview-lightweight/docs:/extract/tradingview-lightweight
# exclude doc build directories by overriding with empty volumes
# We could extract from the build directories, but we need to output the snapshots to the build directory itself for Salmon to pick up...
- /extract/plotly-express/build/
- /extract/ui/build/
- /extract/tradingview-lightweight/build/
- test-sets:/results

# Read the test sets from the results directory and run them against the test server, taking a snapshot of the results.
Expand All @@ -33,7 +35,7 @@ services:
[
'sh',
'-c',
'node snapshot.cjs --directory /test-sets/plotly-express --output /results/plotly-express --errors /errors/plotly-express; node snapshot.cjs --directory /test-sets/ui --output /results/ui --errors /errors/ui',
'node snapshot.cjs --directory /test-sets/plotly-express --output /results/plotly-express --errors /errors/plotly-express; node snapshot.cjs --directory /test-sets/ui --output /results/ui --errors /errors/ui; node snapshot.cjs --directory /test-sets/tradingview-lightweight --output /results/tradingview-lightweight --errors /errors/tradingview-lightweight',
]
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Allows the snapshotter to start its own docker containers for the test server
Expand All @@ -42,15 +44,118 @@ services:
# Map all the results back to the snapshots directory for those docs
- ./plugins/ui/docs/snapshots:/results/ui
- ./plugins/plotly-express/docs/snapshots:/results/plotly-express
- ./plugins/tradingview-lightweight/docs/snapshots:/results/tradingview-lightweight
- ./snapshot-results/errors:/errors

# Pass 2: capture widget PNGs for the tradingview-lightweight docs. Runs
# AFTER salmon's Pass 1 snapshotter has finished and torn its server down.
# Brings up its own python-snapshotter compose via the mounted docker
# socket so it can join the shared snapshot network. The image-snapshotter
# tool itself is plugin-agnostic; per-plugin settings come from
# SNAPSHOTTER_* env vars below.
deephaven-plugins-docs-image-snapshotter-tvl:
build:
context: ./tools/image-snapshotter
container_name: deephaven-plugins-docs-image-snapshotter-tvl
depends_on:
deephaven-plugins-docs-snapshotter:
condition: service_completed_successfully
environment:
SNAPSHOTTER_BASE_URL: 'http://server:10000/ide/'
SNAPSHOTTER_PLUGIN_ROOT: '/work'
SNAPSHOTTER_PLUGIN: 'tradingview-lightweight'
SNAPSHOTTER_TARGET_SELECTOR: '.dh-tvl-chart'
SNAPSHOTTER_WIDGET_TYPE: 'deephaven.plot.tradingview_lightweight.TvlChart'
SNAPSHOTTER_APP_ID: 'tvl.docs.examples'
SNAPSHOTTER_APP_NAME: 'TVL Docs Examples'
SNAPSHOTTER_COMPOSE_FILE: '/workspace/docker/python-snapshotter/docker-compose.yml'
SNAPSHOTTER_SERVER_CONTAINER: 'tvl-snapshotter-server'
# Pass through the host's SNAPSHOTTER_FORCE so callers can opt in to
# cache-busting recapture without editing this file.
SNAPSHOTTER_FORCE: ${SNAPSHOTTER_FORCE:-}
CI: 'true'
# The Pass 2 entrypoint brings up the python-snapshotter test server
# via the mounted docker socket. That compose file bind-mounts the
# generated app.d, which is interpreted against the HOST filesystem
# (the socket is the host's). `${PWD}` is evaluated by compose at
# compose-up time against the user's shell, so HOST_PWD inside the
# container always carries the host's working directory.
HOST_PWD: ${PWD}
volumes:
# Allows the snapshotter to start its own server container alongside us.
- /var/run/docker.sock:/var/run/docker.sock
# docker/python-snapshotter/docker-compose.yml is resolved from the
# host's view of the socket — mount the repo at a stable path inside
# the container so SNAPSHOTTER_COMPOSE_FILE resolves correctly.
- ${PWD}:/workspace
# The spec walks docs/*.md (read-only) and writes PNGs + JSON envelopes
# into docs/snapshots. PLUGIN_ROOT resolves to /work, so /work/docs is
# the docs tree and /work/docs/snapshots is the output dir.
- ./plugins/tradingview-lightweight/docs:/work/docs:ro
- ./plugins/tradingview-lightweight/docs/snapshots:/work/docs/snapshots

# Surface snapshot errors to the user. Compose's `depends_on` conditions
# only fire on success (`service_completed_successfully`); there's no
# "completed-with-any-exit" condition. And dependency stdout doesn't
# stream to the terminal when you `docker compose run <target>` — only
# the target's own stdout does. So the salmon snapshotter's errors were
# silently written to /errors and never shown.
#
# Workaround: this service has no depends_on. The npm `update-doc-snapshots`
# script invokes it as its own `compose run` target right after the main
# chain — so its stdout streams to the user, regardless of whether the
# snapshotter passed or failed. Bind-mounts the same errors dir the
# snapshotter writes to. Exits non-zero if any errors are present.
# Also acts as the post-run chown step. The salmon snapshotter and the
# Pass-2 image-snapshotter both run as root, so the PNGs + JSON envelopes
# they write into docs/snapshots land owned by root and the host user
# can't edit them. Bind-mounting those dirs here (rw) and chowning them
# to SNAPSHOT_UID:SNAPSHOT_GID (exported by tools/run_docker.sh) makes
# them editable on the host. Runs whether or not snapshots succeeded.
deephaven-plugins-docs-error-reporter:
image: alpine:3.20
environment:
SNAPSHOT_UID: ${SNAPSHOT_UID:-0}
SNAPSHOT_GID: ${SNAPSHOT_GID:-0}
volumes:
- ./snapshot-results/errors:/errors
- ./plugins/ui/docs/snapshots:/snapshots/ui
- ./plugins/plotly-express/docs/snapshots:/snapshots/plotly-express
- ./plugins/tradingview-lightweight/docs/snapshots:/snapshots/tradingview-lightweight
command:
- sh
- -c
- |
if [ "$$SNAPSHOT_UID" != "0" ]; then
chown -R "$$SNAPSHOT_UID:$$SNAPSHOT_GID" /errors /snapshots 2>/dev/null || true
fi
had=0
for plugin in plotly-express ui tradingview-lightweight; do
f="/errors/$$plugin/errors.txt"
if [ -s "$$f" ]; then
had=1
echo ""
echo "==================== $$plugin ($$f) ===================="
head -n 200 "$$f"
n=$$(wc -l < "$$f")
if [ "$$n" -gt 200 ]; then
echo "... ($$n total lines; full file at snapshot-results/errors/$$plugin/errors.txt)"
fi
fi
done
if [ "$$had" -eq 0 ]; then
echo "[error-reporter] no snapshot errors recorded."
fi
exit $$had

# Validate MDX and the snapshots that were written are valid
deephaven-plugins-docs-validator:
image: ghcr.io/deephaven/salmon-validator
pull_policy: always
volumes:
- ./plugins/ui/docs/build/markdown:/validate/ui
- ./plugins/plotly-express/docs/build/markdown:/validate/plotly-express
- ./plugins/tradingview-lightweight/docs/build/markdown:/validate/tradingview-lightweight
- ./docker/build/validator-results:/results

volumes:
Expand Down
1 change: 1 addition & 0 deletions docker-compose.docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ services:
volumes:
- ./plugins/ui/docs${BUILT+/build/markdown}:/salmon/core/ui/docs
- ./plugins/plotly-express/docs${BUILT+/build/markdown}:/salmon/core/plotly/docs
- ./plugins/tradingview-lightweight/docs${BUILT+/build/markdown}:/salmon/core/tradingview-lightweight/docs
43 changes: 43 additions & 0 deletions docker/python-snapshotter/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Pass 2 (image-snapshotter) test server. Plugin-agnostic.
#
# Reuses the python-server image already built by salmon's Pass 1
# (../python/docker-compose.yml). The only differences vs. that compose:
#
# - We mount a generated app.d directory at /app.d so the docs examples
# are pre-loaded as Deephaven panels (the Pass 2 server is otherwise
# headless — no code is ever sent over the console).
# - START_OPTS adds -Ddeephaven.application.dir=/app.d to enable app
# mode against that directory.
# - DEEPHAVEN_PLUGINS_STATIC_DATA=1 forces tvl.data / dx.data into
# static mode so screenshots are deterministic.
#
# image-snapshotter's entrypoint sets PASS2_APPD_HOST_PATH to the host
# filesystem path of the generated app.d (bind mounts traverse the host
# because the docker socket is the host's). The `:?` makes compose fail
# fast if the entrypoint forgot to export it.
#
# SNAPSHOTTER_SERVER_CONTAINER lets parallel plugin invocations produce
# unique container names. Serial Pass 2 invocations (the default
# docs-snapshots compose flow) can rely on the default.
#
# The image tag matches what `docker/python/docker-compose.yml` builds —
# `image: python-server:latest` rather than a `build:` block because Pass 1
# always runs first and produces the image. On a clean run with Pass 1
# skipped the image won't exist locally and `up` will fail; that's the
# documented contract.
services:
server:
image: python-server:latest
container_name: ${SNAPSHOTTER_SERVER_CONTAINER:-deephaven-snapshotter-server}
expose:
- 10000
environment:
- START_OPTS=-Xmx4g -DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler -Ddeephaven.console.type=python -Ddeephaven.application.dir=/app.d
- DEEPHAVEN_PLUGINS_STATIC_DATA=1
volumes:
- ${PASS2_APPD_HOST_PATH:?PASS2_APPD_HOST_PATH must be set}:/app.d:ro

networks:
default:
name: deephaven-plugins-docs-snapshot-network
external: true
5 changes: 5 additions & 0 deletions docker/python/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ services:
- 10000
environment:
- START_OPTS=-Xmx4g -DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler -Ddeephaven.console.type=python
# Force tvl.data / dx.data into static mode so docs snapshots are
# reproducible AND so doc blocks that chain `.update(["X = (double)ii"])`
# onto a generator output don't blow up on the refreshing-formula check
# (the merged static+time_table isn't classified as append-only).
- DEEPHAVEN_PLUGINS_STATIC_DATA=1

networks:
default:
Expand Down
Loading
Loading