Files
wehub-resource-sync 6db8fca185
docmd CI verification / verify (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:31:55 +08:00

67 lines
3.0 KiB
Bash

#!/bin/sh
# docmd Docker entrypoint
#
# Handles two cases:
#
# 1. No volume / empty /docs → seeds the demo template so `docmd dev`
# works out of the box with no arguments.
#
# 2. Host-mounted volume → detects the uid:gid that owns /docs and
# re-execs as that identity (via su-exec), so file writes from any
# subcommand — including `docmd init` — land with the correct host
# ownership without needing `-u $(id -u):$(id -g)` from the caller.
#
# This mirrors the pattern used by official images (postgres, redis, etc.).
set -e
FIRST_ARG="${1:-}"
# ── uid remapping ────────────────────────────────────────────────────────────
# If we are currently running as root (the entrypoint is exec'd as root so it
# can inspect /docs ownership), detect the uid:gid of /docs and re-exec as
# that user. This lets `docmd init` and `docmd dev` write to host-mounted
# volumes without permission errors regardless of the host user's uid.
if [ "$(id -u)" = "0" ] && [ -d /docs ]; then
DOCS_UID=$(stat -c '%u' /docs 2>/dev/null || echo "1001")
DOCS_GID=$(stat -c '%g' /docs 2>/dev/null || echo "1001")
# If /docs is owned by root (uid 0) on the host, fall back to the docmd
# user — writing as root inside the container is a security anti-pattern.
if [ "$DOCS_UID" = "0" ]; then
DOCS_UID="1001"
DOCS_GID="1001"
fi
# ── writability check (N-18) ───────────────────────────────────────────
# Catch read-only volume mounts early with a clear message instead of
# letting docmd crash mid-build with a cryptic EROFS / EACCES error.
# Only applies to write commands — `dev`, `build`, `init`.
# Read-only mounts are valid for `validate`, `mcp`, etc.
case "$FIRST_ARG" in
dev|build|init)
if ! touch /docs/.docmd_write_test 2>/dev/null; then
printf '\n[docmd] ERROR: /docs is read-only (or not writable by uid %s).\n' "$DOCS_UID" >&2
printf '[docmd] Mount a writable directory:\n' >&2
printf '[docmd] docker run -v $(pwd)/docs:/docs ghcr.io/docmd-io/docmd\n' >&2
printf '[docmd] Or check directory permissions on the host.\n' >&2
exit 1
fi
rm -f /docs/.docmd_write_test
;;
esac
# Seed demo template before dropping privileges (root can always write).
if [ "$FIRST_ARG" != "init" ] && \
[ -z "$(ls -A /docs 2>/dev/null)" ] && \
[ -d /template ]; then
echo "[docmd] /docs is empty — seeding demo template from /template"
cp -r /template/. /docs/
chown -R "$DOCS_UID:$DOCS_GID" /docs 2>/dev/null || true
fi
# Re-exec as the detected uid:gid so all subsequent writes are correctly owned.
exec su-exec "$DOCS_UID:$DOCS_GID" "$0" "$@"
fi
# ── already the right user (re-exec path lands here) ────────────────────────
exec docmd "$@"