-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathentrypoint.sh
More file actions
executable file
·202 lines (178 loc) · 7.74 KB
/
Copy pathentrypoint.sh
File metadata and controls
executable file
·202 lines (178 loc) · 7.74 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/bin/bash
# Bot container entrypoint — decode secrets, start Chromium, launch bot.
set -e
# --- Verify required CLI tools ---
MISSING=""
for tool in gh glab git gpg; do
if ! command -v "$tool" &>/dev/null; then
MISSING="$MISSING $tool"
fi
done
if [ -n "$MISSING" ]; then
echo "FATAL: Missing required tools:$MISSING" >&2
echo "Rebuild with: docker compose build --no-cache bot" >&2
exit 1
fi
# Kubernetes secretKeyRef auto-decodes base64, so secrets arrive as raw values
# in OpenShift. Local docker-compose still passes them base64-encoded via .env.
# This helper handles both: values starting with "-----" or "{" are not valid
# base64 and are the only two raw formats we expect, so write them as-is.
# Everything else is base64-decoded.
decode_or_raw() {
case "$1" in
-----*|"{"*) printf '%s' "$1" ;;
*) echo "$1" | base64 -d 2>/dev/null ;;
esac
}
# Git credential helpers — thin clients forward to executor sidecar in proxy container
git config --global credential.https://github.com.helper '!/usr/local/bin/gh auth git-credential'
git config --global credential.https://gitlab.cee.redhat.com.helper '!/usr/local/bin/glab credential-helper'
# Write SSO credentials file for stage auth (chrome-devtools)
if [ -n "${SSO_USERNAME:-}" ] && [ -n "${SSO_PASSWORD:-}" ]; then
cat > /home/botuser/app/.credentials <<EOF
{"sso": {"username": "${SSO_USERNAME}", "password": "${SSO_PASSWORD}"}}
EOF
chmod 600 /home/botuser/app/.credentials
unset SSO_USERNAME SSO_PASSWORD
fi
# --- Wait for executor (provides gh/glab/gpg via proxy) ---
# Must be ready BEFORE GPG key lookups (gpg is a thin client to proxy)
EXECUTOR_ADDR="${EXECUTOR_ADDR:-unix:///var/run/devbot/executor.sock}"
echo "Waiting for executor at ${EXECUTOR_ADDR}..."
elapsed=0
if [[ "$EXECUTOR_ADDR" == unix://* ]]; then
SOCK_PATH="${EXECUTOR_ADDR#unix://}"
until [ -S "$SOCK_PATH" ]; do
elapsed=$((elapsed + 1))
[ "$elapsed" -ge 30 ] && { echo "FATAL: executor socket not ready after 30s" >&2; exit 1; }
sleep 1
done
else
EXEC_HOST="${EXECUTOR_ADDR%%:*}"
EXEC_PORT="${EXECUTOR_ADDR##*:}"
until bash -c "echo > /dev/tcp/${EXEC_HOST}/${EXEC_PORT}" 2>/dev/null; do
elapsed=$((elapsed + 1))
[ "$elapsed" -ge 30 ] && { echo "FATAL: executor at ${EXECUTOR_ADDR} not ready after 30s" >&2; exit 1; }
sleep 1
done
fi
echo "Executor ready."
# Per-platform git identity via includeIf (git 2.36+)
# Each platform gets its own name, email, and GPG signing key.
GH_GPG_KEY="$(gpg --list-secret-keys --keyid-format long "${GH_USER_EMAIL}" 2>/dev/null | grep -oP '(?<=/)[A-F0-9]{16}' | head -1)"
GL_GPG_KEY="$(gpg --list-secret-keys --keyid-format long "${GL_USER_EMAIL}" 2>/dev/null | grep -oP '(?<=/)[A-F0-9]{16}' | head -1)"
# Export so run.py's setup_git() writes them into GIT_CONFIG_GLOBAL gitconfig
export GH_GPG_SIGNING_KEY="$GH_GPG_KEY"
export GL_GPG_SIGNING_KEY="$GL_GPG_KEY"
cat > /home/botuser/.gitconfig-gh <<EOF
[user]
name = ${GH_USER_NAME}
email = ${GH_USER_EMAIL}
signingkey = ${GH_GPG_KEY}
EOF
cat > /home/botuser/.gitconfig-gl <<EOF
[user]
name = ${GL_USER_NAME}
email = ${GL_USER_EMAIL}
signingkey = ${GL_GPG_KEY}
EOF
git config --global 'includeIf.hasconfig:remote.*.url:https://github.com/**.path' /home/botuser/.gitconfig-gh
git config --global 'includeIf.hasconfig:remote.*.url:https://gitlab.cee.redhat.com/**.path' /home/botuser/.gitconfig-gl
# Verify per-platform identity + GPG signing (warn-only, never fatal)
verify_platform_signing() {
local platform="$1" url="$2" expected_email="$3"
local tmpdir
tmpdir=$(mktemp -d)
git init -q "$tmpdir"
git -C "$tmpdir" remote add origin "$url"
local resolved_email resolved_key
resolved_email=$(git -C "$tmpdir" config user.email)
resolved_key=$(git -C "$tmpdir" config user.signingkey)
rm -rf "$tmpdir"
if [ -z "$resolved_email" ]; then
echo "WARNING: ${platform} — includeIf did not resolve identity"
return
fi
if [ "$resolved_email" != "$expected_email" ]; then
echo "WARNING: ${platform} — email mismatch: got ${resolved_email}, expected ${expected_email}"
return
fi
if [ -z "$resolved_key" ]; then
echo "WARNING: ${platform} — no GPG signing key resolved"
return
fi
if echo "test" | gpg --local-user "$resolved_key" --sign > /dev/null 2>&1; then
echo "${platform} identity + GPG signing OK (${resolved_email})"
else
echo "WARNING: ${platform} — GPG key cannot sign (missing or expired)"
fi
}
verify_platform_signing "GitHub" "https://github.com/test/repo.git" "${GH_USER_EMAIL}"
verify_platform_signing "GitLab" "https://gitlab.cee.redhat.com/test/repo.git" "${GL_USER_EMAIL}"
# Jira credentials are in the proxy container (mcp-atlassian on port 8444).
# Python skills use JIRA_MCP_URL env var to connect via MCP protocol.
# Point MCP config to the memory server
sed -i "s|http://localhost:8080/mcp|${BOT_MEMORY_URL}|" .mcp.json
# --- Verify auth (via thin client → proxy) ---
echo "Verifying GitHub auth..."
gh auth status 2>&1 | head -3 || { echo "WARNING: gh auth failed"; }
echo "Verifying GitLab auth..."
glab auth status --hostname gitlab.cee.redhat.com 2>&1 | head -3 || { echo "WARNING: glab auth failed"; }
# --- Wait for dependent services (OpenShift deploys all pods concurrently) ---
wait_for_http() {
local name="$1" url="$2" timeout="${3:-120}"
echo "Waiting for ${name} at ${url} (timeout=${timeout}s)..."
local elapsed=0
until curl -sf --noproxy '*' "$url" > /dev/null 2>&1; do
elapsed=$((elapsed + 2))
if [ "$elapsed" -ge "$timeout" ]; then
echo "FATAL: ${name} not ready after ${timeout}s" >&2
exit 1
fi
sleep 2
done
echo "${name} is ready."
}
wait_for_tcp() {
local name="$1" host="$2" port="$3" timeout="${4:-120}"
echo "Waiting for ${name} at ${host}:${port} (timeout=${timeout}s)..."
local elapsed=0
until bash -c "echo > /dev/tcp/${host}/${port}" 2>/dev/null; do
elapsed=$((elapsed + 2))
if [ "$elapsed" -ge "$timeout" ]; then
echo "FATAL: ${name} not ready after ${timeout}s" >&2
exit 1
fi
sleep 2
done
echo "${name} is ready."
}
# Proxy must be up before Chromium (which routes through it)
# Uses TCP check — Squid doesn't serve HTTP on its proxy port
# TODO: update template to replace BOT_PROXY_HEALTH_URL with PROXY_HOST/PROXY_PORT
if [ -n "${PROXY_HOST:-}" ]; then
wait_for_tcp "proxy" "$PROXY_HOST" "${PROXY_PORT:-3128}" "${BOT_PROXY_HEALTH_TIMEOUT:-60}"
fi
# Memory server must be up before the bot connects via MCP
if [ -n "${BOT_MEMORY_HEALTH_URL:-}" ]; then
wait_for_http "memory-server" "$BOT_MEMORY_HEALTH_URL" "${BOT_MEMORY_HEALTH_TIMEOUT:-120}"
fi
# Start headless Chromium in background (Playwright-installed binary)
CHROME_BIN=$(find "$PLAYWRIGHT_BROWSERS_PATH" -name chrome -type f | head -1)
"$CHROME_BIN" \
--headless --no-sandbox --disable-gpu \
--remote-debugging-port=9222 --remote-debugging-address=0.0.0.0 \
--remote-allow-origins=* \
--ignore-certificate-errors \
--host-resolver-rules='MAP consent.trustarc.com 127.0.0.1' \
--proxy-server="${HTTPS_PROXY:-http://proxy:3128}" \
--proxy-bypass-list='*.foo.redhat.com;localhost;127.0.0.1' \
--no-first-run --disable-sync --disable-extensions --disable-popup-blocking &
# Wait for Chromium to be ready
until curl -s http://127.0.0.1:9222/json/version > /dev/null 2>&1; do sleep 1; done
# Run env preset entrypoint scripts (no-op until presets are extracted)
shopt -s nullglob
for script in presets/envs/*/entrypoint.d/*.sh; do bash "$script"; done
shopt -u nullglob
echo "Credentials configured. Chromium started. Starting bot with label: ${BOT_LABEL}"
exec uv run dev-bot --label "$BOT_LABEL"