File size: 3,691 Bytes
26f5c94
 
 
 
 
 
 
 
 
1fb43ac
 
 
 
33dc5a6
 
 
1fb43ac
33dc5a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1fb43ac
 
 
 
 
 
 
 
33dc5a6
 
 
 
 
 
 
 
 
 
 
 
 
 
1fb43ac
33dc5a6
 
 
 
 
26f5c94
1fb43ac
26f5c94
 
 
4eafe9d
26f5c94
 
 
 
33dc5a6
1fb43ac
33dc5a6
26f5c94
33dc5a6
 
26f5c94
 
33dc5a6
 
1fb43ac
33dc5a6
 
1fb43ac
33dc5a6
 
 
 
 
 
 
 
1fb43ac
26f5c94
 
33dc5a6
1fb43ac
26f5c94
 
 
33dc5a6
 
1fb43ac
26f5c94
 
33dc5a6
 
 
 
 
 
 
 
 
 
 
 
1fb43ac
33dc5a6
 
 
 
 
 
 
 
 
26f5c94
33dc5a6
26f5c94
33dc5a6
26f5c94
33dc5a6
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env bash
set -euo pipefail

DATA_DIR="${LABEL_STUDIO_BASE_DATA_DIR:-/label-studio/data}"
LOG_DIR="${LABEL_STUDIO_LOG_DIR:-/label-studio/logs}"
mkdir -p "$DATA_DIR" "$LOG_DIR"

export PYTHONPATH="/app/scripts:${PYTHONPATH:-}"

_log() {
  printf '[%s] %s\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" "$*"
}

_print_startup_environment() {
  python3 - <<'PY'
import os
from datetime import datetime, timezone

safe_r2_variables = {
    "R2_BUCKET_NAME",
    "R2_SYNC_INTERVAL_SEC",
    "R2_SYNC_ON_START",
    "R2_SYNC_ON_STOP",
}
sensitive_name_parts = (
    "ACCESS_KEY",
    "API_KEY",
    "AUTH",
    "CREDENTIAL",
    "DATABASE_URL",
    "PASSWORD",
    "PASSWD",
    "PRIVATE_KEY",
    "REDIS_URL",
    "SECRET",
    "SESSION",
    "TOKEN",
)

def log(message: str) -> None:
    timestamp = datetime.now(timezone.utc).isoformat(timespec="seconds").replace(
        "+00:00", "Z"
    )
    print(f"[{timestamp}] {message}", flush=True)


log("[entrypoint] Startup environment (sensitive values are redacted):")
for name in sorted(os.environ):
    upper_name = name.upper()
    is_r2_credential = (
        upper_name.startswith("R2_") and upper_name not in safe_r2_variables
    )
    is_sensitive = is_r2_credential or any(
        part in upper_name for part in sensitive_name_parts
    )
    if is_sensitive:
        value = "<redacted>"
    else:
        value = os.environ[name].encode(
            "unicode_escape", errors="backslashreplace"
        ).decode("ascii")
    log(f"[entrypoint] {name}={value}")
PY
}

_print_startup_environment

if [[ "${R2_SYNC_ON_START:-1}" == "1" ]] && [[ -n "${R2_ACCESS_KEY_ID:-}" ]]; then
  _log "[r2-sync] Pulling Label Studio state on startup."
  python3 /app/scripts/sync_label_studio_r2.py pull --data-dir "$DATA_DIR" || true
fi

if [[ -n "${SECRET_KEY:-}" ]]; then
  printf 'SECRET_KEY=%s\n' "$SECRET_KEY" > "$DATA_DIR/.env"
fi

_sync_push() {
  if [[ -z "${R2_ACCESS_KEY_ID:-}" ]]; then
    _log "[r2-sync] Push skipped: R2_ACCESS_KEY_ID is not configured."
    return 0
  fi

  python3 /app/scripts/sync_label_studio_r2.py push --data-dir "$DATA_DIR"
}

_sync_on_stop() {
  if [[ "${R2_SYNC_ON_STOP:-1}" == "1" ]]; then
    _log "[r2-sync] Pushing Label Studio state on shutdown."
    _sync_push || true
  else
    _log "[r2-sync] Shutdown push is disabled."
  fi
}

SYNC_PID=""
APP_PID=""
SYNC_INTERVAL="${R2_SYNC_INTERVAL_SEC:-300}"

if [[ "$SYNC_INTERVAL" =~ ^[0-9]+$ ]] && [[ "$SYNC_INTERVAL" -gt 0 ]]; then
  _log "[r2-sync] Periodic push enabled every ${SYNC_INTERVAL} seconds."
  (
    while true; do
      sleep "$SYNC_INTERVAL"
      _log "[r2-sync] Starting periodic push."
      _sync_push || true
    done
  ) &
  SYNC_PID=$!
else
  _log "[r2-sync] Periodic push disabled (R2_SYNC_INTERVAL_SEC=${SYNC_INTERVAL})."
fi

_stop_periodic_sync() {
  if [[ -n "$SYNC_PID" ]] && kill -0 "$SYNC_PID" 2>/dev/null; then
    kill "$SYNC_PID" 2>/dev/null || true
    wait "$SYNC_PID" 2>/dev/null || true
  fi
}

_shutdown() {
  local signal="$1"
  local app_status=0

  trap - INT TERM
  _log "[entrypoint] Received ${signal}; stopping Label Studio."
  _stop_periodic_sync
  if [[ -n "$APP_PID" ]] && kill -0 "$APP_PID" 2>/dev/null; then
    kill -s "$signal" "$APP_PID" 2>/dev/null || true
  fi
  wait "$APP_PID" 2>/dev/null || app_status=$?
  _sync_on_stop
  exit "$app_status"
}

if [[ -n "${SPACE_HOST:-}" ]]; then
  label-studio --host="$SPACE_HOST" &
else
  label-studio --host="${LABEL_STUDIO_HOST:-0.0.0.0}" --port="${LABEL_STUDIO_PORT:-8080}" &
fi
APP_PID=$!

trap '_shutdown INT' INT
trap '_shutdown TERM' TERM

APP_STATUS=0
wait "$APP_PID" || APP_STATUS=$?
trap - INT TERM
_stop_periodic_sync
_sync_on_stop
exit "$APP_STATUS"