Files
ca-archive/build.sh
2026-02-08 23:35:53 +01:00

403 líneas
12 KiB
Bash
Archivo Ejecutable

Este archivo contiene caracteres Unicode invisibles
Este archivo contiene caracteres Unicode invisibles que son indistinguibles para los humanos, pero que pueden ser procesados de forma diferente por un ordenador. Si crees que esto es intencional, puedes ignorar esta advertencia. Usa el botón de Escape para revelarlos.
Este archivo contiene caracteres Unicode que pueden confundirse con otros caracteres. Si crees que esto es intencional, puedes ignorar esta advertencia. Usa el botón de Escape para revelarlos.
#!/bin/bash
# Script de construcción para Classic Add-ons Archive v3.0
# Genera paquetes .xpi (Firefox) y .zip (Chrome)
set -e # Salir si hay errores
echo "=================================================="
echo " Classic Add-ons Archive - Build Script v3.0"
echo "=================================================="
echo ""
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuración
VERSION="3.0.0"
DIST_DIR="dist"
KEYS_DIR="private-keys"
FIREFOX_PACKAGE="ca-archive-${VERSION}.xpi"
CHROME_PACKAGE="ca-archive-${VERSION}-chrome.zip"
CHROME_CRX="ca-archive-${VERSION}-chrome.crx"
CHROME_KEY="$KEYS_DIR/chrome-extension.pem"
FIREFOX_JWT="$KEYS_DIR/firefox-amo-credentials.json"
# Opciones de línea de comandos
SIGN_MODE=""
for arg in "$@"; do
case $arg in
--sign)
SIGN_MODE="all"
shift
;;
--sign-chrome)
SIGN_MODE="chrome"
shift
;;
--sign-firefox)
SIGN_MODE="firefox"
shift
;;
--list|-l)
LIST_CONTENTS=true
shift
;;
*)
;;
esac
done
# Archivos a incluir (relativos al directorio raíz)
INCLUDE_FILES=(
"manifest.json"
"background.js"
"content/"
"skin/"
)
# Archivos a excluir (patrones de exclusión)
EXCLUDE_PATTERNS=(
"*.git*"
"*~"
"*.swp"
".DS_Store"
"Thumbs.db"
"*.tmp"
"*.log"
"*.md" # Excluir documentación (opcional: comentar para incluir)
"install.rdf" # Legacy
"chrome.manifest" # Legacy
"bootstrap.js" # Legacy
"update.xml" # Legacy
"content/db.js" # Legacy (usamos db-webext.js)
"package.json"
"package-lock.json"
"node_modules/"
"dist/"
)
# Función para imprimir con color
print_status() {
echo -e "${GREEN}[✓]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[!]${NC} $1"
}
print_error() {
echo -e "${RED}[✗]${NC} $1"
}
# Verificar que estamos en el directorio correcto
if [ ! -f "manifest.json" ]; then
print_error "No se encuentra manifest.json"
print_error "Ejecuta este script desde el directorio raíz del proyecto"
exit 1
fi
print_status "Directorio de proyecto detectado"
# Crear directorio de distribución
if [ -d "$DIST_DIR" ]; then
print_warning "Limpiando directorio de distribución existente..."
rm -rf "$DIST_DIR"
fi
mkdir -p "$DIST_DIR"
print_status "Directorio de distribución creado: $DIST_DIR/"
# Función para construir el comando de exclusión para zip
build_exclude_args() {
local args=""
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
args="$args -x '$pattern'"
done
echo "$args"
}
# Construir paquete para Firefox (.xpi)
echo ""
echo "Construyendo paquete para Firefox..."
print_status "Empaquetando archivos..."
# Crear archivo zip temporal
TMP_ZIP="$DIST_DIR/temp.zip"
# Comando de zip con exclusiones
zip -r "$TMP_ZIP" "${INCLUDE_FILES[@]}" \
-x "${EXCLUDE_PATTERNS[@]}" \
> /dev/null 2>&1
# Renombrar a .xpi
mv "$TMP_ZIP" "$DIST_DIR/$FIREFOX_PACKAGE"
if [ -f "$DIST_DIR/$FIREFOX_PACKAGE" ]; then
FIREFOX_SIZE=$(du -h "$DIST_DIR/$FIREFOX_PACKAGE" | cut -f1)
print_status "Paquete Firefox creado: $FIREFOX_PACKAGE ($FIREFOX_SIZE)"
else
print_error "Error al crear paquete Firefox"
exit 1
fi
# Construir paquete para Chrome (.zip)
echo ""
echo "Construyendo paquete para Chrome..."
print_status "Empaquetando archivos..."
zip -r "$DIST_DIR/$CHROME_PACKAGE" "${INCLUDE_FILES[@]}" \
-x "${EXCLUDE_PATTERNS[@]}" \
> /dev/null 2>&1
if [ -f "$DIST_DIR/$CHROME_PACKAGE" ]; then
CHROME_SIZE=$(du -h "$DIST_DIR/$CHROME_PACKAGE" | cut -f1)
print_status "Paquete Chrome creado: $CHROME_PACKAGE ($CHROME_SIZE)"
else
print_error "Error al crear paquete Chrome"
exit 1
fi
# Verificar integridad de los paquetes
echo ""
print_status "Verificando paquetes..."
# Verificar Firefox
if unzip -t "$DIST_DIR/$FIREFOX_PACKAGE" > /dev/null 2>&1; then
print_status "Paquete Firefox verificado (integridad OK)"
else
print_error "Paquete Firefox corrupto"
exit 1
fi
# Verificar Chrome
if unzip -t "$DIST_DIR/$CHROME_PACKAGE" > /dev/null 2>&1; then
print_status "Paquete Chrome verificado (integridad OK)"
else
print_error "Paquete Chrome corrupto"
exit 1
fi
# Firma de paquetes si se solicitó
if [ "$SIGN_MODE" = "firefox" ] || [ "$SIGN_MODE" = "all" ]; then
echo ""
echo "=================================================="
echo " Firmando paquete Firefox"
echo "=================================================="
if [ ! -f "$FIREFOX_JWT" ]; then
print_error "No se encontraron credenciales de Firefox: $FIREFOX_JWT"
print_warning "Ejecuta: ./scripts/generate-keys.sh"
exit 1
fi
# Buscar web-ext: primero en node_modules, luego global
WEB_EXT=""
if [ -f "node_modules/.bin/web-ext" ]; then
WEB_EXT="./node_modules/.bin/web-ext"
print_status "Usando web-ext local: $WEB_EXT"
elif command -v npx &> /dev/null; then
WEB_EXT="npx web-ext"
print_status "Usando web-ext via npx"
elif command -v web-ext &> /dev/null; then
WEB_EXT="web-ext"
print_status "Usando web-ext global"
else
print_error "web-ext no está instalado"
print_warning "Instalar con: npm install"
print_warning "O globalmente: npm install -g web-ext"
exit 1
fi
print_status "Firmando con AMO..."
# Leer credenciales del JSON
API_KEY=$(grep -o '"apiKey"[[:space:]]*:[[:space:]]*"[^"]*"' "$FIREFOX_JWT" | cut -d'"' -f4)
API_SECRET=$(grep -o '"apiSecret"[[:space:]]*:[[:space:]]*"[^"]*"' "$FIREFOX_JWT" | cut -d'"' -f4)
if [ -z "$API_KEY" ] || [ -z "$API_SECRET" ]; then
print_error "Credenciales de AMO inválidas en $FIREFOX_JWT"
exit 1
fi
# Firmar con web-ext
# Nota: El ID se lee automáticamente de manifest.json, no se pasa como parámetro
$WEB_EXT sign \
--source-dir=. \
--artifacts-dir="$DIST_DIR" \
--api-key="$API_KEY" \
--api-secret="$API_SECRET" \
--channel=unlisted \
2>&1 | tee "$DIST_DIR/firefox-sign.log"
# Verificar el código de salida
SIGN_EXIT_CODE=${PIPESTATUS[0]}
if [ $SIGN_EXIT_CODE -eq 0 ]; then
print_status "Paquete Firefox firmado exitosamente"
# Buscar el archivo firmado
SIGNED_XPI=$(ls -t "$DIST_DIR"/*.xpi 2>/dev/null | head -1)
if [ -f "$SIGNED_XPI" ]; then
print_status "Archivo firmado: $(basename "$SIGNED_XPI")"
fi
else
print_error "Error al firmar paquete Firefox (código: $SIGN_EXIT_CODE)"
print_warning "Revisa: $DIST_DIR/firefox-sign.log"
exit $SIGN_EXIT_CODE
fi
fi
if [ "$SIGN_MODE" = "chrome" ] || [ "$SIGN_MODE" = "all" ]; then
echo ""
echo "=================================================="
echo " Firmando paquete Chrome"
echo "=================================================="
if [ ! -f "$CHROME_KEY" ]; then
print_error "No se encontró clave de Chrome: $CHROME_KEY"
print_warning "Ejecuta: ./scripts/generate-keys.sh"
exit 1
fi
if ! command -v google-chrome &> /dev/null && ! command -v chromium &> /dev/null; then
print_warning "Chrome/Chromium no encontrado, usando método alternativo..."
# Método alternativo: crear .crx manualmente
print_status "Generando .crx con openssl..."
# Extraer clave pública
openssl rsa -in "$CHROME_KEY" -pubout -outform DER > "$DIST_DIR/public.der" 2>/dev/null
# Crear firma
openssl dgst -sha256 -sign "$CHROME_KEY" -out "$DIST_DIR/signature.bin" "$DIST_DIR/$CHROME_PACKAGE"
# Leer tamaños
pub_size=$(wc -c < "$DIST_DIR/public.der")
sig_size=$(wc -c < "$DIST_DIR/signature.bin")
# Crear header CRX3
(
printf "Cr24" # Magic number
printf '\x03\x00\x00\x00' # Version 3
printf "$(printf '%08x' $pub_size | sed 's/\(..\)/\\x\1/g' | tac -s'\\')" # Public key length (little endian)
printf "$(printf '%08x' $sig_size | sed 's/\(..\)/\\x\1/g' | tac -s'\\')" # Signature length (little endian)
cat "$DIST_DIR/public.der"
cat "$DIST_DIR/signature.bin"
cat "$DIST_DIR/$CHROME_PACKAGE"
) > "$DIST_DIR/$CHROME_CRX"
# Limpiar archivos temporales
rm -f "$DIST_DIR/public.der" "$DIST_DIR/signature.bin"
if [ -f "$DIST_DIR/$CHROME_CRX" ]; then
CRX_SIZE=$(du -h "$DIST_DIR/$CHROME_CRX" | cut -f1)
print_status "Paquete Chrome firmado: $CHROME_CRX ($CRX_SIZE)"
# Calcular hash
CRX_HASH=$(sha256sum "$DIST_DIR/$CHROME_CRX" | cut -d' ' -f1)
echo "$CRX_HASH" > "$DIST_DIR/${CHROME_CRX}.sha256"
print_status "Hash SHA256 guardado"
else
print_error "Error al crear .crx"
fi
else
print_status "Empaquetando con Chrome..."
# Usar Chrome para empaquetar
CHROME_BIN=$(command -v google-chrome || command -v chromium)
"$CHROME_BIN" --pack-extension=. --pack-extension-key="$CHROME_KEY" --no-message-box 2>/dev/null
if [ -f "$(basename $(pwd)).crx" ]; then
mv "$(basename $(pwd)).crx" "$DIST_DIR/$CHROME_CRX"
print_status "Paquete Chrome firmado: $CHROME_CRX"
else
print_error "Error al firmar con Chrome"
fi
fi
# Calcular Extension ID
if [ -f "$CHROME_KEY" ]; then
CHROME_ID=$(openssl rsa -in "$CHROME_KEY" -pubout -outform DER 2>/dev/null | \
openssl dgst -sha256 -binary | \
head -c 16 | \
od -An -tx1 | \
tr -d ' \n' | \
tr '0-9a-f' 'a-p')
echo "$CHROME_ID" > "$DIST_DIR/chrome-extension-id.txt"
print_status "Extension ID: $CHROME_ID"
fi
fi
# Listar contenido (opcional)
if [ "$LIST_CONTENTS" = true ]; then
echo ""
echo "Contenido del paquete Firefox:"
unzip -l "$DIST_DIR/$FIREFOX_PACKAGE"
fi
# Resumen final
echo ""
echo "=================================================="
echo " ✨ Build completado exitosamente"
echo "=================================================="
echo ""
echo "Paquetes generados en: $DIST_DIR/"
echo ""
echo " Firefox: $FIREFOX_PACKAGE ($FIREFOX_SIZE)"
echo " Chrome: $CHROME_PACKAGE ($CHROME_SIZE)"
if [ "$SIGN_MODE" = "chrome" ] || [ "$SIGN_MODE" = "all" ]; then
if [ -f "$DIST_DIR/$CHROME_CRX" ]; then
CRX_SIZE=$(du -h "$DIST_DIR/$CHROME_CRX" | cut -f1)
echo " Chrome (firmado): $CHROME_CRX ($CRX_SIZE)"
fi
fi
echo ""
if [ -z "$SIGN_MODE" ]; then
echo " Paquetes sin firmar. Para firmar usa:"
echo " ./build.sh --sign # Firmar ambos"
echo " ./build.sh --sign-firefox # Solo Firefox"
echo " ./build.sh --sign-chrome # Solo Chrome"
echo ""
fi
echo "Próximos pasos:"
echo ""
if [ -n "$SIGN_MODE" ]; then
echo " Paquetes firmados ✓"
echo ""
echo " Para publicar:"
if [ "$SIGN_MODE" = "firefox" ] || [ "$SIGN_MODE" = "all" ]; then
echo " Firefox AMO: El archivo firmado está listo para subir"
echo " https://addons.mozilla.org/developers/"
fi
if [ "$SIGN_MODE" = "chrome" ] || [ "$SIGN_MODE" = "all" ]; then
echo " Chrome Web Store: Sube el archivo .zip (no .crx)"
echo " https://chrome.google.com/webstore/devconsole"
fi
else
echo " Firefox:"
echo " 1. Ir a about:debugging#/runtime/this-firefox"
echo " 2. Click en 'Cargar complemento temporal'"
echo " 3. Seleccionar: $DIST_DIR/$FIREFOX_PACKAGE"
echo ""
echo " Chrome:"
echo " 1. Ir a chrome://extensions/"
echo " 2. Activar 'Modo de desarrollador'"
echo " 3. Click en 'Cargar extensión sin empaquetar'"
echo " 4. Extraer y seleccionar la carpeta de $CHROME_PACKAGE"
fi
echo ""
echo "=================================================="
exit 0