devs/bin/lib/developers.lib
Mauro Rosero P. 46d3be29ed
[IMPROVED] Depuración y manejo de errores en la función forgejo_create_project
- Añadidas verificaciones preliminares de conectividad a la API
- Validación del token antes de crear el repositorio
- Mejor extracción de URL (con fallback a html_url)
- Instrucciones detalladas para generar token en Forgejo
- Diagnóstico mejorado cuando falla la creación del proyecto

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-03-13 12:04:49 -05:00

414 lines
11 KiB
Bash

#!/bin/bash
#
# Library: developers.lib
# Description: Developers Tools Library
# Modified: 2024/12/09 08:20:00
# Derechos de Autor (C) [2024] [Mauro Rosero P. <mauro@roser.one>]
#
# Este programa es software libre: usted puede redistribuirlo y/o modificarlo
# bajo los términos de la Licencia Pública Affero General de GNU tal como
# lo publica la Free Software Foundation, ya sea la versión 3 de la licencia,
# o (a su elección) cualquier versión posterior.
#
# Este programa se distribuye con la esperanza de que sea útil,
# pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de
# COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la
# Licencia Pública Affero General de GNU para obtener más detalles.
#
# Debería haber recibido una copia de la Licencia Pública Affero General
# junto con este programa. Si no la recibió, consulte <https://www.gnu.org/licenses/>.
GPG_DEFAULT_PATH=$HOME/.gnupg
GPG_CONFIG_PATH=bin/config
GPG_TEMPLATE=gpg.config
GPG_CONFIG=gpg.conf
GPG_BACKUP_CFG=gpg.backup
GPGP_BACKUP_SECRET=gpg.secret
GPG_SUBKEY_ID=""
GPG_REVOKE_FILES="*.rev"
DB_GPG_PATH=$HOME/.gnupg
DB_GPG_FILE=$USER.db
DB_GPG_SUBKEYS_KEY="subkey_id"
DB_GPG_SUBKEYS="GPG_SUBKEYS"
SQL_GPG_SUBKEYS="${DB_GPG_SUBKEYS}.sql"
# Test library
function devslib_test() {
echo "Developers Library loaded!"
exit 1
}
# Configuración global para servicios Git
FORGEJO_API_URL="https://forgejo.rosero.one/api/v1"
FORGEJO_CONFIG_FILE="$HOME/.developer/forgejo.cfg"
# Set gpg environment
function gpg_setting() {
local BIN_CONFIG=$1
local GPG_PATH=$2
local LOCAL_BACKUP=$3
local TIMESTAMP=$4
# Check if gpg directory path exists
if [ ! -d "${GPG_PATH}" ]
then
# Create gpg directory path
mkdir -p ${GPG_PATH}
if [ $? -ne 0 ]; then
return 2
fi
fi
# Check if gpg template file exists
if [ ! -f "${BIN_CONFIG}/${GPG_CFG_PATH}/${GPG_TEMPLATE}" ]
then
return 1
fi
if [ -d "${LOCAL_BACKUP}" ]
then
if [ -f "${GPG_PATH}/${GPG_CONFIG}" ]
then
# Destination file backup
local BACKUP_FILE="${LOCAL_BACKUP}/gpg_${TIMESTAMP}.bak"
cp -f "${GPG_PATH}/${GPG_CONFIG}" "${BACKUP_FILE}"
if [ $? -ne 0 ]; then
return 3
fi
fi
fi
# Copia el archivo de plantilla al destino
cp -f "${BIN_CONFIG}/${GPG_CFG_PATH}/${GPG_TEMPLATE}" "${GPG_PATH}/${GPG_CONFIG}"
return $?
}
# Generate token for backup file
function gpg_backup_token() {
local SECRET_FILE=$1
if [[ ! -e $archivo_token ]]
then
local BACKUP_TOKEN=$(uuidgen | base64 )
echo "$BACKUP_TOKEN" > "$SECRET_FILE"
chmod 600 "$SECRET_FILE"
fi
return 0
}
# FULL EXTENDED GNUGP BACKUP
function developer_backup() {
local DB_BACKUP=$1
local BIN_CONFIG=$2
local TIMESTAMP=$3
local GNUGP_PATH=$4
local rc=0
# Check if backup configuration file exists
if [ ! -f $BIN_CONFIG/$GPG_BACKUP_CFG ]
then
return 10
fi
local LOCAL_BACKUP=$HOME/$(cat < $BIN_CONFIG/$GPG_BACKUP_CFG)
# Check if backup path exist
if [ -z "$LOCAL_BACKUP" ]; then
return 11
fi
if [ ! -d "${LOCAL_BACKUP}" ]
then
mkdir -p "${LOCAL_BACKUP}"
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
fi
gpg_backup_token "${LOCAL_BACKUP}/$GPGP_BACKUP_SECRET"
# Get secret backup
ZPASSWORD=$(echo "$(cat < "${LOCAL_BACKUP}/$GPGP_BACKUP_SECRET")" | base64 -d)
if [ -z "${ZPASSWORD}" ]; then
return 13
fi
# Export full backup keys to backup work path
local TMP_PATH=$(mktemp -d)
local TMP_FILE="gpg.bak"
gpg --export-options backup -o "${TMP_PATH}/${TMP_FILE}" --export
rc=$?
if [ $rc -ne 0 ]; then
rm -rf "${tmp_path}"
return $rc
fi
# Dump GPG_SUBKEYS table to SQL
local TMP_DB_DUMP="${SQL_GPG_SUBKEYS}"
local DB_DUMP="${TMP_PATH}/${TMP_DB_DUMP}"
sqlite_dump "${DB_BACKUP}" "${DB_DUMP}" "${DB_GPG_SUBKEYS}"
rc=$?
if [ ${rc} -ne 0 ]
then
rm -rf "${TMP_PATH}"
return $rc
fi
# Copy full .gnupg for backup
mkdir ${TMP_PATH}/.gnupg
if [ $? -eq 0 ]; then
cp -rf $GNUGP_PATH/* ${TMP_PATH}/.gnupg/
rc=$?
if [ $rc -ne 0 ]
then
rm -rf "${TMP_PATH}"
return $rc
fi
fi
# Copy full .ssh for backup
mkdir ${TMP_PATH}/.ssh
if [ $? -eq 0 ]; then
cp -rf $HOME/.ssh/* ${TMP_PATH}/.ssh/
rc=$?
if [ $rc -ne 0 ]
then
rm -rf "${TMP_PATH}"
return $rc
fi
fi
# Copy .giconfig for user to backup
if [ -f $HOME/.gitconfig ]; then
cp -f $HOME/.gitconfig ${TMP_PATH}/
rc=$?
if [ $rc -ne 0 ]
then
rm -rf "${TMP_PATH}"
return $rc
fi
fi
# Copy .developer folder for user to backup
mkdir ${TMP_PATH}/.developer
if [ $? -eq 0 ] && [ -d $HOME/.developer ]; then
cp -rf $HOME/.developer/* ${TMP_PATH}/.developer/
rc=$?
if [ $rc -ne 0 ]
then
rm -rf "${TMP_PATH}"
return $rc
fi
fi
# Change backup work path to make zip archive
cd "${TMP_PATH}"
# Comprimir el archivo de respaldo en un archivo ZIP protegido con contraseña
BACKUP_FILE="${LOCAL_BACKUP}/gpg_${USER}_${TIMESTAMP}"
zip -qqr -P "${ZPASSWORD}" $BACKUP_FILE * .gnupg .ssh .gitconfig .developer
rc=$?
if [ $rc -ne 0 ]
then
rm -rf "${TMP_PATH}"
return $rc
fi
rm -rf "${TMP_PATH}"
return 0
}
# RESTORE PROFILE DEVELOPER LOCAL BACKUP
function developer_restore() {
local BIN_CONFIG=$1
local BACKUP_ZIP=$2
local rc=0
# Check provided backup zip filename
if [ -z "$BACKUP_ZIP" ]; then
return 10
fi
# Check if backup zip file exists
if [ ! -f "$BACKUP_ZIP" ]
then
return 11
fi
# Check if backup configuration file exists
local LOCAL_BACKUP=$(dirname $BACKUP_ZIP)
if [ ! -f $LOCAL_BACKUP/$GPGP_BACKUP_SECRET ]
then
return 12
fi
# Get secret backup
ZPASSWORD=$(echo "$(cat < "${LOCAL_BACKUP}/$GPGP_BACKUP_SECRET")" | base64 -d)
if [ -z "${ZPASSWORD}" ]; then
return 14
fi
clear
# Restore zip full .gnupg path
unzip -qqo -P "$ZPASSWORD" "$BACKUP_ZIP" ".gnupg"/* -d $HOME
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
# Restore zip full .ssh path
unzip -qqo -P "$ZPASSWORD" "$BACKUP_ZIP" ".ssh"/* -d $HOME
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
# Restore zip full .gitconfig file
unzip -qqo -P "$ZPASSWORD" "$BACKUP_ZIP" ".gitconfig" -d $HOME
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
# Restore zip full .developer directory
unzip -qqo -P "$ZPASSWORD" "$BACKUP_ZIP" ".developer"/* -d $HOME
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
return 0
}
# Función para crear un proyecto Git en Forgejo
# $1: nombre del proyecto
# $2: descripción del proyecto
# $3: tipo de visibilidad (private/public) [por defecto: private]
# $4: ruta local del proyecto (opcional)
# Return: 0 si se crea correctamente, otro valor en caso de error
function forgejo_create_project() {
local PROJECT_NAME=$1
local PROJECT_DESC=$2
local VISIBILITY=${3:-private} # Por defecto private si no se especifica
local PROJECT_PATH=$4
# Verificar parámetros obligatorios
if [ -z "$PROJECT_NAME" ] || [ -z "$PROJECT_DESC" ]; then
return 10 # Error: faltan parámetros obligatorios
fi
# Verificar que el archivo de configuración de Forgejo existe
if [ ! -f "$FORGEJO_CONFIG_FILE" ]; then
mkdir -p "$(dirname "$FORGEJO_CONFIG_FILE")"
# Si el archivo no existe, preguntar por token
if [ -t 0 ]; then # Solo si es terminal interactiva
echo "Archivo de configuración de Forgejo no encontrado."
echo ""
echo "Para generar un token en Forgejo:"
echo "1. Inicie sesión en $FORGEJO_API_URL (sin '/api/v1')"
echo "2. Vaya a Configuración → Aplicaciones"
echo "3. Genere un nuevo token de acceso personal con permisos de 'repo'"
echo ""
read -p "Ingrese su token de acceso de Forgejo: " FORGEJO_TOKEN
echo "FORGEJO_TOKEN=$FORGEJO_TOKEN" > "$FORGEJO_CONFIG_FILE"
chmod 600 "$FORGEJO_CONFIG_FILE" # Restricción de permisos por seguridad
else
return 11 # Error: no existe configuración y no es interactivo
fi
fi
# Cargar token de Forgejo
source "$FORGEJO_CONFIG_FILE"
if [ -z "$FORGEJO_TOKEN" ]; then
return 12 # Error: token no disponible
fi
# Verificar visibilidad válida
if [ "$VISIBILITY" != "private" ] && [ "$VISIBILITY" != "public" ]; then
VISIBILITY="private" # Establecer valor por defecto si es inválido
fi
# Preparar datos para la API
local API_DATA="{\"name\":\"$PROJECT_NAME\",\"description\":\"$PROJECT_DESC\",\"private\":$([ "$VISIBILITY" == "private" ] && echo "true" || echo "false")}"
# Comprobar si podemos acceder a la API
local API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$FORGEJO_API_URL/version")
if [ "$API_STATUS" != "200" ]; then
echo "ERROR: No se puede acceder a la API de Forgejo. Código de estado: $API_STATUS" >&2
echo "{\"error\":\"No se puede acceder a la API. Código: $API_STATUS\"}" > "$HOME/.developer/${PROJECT_NAME}.error"
return 13
fi
# Verificar token
local TOKEN_CHECK=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $FORGEJO_TOKEN" "$FORGEJO_API_URL/user")
if [ "$TOKEN_CHECK" != "200" ]; then
echo "ERROR: Token inválido o sin acceso. Código de estado: $TOKEN_CHECK" >&2
echo "{\"error\":\"Token inválido o sin acceso. Código: $TOKEN_CHECK\"}" > "$HOME/.developer/${PROJECT_NAME}.error"
return 12
fi
# Llamar a la API de Forgejo para crear el repositorio
local API_RESPONSE=$(curl -s -X POST "$FORGEJO_API_URL/user/repos" \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
-d "$API_DATA" 2>/tmp/curl_error.log)
echo "DEBUG: Respuesta API: $API_RESPONSE" >&2
# Verificar respuesta
if echo "$API_RESPONSE" | grep -q "\"id\":[0-9]*"; then
local REPO_URL=$(echo "$API_RESPONSE" | grep -o '"clone_url":"[^"]*"' | cut -d'"' -f4)
if [ -n "$REPO_URL" ]; then
echo "$REPO_URL" > "$HOME/.developer/${PROJECT_NAME}.repo"
else
# Extraer HTML URL como fallback
REPO_URL=$(echo "$API_RESPONSE" | grep -o '"html_url":"[^"]*"' | head -1 | cut -d'"' -f4)
if [ -n "$REPO_URL" ]; then
echo "$REPO_URL" > "$HOME/.developer/${PROJECT_NAME}.repo"
else
echo "ERROR: No se pudo extraer la URL del repositorio." >&2
echo "$API_RESPONSE" > "$HOME/.developer/${PROJECT_NAME}.error"
return 14
fi
fi
# Si se proporcionó una ruta local, configurar el repositorio
if [ -n "$PROJECT_PATH" ] && [ -d "$PROJECT_PATH" ]; then
cd "$PROJECT_PATH"
# Verificar si ya es un repositorio git
if [ -d ".git" ]; then
# Añadir el remoto
git remote add origin "$REPO_URL"
git push -u origin main || git push -u origin master
else
# Inicializar el repositorio y hacer primer commit si no existe
git init
git add .
git commit -m "[INIT] Proyecto $PROJECT_NAME"
git remote add origin "$REPO_URL"
git push -u origin main
fi
fi
return 0 # Éxito
else
# Guardar mensaje de error
echo "$API_RESPONSE" > "$HOME/.developer/${PROJECT_NAME}.error"
return 13 # Error: falló la creación del repositorio
fi
}