Ctrl K
ComunidadGuías…

gitlab/docker-entrypoint-rdt.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/bin/bash
# Robot Dev Team Project
# File: gitlab/docker-entrypoint-rdt.sh
# Description: Entrypoint wrapper for GitLab CE that performs one-time RDT setup.
# License: MIT
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 MCKNLY LLC
#
# Wraps the standard GitLab init command (/assets/init-container) to perform
# first-boot setup automatically:
#
#   1. Waits for GitLab to report healthy (/-/health).
#   2. Reads the auto-generated root password from
#      /etc/gitlab/initial_root_password (written by GitLab on first boot).
#   3. Creates an admin Personal Access Token (api scope) via
#      gitlab-rails runner and writes it to /etc/gitlab/rdt.env.
#   4. Enables outbound requests to local network addresses via the admin API
#      (required so the File Hook can register webhooks that resolve to Docker
#      gateway IPs such as host.docker.internal / 172.x.x.x).
#
# Design: the setup logic runs in a background subshell spawned before
# exec'ing /assets/init-container.  exec replaces this script as PID 1 so
# GitLab's init process behaves exactly as it would without this wrapper.
# The background subshell is reparented to PID 1 and continues running
# independently while GitLab boots.
#
# On subsequent container starts the setup is skipped because the marker
# file /etc/gitlab/.rdt-setup-done already exists.
#
# If /etc/gitlab/initial_root_password is absent (i.e. a custom
# GITLAB_ROOT_PASSWORD was set), automatic PAT creation is skipped and a
# warning is printed. In that case, create the PAT manually, set
# GITLAB_ADMIN_TOKEN in gitlab/.env, and restart the container.

set -eo pipefail

SETUP_MARKER="/etc/gitlab/.rdt-setup-done"
RDT_ENV_FILE="/etc/gitlab/rdt.env"
GITLAB_URL="http://localhost"

# ---------------------------------------------------------------------------
# Spawn the setup watcher in the background BEFORE exec'ing the real init.
# Once exec runs, this script is gone and the subshell is a child of PID 1.
# ---------------------------------------------------------------------------
if [[ ! -f "$SETUP_MARKER" ]]; then
  (
    echo "[RDT] Waiting for GitLab to become healthy before running first-time setup..."
    until curl -sf "$GITLAB_URL/-/health" > /dev/null 2>&1; do
      sleep 10
    done
    echo "[RDT] GitLab is healthy. Starting first-time setup..."

    PASS_FILE="/etc/gitlab/initial_root_password"

    if [[ ! -f "$PASS_FILE" ]]; then
      # Custom GITLAB_ROOT_PASSWORD was set — no auto-generated password file.
      echo "[RDT] WARNING: $PASS_FILE not found."
      echo "[RDT]   This usually means a custom GITLAB_ROOT_PASSWORD was configured."
      echo "[RDT]   To enable automatic webhook provisioning:"
      echo "[RDT]     1. Create an admin PAT (api scope) in the GitLab web UI."
      echo "[RDT]     2. Set GITLAB_ADMIN_TOKEN in gitlab/.env."
      echo "[RDT]     3. Restart the container."
      echo "[RDT]   Alternatively, run: bash gitlab/setup-gitlab.sh"
      exit 0
    fi

    # -----------------------------------------------------------------------
    # Create (or retrieve) the admin PAT via Rails runner.
    # find_or_initialize_by makes this idempotent: re-running against an
    # existing 'rdt-admin' token updates it rather than creating a duplicate.
    # GitLab 17+ requires a non-null expiration date; use 365 days from today.
    # -----------------------------------------------------------------------
    echo "[RDT] Creating admin Personal Access Token..."
    # Disable set -e for the rails runner call so we can capture and report
    # any failure rather than silently exiting the background subshell.
    set +e
    RUNNER_OUT=$(gitlab-rails runner "
      user = User.find_by_username('root')
      pat = user.personal_access_tokens.find_or_initialize_by(name: 'rdt-admin')
      pat.scopes = ['api']
      pat.expires_at = Date.today + 365
      pat.save!
      puts pat.token
    " 2>&1)
    RUNNER_EXIT=$?
    set -e

    if [[ $RUNNER_EXIT -ne 0 ]]; then
      echo "[RDT] ERROR: gitlab-rails runner exited with status $RUNNER_EXIT."
      echo "$RUNNER_OUT" | grep -iE "error|invalid|exception|validation" | head -5
      echo "[RDT]   File Hook webhook provisioning will be unavailable until a valid"
      echo "[RDT]   GITLAB_ADMIN_TOKEN is written to $RDT_ENV_FILE or set in gitlab/.env."
      exit 0
    fi

    TOKEN=$(echo "$RUNNER_OUT" | tail -n1)
    if [[ -z "$TOKEN" || ! "$TOKEN" =~ ^glpat- ]]; then
      echo "[RDT] WARNING: PAT creation returned unexpected output: '${TOKEN}'."
      echo "[RDT]   File Hook webhook provisioning will be unavailable until a valid"
      echo "[RDT]   GITLAB_ADMIN_TOKEN is written to $RDT_ENV_FILE or set in gitlab/.env."
      exit 0
    fi

    echo "[RDT] Admin PAT created. Writing to $RDT_ENV_FILE..."
    echo "GITLAB_ADMIN_TOKEN=$TOKEN" > "$RDT_ENV_FILE"
    # Readable by root and the git user (which runs Sidekiq and file hooks).
    chown root:git "$RDT_ENV_FILE"
    chmod 640 "$RDT_ENV_FILE"

    # -----------------------------------------------------------------------
    # Enable outbound requests to local/private network addresses.
    # GitLab blocks these by default; the setting is stored in the database
    # and cannot be configured in gitlab.rb — it must be applied via the API.
    # -----------------------------------------------------------------------
    echo "[RDT] Enabling outbound requests to local network addresses..."
    RESULT=$(curl -sf -X PUT \
      -H "PRIVATE-TOKEN: $TOKEN" \
      "$GITLAB_URL/api/v4/application/settings" \
      --data "allow_local_requests_from_web_hooks_and_services=true" \
      --data "allow_local_requests_from_system_hooks=true")
    ACTUAL=$(echo "$RESULT" | python3 -c \
      "import sys,json; s=json.load(sys.stdin); print(s.get('allow_local_requests_from_web_hooks_and_services','?'))" \
      2>/dev/null || echo "?")
    if [[ "$ACTUAL" == "True" ]]; then
      echo "[RDT] Local network webhook delivery enabled."
    else
      echo "[RDT] WARNING: Setting may not have applied (got: $ACTUAL)."
      echo "[RDT]   Check manually in Admin > Settings > Network > Outbound requests."
    fi

    touch "$SETUP_MARKER"
    echo "[RDT] First-time setup complete."
  ) &
fi

# ---------------------------------------------------------------------------
# Hand off to the standard GitLab init as PID 1.
# exec replaces this script in-place so /assets/init-container runs exactly
# as it would without the wrapper.
# ---------------------------------------------------------------------------
exec /assets/init-container