Skip to content

Guía de Despliegue y Actualización Automatizada con GitHub Actions para Aplicaciones Electron de Código Abierto

1. Introducción

Este artículo proporciona una guía detallada sobre cómo usar GitHub Actions para lograr la construcción, publicación y actualizaciones automáticas de aplicaciones Electron a través de UpgradeLink. A través de esta guía, aprenderás a configurar flujos de trabajo de GitHub Actions para completar el proceso de automatización completo desde la presentación del código hasta las actualizaciones de la aplicación.

2. Introducción a Herramientas Fundamentales

UpgradeLink proporciona un complemento GitHub Action para cargar archivos de actualización generados por aplicaciones Electron al servidor de UpgradeLink. UpgradeLink lee las direcciones de los archivos de la aplicación desde archivos JSON, guarda los archivos y crea automáticamente archivos de versión de la aplicación y estrategias de actualización correspondientes.

2. Proyecto de Ejemplo con Flujo de Trabajo Completo

Proyecto de ejemplo con flujo de trabajo completo:

3. Descripción del Flujo de Trabajo

El flujo de trabajo consta de tres trabajos principales:

  1. electron-build: Construir y publicar paquetes de aplicaciones Electron para diferentes plataformas y arquitecturas

    • Construcción multiplataforma: Soporta macOS, Linux y Windows simultáneamente
    • Extracción de versión: Extraer número de versión de la aplicación desde la salida de construcción de Electron
  2. electron-release: Publicar versiones basadas en los paquetes construidos por electron-build

    • Gestión de publicaciones: Crear automáticamente GitHub Release y cargar paquetes de instalación de la aplicación
    • Parámetros de salida: Salir número de versión de la aplicación para trabajos posteriores
  3. upgradeLink-upload: Sincronizar información de actualización con UpgradeLink

    • Dependencia: Esperar la finalización de los dos trabajos anteriores
    • Conciencia de versión: Obtener número de versión de la aplicación a través de parámetros de salida
    • Llamadas a API: Usar UpgradeLink Action para cargar paquetes de instalación correspondientes al servidor de actualización

4. Explicación Detallada de los Pasos de Integración

1. Preparación

Primero, asegúrate de que:

  • Se ha creado el repositorio de GitHub y se ha cargado el código de la aplicación Electron
  • Tienes una cuenta de la plataforma UpgradeLink y has obtenido las siguientes credenciales:
  • Configura la dirección del repositorio de GitHub en la configuración de la aplicación electron en la plataforma UpgradeLink.

2. Configurar Secretos de GitHub

Agrega las siguientes variables de entorno cifradas en Configuración del repositorio de GitHub > Seguridad > Secretos y variables > Acciones:

Nombre del SecretoDescripción
UPGRADE_LINK_ACCESS_KEYClave de acceso proporcionada por la plataforma UpgradeLink para autenticación de llamadas a la API
UPGRADE_LINK_ELECTRON_KEYIdentificador único asignado por la plataforma UpgradeLink para tu aplicación Electron

3. Edita el archivo electron-demo/.github/workflows/main.yml de GitHub Action, ajústalo según tus necesidades.

yaml
name: 'publish'

on:
  push:
    branches:
      - main
    tags:
      - '*.*.*'

jobs:
  electron-build:
    outputs:
      appVersion: ${{ steps.extract-version.outputs.appVersion }}
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          # Plataforma Linux
          - platform: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            artifact-name: ubuntu-x86_64
            arch-suffix: x64
            # Definir directamente el comando de construcción completo incluyendo información del canal
            build-command: "yarn electron-builder --linux --x64 --publish always --config.publish.channel=latest-linux"

          - platform: ubuntu-22.04
            target: aarch64-unknown-linux-gnu
            artifact-name: ubuntu-aarch64
            arch-suffix: arm64
            build-command: "yarn electron-builder --linux --arm64 --publish always --config.publish.channel=latest-linux"

          # Plataforma macOS
          - platform: macos-latest
            target: aarch64-apple-darwin
            artifact-name: macos-arm64
            arch-suffix: arm64
            build-command: "yarn electron-builder --mac --arm64 --publish always --config.publish.channel=latest-mac"

          - platform: macos-latest
            target: x86_64-apple-darwin
            artifact-name: macos-x64
            arch-suffix: x64
            build-command: "yarn electron-builder --mac --x64 --publish always --config.publish.channel=latest-mac"

          # Plataforma Windows
          - platform: windows-latest
            target: x86_64-pc-windows-msvc
            artifact-name: windows-x64
            arch-suffix: x64
            build-command: "yarn electron-builder --win --x64 --publish always --config.publish.channel=latest-win"

    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - name: setup node
        uses: actions/setup-node@v4
        with:
          node-version: lts/*
          cache: 'yarn'

      - name: Instalar dependencias con yarn
        run: yarn install

      - name: Listar dependencias instaladas
        run: yarn list

      - name: instalar dependencias (solo ubuntu)
        if: startsWith(matrix.platform, 'ubuntu')
        run: |
          sudo apt-get update
          sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils

      - name: instalar dependencias (solo macos)
        if: matrix.platform == 'macos-latest'
        run: |
          brew install automake autoconf libtool

      - name: instalar dependencias frontend
        run: yarn install

      - name: Instalar rimraf
        run: yarn add rimraf --dev

      - name: Construir aplicación Electron
        # Ejecutar directamente el comando de construcción completo definido en la matriz
        run: ${{ matrix.build-command }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Limpiar Artefactos para Linux
        if: startsWith(matrix.platform, 'ubuntu')
        run: |
          mkdir -p dist-temp
          find dist -maxdepth 1 -type f \( -name "*.AppImage" -o -name "*.yml" -o -name "*.zip" \) -exec cp {} dist-temp/ \;
          rm -rf dist
          mv dist-temp dist
          echo "Archivos de publicación retenidos:"
          ls -la dist

      - name: Limpiar Artefactos para macOS
        if: matrix.platform == 'macos-latest'
        run: |
          mkdir -p dist-temp
          find dist -maxdepth 1 -type f \( -name "*.dmg" -o -name "*.pkg" -o -name "*.zip" -o -name "*.yml" \) -exec cp {} dist-temp/ \;
          rm -rf dist
          mv dist-temp dist
          echo "Archivos de publicación retenidos:"
          ls -la dist

      - name: Limpiar Artefactos para Windows
        if: matrix.platform == 'windows-latest'
        run: |
          New-Item -ItemType Directory -Path dist-temp -Force | Out-Null
          Get-ChildItem -Path dist -File | Where-Object {
              $_.Name -like "*.exe" -or $_.Name -like "*.msi" -or $_.Name -like "*.zip" -or $_.Name -like "*.yml"
          } | Copy-Item -Destination dist-temp/
          Remove-Item -Path dist -Recurse -Force
          Rename-Item -Path dist-temp -NewName dist
          Write-Host "Archivos de publicación retenidos:"
          Get-ChildItem -Path dist

      - name: Renombrar archivos con sufijo de arquitectura (Linux/macOS)
        if: startsWith(matrix.platform, 'ubuntu') || matrix.platform == 'macos-latest'
        run: |
          cd dist

          ARCH_SUFFIX="${{ matrix.arch-suffix }}"

          if [ "$ARCH_SUFFIX" != "x64" ] && [ "$ARCH_SUFFIX" != "arm64" ]; then
            echo "Error: Sufijo de arquitectura incorrecto - $ARCH_SUFFIX"
            exit 1
          fi

          # Procesar primero identificadores de plataforma duplicados
          for file in *.yml; do
            if [ -f "$file" ]; then
              # Reemplazo fijo -linux-linux por -linux
              if [[ "$file" == *-linux-linux* ]]; then
                new_file="${file//-linux-linux/-linux}"
                mv "$file" "$new_file"
                echo "Reemplazar identificador duplicado: $file -> $new_file"
                file="$new_file"
              fi

              # Reemplazo fijo -mac-mac por -mac
              if [[ "$file" == *-mac-mac* ]]; then
                new_file="${file//-mac-mac/-mac}"
                mv "$file" "$new_file"
                echo "Reemplazar identificador duplicado: $file -> $new_file"
                file="$new_file"
              fi
          
              # Reemplazo fijo x86_64-x64 por -x64
              if [[ "$file" == *-x86_64-x64* ]]; then
                new_file="${file//x86_64-x64/-x64}"
                mv "$file" "$new_file"
                echo "Reemplazar identificador duplicado: $file -> $new_file"
                file="$new_file"
              fi

              # Procesar sufijo de arquitectura
              if [[ "$file" != *-"$ARCH_SUFFIX".* ]]; then
                filename="${file%.*}"
                extension="${file#$filename}"
                new_filename="${filename}-${ARCH_SUFFIX}${extension}"
                mv "$file" "$new_filename"
                echo "Agregar sufijo de arquitectura: $file -> $new_filename"
              else
                echo "Archivo procesado: $file"
              fi
            fi
          done

          echo "Lista final de archivos:"
          ls -l

      - name: Renombrar archivos con sufijo de arquitectura (Windows)
        if: matrix.platform == 'windows-latest'
        run: |
          cd dist
          
          $ARCH_SUFFIX = "${{ matrix.arch-suffix }}"
          if ($ARCH_SUFFIX -ne "x64" -and $ARCH_SUFFIX -ne "arm64") {
            Write-Error "Error: Sufijo de arquitectura incorrecto - $ARCH_SUFFIX"
            exit 1
          }
          
          Get-ChildItem -File | ForEach-Object {
            $file = $_
            if ($file.Name -match "-$ARCH_SUFFIX\.[^.]+$") {
              Write-Host "Archivo ya contiene sufijo de arquitectura: $($file.Name)"
            } else {
              $filename = $file.BaseName
              $extension = $file.Extension
              $new_filename = "$filename-$ARCH_SUFFIX$extension"
              Rename-Item -Path $file.FullName -NewName $new_filename
              Write-Host "Renombrar: $($file.Name) -> $new_filename"
            }
          }
          
          Write-Host "Archivos después de renombrar:"
          Get-ChildItem -File

      - name: Extraer versión
        id: extract-version
        run: |
          # Priorizar obtener número de versión desde etiqueta
          if [[ "${{ github.ref }}" == refs/tags/* ]]; then
            VERSION=${{ github.ref_name }}
          else
            # Si no es un push de etiqueta, leer número de versión desde package.json
            VERSION=$(node -p "require('./package.json').version")
            # O usar un valor predeterminado fijo
            # VERSION="dev-$(date +%Y%m%d)"
          fi
          echo "appVersion=$VERSION" >> $GITHUB_OUTPUT
          echo "Extracted version: $VERSION"
        shell: bash

      - name: Cargar artefactos
        uses: actions/upload-artifact@v4.0.0
        with:
          name: ${{ matrix.artifact-name }}
          path: dist/*
          if-no-files-found: error

  electron-release:
    needs: electron-build
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    steps:
      - name: Descargar todos los artefactos
        uses: actions/download-artifact@v4
        with:
          path: artifacts
          merge-multiple: false

      - name: Verificar archivos de artefactos
        run: |
          echo "Estructura de archivos descargada:"
          tree artifacts
          
          if [ -z "$(find artifacts -type f)" ]; then
            echo "Error: No se encontraron archivos de artifact"
            exit 1
          fi

      - name: Preparar archivos de publicación
        run: |
          mkdir -p release-files
          find artifacts -type f -exec cp {} release-files/ \;
          echo "Archivos preparados para publicación:"
          ls -l release-files

      - name: Crear GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ needs.electron-build.outputs.appVersion }}
          name: Release ${{ needs.electron-build.outputs.appVersion }}
          files: release-files/*
          draft: false
          prerelease: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
yaml
  upgradeLink-upload:
     # Depender tanto de electron-build como de electron-release para asegurar acceso a la salida de electron-build
     needs: [ electron-build, electron-release ]
     permissions:
       contents: write
     runs-on: ubuntu-latest
     steps:
       - name: Enviar solicitud a UpgradeLink
         uses: toolsetlink/upgradelink-action-electron@v1.0.1
         with:
           source-url: 'https://github.com/toolsetlink/electron-demo/releases/download/${{ needs.electron-build.outputs.appVersion }}'
           access-key: ${{ secrets.UPGRADE_LINK_ACCESS_KEY }}  # Clave ACCESS_KEY
           electron-key: ${{ secrets.UPGRADE_LINK_ELECTRON_KEY }}    # Identificador único de la aplicación electron ELECTRON_KEY
           github-token: ${{ secrets.GITHUB_TOKEN }}
           version: ${{ needs.electron-build.outputs.appVersion }}
           prompt-upgrade-content: 'Contenido del mensaje de actualización'

5. Problemas Comunes y Soluciones

1. Problemas de Firma

2. Solución de Problemas de Construcción

  • Verificar registros de GitHub Actions para información de error específica
  • Confirmar que todas las dependencias estén correctamente instaladas, especialmente las dependencias del sistema para la plataforma Linux
  • Asegurar compatibilidad de versión de Node.js
  • Verificar si el identificador de la aplicación en la consola de UpgradeLink coincide con la configuración
  • Confirmar si se generan archivos correctos de paquetes de instalación en GitHub Releases

6. Resumen

A través de la configuración anterior, puedes lograr la automatización completa de los procesos de construcción, publicación y actualización de aplicaciones Electron. Cada vez que se empuje código a la rama especificada, GitHub Actions completará automáticamente el siguiente trabajo:

  1. Detectar cambios en el código
  2. Construir aplicación Electron en entornos multiplataforma
  3. Crear GitHub Release y cargar paquetes de instalación
  4. Extraer número de versión de la aplicación
  5. Sincronizar información de actualización con la plataforma UpgradeLink
  6. Los usuarios finales recibirán notificaciones de actualización de la aplicación a través de UpgradeLink

Este flujo de trabajo automatizado mejora enormemente la eficiencia del desarrollo, reduce errores de operación manual y permite a los desarrolladores enfocarse más en el desarrollo de funciones de la aplicación.

toolsetlink@163.com