| 1 | #!/usr/bin/env bash |
| 2 | set -euo pipefail |
| 3 | |
| 4 | if [[ "${EUID}" -ne 0 ]]; then |
| 5 | echo "Run as root: sudo bash scripts/tencent-lighthouse/install-services.sh" >&2 |
| 6 | exit 1 |
| 7 | fi |
| 8 | |
| 9 | REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" |
| 10 | CODEWHALE_USER="${CODEWHALE_USER:-${DEEPSEEK_USER:-codewhale}}" |
| 11 | CODEWHALE_ROOT="${CODEWHALE_ROOT:-${DEEPSEEK_ROOT:-/opt/codewhale}}" |
| 12 | BRIDGE_KIND="${CODEWHALE_BRIDGE:-${DEEPSEEK_BRIDGE:-feishu}}" |
| 13 | |
| 14 | case "${BRIDGE_KIND}" in |
| 15 | feishu|lark) |
| 16 | BRIDGE_SRC="integrations/feishu-bridge" |
| 17 | BRIDGE_DST="${CODEWHALE_ROOT}/bridge" |
| 18 | BRIDGE_UNIT="codewhale-feishu-bridge.service" |
| 19 | BRIDGE_ENV="/etc/codewhale/feishu-bridge.env" |
| 20 | BRIDGE_ENV_EXAMPLE="deploy/tencent-lighthouse/examples/feishu-bridge.env.example" |
| 21 | BRIDGE_STATE_DIR="/var/lib/codewhale-feishu-bridge" |
| 22 | VALIDATOR="integrations/feishu-bridge/scripts/validate-config.mjs" |
| 23 | ;; |
| 24 | telegram) |
| 25 | BRIDGE_SRC="integrations/telegram-bridge" |
| 26 | BRIDGE_DST="${CODEWHALE_ROOT}/telegram-bridge" |
| 27 | BRIDGE_UNIT="codewhale-telegram-bridge.service" |
| 28 | BRIDGE_ENV="/etc/codewhale/telegram-bridge.env" |
| 29 | BRIDGE_ENV_EXAMPLE="deploy/tencent-lighthouse/examples/telegram-bridge.env.example" |
| 30 | BRIDGE_STATE_DIR="/var/lib/codewhale-telegram-bridge" |
| 31 | VALIDATOR="integrations/telegram-bridge/scripts/validate-config.mjs" |
| 32 | ;; |
| 33 | *) |
| 34 | echo "Unknown bridge '${BRIDGE_KIND}'. Use CODEWHALE_BRIDGE=feishu or CODEWHALE_BRIDGE=telegram." >&2 |
| 35 | exit 1 |
| 36 | ;; |
| 37 | esac |
| 38 | |
| 39 | install -d -m 0750 -o root -g "${CODEWHALE_USER}" /etc/codewhale |
| 40 | install -d -m 0700 -o "${CODEWHALE_USER}" -g "${CODEWHALE_USER}" "${BRIDGE_STATE_DIR}" |
| 41 | mkdir -p "$(dirname "${BRIDGE_DST}")" |
| 42 | |
| 43 | if [[ ! -f /etc/codewhale/runtime.env && -f "${REPO_ROOT}/deploy/tencent-lighthouse/examples/runtime.env.example" ]]; then |
| 44 | install -m 0640 -o root -g "${CODEWHALE_USER}" \ |
| 45 | "${REPO_ROOT}/deploy/tencent-lighthouse/examples/runtime.env.example" \ |
| 46 | /etc/codewhale/runtime.env |
| 47 | fi |
| 48 | |
| 49 | if [[ ! -f "${BRIDGE_ENV}" && -f "${REPO_ROOT}/${BRIDGE_ENV_EXAMPLE}" ]]; then |
| 50 | install -m 0640 -o root -g "${CODEWHALE_USER}" \ |
| 51 | "${REPO_ROOT}/${BRIDGE_ENV_EXAMPLE}" \ |
| 52 | "${BRIDGE_ENV}" |
| 53 | fi |
| 54 | # Build the new bridge tree beside the live one and swap it in only once its |
| 55 | # dependencies installed. A failed copy or `npm ci` (which empties |
| 56 | # node_modules first) leaves the running bridge's tree exactly as it was. |
| 57 | stage="$(mktemp -d "${BRIDGE_DST}.stage.XXXXXX")" |
| 58 | previous="" |
| 59 | trap 'if [[ -n "${stage}" ]]; then rm -rf "${stage}"; fi' EXIT |
| 60 | chmod 0755 "${stage}" |
| 61 | rsync -a \ |
| 62 | --exclude node_modules \ |
| 63 | "${REPO_ROOT}/${BRIDGE_SRC}/" \ |
| 64 | "${stage}/" |
| 65 | chown -R "${CODEWHALE_USER}:${CODEWHALE_USER}" "${stage}" |
| 66 | |
| 67 | if [[ -f "${stage}/package-lock.json" ]]; then |
| 68 | sudo -u "${CODEWHALE_USER}" npm --prefix "${stage}" ci --omit=dev |
| 69 | else |
| 70 | sudo -u "${CODEWHALE_USER}" npm --prefix "${stage}" install --omit=dev |
| 71 | fi |
| 72 | |
| 73 | if [[ -e "${BRIDGE_DST}" ]]; then |
| 74 | previous="${BRIDGE_DST}.previous.$$" |
| 75 | mv "${BRIDGE_DST}" "${previous}" |
| 76 | fi |
| 77 | if ! mv "${stage}" "${BRIDGE_DST}"; then |
| 78 | # Put the old tree back rather than leave the service without one. |
| 79 | if [[ -n "${previous}" ]]; then mv "${previous}" "${BRIDGE_DST}"; fi |
| 80 | echo "Could not move the new bridge into ${BRIDGE_DST}; the previous tree was restored." >&2 |
| 81 | exit 1 |
| 82 | fi |
| 83 | stage="" |
| 84 | if [[ -n "${previous}" ]]; then rm -rf "${previous}"; fi |
| 85 | |
| 86 | install -m 0644 "${REPO_ROOT}/deploy/tencent-lighthouse/systemd/codewhale-runtime.service" /etc/systemd/system/codewhale-runtime.service |
| 87 | install -m 0644 "${REPO_ROOT}/deploy/tencent-lighthouse/systemd/${BRIDGE_UNIT}" "/etc/systemd/system/${BRIDGE_UNIT}" |
| 88 | |
| 89 | systemctl daemon-reload |
| 90 | systemctl enable codewhale-runtime "${BRIDGE_UNIT}" |
| 91 | |
| 92 | cat <<'EOF' |
| 93 | Services installed but not started. |
| 94 | |
| 95 | Before starting, verify: |
| 96 | /etc/codewhale/runtime.env |
| 97 | EOF |
| 98 | cat <<EOF |
| 99 | ${BRIDGE_ENV} |
| 100 | sudo -u ${CODEWHALE_USER} node ${REPO_ROOT}/${VALIDATOR} --env ${BRIDGE_ENV} --runtime-env /etc/codewhale/runtime.env --workspace-root /opt/whalebro --check-filesystem |
| 101 | Then run: |
| 102 | sudo systemctl start codewhale-runtime |
| 103 | sudo systemctl start ${BRIDGE_UNIT} |
| 104 | sudo CODEWHALE_BRIDGE=${BRIDGE_KIND} bash /opt/whalebro/codewhale/scripts/tencent-lighthouse/doctor.sh |
| 105 | sudo journalctl -u ${BRIDGE_UNIT} -f |
| 106 | EOF |
| 107 |